]> granicus.if.org Git - clang/commitdiff
Add padding inreg registers to cause llvm to skip ecx when needed with
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 24 Oct 2012 01:59:00 +0000 (01:59 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 24 Oct 2012 01:59:00 +0000 (01:59 +0000)
the x86_fastcallcc calling convention.

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

lib/CodeGen/ABIInfo.h
lib/CodeGen/CGCall.cpp
lib/CodeGen/TargetInfo.cpp
test/CodeGen/stdcall-fastcall.c

index 1dd1d195c21e699f88fb3bf346808938f0bd8ebb..da6d035dfaf0586fbfc1b9ddc6f7a0aea3d6e635 100644 (file)
@@ -70,46 +70,52 @@ namespace clang {
   private:
     Kind TheKind;
     llvm::Type *TypeData;
-    llvm::Type *PaddingType; // Currently allowed only for Direct.
+    llvm::Type *PaddingType;
     unsigned UIntData;
     bool BoolData0;
     bool BoolData1;
     bool InReg;
+    bool PaddingInReg;
 
     ABIArgInfo(Kind K, llvm::Type *TD, unsigned UI, bool B0, bool B1, bool IR,
-               llvm::Type* P)
+               bool PIR, llvm::Type* P)
       : TheKind(K), TypeData(TD), PaddingType(P), UIntData(UI), BoolData0(B0),
-        BoolData1(B1), InReg(IR) {}
+        BoolData1(B1), InReg(IR), PaddingInReg(PIR) {}
 
   public:
     ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
 
     static ABIArgInfo getDirect(llvm::Type *T = 0, unsigned Offset = 0,
                                 llvm::Type *Padding = 0) {
-      return ABIArgInfo(Direct, T, Offset, false, false, false, Padding);
+      return ABIArgInfo(Direct, T, Offset, false, false, false, false, Padding);
     }
     static ABIArgInfo getDirectInReg(llvm::Type *T = 0) {
-      return ABIArgInfo(Direct, T, 0, false, false, true, 0);
+      return ABIArgInfo(Direct, T, 0, false, false, true, false, 0);
     }
     static ABIArgInfo getExtend(llvm::Type *T = 0) {
-      return ABIArgInfo(Extend, T, 0, false, false, false, 0);
+      return ABIArgInfo(Extend, T, 0, false, false, false, false, 0);
     }
     static ABIArgInfo getExtendInReg(llvm::Type *T = 0) {
-      return ABIArgInfo(Extend, T, 0, false, false, true, 0);
+      return ABIArgInfo(Extend, T, 0, false, false, true, false, 0);
     }
     static ABIArgInfo getIgnore() {
-      return ABIArgInfo(Ignore, 0, 0, false, false, false, 0);
+      return ABIArgInfo(Ignore, 0, 0, false, false, false, false, 0);
     }
     static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true
                                   , bool Realign = false) {
-      return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, false, 0);
+      return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, false, false, 0);
     }
     static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true
                                   , bool Realign = false) {
-      return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, true, 0);
+      return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, true, false, 0);
     }
     static ABIArgInfo getExpand() {
-      return ABIArgInfo(Expand, 0, 0, false, false, false, 0);
+      return ABIArgInfo(Expand, 0, 0, false, false, false, false, 0);
+    }
+    static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
+                                           llvm::Type *Padding) {
+     return ABIArgInfo(Expand, 0, 0, false, false, false, PaddingInReg,
+                       Padding);
     }
 
     Kind getKind() const { return TheKind; }
@@ -133,6 +139,10 @@ namespace clang {
       return PaddingType;
     }
 
