summaryrefslogtreecommitdiff
path: root/lib/Target/Mips/MipsInstructionSelector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Mips/MipsInstructionSelector.cpp')
-rw-r--r--lib/Target/Mips/MipsInstructionSelector.cpp206
1 files changed, 179 insertions, 27 deletions
diff --git a/lib/Target/Mips/MipsInstructionSelector.cpp b/lib/Target/Mips/MipsInstructionSelector.cpp
index 45a47ad3c087..f8fc7cb0898b 100644
--- a/lib/Target/Mips/MipsInstructionSelector.cpp
+++ b/lib/Target/Mips/MipsInstructionSelector.cpp
@@ -17,6 +17,7 @@
#include "MipsTargetMachine.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
#define DEBUG_TYPE "mips-isel"
@@ -33,7 +34,7 @@ public:
MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
const MipsRegisterBankInfo &RBI);
- bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override;
+ bool select(MachineInstr &I) override;
static const char *getName() { return DEBUG_TYPE; }
private:
@@ -44,6 +45,8 @@ private:
const TargetRegisterClass *
getRegClassForTypeOnBank(unsigned OpSize, const RegisterBank &RB,
const RegisterBankInfo &RBI) const;
+ unsigned selectLoadStoreOpCode(MachineInstr &I,
+ MachineRegisterInfo &MRI) const;
const MipsTargetMachine &TM;
const MipsSubtarget &STI;
@@ -84,7 +87,7 @@ MipsInstructionSelector::MipsInstructionSelector(
bool MipsInstructionSelector::selectCopy(MachineInstr &I,
MachineRegisterInfo &MRI) const {
Register DstReg = I.getOperand(0).getReg();
- if (TargetRegisterInfo::isPhysicalRegister(DstReg))
+ if (Register::isPhysicalRegister(DstReg))
return true;
const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
@@ -158,9 +161,15 @@ bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
}
/// 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;
+unsigned
+MipsInstructionSelector::selectLoadStoreOpCode(MachineInstr &I,
+ MachineRegisterInfo &MRI) const {
+ STI.getRegisterInfo();
+ const Register DestReg = I.getOperand(0).getReg();
+ const unsigned RegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
+ const unsigned MemSizeInBytes = (*I.memoperands_begin())->getSize();
+ unsigned Opc = I.getOpcode();
+ const bool isStore = Opc == TargetOpcode::G_STORE;
if (RegBank == Mips::GPRBRegBankID) {
if (isStore)
switch (MemSizeInBytes) {
@@ -192,10 +201,24 @@ static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes,
case 4:
return isStore ? Mips::SWC1 : Mips::LWC1;
case 8:
- if (isFP64)
+ if (STI.isFP64bit())
return isStore ? Mips::SDC164 : Mips::LDC164;
else
return isStore ? Mips::SDC1 : Mips::LDC1;
+ case 16: {
+ assert(STI.hasMSA() && "Vector instructions require target with MSA.");
+ const unsigned VectorElementSizeInBytes =
+ MRI.getType(DestReg).getElementType().getSizeInBytes();
+ if (VectorElementSizeInBytes == 1)
+ return isStore ? Mips::ST_B : Mips::LD_B;
+ if (VectorElementSizeInBytes == 2)
+ return isStore ? Mips::ST_H : Mips::LD_H;
+ if (VectorElementSizeInBytes == 4)
+ return isStore ? Mips::ST_W : Mips::LD_W;
+ if (VectorElementSizeInBytes == 8)
+ return isStore ? Mips::ST_D : Mips::LD_D;
+ return Opc;
+ }
default:
return Opc;
}
@@ -203,8 +226,7 @@ static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes,
return Opc;
}
-bool MipsInstructionSelector::select(MachineInstr &I,
- CodeGenCoverage &CoverageInfo) const {
+bool MipsInstructionSelector::select(MachineInstr &I) {
MachineBasicBlock &MBB = *I.getParent();
MachineFunction &MF = *MBB.getParent();
@@ -231,7 +253,7 @@ bool MipsInstructionSelector::select(MachineInstr &I,
return true;
}
- if (selectImpl(I, CoverageInfo))
+ if (selectImpl(I, *CoverageInfo))
return true;
MachineInstr *MI = nullptr;
@@ -265,6 +287,11 @@ bool MipsInstructionSelector::select(MachineInstr &I,
.add(I.getOperand(2));
break;
}
+ case G_INTTOPTR:
+ case G_PTRTOINT: {
+ I.setDesc(TII.get(COPY));
+ return selectCopy(I, MRI);
+ }
case G_FRAME_INDEX: {
MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
.add(I.getOperand(0))
@@ -279,12 +306,71 @@ bool MipsInstructionSelector::select(MachineInstr &I,
.add(I.getOperand(1));
break;
}
+ case G_BRJT: {
+ unsigned EntrySize =
+ MF.getJumpTableInfo()->getEntrySize(MF.getDataLayout());
+ assert(isPowerOf2_32(EntrySize) &&
+ "Non-power-of-two jump-table entry size not supported.");
+
+ Register JTIndex = MRI.createVirtualRegister(&Mips::GPR32RegClass);
+ MachineInstr *SLL = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SLL))
+ .addDef(JTIndex)
+ .addUse(I.getOperand(2).getReg())
+ .addImm(Log2_32(EntrySize));
+ if (!constrainSelectedInstRegOperands(*SLL, TII, TRI, RBI))
+ return false;
+
+ Register DestAddress = MRI.createVirtualRegister(&Mips::GPR32RegClass);
+ MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
+ .addDef(DestAddress)
+ .addUse(I.getOperand(0).getReg())
+ .addUse(JTIndex);
+ if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
+ return false;
+
+ Register Dest = MRI.createVirtualRegister(&Mips::GPR32RegClass);
+ MachineInstr *LW =
+ BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
+ .addDef(Dest)
+ .addUse(DestAddress)
+ .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_LO)
+ .addMemOperand(MF.getMachineMemOperand(
+ MachinePointerInfo(), MachineMemOperand::MOLoad, 4, 4));
+ if (!constrainSelectedInstRegOperands(*LW, TII, TRI, RBI))
+ return false;
+
+ if (MF.getTarget().isPositionIndependent()) {
+ Register DestTmp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
+ LW->getOperand(0).setReg(DestTmp);
+ MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
+ .addDef(Dest)
+ .addUse(DestTmp)
+ .addUse(MF.getInfo<MipsFunctionInfo>()
+ ->getGlobalBaseRegForGlobalISel());
+ if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
+ return false;
+ }
+
+ MachineInstr *Branch =
+ BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
+ .addUse(Dest);
+ if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
+ return false;
+
+ I.eraseFromParent();
+ return true;
+ }
+ case G_BRINDIRECT: {
+ MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
+ .add(I.getOperand(0));
+ 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))
+ if (Register::isPhysicalRegister(DestReg))
DefRC = TRI.getRegClass(DestReg);
else
DefRC = getRegClassForTypeOnBank(OpSize,
@@ -297,26 +383,35 @@ bool MipsInstructionSelector::select(MachineInstr &I,
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());
+ const unsigned NewOpc = selectLoadStoreOpCode(I, MRI);
if (NewOpc == I.getOpcode())
return false;
+ MachineOperand BaseAddr = I.getOperand(1);
+ int64_t SignedOffset = 0;
+ // Try to fold load/store + G_GEP + G_CONSTANT
+ // %SignedOffset:(s32) = G_CONSTANT i32 16_bit_signed_immediate
+ // %Addr:(p0) = G_GEP %BaseAddr, %SignedOffset
+ // %LoadResult/%StoreSrc = load/store %Addr(p0)
+ // into:
+ // %LoadResult/%StoreSrc = NewOpc %BaseAddr(p0), 16_bit_signed_immediate
+
+ MachineInstr *Addr = MRI.getVRegDef(I.getOperand(1).getReg());
+ if (Addr->getOpcode() == G_GEP) {
+ MachineInstr *Offset = MRI.getVRegDef(Addr->getOperand(2).getReg());
+ if (Offset->getOpcode() == G_CONSTANT) {
+ APInt OffsetValue = Offset->getOperand(1).getCImm()->getValue();
+ if (OffsetValue.isSignedIntN(16)) {
+ BaseAddr = Addr->getOperand(1);
+ SignedOffset = OffsetValue.getSExtValue();
+ }
+ }
+ }
+
MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
.add(I.getOperand(0))
- .add(I.getOperand(1))
- .addImm(0)
+ .add(BaseAddr)
+ .addImm(SignedOffset)
.addMemOperand(*I.memoperands_begin());
break;
}
@@ -356,6 +451,18 @@ bool MipsInstructionSelector::select(MachineInstr &I,
.add(I.getOperand(3));
break;
}
+ case G_IMPLICIT_DEF: {
+ MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::IMPLICIT_DEF))
+ .add(I.getOperand(0));
+
+ // Set class based on register bank, there can be fpr and gpr implicit def.
+ MRI.setRegClass(MI->getOperand(0).getReg(),
+ getRegClassForTypeOnBank(
+ MRI.getType(I.getOperand(0).getReg()).getSizeInBits(),
+ *RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI),
+ RBI));
+ break;
+ }
case G_CONSTANT: {
MachineIRBuilder B(I);
if (!materialize32BitImm(I.getOperand(0).getReg(),
@@ -423,7 +530,7 @@ bool MipsInstructionSelector::select(MachineInstr &I,
Opcode = Mips::TRUNC_W_S;
else
Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
- unsigned ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass);
+ Register ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass);
MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
.addDef(ResultInFPR)
.addUse(I.getOperand(1).getReg());
@@ -496,6 +603,24 @@ bool MipsInstructionSelector::select(MachineInstr &I,
I.eraseFromParent();
return true;
}
+ case G_JUMP_TABLE: {
+ if (MF.getTarget().isPositionIndependent()) {
+ MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
+ .addDef(I.getOperand(0).getReg())
+ .addReg(MF.getInfo<MipsFunctionInfo>()
+ ->getGlobalBaseRegForGlobalISel())
+ .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_GOT)
+ .addMemOperand(
+ MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
+ MachineMemOperand::MOLoad, 4, 4));
+ } else {
+ MI =
+ BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
+ .addDef(I.getOperand(0).getReg())
+ .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_HI);
+ }
+ break;
+ }
case G_ICMP: {
struct Instr {
unsigned Opcode;
@@ -626,7 +751,7 @@ bool MipsInstructionSelector::select(MachineInstr &I,
// 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);
+ Register TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
.addDef(TrueInReg)
.addUse(Mips::ZERO)
@@ -654,6 +779,33 @@ bool MipsInstructionSelector::select(MachineInstr &I,
I.eraseFromParent();
return true;
}
+ case G_FENCE: {
+ MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SYNC)).addImm(0);
+ break;
+ }
+ case G_VASTART: {
+ MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
+ int FI = FuncInfo->getVarArgsFrameIndex();
+
+ Register LeaReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
+ MachineInstr *LEA_ADDiu =
+ BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LEA_ADDiu))
+ .addDef(LeaReg)
+ .addFrameIndex(FI)
+ .addImm(0);
+ if (!constrainSelectedInstRegOperands(*LEA_ADDiu, TII, TRI, RBI))
+ return false;
+
+ MachineInstr *Store = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SW))
+ .addUse(LeaReg)
+ .addUse(I.getOperand(0).getReg())
+ .addImm(0);
+ if (!constrainSelectedInstRegOperands(*Store, TII, TRI, RBI))
+ return false;
+
+ I.eraseFromParent();
+ return true;
+ }
default:
return false;
}