Add padding inreg registers to cause llvm to skip ecx when needed with

the x86_fastcallcc calling convention.

llvm-svn: 166538
This commit is contained in:
Rafael Espindola 2012-10-24 01:59:00 +00:00
parent 077dd59371
commit fad28de40c
4 changed files with 64 additions and 35 deletions

View 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;

View 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) {

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

View 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);
}