diff options
author | Petar Jovanovic <petar.jovanovic@mips.com> | 2018-09-10 15:56:52 +0000 |
---|---|---|
committer | Petar Jovanovic <petar.jovanovic@mips.com> | 2018-09-10 15:56:52 +0000 |
commit | ce4dd0ae38378b30281e24cd0d2126e6912eb110 (patch) | |
tree | 54e7720c3c0199a86c66ef554e112194723b0164 /llvm/lib/Target/Mips/MipsInstructionSelector.cpp | |
parent | d76177869a9005f71f134dc0a1920c12665f347d (diff) | |
download | bcm5719-llvm-ce4dd0ae38378b30281e24cd0d2126e6912eb110.tar.gz bcm5719-llvm-ce4dd0ae38378b30281e24cd0d2126e6912eb110.zip |
[MIPS GlobalISel] Select icmp
Select 32bit integer compare instructions for MIPS32.
Patch by Petar Avramovic.
Differential Revision: https://reviews.llvm.org/D51489
llvm-svn: 341840
Diffstat (limited to 'llvm/lib/Target/Mips/MipsInstructionSelector.cpp')
-rw-r--r-- | llvm/lib/Target/Mips/MipsInstructionSelector.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp index 6c5b83021f7..fbc15649c8a 100644 --- a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp +++ b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp @@ -15,6 +15,7 @@ #include "MipsRegisterBankInfo.h" #include "MipsTargetMachine.h" #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #define DEBUG_TYPE "mips-isel" @@ -193,7 +194,85 @@ bool MipsInstructionSelector::select(MachineInstr &I, I.eraseFromParent(); return true; } + case G_ICMP: { + struct Instr { + unsigned Opcode, Def, LHS, RHS; + Instr(unsigned Opcode, unsigned Def, unsigned LHS, unsigned RHS) + : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){}; + + bool hasImm() const { + if (Opcode == Mips::SLTiu || Opcode == Mips::XORi) + return true; + return false; + } + }; + + SmallVector<struct Instr, 2> Instructions; + unsigned ICMPReg = I.getOperand(0).getReg(); + unsigned Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass); + unsigned LHS = I.getOperand(2).getReg(); + unsigned RHS = I.getOperand(3).getReg(); + CmpInst::Predicate Cond = + static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate()); + + switch (Cond) { + case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1 + Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS); + Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1); + break; + case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS) + Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS); + Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp); + break; + case CmpInst::ICMP_UGT: // LHS > RHS -> RHS < LHS + Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS); + break; + case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS) + Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS); + Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); + break; + case CmpInst::ICMP_ULT: // LHS < RHS -> LHS < RHS + Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS); + break; + case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS) + Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS); + Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); + break; + case CmpInst::ICMP_SGT: // LHS > RHS -> RHS < LHS + Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS); + break; + case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS) + Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS); + Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); + break; + case CmpInst::ICMP_SLT: // LHS < RHS -> LHS < RHS + Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS); + break; + case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS) + Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS); + Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); + break; + default: + return false; + } + + MachineIRBuilder B(I); + for (const struct Instr &Instruction : Instructions) { + MachineInstrBuilder MIB = + B.buildInstr(Instruction.Opcode, Instruction.Def, Instruction.LHS); + + if (Instruction.hasImm()) + MIB.addImm(Instruction.RHS); + else + MIB.addUse(Instruction.RHS); + + if (!MIB.constrainAllUses(TII, TRI, RBI)) + return false; + } + I.eraseFromParent(); + return true; + } default: return false; } |