aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp')
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp671
1 files changed, 0 insertions, 671 deletions
diff --git a/contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp b/contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
deleted file mode 100644
index 45a47ad3c087..000000000000
--- a/contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
+++ /dev/null
@@ -1,671 +0,0 @@
-//===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-/// \file
-/// This file implements the targeting of the InstructionSelector class for
-/// Mips.
-/// \todo This should be generated by TableGen.
-//===----------------------------------------------------------------------===//
-
-#include "MCTargetDesc/MipsInstPrinter.h"
-#include "MipsMachineFunction.h"
-#include "MipsRegisterBankInfo.h"
-#include "MipsTargetMachine.h"
-#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
-#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
-
-#define DEBUG_TYPE "mips-isel"
-
-using namespace llvm;
-
-namespace {
-
-#define GET_GLOBALISEL_PREDICATE_BITSET
-#include "MipsGenGlobalISel.inc"
-#undef GET_GLOBALISEL_PREDICATE_BITSET
-
-class MipsInstructionSelector : public InstructionSelector {
-public:
- MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
- const MipsRegisterBankInfo &RBI);
-
- bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override;
- static const char *getName() { return DEBUG_TYPE; }
-
-private:
- bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
- bool materialize32BitImm(Register DestReg, APInt Imm,
- MachineIRBuilder &B) const;
- bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
- const TargetRegisterClass *
- getRegClassForTypeOnBank(unsigned OpSize, const RegisterBank &RB,
- const RegisterBankInfo &RBI) const;
-
- const MipsTargetMachine &TM;
- const MipsSubtarget &STI;
- const MipsInstrInfo &TII;
- const MipsRegisterInfo &TRI;
- const MipsRegisterBankInfo &RBI;
-
-#define GET_GLOBALISEL_PREDICATES_DECL
-#include "MipsGenGlobalISel.inc"
-#undef GET_GLOBALISEL_PREDICATES_DECL
-
-#define GET_GLOBALISEL_TEMPORARIES_DECL
-#include "MipsGenGlobalISel.inc"
-#undef GET_GLOBALISEL_TEMPORARIES_DECL
-};
-
-} // end anonymous namespace
-
-#define GET_GLOBALISEL_IMPL
-#include "MipsGenGlobalISel.inc"
-#undef GET_GLOBALISEL_IMPL
-
-MipsInstructionSelector::MipsInstructionSelector(
- const MipsTargetMachine &TM, const MipsSubtarget &STI,
- const MipsRegisterBankInfo &RBI)
- : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
- TRI(*STI.getRegisterInfo()), RBI(RBI),
-
-#define GET_GLOBALISEL_PREDICATES_INIT
-#include "MipsGenGlobalISel.inc"
-#undef GET_GLOBALISEL_PREDICATES_INIT
-#define GET_GLOBALISEL_TEMPORARIES_INIT
-#include "MipsGenGlobalISel.inc"
-#undef GET_GLOBALISEL_TEMPORARIES_INIT
-{
-}
-
-bool MipsInstructionSelector::selectCopy(MachineInstr &I,
- MachineRegisterInfo &MRI) const {
- Register DstReg = I.getOperand(0).getReg();
- if (TargetRegisterInfo::isPhysicalRegister(DstReg))
- return true;
-
- const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
- const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
-
- const TargetRegisterClass *RC = &Mips::GPR32RegClass;
- if (RegBank->getID() == Mips::FPRBRegBankID) {
- if (DstSize == 32)
- RC = &Mips::FGR32RegClass;
- else if (DstSize == 64)
- RC = STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
- else
- llvm_unreachable("Unsupported destination size");
- }
- if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
- LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
- << " operand\n");
- return false;
- }
- return true;
-}
-
-const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank(
- unsigned OpSize, const RegisterBank &RB,
- const RegisterBankInfo &RBI) const {
- if (RB.getID() == Mips::GPRBRegBankID)
- return &Mips::GPR32RegClass;
-
- if (RB.getID() == Mips::FPRBRegBankID)
- return OpSize == 32
- ? &Mips::FGR32RegClass
- : STI.hasMips32r6() || STI.isFP64bit() ? &Mips::FGR64RegClass
- : &Mips::AFGR64RegClass;
-
- llvm_unreachable("getRegClassForTypeOnBank can't find register class.");
- return nullptr;
-}
-
-bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
- MachineIRBuilder &B) const {
- assert(Imm.getBitWidth() == 32 && "Unsupported immediate size.");
- // Ori zero extends immediate. Used for values with zeros in high 16 bits.
- if (Imm.getHiBits(16).isNullValue()) {
- MachineInstr *Inst = B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)})
- .addImm(Imm.getLoBits(16).getLimitedValue());
- return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
- }
- // Lui places immediate in high 16 bits and sets low 16 bits to zero.
- if (Imm.getLoBits(16).isNullValue()) {
- MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {})
- .addImm(Imm.getHiBits(16).getLimitedValue());
- return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
- }
- // ADDiu sign extends immediate. Used for values with 1s in high 17 bits.
- if (Imm.isSignedIntN(16)) {
- MachineInstr *Inst = B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)})
- .addImm(Imm.getLoBits(16).getLimitedValue());
- return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
- }
- // Values that cannot be materialized with single immediate instruction.
- Register LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass);
- MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {})
- .addImm(Imm.getHiBits(16).getLimitedValue());
- MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg})
- .addImm(Imm.getLoBits(16).getLimitedValue());
- if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
- return false;
- if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI))
- return false;
- return true;
-}
-
-/// Returning Opc indicates that we failed to select MIPS instruction opcode.
-static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes,
- unsigned RegBank, bool isFP64) {
- bool isStore = Opc == TargetOpcode::G_STORE;
- if (RegBank == Mips::GPRBRegBankID) {
- if (isStore)
- switch (MemSizeInBytes) {
- case 4:
- return Mips::SW;
- case 2:
- return Mips::SH;
- case 1:
- return Mips::SB;
- default:
- return Opc;
- }
- else
- // Unspecified extending load is selected into zeroExtending load.
- switch (MemSizeInBytes) {
- case 4:
- return Mips::LW;
- case 2:
- return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
- case 1:
- return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
- default:
- return Opc;
- }
- }
-
- if (RegBank == Mips::FPRBRegBankID) {
- switch (MemSizeInBytes) {
- case 4:
- return isStore ? Mips::SWC1 : Mips::LWC1;
- case 8:
- if (isFP64)
- return isStore ? Mips::SDC164 : Mips::LDC164;
- else
- return isStore ? Mips::SDC1 : Mips::LDC1;
- default:
- return Opc;
- }
- }
- return Opc;
-}
-
-bool MipsInstructionSelector::select(MachineInstr &I,
- CodeGenCoverage &CoverageInfo) const {
-
- MachineBasicBlock &MBB = *I.getParent();
- MachineFunction &MF = *MBB.getParent();
- MachineRegisterInfo &MRI = MF.getRegInfo();
-
- if (!isPreISelGenericOpcode(I.getOpcode())) {
- if (I.isCopy())
- return selectCopy(I, MRI);
-
- return true;
- }
-
- if (I.getOpcode() == Mips::G_MUL) {
- MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL))
- .add(I.getOperand(0))
- .add(I.getOperand(1))
- .add(I.getOperand(2));
- if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI))
- return false;
- Mul->getOperand(3).setIsDead(true);
- Mul->getOperand(4).setIsDead(true);
-
- I.eraseFromParent();
- return true;
- }
-
- if (selectImpl(I, CoverageInfo))
- return true;
-
- MachineInstr *MI = nullptr;
- using namespace TargetOpcode;
-
- switch (I.getOpcode()) {
- case G_UMULH: {
- Register PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
- MachineInstr *PseudoMULTu, *PseudoMove;
-
- PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu))
- .addDef(PseudoMULTuReg)
- .add(I.getOperand(1))
- .add(I.getOperand(2));
- if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI))
- return false;
-
- PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI))
- .addDef(I.getOperand(0).getReg())
- .addUse(PseudoMULTuReg);
- if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
- return false;
-
- I.eraseFromParent();
- return true;
- }
- case G_GEP: {
- MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
- .add(I.getOperand(0))
- .add(I.getOperand(1))
- .add(I.getOperand(2));
- break;
- }
- case G_FRAME_INDEX: {
- MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
- .add(I.getOperand(0))
- .add(I.getOperand(1))
- .addImm(0);
- break;
- }
- case G_BRCOND: {
- MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE))
- .add(I.getOperand(0))
- .addUse(Mips::ZERO)
- .add(I.getOperand(1));
- break;
- }
- case G_PHI: {
- const Register DestReg = I.getOperand(0).getReg();
- const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
-
- const TargetRegisterClass *DefRC = nullptr;
- if (TargetRegisterInfo::isPhysicalRegister(DestReg))
- DefRC = TRI.getRegClass(DestReg);
- else
- DefRC = getRegClassForTypeOnBank(OpSize,
- *RBI.getRegBank(DestReg, MRI, TRI), RBI);
-
- I.setDesc(TII.get(TargetOpcode::PHI));
- return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
- }
- case G_STORE:
- case G_LOAD:
- case G_ZEXTLOAD:
- case G_SEXTLOAD: {
- const Register DestReg = I.getOperand(0).getReg();
- const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
- const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
- const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize();
-
- if (DestRegBank == Mips::GPRBRegBankID && OpSize != 32)
- return false;
-
- if (DestRegBank == Mips::FPRBRegBankID && OpSize != 32 && OpSize != 64)
- return false;
-
- const unsigned NewOpc = selectLoadStoreOpCode(
- I.getOpcode(), OpMemSizeInBytes, DestRegBank, STI.isFP64bit());
- if (NewOpc == I.getOpcode())
- return false;
-
- MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
- .add(I.getOperand(0))
- .add(I.getOperand(1))
- .addImm(0)
- .addMemOperand(*I.memoperands_begin());
- break;
- }
- case G_UDIV:
- case G_UREM:
- case G_SDIV:
- case G_SREM: {
- Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
- bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV;
- bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV;
-
- MachineInstr *PseudoDIV, *PseudoMove;
- PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(),
- TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
- .addDef(HILOReg)
- .add(I.getOperand(1))
- .add(I.getOperand(2));
- if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI))
- return false;
-
- PseudoMove = BuildMI(MBB, I, I.getDebugLoc(),
- TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
- .addDef(I.getOperand(0).getReg())
- .addUse(HILOReg);
- if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
- return false;
-
- I.eraseFromParent();
- return true;
- }
- case G_SELECT: {
- // Handle operands with pointer type.
- MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I))
- .add(I.getOperand(0))
- .add(I.getOperand(2))
- .add(I.getOperand(1))
- .add(I.getOperand(3));
- break;
- }
- case G_CONSTANT: {
- MachineIRBuilder B(I);
- if (!materialize32BitImm(I.getOperand(0).getReg(),
- I.getOperand(1).getCImm()->getValue(), B))
- return false;
-
- I.eraseFromParent();
- return true;
- }
- case G_FCONSTANT: {
- const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF();
- APInt APImm = FPimm.bitcastToAPInt();
- unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
-
- if (Size == 32) {
- Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
- MachineIRBuilder B(I);
- if (!materialize32BitImm(GPRReg, APImm, B))
- return false;
-
- MachineInstrBuilder MTC1 =
- B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg});
- if (!MTC1.constrainAllUses(TII, TRI, RBI))
- return false;
- }
- if (Size == 64) {
- Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass);
- Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass);
- MachineIRBuilder B(I);
- if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B))
- return false;
- if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B))
- return false;
-
- MachineInstrBuilder PairF64 = B.buildInstr(
- STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
- {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
- if (!PairF64.constrainAllUses(TII, TRI, RBI))
- return false;
- }
-
- I.eraseFromParent();
- return true;
- }
- case G_FABS: {
- unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
- unsigned FABSOpcode =
- Size == 32 ? Mips::FABS_S
- : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
- MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode))
- .add(I.getOperand(0))
- .add(I.getOperand(1));
- break;
- }
- case G_FPTOSI: {
- unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits();
- unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
- (void)ToSize;
- assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI");
- assert((FromSize == 32 || FromSize == 64) &&
- "Unsupported floating point size for G_FPTOSI");
-
- unsigned Opcode;
- if (FromSize == 32)
- Opcode = Mips::TRUNC_W_S;
- else
- Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
- unsigned ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass);
- MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
- .addDef(ResultInFPR)
- .addUse(I.getOperand(1).getReg());
- if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI))
- return false;
-
- MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1))
- .addDef(I.getOperand(0).getReg())
- .addUse(ResultInFPR);
- if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
- return false;
-
- I.eraseFromParent();
- return true;
- }
- case G_GLOBAL_VALUE: {
- const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
- if (MF.getTarget().isPositionIndependent()) {
- MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
- .addDef(I.getOperand(0).getReg())
- .addReg(MF.getInfo<MipsFunctionInfo>()
- ->getGlobalBaseRegForGlobalISel())
- .addGlobalAddress(GVal);
- // Global Values that don't have local linkage are handled differently
- // when they are part of call sequence. MipsCallLowering::lowerCall
- // creates G_GLOBAL_VALUE instruction as part of call sequence and adds
- // MO_GOT_CALL flag when Callee doesn't have local linkage.
- if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL)
- LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL);
- else
- LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT);
- LWGOT->addMemOperand(
- MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
- MachineMemOperand::MOLoad, 4, 4));
- if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI))
- return false;
-
- if (GVal->hasLocalLinkage()) {
- Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
- LWGOT->getOperand(0).setReg(LWGOTDef);
-
- MachineInstr *ADDiu =
- BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
- .addDef(I.getOperand(0).getReg())
- .addReg(LWGOTDef)
- .addGlobalAddress(GVal);
- ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
- if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
- return false;
- }
- } else {
- Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
-
- MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
- .addDef(LUiReg)
- .addGlobalAddress(GVal);
- LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI);
- if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
- return false;
-
- MachineInstr *ADDiu =
- BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
- .addDef(I.getOperand(0).getReg())
- .addUse(LUiReg)
- .addGlobalAddress(GVal);
- ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
- if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
- return false;
- }
- I.eraseFromParent();
- return true;
- }
- case G_ICMP: {
- struct Instr {
- unsigned Opcode;
- Register Def, LHS, RHS;
- Instr(unsigned Opcode, Register Def, Register LHS, Register 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;
- Register ICMPReg = I.getOperand(0).getReg();
- Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
- Register LHS = I.getOperand(2).getReg();
- Register 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;
- }
- case G_FCMP: {
- unsigned MipsFCMPCondCode;
- bool isLogicallyNegated;
- switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>(
- I.getOperand(1).getPredicate())) {
- case CmpInst::FCMP_UNO: // Unordered
- case CmpInst::FCMP_ORD: // Ordered (OR)
- MipsFCMPCondCode = Mips::FCOND_UN;
- isLogicallyNegated = Cond != CmpInst::FCMP_UNO;
- break;
- case CmpInst::FCMP_OEQ: // Equal
- case CmpInst::FCMP_UNE: // Not Equal (NEQ)
- MipsFCMPCondCode = Mips::FCOND_OEQ;
- isLogicallyNegated = Cond != CmpInst::FCMP_OEQ;
- break;
- case CmpInst::FCMP_UEQ: // Unordered or Equal
- case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL)
- MipsFCMPCondCode = Mips::FCOND_UEQ;
- isLogicallyNegated = Cond != CmpInst::FCMP_UEQ;
- break;
- case CmpInst::FCMP_OLT: // Ordered or Less Than
- case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE)
- MipsFCMPCondCode = Mips::FCOND_OLT;
- isLogicallyNegated = Cond != CmpInst::FCMP_OLT;
- break;
- case CmpInst::FCMP_ULT: // Unordered or Less Than
- case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE)
- MipsFCMPCondCode = Mips::FCOND_ULT;
- isLogicallyNegated = Cond != CmpInst::FCMP_ULT;
- break;
- case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal
- case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT)
- MipsFCMPCondCode = Mips::FCOND_OLE;
- isLogicallyNegated = Cond != CmpInst::FCMP_OLE;
- break;
- case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal
- case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT)
- MipsFCMPCondCode = Mips::FCOND_ULE;
- isLogicallyNegated = Cond != CmpInst::FCMP_ULE;
- break;
- default:
- return false;
- }
-
- // Default compare result in gpr register will be `true`.
- // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false
- // using MOVF_I. When orignal predicate (Cond) is logically negated
- // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used.
- unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
-
- unsigned TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
- BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
- .addDef(TrueInReg)
- .addUse(Mips::ZERO)
- .addImm(1);
-
- unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits();
- unsigned FCMPOpcode =
- Size == 32 ? Mips::FCMP_S32
- : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
- MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode))
- .addUse(I.getOperand(2).getReg())
- .addUse(I.getOperand(3).getReg())
- .addImm(MipsFCMPCondCode);
- if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI))
- return false;
-
- MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode))
- .addDef(I.getOperand(0).getReg())
- .addUse(Mips::ZERO)
- .addUse(Mips::FCC0)
- .addUse(TrueInReg);
- if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
- return false;
-
- I.eraseFromParent();
- return true;
- }
- default:
- return false;
- }
-
- I.eraseFromParent();
- return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
-}
-
-namespace llvm {
-InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM,
- MipsSubtarget &Subtarget,
- MipsRegisterBankInfo &RBI) {
- return new MipsInstructionSelector(TM, Subtarget, RBI);
-}
-} // end namespace llvm