]> granicus.if.org Git - clang/commitdiff
Fix handling of the regparm attribute in the presence of classes with copy
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 19 Oct 2012 05:04:37 +0000 (05:04 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 19 Oct 2012 05:04:37 +0000 (05:04 +0000)
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.

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

lib/CodeGen/ABIInfo.h
lib/CodeGen/CGCall.cpp
lib/CodeGen/TargetInfo.cpp
test/CodeGenCXX/regparm.cpp

index fb5eadbede1daf01fde64eb2e9c3605a5c202ca1..1dd1d195c21e699f88fb3bf346808938f0bd8ebb 100644 (file)
@@ -88,7 +88,7 @@ namespace clang {
                                 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) {
index 2ef5bd27a0a24add4b853b03a2d53e720dd0a364..afcf541a3d39bf43452cc54469045075cb90331e 100644 (file)
@@ -1051,6 +1051,9 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
       break;
 
     case ABIArgInfo::Indirect:
+      if (AI.getInReg())
+        Attrs.addAttribute(llvm::Attributes::InReg);
+
       if (AI.getIndirectByVal())
         Attrs.addAttribute(llvm::Attributes::ByVal);
 
index ad59fd2c90860619ff624e4555442351067aa955..ca9cfbbfef23e5eb5d8de2911f16a58859ead679 100644 (file)
@@ -519,7 +519,8 @@ class X86_32ABIInfo : public ABIInfo {
 
   /// 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 X86_32ABIInfo : public ABIInfo {
   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 @@ unsigned X86_32ABIInfo::getTypeStackAlignInBytes(QualType Ty,
   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 @@ X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const {
   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 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty) const {
       // 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 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty) const {
         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 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty) const {
   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 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const {
 
   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,
index f0ebd2be41675c513aa0febf750296b4ce52db62..07e9aa046ef53fe4e0335d3fd58a5d1fbe22dcca 100644 (file)
@@ -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);
+}