[cfe-commits] r159676 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGen/mips-vector-arg.c test/CodeGen/mips-vector-return.c
Akira Hatanaka
ahatanaka at mips.com
Tue Jul 3 12:24:06 PDT 2012
Author: ahatanak
Date: Tue Jul 3 14:24:06 2012
New Revision: 159676
URL: http://llvm.org/viewvc/llvm-project?rev=159676&view=rev
Log:
Make the following changes in the way Mips handles vector arguments and return
values:
- Return integer vectors in integer registers.
- Pass vector arguments in integer registers.
- Set an upper bound for argument alignment. The largest alignment is 8-byte
for O32 and 16-byte for N32/64.
Added:
cfe/trunk/test/CodeGen/mips-vector-arg.c
Modified:
cfe/trunk/lib/CodeGen/TargetInfo.cpp
cfe/trunk/test/CodeGen/mips-vector-return.c
Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=159676&r1=159675&r2=159676&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Tue Jul 3 14:24:06 2012
@@ -3166,14 +3166,16 @@
namespace {
class MipsABIInfo : public ABIInfo {
bool IsO32;
- unsigned MinABIStackAlignInBytes;
- llvm::Type* CoerceToIntArgs(uint64_t TySize) const;
+ unsigned MinABIStackAlignInBytes, StackAlignInBytes;
+ void CoerceToIntArgs(uint64_t TySize,
+ SmallVector<llvm::Type*, 8> &ArgList) const;
llvm::Type* HandleAggregates(QualType Ty, uint64_t TySize) const;
llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const;
llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset) const;
public:
MipsABIInfo(CodeGenTypes &CGT, bool _IsO32) :
- ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8) {}
+ ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8),
+ StackAlignInBytes(IsO32 ? 8 : 16) {}
ABIArgInfo classifyReturnType(QualType RetTy) const;
ABIArgInfo classifyArgumentType(QualType RetTy, uint64_t &Offset) const;
@@ -3202,10 +3204,10 @@
};
}
-llvm::Type* MipsABIInfo::CoerceToIntArgs(uint64_t TySize) const {
- SmallVector<llvm::Type*, 8> ArgList;
- llvm::IntegerType *IntTy = llvm::IntegerType::get(getVMContext(),
- MinABIStackAlignInBytes * 8);
+void MipsABIInfo::CoerceToIntArgs(uint64_t TySize,
+ SmallVector<llvm::Type*, 8> &ArgList) const {
+ llvm::IntegerType *IntTy =
+ llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
// Add (TySize / MinABIStackAlignInBytes) args of IntTy.
for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
@@ -3216,24 +3218,28 @@
if (R)
ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
-
- return llvm::StructType::get(getVMContext(), ArgList);
}
// In N32/64, an aligned double precision floating point field is passed in
// a register.
llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
- if (IsO32)
- return CoerceToIntArgs(TySize);
+ SmallVector<llvm::Type*, 8> ArgList, IntArgList;
+
+ if (IsO32) {
+ CoerceToIntArgs(TySize, ArgList);
+ return llvm::StructType::get(getVMContext(), ArgList);
+ }
if (Ty->isComplexType())
return CGT.ConvertType(Ty);
const RecordType *RT = Ty->getAs<RecordType>();
- // Unions are passed in integer registers.
- if (!RT || !RT->isStructureOrClassType())
- return CoerceToIntArgs(TySize);
+ // Unions/vectors are passed in integer registers.
+ if (!RT || !RT->isStructureOrClassType()) {
+ CoerceToIntArgs(TySize, ArgList);
+ return llvm::StructType::get(getVMContext(), ArgList);
+ }
const RecordDecl *RD = RT->getDecl();
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
@@ -3242,7 +3248,6 @@
uint64_t LastOffset = 0;
unsigned idx = 0;
llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64);
- SmallVector<llvm::Type*, 8> ArgList;
// Iterate over fields in the struct/class and check if there are any aligned
// double fields.
@@ -3267,15 +3272,8 @@
LastOffset = Offset + 64;
}
- // Add ((TySize - LastOffset) / 64) args of type i64.
- for (unsigned N = (TySize - LastOffset) / 64; N; --N)
- ArgList.push_back(I64);
-
- // If the size of the remainder is not zero, add one more integer type to
- // ArgList.
- unsigned R = (TySize - LastOffset) % 64;
- if (R)
- ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
+ CoerceToIntArgs(TySize - LastOffset, IntArgList);
+ ArgList.append(IntArgList.begin(), IntArgList.end());
return llvm::StructType::get(getVMContext(), ArgList);
}
@@ -3295,11 +3293,12 @@
uint64_t TySize = getContext().getTypeSize(Ty);
uint64_t Align = getContext().getTypeAlign(Ty) / 8;
- Align = std::max(Align, (uint64_t)MinABIStackAlignInBytes);
+ Align = std::min(std::max(Align, (uint64_t)MinABIStackAlignInBytes),
+ (uint64_t)StackAlignInBytes);
Offset = llvm::RoundUpToAlignment(Offset, Align);
Offset += llvm::RoundUpToAlignment(TySize, Align * 8) / 8;
- if (isAggregateTypeForABI(Ty)) {
+ if (isAggregateTypeForABI(Ty) || Ty->isVectorType()) {
// Ignore empty aggregates.
if (TySize == 0)
return ABIArgInfo::getIgnore();
@@ -3331,7 +3330,7 @@
llvm::Type*
MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const {
const RecordType *RT = RetTy->getAs<RecordType>();
- SmallVector<llvm::Type*, 2> RTList;
+ SmallVector<llvm::Type*, 8> RTList;
if (RT && RT->isStructureOrClassType()) {
const RecordDecl *RD = RT->getDecl();
@@ -3366,11 +3365,7 @@
}
}
- RTList.push_back(llvm::IntegerType::get(getVMContext(),
- std::min(Size, (uint64_t)64)));
- if (Size > 64)
- RTList.push_back(llvm::IntegerType::get(getVMContext(), Size - 64));
-
+ CoerceToIntArgs(Size, RTList);
return llvm::StructType::get(getVMContext(), RTList);
}
@@ -3385,6 +3380,10 @@
if (RetTy->isAnyComplexType())
return ABIArgInfo::getDirect();
+ // O32 returns integer vectors in registers.
+ if (IsO32 && RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())
+ return ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size));
+
if (!IsO32 && !isRecordWithNonTrivialDestructorOrCopyConstructor(RetTy))
return ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size));
}
Added: cfe/trunk/test/CodeGen/mips-vector-arg.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/mips-vector-arg.c?rev=159676&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/mips-vector-arg.c (added)
+++ cfe/trunk/test/CodeGen/mips-vector-arg.c Tue Jul 3 14:24:06 2012
@@ -0,0 +1,28 @@
+// RUN: %clang -target mipsel-unknown-linux -ccc-clang-archs mipsel -O3 -S -o - -emit-llvm %s | FileCheck %s -check-prefix=O32
+// RUN: %clang -target mips64el-unknown-linux -ccc-clang-archs mips64el -O3 -S -mabi=n64 -o - -emit-llvm %s | FileCheck %s -check-prefix=N64
+
+// check that
+// 1. vector arguments are passed in integer registers
+// 2. argument alignment is no larger than 8-byte for O32 and 16-byte for N64.
+
+typedef float v4sf __attribute__ ((__vector_size__ (16)));
+typedef int v4i32 __attribute__ ((__vector_size__ (16)));
+
+// O32: define void @test_v4sf(i32 %a1.coerce0, i32 %a1.coerce1, i32 %a1.coerce2, i32 %a1.coerce3, i32 %a2, i32, i32 %a3.coerce0, i32 %a3.coerce1, i32 %a3.coerce2, i32 %a3.coerce3) nounwind
+// O32: declare i32 @test_v4sf_2(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32)
+// N64: define void @test_v4sf(i64 %a1.coerce0, i64 %a1.coerce1, i32 %a2, i64, i64 %a3.coerce0, i64 %a3.coerce1) nounwind
+// N64: declare i32 @test_v4sf_2(i64, i64, i32, i64, i64, i64)
+extern test_v4sf_2(v4sf, int, v4sf);
+void test_v4sf(v4sf a1, int a2, v4sf a3) {
+ test_v4sf_2(a3, a2, a1);
+}
+
+// O32: define void @test_v4i32(i32 %a1.coerce0, i32 %a1.coerce1, i32 %a1.coerce2, i32 %a1.coerce3, i32 %a2, i32, i32 %a3.coerce0, i32 %a3.coerce1, i32 %a3.coerce2, i32 %a3.coerce3) nounwind
+// O32: declare i32 @test_v4i32_2(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32)
+// N64: define void @test_v4i32(i64 %a1.coerce0, i64 %a1.coerce1, i32 %a2, i64, i64 %a3.coerce0, i64 %a3.coerce1) nounwind
+// N64: declare i32 @test_v4i32_2(i64, i64, i32, i64, i64, i64)
+extern test_v4i32_2(v4i32, int, v4i32);
+void test_v4i32(v4i32 a1, int a2, v4i32 a3) {
+ test_v4i32_2(a3, a2, a1);
+}
+
Modified: cfe/trunk/test/CodeGen/mips-vector-return.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/mips-vector-return.c?rev=159676&r1=159675&r2=159676&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/mips-vector-return.c (original)
+++ cfe/trunk/test/CodeGen/mips-vector-return.c Tue Jul 3 14:24:06 2012
@@ -6,6 +6,7 @@
// integer registers.
typedef float v4sf __attribute__ ((__vector_size__ (16)));
typedef double v4df __attribute__ ((__vector_size__ (32)));
+typedef int v4i32 __attribute__ ((__vector_size__ (16)));
// O32: define void @test_v4sf(<4 x float>* noalias nocapture sret
// N64: define { i64, i64 } @test_v4sf
@@ -19,3 +20,12 @@
return (v4df){0.0, a, 0.0, 0.0};
}
+// O32 returns integer vectors whose size is equal to or smaller than 16-bytes
+// in integer registers.
+//
+// O32: define { i32, i32, i32, i32 } @test_v4i32
+// N64: define { i64, i64 } @test_v4i32
+v4i32 test_v4i32(int a) {
+ return (v4i32){0, a, 0, 0};
+}
+
More information about the cfe-commits
mailing list