diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2012-10-24 01:59:00 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2012-10-24 01:59:00 +0000 |
commit | fad28de40c545b053364528f1aa5864ab289e897 (patch) | |
tree | 747dbc20edae512ef1482b9d8a0fa6ea2c4d7609 /clang | |
parent | 077dd593715c6c869d8e092793f2d9b1d662fefc (diff) | |
download | bcm5719-llvm-fad28de40c545b053364528f1aa5864ab289e897.tar.gz bcm5719-llvm-fad28de40c545b053364528f1aa5864ab289e897.zip |
Add padding inreg registers to cause llvm to skip ecx when needed with
the x86_fastcallcc calling convention.
llvm-svn: 166538
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/CodeGen/ABIInfo.h | 32 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 42 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 21 | ||||
-rw-r--r-- | clang/test/CodeGen/stdcall-fastcall.c | 4 |
4 files changed, 64 insertions, 35 deletions
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h index 1dd1d195c21..da6d035dfaf 100644 --- a/clang/lib/CodeGen/ABIInfo.h +++ b/clang/lib/CodeGen/ABIInfo.h @@ -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; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index afcf541a3d3..b356e640a1c 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -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) { diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 534c8f685d5..2c2d17df77b 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -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) diff --git a/clang/test/CodeGen/stdcall-fastcall.c b/clang/test/CodeGen/stdcall-fastcall.c index dac2a3a1428..d5181788228 100644 --- a/clang/test/CodeGen/stdcall-fastcall.c +++ b/clang/test/CodeGen/stdcall-fastcall.c @@ -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); } |