summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/Mips/MipsInstructionSelector.cpp79
-rw-r--r--llvm/lib/Target/Mips/MipsLegalizerInfo.cpp4
-rw-r--r--llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp6
3 files changed, 89 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;
}
diff --git a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp
index 7e7094061ec..4da1fb205e5 100644
--- a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp
@@ -32,6 +32,10 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
getActionDefinitionsBuilder({G_AND, G_OR, G_XOR, G_SHL, G_ASHR, G_LSHR})
.legalFor({s32});
+ getActionDefinitionsBuilder(G_ICMP)
+ .legalFor({{s32, s32}})
+ .minScalar(0, s32);
+
getActionDefinitionsBuilder(G_CONSTANT)
.legalFor({s32});
diff --git a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp
index c7844c30b32..96ca1cdd643 100644
--- a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp
@@ -98,6 +98,12 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
OperandsMapping =
getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
break;
+ case G_ICMP:
+ OperandsMapping =
+ getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
+ &Mips::ValueMappings[Mips::GPRIdx],
+ &Mips::ValueMappings[Mips::GPRIdx]});
+ break;
default:
return getInvalidInstructionMapping();
}
OpenPOWER on IntegriCloud