[llvm] r277348 - [mips][fastisel] Correct argument lowering for (f64, f64, i32) and similar.
Daniel Sanders via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 1 08:32:52 PDT 2016
Author: dsanders
Date: Mon Aug 1 10:32:51 2016
New Revision: 277348
URL: http://llvm.org/viewvc/llvm-project?rev=277348&view=rev
Log:
[mips][fastisel] Correct argument lowering for (f64, f64, i32) and similar.
Summary:
Allocating an AFGR64 shadows two GPR32's instead of just one.
This fixes an LNT regression detected by our internal buildbots.
Reviewers: sdardis
Subscribers: dsanders, sdardis, llvm-commits
Differential Revision: https://reviews.llvm.org/D23012
Modified:
llvm/trunk/lib/Target/Mips/MipsFastISel.cpp
llvm/trunk/test/CodeGen/Mips/Fast-ISel/sel1.ll
Modified: llvm/trunk/lib/Target/Mips/MipsFastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsFastISel.cpp?rev=277348&r1=277347&r2=277348&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsFastISel.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsFastISel.cpp Mon Aug 1 10:32:51 2016
@@ -1275,10 +1275,13 @@ bool MipsFastISel::fastLowerArguments()
return false;
}
- static const MCPhysReg GPR32ArgRegs[] = {Mips::A0, Mips::A1, Mips::A2,
- Mips::A3};
- static const MCPhysReg FGR32ArgRegs[] = {Mips::F12, Mips::F14};
- static const MCPhysReg AFGR64ArgRegs[] = {Mips::D6, Mips::D7};
+ const ArrayRef<MCPhysReg> GPR32ArgRegs = {Mips::A0, Mips::A1, Mips::A2,
+ Mips::A3};
+ const ArrayRef<MCPhysReg> FGR32ArgRegs = {Mips::F12, Mips::F14};
+ const ArrayRef<MCPhysReg> AFGR64ArgRegs = {Mips::D6, Mips::D7};
+ ArrayRef<MCPhysReg>::iterator NextGPR32 = GPR32ArgRegs.begin();
+ ArrayRef<MCPhysReg>::iterator NextFGR32 = FGR32ArgRegs.begin();
+ ArrayRef<MCPhysReg>::iterator NextAFGR64 = AFGR64ArgRegs.begin();
struct AllocatedReg {
const TargetRegisterClass *RC;
@@ -1287,18 +1290,11 @@ bool MipsFastISel::fastLowerArguments()
: RC(RC), Reg(Reg) {}
};
- // Only handle simple cases. i.e. Up to four integer arguments.
- // Supporting floating point significantly complicates things so we leave
- // that out for now.
+ // Only handle simple cases. i.e. All arguments are directly mapped to
+ // registers of the appropriate type.
SmallVector<AllocatedReg, 4> Allocation;
unsigned Idx = 1;
- bool HasAllocatedNonFGR = false;
for (const auto &FormalArg : F->args()) {
- if (Idx > 4) {
- DEBUG(dbgs() << ".. gave up (too many arguments)\n");
- return false;
- }
-
if (F->getAttributes().hasAttribute(Idx, Attribute::InReg) ||
F->getAttributes().hasAttribute(Idx, Attribute::StructRet) ||
F->getAttributes().hasAttribute(Idx, Attribute::ByVal)) {
@@ -1330,9 +1326,18 @@ bool MipsFastISel::fastLowerArguments()
DEBUG(dbgs() << ".. .. gave up (i8/i16 arg is not extended)\n");
return false;
}
- DEBUG(dbgs() << ".. .. GPR32(" << GPR32ArgRegs[Idx - 1] << ")\n");
- Allocation.emplace_back(&Mips::GPR32RegClass, GPR32ArgRegs[Idx - 1]);
- HasAllocatedNonFGR = true;
+
+ if (NextGPR32 == GPR32ArgRegs.end()) {
+ DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n");
+ return false;
+ }
+
+ DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n");
+ Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++);
+
+ // Allocating any GPR32 prohibits further use of floating point arguments.
+ NextFGR32 = FGR32ArgRegs.end();
+ NextAFGR64 = AFGR64ArgRegs.end();
break;
case MVT::i32:
@@ -1341,29 +1346,50 @@ bool MipsFastISel::fastLowerArguments()
DEBUG(dbgs() << ".. .. gave up (i32 arg is zero extended)\n");
return false;
}
- DEBUG(dbgs() << ".. .. GPR32(" << GPR32ArgRegs[Idx - 1] << ")\n");
- Allocation.emplace_back(&Mips::GPR32RegClass, GPR32ArgRegs[Idx - 1]);
- HasAllocatedNonFGR = true;
+
+ if (NextGPR32 == GPR32ArgRegs.end()) {
+ DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n");
+ return false;
+ }
+
+ DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n");
+ Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++);
+
+ // Allocating any GPR32 prohibits further use of floating point arguments.
+ NextFGR32 = FGR32ArgRegs.end();
+ NextAFGR64 = AFGR64ArgRegs.end();
break;
case MVT::f32:
- if (Idx > 2 || HasAllocatedNonFGR) {
- DEBUG(dbgs() << ".. .. gave up (f32 arg needed i32)\n");
+ if (NextFGR32 == FGR32ArgRegs.end()) {
+ DEBUG(dbgs() << ".. .. gave up (ran out of FGR32 arguments)\n");
return false;
- } else {
- DEBUG(dbgs() << ".. .. FGR32(" << FGR32ArgRegs[Idx - 1] << ")\n");
- Allocation.emplace_back(&Mips::FGR32RegClass, FGR32ArgRegs[Idx - 1]);
}
+ DEBUG(dbgs() << ".. .. FGR32(" << *NextFGR32 << ")\n");
+ Allocation.emplace_back(&Mips::FGR32RegClass, *NextFGR32++);
+ // Allocating an FGR32 also allocates the super-register AFGR64, and
+ // ABI rules require us to skip the corresponding GPR32.
+ if (NextGPR32 != GPR32ArgRegs.end())
+ NextGPR32++;
+ if (NextAFGR64 != AFGR64ArgRegs.end())
+ NextAFGR64++;
break;
case MVT::f64:
- if (Idx > 2 || HasAllocatedNonFGR) {
- DEBUG(dbgs() << ".. .. gave up (f64 arg needed 2xi32)\n");
+ if (NextAFGR64 == AFGR64ArgRegs.end()) {
+ DEBUG(dbgs() << ".. .. gave up (ran out of AFGR64 arguments)\n");
return false;
- } else {
- DEBUG(dbgs() << ".. .. AFGR64(" << AFGR64ArgRegs[Idx - 1] << ")\n");
- Allocation.emplace_back(&Mips::AFGR64RegClass, AFGR64ArgRegs[Idx - 1]);
}
+ DEBUG(dbgs() << ".. .. AFGR64(" << *NextAFGR64 << ")\n");
+ Allocation.emplace_back(&Mips::AFGR64RegClass, *NextAFGR64++);
+ // Allocating an FGR32 also allocates the super-register AFGR64, and
+ // ABI rules require us to skip the corresponding GPR32 pair.
+ if (NextGPR32 != GPR32ArgRegs.end())
+ NextGPR32++;
+ if (NextGPR32 != GPR32ArgRegs.end())
+ NextGPR32++;
+ if (NextFGR32 != FGR32ArgRegs.end())
+ NextFGR32++;
break;
default:
Modified: llvm/trunk/test/CodeGen/Mips/Fast-ISel/sel1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/Fast-ISel/sel1.ll?rev=277348&r1=277347&r2=277348&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/Fast-ISel/sel1.ll (original)
+++ llvm/trunk/test/CodeGen/Mips/Fast-ISel/sel1.ll Mon Aug 1 10:32:51 2016
@@ -80,6 +80,20 @@ entry:
ret float %res
}
+define float @sel_float2(float %k, float %l, i32 %j) {
+entry:
+ ; CHECK-LABEL: sel_float2:
+
+ ; CHECK-DAG: xor $[[T0:[0-9]+]], $6, $zero
+ ; CHECK: sltu $[[T1:[0-9]+]], $zero, $[[T0]]
+ ; CHECK-NEXT: andi $[[T2:[0-9]+]], $[[T1]], 1
+ ; CHECK: movn.s $f14, $f12, $[[T2]]
+ ; CHECK: mov.s $f0, $f14
+ %cond = icmp ne i32 %j, 0
+ %res = select i1 %cond, float %k, float %l
+ ret float %res
+}
+
define double @sel_double(i32 %j, double %k, double %l) {
entry:
; CHECK-LABEL: sel_double:
@@ -94,4 +108,19 @@ entry:
%cond = icmp ne i32 %j, 0
%res = select i1 %cond, double %k, double %l
ret double %res
+}
+
+define double @sel_double2(double %k, double %l, i32 %j) {
+entry:
+ ; CHECK-LABEL: sel_double2:
+
+ ; CHECK-DAG: lw $[[SEL:[0-9]+]], 16($sp)
+ ; CHECK-DAG: xor $[[T0:[0-9]+]], $[[SEL]], $zero
+ ; CHECK: sltu $[[T1:[0-9]+]], $zero, $[[T0]]
+ ; CHECK-NEXT: andi $[[T2:[0-9]+]], $[[T1]], 1
+ ; CHECK: movn.d $f14, $f12, $[[T2]]
+ ; CHECK: mov.d $f0, $f14
+ %cond = icmp ne i32 %j, 0
+ %res = select i1 %cond, double %k, double %l
+ ret double %res
}
More information about the llvm-commits
mailing list