]> granicus.if.org Git - clang/commitdiff
[mips] Mark aggregates returned in registers with the 'inreg' attribute.
authorDaniel Sanders <daniel.sanders@imgtec.com>
Thu, 4 Sep 2014 15:05:39 +0000 (15:05 +0000)
committerDaniel Sanders <daniel.sanders@imgtec.com>
Thu, 4 Sep 2014 15:05:39 +0000 (15:05 +0000)
Summary:
This allows us to easily find them in the backend after the aggregates have
been lowered to other types. This is important on big-endian targets using
the N32/N64 ABI's since these ABI's must shift small structures into the
upper bits of the register.

Reviewers: atanasyan

Reviewed By: atanasyan

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D5005

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@217160 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/TargetInfo.cpp
test/CodeGen/mips-vector-return.c
test/CodeGen/mips64-class-return.cpp

index d33d6a09e0113581f7f2eb1e9be660339685655a..4dbbc55915a44b64cf5f68ce3cac0387162bc8ef 100644 (file)
@@ -5561,12 +5561,15 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
       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)
-        return ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size));
+      // O32 returns integer vectors in registers and N32/N64 returns all small
+      // aggregates in registers..
+      if (!IsO32 ||
+          (RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())) {
+        ABIArgInfo ArgInfo =
+            ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size));
+        ArgInfo.setInReg(true);
+        return ArgInfo;
+      }
     }
 
     return ABIArgInfo::getIndirect(0);
index a7c8ce157c84119a072c73c19f2a60a25d497f8c..8af4998cdf7c9177bf33e7949eca9e276f0ae610 100644 (file)
@@ -9,7 +9,7 @@ typedef double v4df __attribute__ ((__vector_size__ (32)));
 typedef int v4i32 __attribute__ ((__vector_size__ (16)));
 
 // O32-LABEL: define void @test_v4sf(<4 x float>* noalias nocapture sret
-// N64: define { i64, i64 } @test_v4sf
+// N64: define inreg { i64, i64 } @test_v4sf
 v4sf test_v4sf(float a) {
   return (v4sf){0.0f, a, 0.0f, 0.0f};
 }
@@ -23,8 +23,8 @@ v4df test_v4df(double a) {
 // 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
+// O32: define inreg { i32, i32, i32, i32 } @test_v4i32
+// N64: define inreg { i64, i64 } @test_v4i32
 v4i32 test_v4i32(int a) {
   return (v4i32){0, a, 0, 0};
 }
index a473c13195507b782febe498d9979042fce8f364..b466098da83fb1293421c860175f92b00fc65c77 100644 (file)
@@ -24,17 +24,17 @@ extern D0 gd0;
 extern D1 gd1;
 extern D2 gd2;
 
-// CHECK: define { i64, i64 } @_Z4foo1v() 
+// CHECK: define inreg { i64, i64 } @_Z4foo1v()
 D0 foo1(void) {
   return gd0;
 }
 
-// CHECK: define { double, float } @_Z4foo2v() 
+// CHECK: define inreg { double, float } @_Z4foo2v()
 D1 foo2(void) {
   return gd1;
 }
 
-// CHECK-LABEL: define void @_Z4foo32D2(i64 %a0.coerce0, double %a0.coerce1) 
+// CHECK-LABEL: define void @_Z4foo32D2(i64 %a0.coerce0, double %a0.coerce1)
 void foo3(D2 a0) {
   gd2 = a0;
 }