зеркало из https://github.com/microsoft/clang-1.git
Add padding inreg registers to cause llvm to skip ecx when needed with
the x86_fastcallcc calling convention. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166538 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
b693269223
Коммит
e4aeeaae8e
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче