r267496 - [lanai] Update handling of structs in arguments to be passed in registers.
Jacques Pienaar via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 25 17:09:29 PDT 2016
Author: jpienaar
Date: Mon Apr 25 19:09:29 2016
New Revision: 267496
URL: http://llvm.org/viewvc/llvm-project?rev=267496&view=rev
Log:
[lanai] Update handling of structs in arguments to be passed in registers.
Previously aggregate types were passed byval, change the ABI to pass these in registers instead.
Modified:
cfe/trunk/lib/CodeGen/TargetInfo.cpp
cfe/trunk/test/CodeGen/lanai-arguments.c
Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=267496&r1=267495&r2=267496&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Mon Apr 25 19:09:29 2016
@@ -6691,6 +6691,7 @@ public:
I.info = classifyArgumentType(I.type, State);
}
+ ABIArgInfo getIndirectResult(QualType Ty, bool ByVal, CCState &State) const;
ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const;
};
} // end anonymous namespace
@@ -6712,21 +6713,72 @@ bool LanaiABIInfo::shouldUseInReg(QualTy
return true;
}
+ABIArgInfo LanaiABIInfo::getIndirectResult(QualType Ty, bool ByVal,
+ CCState &State) const {
+ if (!ByVal) {
+ if (State.FreeRegs) {
+ --State.FreeRegs; // Non-byval indirects just use one pointer.
+ return getNaturalAlignIndirectInReg(Ty);
+ }
+ return getNaturalAlignIndirect(Ty, false);
+ }
+
+ // Compute the byval alignment.
+ constexpr unsigned MinABIStackAlignInBytes = 4;
+ unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
+ return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true,
+ /*Realign=*/TypeAlign >
+ MinABIStackAlignInBytes);
+}
+
ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty,
CCState &State) const {
- if (isAggregateTypeForABI(Ty))
- return getNaturalAlignIndirect(Ty);
+ // Check with the C++ ABI first.
+ const RecordType *RT = Ty->getAs<RecordType>();
+ if (RT) {
+ CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
+ if (RAA == CGCXXABI::RAA_Indirect) {
+ return getIndirectResult(Ty, /*ByVal=*/false, State);
+ } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
+ return getNaturalAlignIndirect(Ty, /*ByRef=*/true);
+ }
+ }
+
+ if (isAggregateTypeForABI(Ty)) {
+ // Structures with flexible arrays are always indirect.
+ if (RT && RT->getDecl()->hasFlexibleArrayMember())
+ return getIndirectResult(Ty, /*ByVal=*/true, State);
+
+ // Ignore empty structs/unions.
+ if (isEmptyRecord(getContext(), Ty, true))
+ return ABIArgInfo::getIgnore();
+
+ llvm::LLVMContext &LLVMContext = getVMContext();
+ unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32;
+ if (SizeInRegs <= State.FreeRegs) {
+ llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
+ SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
+ llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
+ State.FreeRegs -= SizeInRegs;
+ return ABIArgInfo::getDirectInReg(Result);
+ } else {
+ State.FreeRegs = 0;
+ }
+ return getIndirectResult(Ty, true, State);
+ }
// Treat an enum type as its underlying type.
if (const auto *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
- if (shouldUseInReg(Ty, State))
- return ABIArgInfo::getDirectInReg();
-
- if (Ty->isPromotableIntegerType())
+ bool InReg = shouldUseInReg(Ty, State);
+ if (Ty->isPromotableIntegerType()) {
+ if (InReg)
+ return ABIArgInfo::getDirectInReg();
return ABIArgInfo::getExtend();
-
+ }
+ if (InReg)
+ return ABIArgInfo::getDirectInReg();
return ABIArgInfo::getDirect();
}
Modified: cfe/trunk/test/CodeGen/lanai-arguments.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/lanai-arguments.c?rev=267496&r1=267495&r2=267496&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/lanai-arguments.c (original)
+++ cfe/trunk/test/CodeGen/lanai-arguments.c Mon Apr 25 19:09:29 2016
@@ -10,7 +10,7 @@ typedef struct {
int aa;
int bb;
} s1;
-// CHECK: define void @f1(%struct.s1* byval align 4 %i)
+// CHECK: define void @f1(i32 inreg %i.coerce0, i32 inreg %i.coerce1)
void f1(s1 i) {}
typedef struct {
@@ -61,8 +61,8 @@ union simple_union {
int a;
char b;
};
-// Unions should be passed as byval structs.
-// CHECK: define void @f9(%union.simple_union* byval align 4 %s)
+// Unions should be passed inreg.
+// CHECK: define void @f9(i32 inreg %s.coerce)
void f9(union simple_union s) {}
typedef struct {
@@ -70,6 +70,6 @@ typedef struct {
int b3 : 3;
int b8 : 8;
} bitfield1;
-// Bitfields should be passed as byval structs.
-// CHECK: define void @f10(%struct.bitfield1* byval align 4 %bf1)
+// Bitfields should be passed inreg.
+// CHECK: define void @f10(i32 inreg %bf1.coerce)
void f10(bitfield1 bf1) {}
More information about the cfe-commits
mailing list