diff options
| author | Vasileios Kalintiris <Vasileios.Kalintiris@imgtec.com> | 2015-06-01 15:48:09 +0000 |
|---|---|---|
| committer | Vasileios Kalintiris <Vasileios.Kalintiris@imgtec.com> | 2015-06-01 15:48:09 +0000 |
| commit | 7f680e156ed553a07e2b1779ec5a8f745f5fb1e3 (patch) | |
| tree | 2c7abc1372342eedc714d50957717cde25bf5aee /llvm/lib/Target/Mips/MipsFastISel.cpp | |
| parent | 743d1a7a698fce5c1b9e1e89a1816695098a593b (diff) | |
| download | bcm5719-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.cpp | 33 |
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) { |

