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