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) {} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits