diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/Mips/MipsInstructionSelector.cpp | 79 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsLegalizerInfo.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp | 6 | 
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();    }  | 

