summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Mips/MipsFastISel.cpp
diff options
context:
space:
mode:
authorVasileios Kalintiris <Vasileios.Kalintiris@imgtec.com>2015-06-01 15:48:09 +0000
committerVasileios Kalintiris <Vasileios.Kalintiris@imgtec.com>2015-06-01 15:48:09 +0000
commit7f680e156ed553a07e2b1779ec5a8f745f5fb1e3 (patch)
tree2c7abc1372342eedc714d50957717cde25bf5aee /llvm/lib/Target/Mips/MipsFastISel.cpp
parent743d1a7a698fce5c1b9e1e89a1816695098a593b (diff)
downloadbcm5719-llvm-7f680e156ed553a07e2b1779ec5a8f745f5fb1e3.tar.gz
bcm5719-llvm-7f680e156ed553a07e2b1779ec5a8f745f5fb1e3.zip
[mips][FastISel] Clobber HI0/LO0 registers in MUL instructions.
Summary: The contents of the HI/LO registers are unpredictable after the execution of the MUL instruction. In addition to implicitly defining these registers in the MUL instruction definition, we have to mark those registers as dead too. Without this the fast register allocator is running out of registers when the MUL instruction is followed by another one that tries to allocate the AC0 register. Based on a patch by Reed Kotler. Reviewers: dsanders, rkotler Subscribers: llvm-commits, rfuhler Differential Revision: http://reviews.llvm.org/D9825 llvm-svn: 238755
Diffstat (limited to 'llvm/lib/Target/Mips/MipsFastISel.cpp')
-rw-r--r--llvm/lib/Target/Mips/MipsFastISel.cpp33
1 files changed, 33 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/MipsFastISel.cpp b/llvm/lib/Target/Mips/MipsFastISel.cpp
index 4faee10744b..17d9f86808f 100644
--- a/llvm/lib/Target/Mips/MipsFastISel.cpp
+++ b/llvm/lib/Target/Mips/MipsFastISel.cpp
@@ -156,6 +156,12 @@ private:
unsigned MemReg, int64_t MemOffset) {
return emitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset);
}
+
+ unsigned fastEmitInst_rr(unsigned MachineInstOpcode,
+ const TargetRegisterClass *RC,
+ unsigned Op0, bool Op0IsKill,
+ unsigned Op1, bool Op1IsKill);
+
// for some reason, this default is not generated by tablegen
// so we explicitly generate it here.
//
@@ -1563,6 +1569,33 @@ void MipsFastISel::simplifyAddress(Address &Addr) {
}
}
+unsigned MipsFastISel::fastEmitInst_rr(unsigned MachineInstOpcode,
+ const TargetRegisterClass *RC,
+ unsigned Op0, bool Op0IsKill,
+ unsigned Op1, bool Op1IsKill) {
+ // We treat the MUL instruction in a special way because it clobbers
+ // the HI0 & LO0 registers. The TableGen definition of this instruction can
+ // mark these registers only as implicitly defined. As a result, the
+ // register allocator runs out of registers when this instruction is
+ // followed by another instruction that defines the same registers too.
+ // We can fix this by explicitly marking those registers as dead.
+ if (MachineInstOpcode == Mips::MUL) {
+ unsigned ResultReg = createResultReg(RC);
+ const MCInstrDesc &II = TII.get(MachineInstOpcode);
+ Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs());
+ Op1 = constrainOperandRegClass(II, Op1, II.getNumDefs() + 1);
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
+ .addReg(Op0, getKillRegState(Op0IsKill))
+ .addReg(Op1, getKillRegState(Op1IsKill))
+ .addReg(Mips::HI0, RegState::ImplicitDefine | RegState::Dead)
+ .addReg(Mips::LO0, RegState::ImplicitDefine | RegState::Dead);
+ return ResultReg;
+ }
+
+ return FastISel::fastEmitInst_rr(MachineInstOpcode, RC, Op0, Op0IsKill, Op1,
+ Op1IsKill);
+}
+
namespace llvm {
FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
const TargetLibraryInfo *libInfo) {
OpenPOWER on IntegriCloud