In order to correctly compile
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 24 Jul 2012 21:40:17 +0000 (21:40 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 24 Jul 2012 21:40:17 +0000 (21:40 +0000)
struct s {
  double x1;
  float x2;
};
__attribute__((regparm(3))) struct s f(int a, int b, int c);
void g(void) {
  f(41, 42, 43);
}

We need to be able to represent passing the address of s to f (sret) in a
register (inreg). Turns out that all that is needed is to not mark them as
mutually incompatible.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160695 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Attributes.h
test/CodeGen/X86/inreg.ll [new file with mode: 0644]

index 59fdd993751bf2dd1a3792a66035be714445688e..0228d8691d2d9f46b30a501a947d15fa331229e2 100644 (file)
@@ -165,8 +165,9 @@ const AttrConst FunctionOnly = {NoReturn_i | NoUnwind_i | ReadNone_i |
 const AttrConst VarArgsIncompatible = {StructRet_i};
 
 /// @brief Attributes that are mutually incompatible.
-const AttrConst MutuallyIncompatible[4] = {
-  {ByVal_i | InReg_i | Nest_i | StructRet_i},
+const AttrConst MutuallyIncompatible[5] = {
+  {ByVal_i | Nest_i | StructRet_i},
+  {ByVal_i | Nest_i | InReg_i },
   {ZExt_i  | SExt_i},
   {ReadNone_i | ReadOnly_i},
   {NoInline_i | AlwaysInline_i}
diff --git a/test/CodeGen/X86/inreg.ll b/test/CodeGen/X86/inreg.ll
new file mode 100644 (file)
index 0000000..8981033
--- /dev/null
@@ -0,0 +1,19 @@
+; RUN: llc < %s -march=x86 | FileCheck %s
+
+%struct.s = type { double, float }
+
+define void @g() nounwind {
+entry:
+  %tmp = alloca %struct.s, align 4
+  call void @f(%struct.s* inreg sret %tmp, i32 inreg 41, i32 inreg 42, i32 43)
+  ret void
+  ; CHECK: g:
+  ; CHECK: subl {{.*}}, %esp
+  ; CHECK-NEXT: $43, (%esp)
+  ; CHECK-NEXT: leal    16(%esp), %eax
+  ; CHECK-NEXT: movl    $41, %edx
+  ; CHECK-NEXT: movl    $42, %ecx
+  ; CHECK-NEXT: calll   f
+}
+
+declare void @f(%struct.s* inreg sret, i32 inreg, i32 inreg, i32)