+    bool getPaddingInReg() const {
+      return PaddingInReg;
+    }
+
     llvm::Type *getCoerceToType() const {
       assert(canHaveCoerceToType() && "Invalid kind!");
       return TypeData;
index afcf541a3d39bf43452cc54469045075cb90331e..b356e640a1c47b82c63bcf0be560a42232cd16e2 100644 (file)
@@ -867,6 +867,10 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
          ie = FI.arg_end(); it != ie; ++it) {
     const ABIArgInfo &argAI = it->info;
 
+    // Insert a padding type to ensure proper alignment.
+    if (llvm::Type *PaddingType = argAI.getPaddingType())
+      argTypes.push_back(PaddingType);
+
     switch (argAI.getKind()) {
     case ABIArgInfo::Ignore:
       break;
@@ -880,9 +884,6 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
 
     case ABIArgInfo::Extend:
     case ABIArgInfo::Direct: {
-      // Insert a padding type to ensure proper alignment.
-      if (llvm::Type *PaddingType = argAI.getPaddingType())
-        argTypes.push_back(PaddingType);
       // If the coerce-to type is a first class aggregate, flatten it.  Either
       // way is semantically identical, but fast-isel and the optimizer
       // generally likes scalar values better than FCAs.
@@ -1019,6 +1020,18 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
     const ABIArgInfo &AI = it->info;
     llvm::AttrBuilder Attrs;
 
+    if (AI.getPaddingType()) {
+      if (AI.getPaddingInReg()) {
+        llvm::AttrBuilder PadAttrs;
+        PadAttrs.addAttribute(llvm::Attributes::InReg);
+
+        llvm::Attributes A =llvm::Attributes::get(getLLVMContext(), PadAttrs);
+        PAL.push_back(llvm::AttributeWithIndex::get(Index, A));
+      }
+      // Increment Index if there is padding.
+      ++Index;
+    }
+
     // 'restrict' -> 'noalias' is done in EmitFunctionProlog when we
     // have the corresponding parameter variable.  It doesn't make
     // sense to do it here because parameters are so messed up.
@@ -1035,9 +1048,6 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
 
       // FIXME: handle sseregparm someday...
 
-      // Increment Index if there is padding.
-      Index += (AI.getPaddingType() != 0);
-
       if (llvm::StructType *STy =
           dyn_cast<llvm::StructType>(AI.getCoerceToType())) {
         unsigned Extra = STy->getNumElements()-1;  // 1 will be added below.
@@ -1155,6 +1165,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
     bool isPromoted =
       isa<ParmVarDecl>(Arg) && cast<ParmVarDecl>(Arg)->isKNRPromoted();
 
+    // Skip the dummy padding argument.
+    if (ArgI.getPaddingType())
+      ++AI;
+
     switch (ArgI.getKind()) {
     case ABIArgInfo::Indirect: {
       llvm::Value *V = AI;
@@ -1196,9 +1210,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
 
     case ABIArgInfo::Extend:
     case ABIArgInfo::Direct: {
-      // Skip the dummy padding argument.
-      if (ArgI.getPaddingType())
-        ++AI;
 
       // If we have the trivial case, handle it with no muss and fuss.
       if (!isa<llvm::StructType>(ArgI.getCoerceToType()) &&
@@ -1976,6 +1987,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
 
     unsigned TypeAlign =
       getContext().getTypeAlignInChars(I->Ty).getQuantity();
+
+    // Insert a padding argument to ensure proper alignment.
+    if (llvm::Type *PaddingType = ArgInfo.getPaddingType()) {
+      Args.push_back(llvm::UndefValue::get(PaddingType));
+      ++IRArgNo;
+    }
+
     switch (ArgInfo.getKind()) {
     case ABIArgInfo::Indirect: {
       if (RV.isScalar() || RV.isComplex()) {
@@ -2031,12 +2049,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
 
     case ABIArgInfo::Extend:
     case ABIArgInfo::Direct: {
-      // Insert a padding argument to ensure proper alignment.
-      if (llvm::Type *PaddingType = ArgInfo.getPaddingType()) {
-        Args.push_back(llvm::UndefValue::get(PaddingType));
-        ++IRArgNo;
-      }
-
       if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) &&
           ArgInfo.getCoerceToType() == ConvertType(info_it->type) &&
           ArgInfo.getDirectOffset() == 0) {
index 534c8f685d5a939c11ebf359f5b9294ce0207873..2c2d17df77b4fddec0ed2bf389b1b0a08ca1e05e 100644 (file)
@@ -531,7 +531,7 @@ class X86_32ABIInfo : public ABIInfo {
   ABIArgInfo classifyArgumentType(QualType RetTy, unsigned &FreeRegs,
                                   bool IsFastCall) const;
   bool shouldUseInReg(QualType Ty, unsigned &FreeRegs,
-                      bool IsFastCall) const;
+                      bool IsFastCall, bool &NeedsPadding) const;
 
 public:
 
@@ -807,7 +807,8 @@ X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const {
 }
 
 bool X86_32ABIInfo::shouldUseInReg(QualType Ty, unsigned &FreeRegs,
-                                   bool IsFastCall) const {
+                                   bool IsFastCall, bool &NeedsPadding) const {
+  NeedsPadding = false;
   Class C = classify(Ty);
   if (C == Float)
     return false;
@@ -838,6 +839,9 @@ bool X86_32ABIInfo::shouldUseInReg(QualType Ty, unsigned &FreeRegs,
     if (Ty->isReferenceType())
       return true;
 
+    if (FreeRegs)
+      NeedsPadding = true;
+
     return false;
   }
 
@@ -864,16 +868,18 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
     if (isEmptyRecord(getContext(), Ty, true))
       return ABIArgInfo::getIgnore();
 
-    if (shouldUseInReg(Ty, FreeRegs, IsFastCall)) {
+    llvm::LLVMContext &LLVMContext = getVMContext();
+    llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
+    bool NeedsPadding;
+    if (shouldUseInReg(Ty, FreeRegs, IsFastCall, NeedsPadding)) {
       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);
     }
+    llvm::IntegerType *PaddingType = NeedsPadding ? Int32 : 0;
 
     // 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
@@ -881,7 +887,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
     // optimizations.
     if (getContext().getTypeSize(Ty) <= 4*32 &&
         canExpandIndirectArgument(Ty, getContext()))
-      return ABIArgInfo::getExpand();
+      return ABIArgInfo::getExpandWithPadding(IsFastCall, PaddingType);
 
     return getIndirectResult(Ty, true, FreeRegs);
   }
@@ -914,7 +920,8 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
   if (const EnumType *EnumTy = Ty->getAs<EnumType>())
     Ty = EnumTy->getDecl()->getIntegerType();
 
-  bool InReg = shouldUseInReg(Ty, FreeRegs, IsFastCall);
+  bool NeedsPadding;
+  bool InReg = shouldUseInReg(Ty, FreeRegs, IsFastCall, NeedsPadding);
 
   if (Ty->isPromotableIntegerType()) {
     if (InReg)
index dac2a3a1428668d452affa0101e3cbc141216df8..d518178822831772796b8d0884e15effd40e3d6c 100644 (file)
@@ -62,7 +62,7 @@ struct S1 {
 void __attribute__((fastcall)) foo2(struct S1 y);
 void bar2(struct S1 y) {
   // CHECK: define void @bar2
-  // CHECK: call x86_fastcallcc void @foo2(i32 %
+  // CHECK: call x86_fastcallcc void @foo2(i32 inreg undef, i32 %
   foo2(y);
 }
 
@@ -110,7 +110,7 @@ void bar7(int a, struct S1 b, int c) {
 void __attribute__((fastcall)) foo8(struct S1 a, int b);
 void bar8(struct S1 a, int b) {
   // CHECK: define void @bar8
-  // CHECK: call x86_fastcallcc void @foo8(i32 %{{.*}}, i32 inreg %
+  // CHECK: call x86_fastcallcc void @foo8(i32 inreg undef, i32 %{{.*}}, i32 inreg %
   foo8(a, b);
 }