In order to correctly compile

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
This commit is contained in:
Rafael Espindola 2012-07-24 21:40:17 +00:00
parent 16b7dd64e9
commit cde227bc2a
2 changed files with 22 additions and 2 deletions

View File

@ -165,8 +165,9 @@ const AttrConst FunctionOnly = {NoReturn_i | NoUnwind_i | ReadNone_i |
const AttrConst VarArgsIncompatible = {StructRet_i}; const AttrConst VarArgsIncompatible = {StructRet_i};
/// @brief Attributes that are mutually incompatible. /// @brief Attributes that are mutually incompatible.
const AttrConst MutuallyIncompatible[4] = { const AttrConst MutuallyIncompatible[5] = {
{ByVal_i | InReg_i | Nest_i | StructRet_i}, {ByVal_i | Nest_i | StructRet_i},
{ByVal_i | Nest_i | InReg_i },
{ZExt_i | SExt_i}, {ZExt_i | SExt_i},
{ReadNone_i | ReadOnly_i}, {ReadNone_i | ReadOnly_i},
{NoInline_i | AlwaysInline_i} {NoInline_i | AlwaysInline_i}

19
test/CodeGen/X86/inreg.ll Normal file
View File

@ -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)