summaryrefslogtreecommitdiff
path: root/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/GlobalISel/LegalizerHelper.cpp')
-rw-r--r--lib/CodeGen/GlobalISel/LegalizerHelper.cpp230
1 files changed, 194 insertions, 36 deletions
diff --git a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 5258370e6680..87a658be4c29 100644
--- a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -17,12 +17,11 @@
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetLowering.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
-#include <sstream>
#define DEBUG_TYPE "legalizer"
@@ -91,6 +90,15 @@ static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
case TargetOpcode::G_FADD:
assert((Size == 32 || Size == 64) && "Unsupported size");
return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
+ case TargetOpcode::G_FSUB:
+ assert((Size == 32 || Size == 64) && "Unsupported size");
+ return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
+ case TargetOpcode::G_FMUL:
+ assert((Size == 32 || Size == 64) && "Unsupported size");
+ return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
+ case TargetOpcode::G_FDIV:
+ assert((Size == 32 || Size == 64) && "Unsupported size");
+ return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
case TargetOpcode::G_FREM:
return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
case TargetOpcode::G_FPOW:
@@ -128,7 +136,7 @@ LegalizerHelper::LegalizeResult
LegalizerHelper::libcall(MachineInstr &MI) {
LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
unsigned Size = LLTy.getSizeInBits();
- auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
+ auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
MIRBuilder.setInstr(MI);
@@ -146,6 +154,9 @@ LegalizerHelper::libcall(MachineInstr &MI) {
break;
}
case TargetOpcode::G_FADD:
+ case TargetOpcode::G_FSUB:
+ case TargetOpcode::G_FMUL:
+ case TargetOpcode::G_FDIV:
case TargetOpcode::G_FPOW:
case TargetOpcode::G_FREM: {
Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
@@ -169,12 +180,18 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
MIRBuilder.setInstr(MI);
+ int64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
+ int64_t NarrowSize = NarrowTy.getSizeInBits();
+
switch (MI.getOpcode()) {
default:
return UnableToLegalize;
case TargetOpcode::G_IMPLICIT_DEF: {
- int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
- NarrowTy.getSizeInBits();
+ // FIXME: add support for when SizeOp0 isn't an exact multiple of
+ // NarrowSize.
+ if (SizeOp0 % NarrowSize != 0)
+ return UnableToLegalize;
+ int NumParts = SizeOp0 / NarrowSize;
SmallVector<unsigned, 2> DstRegs;
for (int i = 0; i < NumParts; ++i) {
@@ -187,9 +204,12 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
return Legalized;
}
case TargetOpcode::G_ADD: {
+ // FIXME: add support for when SizeOp0 isn't an exact multiple of
+ // NarrowSize.
+ if (SizeOp0 % NarrowSize != 0)
+ return UnableToLegalize;
// Expand in terms of carry-setting/consuming G_ADDE instructions.
- int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
- NarrowTy.getSizeInBits();
+ int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
@@ -217,9 +237,12 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
if (TypeIdx != 1)
return UnableToLegalize;
- int64_t NarrowSize = NarrowTy.getSizeInBits();
- int NumParts =
- MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() / NarrowSize;
+ int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
+ // FIXME: add support for when SizeOp1 isn't an exact multiple of
+ // NarrowSize.
+ if (SizeOp1 % NarrowSize != 0)
+ return UnableToLegalize;
+ int NumParts = SizeOp1 / NarrowSize;
SmallVector<unsigned, 2> SrcRegs, DstRegs;
SmallVector<uint64_t, 2> Indexes;
@@ -266,12 +289,12 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
return Legalized;
}
case TargetOpcode::G_INSERT: {
- if (TypeIdx != 0)
+ // FIXME: add support for when SizeOp0 isn't an exact multiple of
+ // NarrowSize.
+ if (SizeOp0 % NarrowSize != 0)
return UnableToLegalize;
- int64_t NarrowSize = NarrowTy.getSizeInBits();
- int NumParts =
- MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
+ int NumParts = SizeOp0 / NarrowSize;
SmallVector<unsigned, 2> SrcRegs, DstRegs;
SmallVector<uint64_t, 2> Indexes;
@@ -326,9 +349,11 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
return Legalized;
}
case TargetOpcode::G_LOAD: {
- unsigned NarrowSize = NarrowTy.getSizeInBits();
- int NumParts =
- MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
+ // FIXME: add support for when SizeOp0 isn't an exact multiple of
+ // NarrowSize.
+ if (SizeOp0 % NarrowSize != 0)
+ return UnableToLegalize;
+ int NumParts = SizeOp0 / NarrowSize;
LLT OffsetTy = LLT::scalar(
MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
@@ -353,9 +378,11 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
return Legalized;
}
case TargetOpcode::G_STORE: {
- unsigned NarrowSize = NarrowTy.getSizeInBits();
- int NumParts =
- MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
+ // FIXME: add support for when SizeOp0 isn't an exact multiple of
+ // NarrowSize.
+ if (SizeOp0 % NarrowSize != 0)
+ return UnableToLegalize;
+ int NumParts = SizeOp0 / NarrowSize;
LLT OffsetTy = LLT::scalar(
MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
@@ -377,11 +404,13 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
return Legalized;
}
case TargetOpcode::G_CONSTANT: {
- unsigned NarrowSize = NarrowTy.getSizeInBits();
- int NumParts =
- MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
+ // FIXME: add support for when SizeOp0 isn't an exact multiple of
+ // NarrowSize.
+ if (SizeOp0 % NarrowSize != 0)
+ return UnableToLegalize;
+ int NumParts = SizeOp0 / NarrowSize;
const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
- LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
+ LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
SmallVector<unsigned, 2> DstRegs;
for (int i = 0; i < NumParts; ++i) {
@@ -396,6 +425,53 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
MI.eraseFromParent();
return Legalized;
}
+ case TargetOpcode::G_OR: {
+ // Legalize bitwise operation:
+ // A = BinOp<Ty> B, C
+ // into:
+ // B1, ..., BN = G_UNMERGE_VALUES B
+ // C1, ..., CN = G_UNMERGE_VALUES C
+ // A1 = BinOp<Ty/N> B1, C2
+ // ...
+ // AN = BinOp<Ty/N> BN, CN
+ // A = G_MERGE_VALUES A1, ..., AN
+
+ // FIXME: add support for when SizeOp0 isn't an exact multiple of
+ // NarrowSize.
+ if (SizeOp0 % NarrowSize != 0)
+ return UnableToLegalize;
+ int NumParts = SizeOp0 / NarrowSize;
+
+ // List the registers where the destination will be scattered.
+ SmallVector<unsigned, 2> DstRegs;
+ // List the registers where the first argument will be split.
+ SmallVector<unsigned, 2> SrcsReg1;
+ // List the registers where the second argument will be split.
+ SmallVector<unsigned, 2> SrcsReg2;
+ // Create all the temporary registers.
+ for (int i = 0; i < NumParts; ++i) {
+ unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
+ unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
+ unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
+
+ DstRegs.push_back(DstReg);
+ SrcsReg1.push_back(SrcReg1);
+ SrcsReg2.push_back(SrcReg2);
+ }
+ // Explode the big arguments into smaller chunks.
+ MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
+ MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
+
+ // Do the operation on each small part.
+ for (int i = 0; i < NumParts; ++i)
+ MIRBuilder.buildOr(DstRegs[i], SrcsReg1[i], SrcsReg2[i]);
+
+ // Gather the destination registers into the final destination.
+ unsigned DstReg = MI.getOperand(0).getReg();
+ MIRBuilder.buildMerge(DstReg, DstRegs);
+ MI.eraseFromParent();
+ return Legalized;
+ }
}
}
@@ -597,22 +673,58 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
MI.eraseFromParent();
return Legalized;
}
+ case TargetOpcode::G_FCMP: {
+ unsigned Op0Ext, Op1Ext, DstReg;
+ unsigned Cmp1 = MI.getOperand(2).getReg();
+ unsigned Cmp2 = MI.getOperand(3).getReg();
+ if (TypeIdx == 0) {
+ Op0Ext = Cmp1;
+ Op1Ext = Cmp2;
+ DstReg = MRI.createGenericVirtualRegister(WideTy);
+ } else {
+ Op0Ext = MRI.createGenericVirtualRegister(WideTy);
+ Op1Ext = MRI.createGenericVirtualRegister(WideTy);
+ DstReg = MI.getOperand(0).getReg();
+ MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op0Ext, Cmp1);
+ MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op1Ext, Cmp2);
+ }
+ MIRBuilder.buildFCmp(
+ static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
+ DstReg, Op0Ext, Op1Ext);
+ if (TypeIdx == 0)
+ MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
+ DstReg);
+ MI.eraseFromParent();
+ return Legalized;
+ }
case TargetOpcode::G_ICMP: {
- assert(TypeIdx == 1 && "unable to legalize predicate");
bool IsSigned = CmpInst::isSigned(
static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
- unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
- unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
- if (IsSigned) {
- MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
- MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
+ unsigned Cmp1 = MI.getOperand(2).getReg();
+ unsigned Cmp2 = MI.getOperand(3).getReg();
+ unsigned Op0Ext, Op1Ext, DstReg;
+ if (TypeIdx == 0) {
+ Op0Ext = Cmp1;
+ Op1Ext = Cmp2;
+ DstReg = MRI.createGenericVirtualRegister(WideTy);
} else {
- MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
- MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
+ Op0Ext = MRI.createGenericVirtualRegister(WideTy);
+ Op1Ext = MRI.createGenericVirtualRegister(WideTy);
+ DstReg = MI.getOperand(0).getReg();
+ if (IsSigned) {
+ MIRBuilder.buildSExt(Op0Ext, Cmp1);
+ MIRBuilder.buildSExt(Op1Ext, Cmp2);
+ } else {
+ MIRBuilder.buildZExt(Op0Ext, Cmp1);
+ MIRBuilder.buildZExt(Op1Ext, Cmp2);
+ }
}
MIRBuilder.buildICmp(
static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
- MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
+ DstReg, Op0Ext, Op1Ext);
+ if (TypeIdx == 0)
+ MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
+ DstReg);
MI.eraseFromParent();
return Legalized;
}
@@ -623,6 +735,35 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
MI.getOperand(2).setReg(OffsetExt);
return Legalized;
}
+ case TargetOpcode::G_PHI: {
+ assert(TypeIdx == 0 && "Expecting only Idx 0");
+ auto getExtendedReg = [&](unsigned Reg, MachineBasicBlock &MBB) {
+ auto FirstTermIt = MBB.getFirstTerminator();
+ MIRBuilder.setInsertPt(MBB, FirstTermIt);
+ MachineInstr *DefMI = MRI.getVRegDef(Reg);
+ MachineInstrBuilder MIB;
+ if (DefMI->getOpcode() == TargetOpcode::G_TRUNC)
+ MIB = MIRBuilder.buildAnyExtOrTrunc(WideTy,
+ DefMI->getOperand(1).getReg());
+ else
+ MIB = MIRBuilder.buildAnyExt(WideTy, Reg);
+ return MIB->getOperand(0).getReg();
+ };
+ auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, WideTy);
+ for (auto OpIt = MI.operands_begin() + 1, OpE = MI.operands_end();
+ OpIt != OpE;) {
+ unsigned Reg = OpIt++->getReg();
+ MachineBasicBlock *OpMBB = OpIt++->getMBB();
+ MIB.addReg(getExtendedReg(Reg, *OpMBB));
+ MIB.addMBB(OpMBB);
+ }
+ auto *MBB = MI.getParent();
+ MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI());
+ MIRBuilder.buildTrunc(MI.getOperand(0).getReg(),
+ MIB->getOperand(0).getReg());
+ MI.eraseFromParent();
+ return Legalized;
+ }
}
}
@@ -683,7 +824,7 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
return UnableToLegalize;
unsigned Res = MI.getOperand(0).getReg();
Type *ZeroTy;
- LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
+ LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
switch (Ty.getSizeInBits()) {
case 16:
ZeroTy = Type::getHalfTy(Ctx);
@@ -726,6 +867,18 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
MI.eraseFromParent();
return Legalized;
}
+ case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
+ unsigned OldValRes = MI.getOperand(0).getReg();
+ unsigned SuccessRes = MI.getOperand(1).getReg();
+ unsigned Addr = MI.getOperand(2).getReg();
+ unsigned CmpVal = MI.getOperand(3).getReg();
+ unsigned NewVal = MI.getOperand(4).getReg();
+ MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
+ **MI.memoperands_begin());
+ MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
+ MI.eraseFromParent();
+ return Legalized;
+ }
}
}
@@ -741,7 +894,12 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
case TargetOpcode::G_ADD: {
unsigned NarrowSize = NarrowTy.getSizeInBits();
unsigned DstReg = MI.getOperand(0).getReg();
- int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
+ unsigned Size = MRI.getType(DstReg).getSizeInBits();
+ int NumParts = Size / NarrowSize;
+ // FIXME: Don't know how to handle the situation where the small vectors
+ // aren't all the same size yet.
+ if (Size % NarrowSize != 0)
+ return UnableToLegalize;
MIRBuilder.setInstr(MI);