[cfe-commits] r166266 - in /cfe/trunk: lib/CodeGen/ABIInfo.h lib/CodeGen/CGCall.cpp lib/CodeGen/TargetInfo.cpp test/CodeGenCXX/regparm.cpp

Rafael Espindola rafael.espindola at gmail.com
Thu Oct 18 22:04:37 PDT 2012


Author: rafael
Date: Fri Oct 19 00:04:37 2012
New Revision: 166266

URL: http://llvm.org/viewvc/llvm-project?rev=166266&view=rev
Log:
Fix handling of the regparm attribute in the presence of classes with copy
constructors.

When I first moved regparm support to TargetInfo.cpp I tried to isolate it
in classifyArgumentTypeWithReg, but it is actually a lot easier to flip the
code around and check for regparm at the end of the decision tree.

Without this refactoring classifyArgumentTypeWithReg would have to duplicate
the logic about when to use non-byval indirect arguments.

Modified:
    cfe/trunk/lib/CodeGen/ABIInfo.h
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/CodeGen/TargetInfo.cpp
    cfe/trunk/test/CodeGenCXX/regparm.cpp

Modified: cfe/trunk/lib/CodeGen/ABIInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ABIInfo.h?rev=166266&r1=166265&r2=166266&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ABIInfo.h (original)
+++ cfe/trunk/lib/CodeGen/ABIInfo.h Fri Oct 19 00:04:37 2012
@@ -88,7 +88,7 @@
                                 llvm::Type *Padding = 0) {
       return ABIArgInfo(Direct, T, Offset, false, false, false, Padding);
     }
-    static ABIArgInfo getDirectInReg(llvm::Type *T) {
+    static ABIArgInfo getDirectInReg(llvm::Type *T = 0) {
       return ABIArgInfo(Direct, T, 0, false, false, true, 0);
     }
     static ABIArgInfo getExtend(llvm::Type *T = 0) {

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=166266&r1=166265&r2=166266&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Fri Oct 19 00:04:37 2012
@@ -1051,6 +1051,9 @@
       break;
 
     case ABIArgInfo::Indirect:
+      if (AI.getInReg())
+        Attrs.addAttribute(llvm::Attributes::InReg);
+
       if (AI.getIndirectByVal())
         Attrs.addAttribute(llvm::Attributes::ByVal);
 

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=166266&r1=166265&r2=166266&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Fri Oct 19 00:04:37 2012
@@ -519,7 +519,8 @@
 
   /// getIndirectResult - Give a source type \arg Ty, return a suitable result
   /// such that the argument will be passed in memory.
-  ABIArgInfo getIndirectResult(QualType Ty, bool ByVal = true) const;
+  ABIArgInfo getIndirectResult(QualType Ty, bool ByVal,
+                               unsigned &FreeRegs) const;
 
   /// \brief Return the alignment to use for the given type on the stack.
   unsigned getTypeStackAlignInBytes(QualType Ty, unsigned Align) const;
@@ -527,9 +528,8 @@
   Class classify(QualType Ty) const;
   ABIArgInfo classifyReturnType(QualType RetTy,
                                 unsigned callingConvention) const;
-  ABIArgInfo classifyArgumentTypeWithReg(QualType RetTy,
-                                         unsigned &FreeRegs) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, unsigned &FreeRegs) const;
+  bool shouldUseInReg(QualType Ty, unsigned &FreeRegs) const;
 
 public:
 
@@ -766,9 +766,15 @@
   return MinABIStackAlignInBytes;
 }
 
-ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal) const {
-  if (!ByVal)
+ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal,
+                                            unsigned &FreeRegs) const {
+  if (!ByVal) {
+    if (FreeRegs) {
+      --FreeRegs; // Non byval indirects just use one pointer.
+      return ABIArgInfo::getIndirectInReg(0, false);
+    }
     return ABIArgInfo::getIndirect(0, false);
+  }
 
   // Compute the byval alignment.
   unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
@@ -798,45 +804,23 @@
   return Integer;
 }
 
