aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/Mips/MipsLegalizerInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Mips/MipsLegalizerInfo.cpp')
-rw-r--r--lib/Target/Mips/MipsLegalizerInfo.cpp244
1 files changed, 230 insertions, 14 deletions
diff --git a/lib/Target/Mips/MipsLegalizerInfo.cpp b/lib/Target/Mips/MipsLegalizerInfo.cpp
index e442a81837ed..bb4a1d902d75 100644
--- a/lib/Target/Mips/MipsLegalizerInfo.cpp
+++ b/lib/Target/Mips/MipsLegalizerInfo.cpp
@@ -16,18 +16,65 @@
using namespace llvm;
+struct TypesAndMemOps {
+ LLT ValTy;
+ LLT PtrTy;
+ unsigned MemSize;
+ bool MustBeNaturallyAligned;
+};
+
+static bool
+CheckTy0Ty1MemSizeAlign(const LegalityQuery &Query,
+ std::initializer_list<TypesAndMemOps> SupportedValues) {
+ for (auto &Val : SupportedValues) {
+ if (Val.ValTy != Query.Types[0])
+ continue;
+ if (Val.PtrTy != Query.Types[1])
+ continue;
+ if (Val.MemSize != Query.MMODescrs[0].SizeInBits)
+ continue;
+ if (Val.MustBeNaturallyAligned &&
+ Query.MMODescrs[0].SizeInBits % Query.MMODescrs[0].AlignInBits != 0)
+ continue;
+ return true;
+ }
+ return false;
+}
+
+static bool CheckTyN(unsigned N, const LegalityQuery &Query,
+ std::initializer_list<LLT> SupportedValues) {
+ for (auto &Val : SupportedValues)
+ if (Val == Query.Types[N])
+ return true;
+ return false;
+}
+
MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
using namespace TargetOpcode;
const LLT s1 = LLT::scalar(1);
const LLT s32 = LLT::scalar(32);
const LLT s64 = LLT::scalar(64);
+ const LLT v16s8 = LLT::vector(16, 8);
+ const LLT v8s16 = LLT::vector(8, 16);
+ const LLT v4s32 = LLT::vector(4, 32);
+ const LLT v2s64 = LLT::vector(2, 64);
const LLT p0 = LLT::pointer(0, 32);
- getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL})
+ getActionDefinitionsBuilder({G_SUB, G_MUL})
.legalFor({s32})
.clampScalar(0, s32, s32);
+ getActionDefinitionsBuilder(G_ADD)
+ .legalIf([=, &ST](const LegalityQuery &Query) {
+ if (CheckTyN(0, Query, {s32}))
+ return true;
+ if (ST.hasMSA() && CheckTyN(0, Query, {v16s8, v8s16, v4s32, v2s64}))
+ return true;
+ return false;
+ })
+ .clampScalar(0, s32, s32);
+
getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_USUBO, G_USUBE, G_UMULO})
.lowerFor({{s32, s1}});
@@ -36,13 +83,26 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
.maxScalar(0, s32);
getActionDefinitionsBuilder({G_LOAD, G_STORE})
- .legalForTypesWithMemDesc({{s32, p0, 8, 8},
- {s32, p0, 16, 8},
- {s32, p0, 32, 8},
- {s64, p0, 64, 8},
- {p0, p0, 32, 8}})
+ .legalIf([=, &ST](const LegalityQuery &Query) {
+ if (CheckTy0Ty1MemSizeAlign(Query, {{s32, p0, 8, ST.hasMips32r6()},
+ {s32, p0, 16, ST.hasMips32r6()},
+ {s32, p0, 32, ST.hasMips32r6()},
+ {p0, p0, 32, ST.hasMips32r6()},
+ {s64, p0, 64, ST.hasMips32r6()}}))
+ return true;
+ if (ST.hasMSA() &&
+ CheckTy0Ty1MemSizeAlign(Query, {{v16s8, p0, 128, false},
+ {v8s16, p0, 128, false},
+ {v4s32, p0, 128, false},
+ {v2s64, p0, 128, false}}))
+ return true;
+ return false;
+ })
.minScalar(0, s32);
+ getActionDefinitionsBuilder(G_IMPLICIT_DEF)
+ .legalFor({s32, s64});
+
getActionDefinitionsBuilder(G_UNMERGE_VALUES)
.legalFor({{s32, s64}});
@@ -50,9 +110,17 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
.legalFor({{s64, s32}});
getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD})
- .legalForTypesWithMemDesc({{s32, p0, 8, 8},
- {s32, p0, 16, 8}})
- .minScalar(0, s32);
+ .legalForTypesWithMemDesc({{s32, p0, 8, 8},
+ {s32, p0, 16, 8}})
+ .clampScalar(0, s32, s32);
+
+ getActionDefinitionsBuilder({G_ZEXT, G_SEXT})
+ .legalIf([](const LegalityQuery &Query) { return false; })
+ .maxScalar(0, s32);
+
+ getActionDefinitionsBuilder(G_TRUNC)
+ .legalIf([](const LegalityQuery &Query) { return false; })
+ .maxScalar(1, s32);
getActionDefinitionsBuilder(G_SELECT)
.legalForCartesianProduct({p0, s32, s64}, {s32})
@@ -63,6 +131,12 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
.legalFor({s32})
.minScalar(0, s32);
+ getActionDefinitionsBuilder(G_BRJT)
+ .legalFor({{p0, s32}});
+
+ getActionDefinitionsBuilder(G_BRINDIRECT)
+ .legalFor({p0});
+
getActionDefinitionsBuilder(G_PHI)
.legalFor({p0, s32, s64})
.minScalar(0, s32);
@@ -77,8 +151,9 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
.libcallFor({s64});
getActionDefinitionsBuilder({G_SHL, G_ASHR, G_LSHR})
- .legalFor({s32, s32})
- .minScalar(1, s32);
+ .legalFor({{s32, s32}})
+ .clampScalar(1, s32, s32)
+ .clampScalar(0, s32, s32);
getActionDefinitionsBuilder(G_ICMP)
.legalForCartesianProduct({s32}, {s32, p0})
@@ -89,15 +164,24 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
.legalFor({s32})
.clampScalar(0, s32, s32);
- getActionDefinitionsBuilder(G_GEP)
+ getActionDefinitionsBuilder({G_GEP, G_INTTOPTR})
.legalFor({{p0, s32}});
+ getActionDefinitionsBuilder(G_PTRTOINT)
+ .legalFor({{s32, p0}});
+
getActionDefinitionsBuilder(G_FRAME_INDEX)
.legalFor({p0});
- getActionDefinitionsBuilder(G_GLOBAL_VALUE)
+ getActionDefinitionsBuilder({G_GLOBAL_VALUE, G_JUMP_TABLE})
.legalFor({p0});
+ getActionDefinitionsBuilder(G_DYN_STACKALLOC)
+ .lowerFor({{p0, s32}});
+
+ getActionDefinitionsBuilder(G_VASTART)
+ .legalFor({p0});
+
// FP instructions
getActionDefinitionsBuilder(G_FCONSTANT)
.legalFor({s32, s64});
@@ -126,6 +210,7 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
getActionDefinitionsBuilder(G_FPTOUI)
.libcallForCartesianProduct({s64}, {s64, s32})
+ .lowerForCartesianProduct({s32}, {s64, s32})
.minScalar(0, s32);
// Int to FP conversion instructions
@@ -136,8 +221,11 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
getActionDefinitionsBuilder(G_UITOFP)
.libcallForCartesianProduct({s64, s32}, {s64})
+ .customForCartesianProduct({s64, s32}, {s32})
.minScalar(1, s32);
+ getActionDefinitionsBuilder(G_SEXT_INREG).lower();
+
computeTables();
verify(*ST.getInstrInfo());
}
@@ -150,6 +238,134 @@ bool MipsLegalizerInfo::legalizeCustom(MachineInstr &MI,
using namespace TargetOpcode;
MIRBuilder.setInstr(MI);
+ const MipsSubtarget &STI =
+ static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget());
+ const LLT s32 = LLT::scalar(32);
+ const LLT s64 = LLT::scalar(64);
- return false;
+ switch (MI.getOpcode()) {
+ case G_UITOFP: {
+ Register Dst = MI.getOperand(0).getReg();
+ Register Src = MI.getOperand(1).getReg();
+ LLT DstTy = MRI.getType(Dst);
+ LLT SrcTy = MRI.getType(Src);
+
+ if (SrcTy != s32)
+ return false;
+ if (DstTy != s32 && DstTy != s64)
+ return false;
+
+ // Let 0xABCDEFGH be given unsigned in MI.getOperand(1). First let's convert
+ // unsigned to double. Mantissa has 52 bits so we use following trick:
+ // First make floating point bit mask 0x43300000ABCDEFGH.
+ // Mask represents 2^52 * 0x1.00000ABCDEFGH i.e. 0x100000ABCDEFGH.0 .
+ // Next, subtract 2^52 * 0x1.0000000000000 i.e. 0x10000000000000.0 from it.
+ // Done. Trunc double to float if needed.
+
+ MachineInstrBuilder Bitcast = MIRBuilder.buildInstr(
+ STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64, {s64},
+ {Src, MIRBuilder.buildConstant(s32, UINT32_C(0x43300000))});
+ Bitcast.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(),
+ *STI.getRegBankInfo());
+
+ MachineInstrBuilder TwoP52FP = MIRBuilder.buildFConstant(
+ s64, BitsToDouble(UINT64_C(0x4330000000000000)));
+
+ if (DstTy == s64)
+ MIRBuilder.buildFSub(Dst, Bitcast, TwoP52FP);
+ else {
+ MachineInstrBuilder ResF64 = MIRBuilder.buildFSub(s64, Bitcast, TwoP52FP);
+ MIRBuilder.buildFPTrunc(Dst, ResF64);
+ }
+
+ MI.eraseFromParent();
+ break;
+ }
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+static bool SelectMSA3OpIntrinsic(MachineInstr &MI, unsigned Opcode,
+ MachineIRBuilder &MIRBuilder,
+ const MipsSubtarget &ST) {
+ assert(ST.hasMSA() && "MSA intrinsic not supported on target without MSA.");
+ if (!MIRBuilder.buildInstr(Opcode)
+ .add(MI.getOperand(0))
+ .add(MI.getOperand(2))
+ .add(MI.getOperand(3))
+ .constrainAllUses(MIRBuilder.getTII(), *ST.getRegisterInfo(),
+ *ST.getRegBankInfo()))
+ return false;
+ MI.eraseFromParent();
+ return true;
+}
+
+static bool MSA3OpIntrinsicToGeneric(MachineInstr &MI, unsigned Opcode,
+ MachineIRBuilder &MIRBuilder,
+ const MipsSubtarget &ST) {
+ assert(ST.hasMSA() && "MSA intrinsic not supported on target without MSA.");
+ MIRBuilder.buildInstr(Opcode)
+ .add(MI.getOperand(0))
+ .add(MI.getOperand(2))
+ .add(MI.getOperand(3));
+ MI.eraseFromParent();
+ return true;
+}
+
+bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
+ MachineRegisterInfo &MRI,
+ MachineIRBuilder &MIRBuilder) const {
+ const MipsSubtarget &ST =
+ static_cast<const MipsSubtarget &>(MI.getMF()->getSubtarget());
+ const MipsInstrInfo &TII = *ST.getInstrInfo();
+ const MipsRegisterInfo &TRI = *ST.getRegisterInfo();
+ const RegisterBankInfo &RBI = *ST.getRegBankInfo();
+ MIRBuilder.setInstr(MI);
+
+ switch (MI.getIntrinsicID()) {
+ case Intrinsic::memcpy:
+ case Intrinsic::memset:
+ case Intrinsic::memmove:
+ if (createMemLibcall(MIRBuilder, MRI, MI) ==
+ LegalizerHelper::UnableToLegalize)
+ return false;
+ MI.eraseFromParent();
+ return true;
+ case Intrinsic::trap: {
+ MachineInstr *Trap = MIRBuilder.buildInstr(Mips::TRAP);
+ MI.eraseFromParent();
+ return constrainSelectedInstRegOperands(*Trap, TII, TRI, RBI);
+ }
+ case Intrinsic::vacopy: {
+ Register Tmp = MRI.createGenericVirtualRegister(LLT::pointer(0, 32));
+ MachinePointerInfo MPO;
+ MIRBuilder.buildLoad(Tmp, MI.getOperand(2),
+ *MI.getMF()->getMachineMemOperand(
+ MPO, MachineMemOperand::MOLoad, 4, 4));
+ MIRBuilder.buildStore(Tmp, MI.getOperand(1),
+ *MI.getMF()->getMachineMemOperand(
+ MPO, MachineMemOperand::MOStore, 4, 4));
+ MI.eraseFromParent();
+ return true;
+ }
+ case Intrinsic::mips_addv_b:
+ case Intrinsic::mips_addv_h:
+ case Intrinsic::mips_addv_w:
+ case Intrinsic::mips_addv_d:
+ return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_ADD, MIRBuilder, ST);
+ case Intrinsic::mips_addvi_b:
+ return SelectMSA3OpIntrinsic(MI, Mips::ADDVI_B, MIRBuilder, ST);
+ case Intrinsic::mips_addvi_h:
+ return SelectMSA3OpIntrinsic(MI, Mips::ADDVI_H, MIRBuilder, ST);
+ case Intrinsic::mips_addvi_w:
+ return SelectMSA3OpIntrinsic(MI, Mips::ADDVI_W, MIRBuilder, ST);
+ case Intrinsic::mips_addvi_d:
+ return SelectMSA3OpIntrinsic(MI, Mips::ADDVI_D, MIRBuilder, ST);
+ default:
+ break;
+ }
+ return true;
}