-ABIArgInfo
-X86_32ABIInfo::classifyArgumentTypeWithReg(QualType Ty,
-                                           unsigned &FreeRegs) const {
-  // Common case first.
-  if (FreeRegs == 0)
-    return classifyArgumentType(Ty);
-
+bool X86_32ABIInfo::shouldUseInReg(QualType Ty, unsigned &FreeRegs) const {
   Class C = classify(Ty);
   if (C == Float)
-    return classifyArgumentType(Ty);
+    return false;
 
   unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32;
-  if (SizeInRegs == 0)
-    return classifyArgumentType(Ty);
-
   if (SizeInRegs > FreeRegs) {
     FreeRegs = 0;
-    return classifyArgumentType(Ty);
+    return false;
   }
-  assert(SizeInRegs >= 1 && SizeInRegs <= 3);
-  FreeRegs -= SizeInRegs;
 
-  // If it is a simple scalar, keep the type so that we produce a cleaner IR.
-  ABIArgInfo Foo = classifyArgumentType(Ty);
-  if (Foo.isDirect() && !Foo.getDirectOffset() && !Foo.getPaddingType())
-    return ABIArgInfo::getDirectInReg(Foo.getCoerceToType());
-  if (Foo.isExtend())
-    return ABIArgInfo::getExtendInReg(Foo.getCoerceToType());
-
-  llvm::LLVMContext &LLVMContext = getVMContext();
-  llvm::Type *Int32 = llvm::Type::getInt32Ty(LLVMContext);
-  SmallVector<llvm::Type*, 3> Elements;
-  for (unsigned I = 0; I < SizeInRegs; ++I)
-    Elements.push_back(Int32);
-  llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
-  return ABIArgInfo::getDirectInReg(Result);
+  FreeRegs -= SizeInRegs;
+  return true;
 }
 
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
+                                               unsigned &FreeRegs) const {
   // FIXME: Set alignment on indirect arguments.
   if (isAggregateTypeForABI(Ty)) {
     // Structures with flexible arrays are always indirect.
@@ -844,16 +828,27 @@
       // Structures with either a non-trivial destructor or a non-trivial
       // copy constructor are always indirect.
       if (hasNonTrivialDestructorOrCopyConstructor(RT))
-        return getIndirectResult(Ty, /*ByVal=*/false);
+        return getIndirectResult(Ty, false, FreeRegs);
 
       if (RT->getDecl()->hasFlexibleArrayMember())
-        return getIndirectResult(Ty);
+        return getIndirectResult(Ty, true, FreeRegs);
     }
 
     // Ignore empty structs/unions.
     if (isEmptyRecord(getContext(), Ty, true))
       return ABIArgInfo::getIgnore();
 
+    if (shouldUseInReg(Ty, FreeRegs)) {
+      unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32;
+      llvm::LLVMContext &LLVMContext = getVMContext();
+      llvm::Type *Int32 = llvm::Type::getInt32Ty(LLVMContext);
+      SmallVector<llvm::Type*, 3> Elements;
+      for (unsigned I = 0; I < SizeInRegs; ++I)
+        Elements.push_back(Int32);
+      llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
+      return ABIArgInfo::getDirectInReg(Result);
+    }
+
     // Expand small (<= 128-bit) record types when we know that the stack layout
     // of those arguments will match the struct. This is important because the
     // LLVM backend isn't smart enough to remove byval, which inhibits many
@@ -862,7 +857,7 @@
         canExpandIndirectArgument(Ty, getContext()))
       return ABIArgInfo::getExpand();
 
-    return getIndirectResult(Ty);
+    return getIndirectResult(Ty, true, FreeRegs);
   }
 
   if (const VectorType *VT = Ty->getAs<VectorType>()) {
@@ -893,8 +888,16 @@
   if (const EnumType *EnumTy = Ty->getAs<EnumType>())
     Ty = EnumTy->getDecl()->getIntegerType();
 
-  return (Ty->isPromotableIntegerType() ?
-          ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+  bool InReg = shouldUseInReg(Ty, FreeRegs);
+
+  if (Ty->isPromotableIntegerType()) {
+    if (InReg)
+      return ABIArgInfo::getExtendInReg();
+    return ABIArgInfo::getExtend();
+  }
+  if (InReg)
+    return ABIArgInfo::getDirectInReg();
+  return ABIArgInfo::getDirect();
 }
 
 void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const {
@@ -916,7 +919,7 @@
 
   for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
        it != ie; ++it)
-    it->info = classifyArgumentTypeWithReg(it->type, FreeRegs);
+    it->info = classifyArgumentType(it->type, FreeRegs);
 }
 
 llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,

Modified: cfe/trunk/test/CodeGenCXX/regparm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/regparm.cpp?rev=166266&r1=166265&r2=166266&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/regparm.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/regparm.cpp Fri Oct 19 00:04:37 2012
@@ -4,3 +4,24 @@
 // CHECK: _Z3fooRi(i32* inreg
 void __attribute__ ((regparm (1)))  foo(int &a) {
 }
+
+struct S1 {
+  int x;
+  S1(const S1 &y);
+};
+
+void __attribute__((regparm(3))) foo2(S1 a, int b);
+// CHECK: declare void @_Z4foo22S1i(%struct.S1* inreg, i32 inreg)
+void bar2(S1 a, int b) {
+  foo2(a, b);
+}
+
+struct S2 {
+  int x;
+};
+
+void __attribute__((regparm(3))) foo3(struct S2 a, int b);
+// declare void @_Z4foo12S1i(i32 inreg, i32 inreg) optsize
+void bar3(struct S2 a, int b) {
+  foo3(a, b);
+}





More information about the cfe-commits mailing list