1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 20:23:11 +01:00

GlobalISel: Make type for lower action more consistently optional

Some of the lower implementations were relying on this, however the
type was not set depending on which form .lower* helper form you were
using. For instance, if you used an unconditonal lower(), the type was
never set. Most of the lower actions do not benefit from a type
parameter, and just expand in terms of the original operation's types.

However, some lowerings could benefit from an additional type hint to
combine a promotion and an expansion. An example of this is for
add/sub sat. The DAG integer legalization tries to use smarter
expansions directly when promoting the integer type, and doesn't
always produce the same instruction with a wider type.

Treat this as an optional hint argument, that only means something for
specific lower actions. It may be useful to generalize this mechanism
to pass a full list of type indexes and desired types, but I haven't
run into a case like that yet.
This commit is contained in:
Matt Arsenault 2020-07-15 11:10:54 -04:00
parent 78cee19819
commit 4a4ddffaf1
4 changed files with 49 additions and 45 deletions

View File

@ -176,10 +176,12 @@ few actions in common:
elements in one of the types to a specific type would make it more legal. elements in one of the types to a specific type would make it more legal.
This action supports vectors. This action supports vectors.
* ``lowerIf()``, ``lowerFor()``, etc. declare an instruction to be illegal if the * ``lowerIf()``, ``lowerFor()``, etc. declare an instruction to be
predicate is satisfied and indicates that replacing it with equivalent illegal if the predicate is satisfied and indicates that replacing
instruction(s) would make it more legal. Support for this action differs for it with equivalent instruction(s) would make it more legal. Support
each opcode. for this action differs for each opcode. These may provide an
optional LegalizeMutation containing a type to attempt to perform
the expansion in a different type.
* ``libcallIf()``, ``libcallFor()``, etc. declare an instruction to be illegal if the * ``libcallIf()``, ``libcallFor()``, etc. declare an instruction to be illegal if the
predicate is satisfied and indicates that replacing it with a libcall would predicate is satisfied and indicates that replacing it with a libcall would

View File

@ -325,20 +325,20 @@ public:
LegalizeResult lowerBitcast(MachineInstr &MI); LegalizeResult lowerBitcast(MachineInstr &MI);
LegalizeResult lowerLoad(MachineInstr &MI); LegalizeResult lowerLoad(MachineInstr &MI);
LegalizeResult lowerStore(MachineInstr &MI); LegalizeResult lowerStore(MachineInstr &MI);
LegalizeResult lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult lowerBitCount(MachineInstr &MI);
LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI); LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI);
LegalizeResult lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult lowerUITOFP(MachineInstr &MI);
LegalizeResult lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult lowerSITOFP(MachineInstr &MI);
LegalizeResult lowerFPTOUI(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult lowerFPTOUI(MachineInstr &MI);
LegalizeResult lowerFPTOSI(MachineInstr &MI); LegalizeResult lowerFPTOSI(MachineInstr &MI);
LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI); LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI);
LegalizeResult lowerFPTRUNC(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult lowerFPTRUNC(MachineInstr &MI);
LegalizeResult lowerFPOWI(MachineInstr &MI); LegalizeResult lowerFPOWI(MachineInstr &MI);
LegalizeResult lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult lowerMinMax(MachineInstr &MI);
LegalizeResult lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult lowerFCopySign(MachineInstr &MI);
LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI); LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI);
LegalizeResult lowerFMad(MachineInstr &MI); LegalizeResult lowerFMad(MachineInstr &MI);
LegalizeResult lowerIntrinsicRound(MachineInstr &MI); LegalizeResult lowerIntrinsicRound(MachineInstr &MI);

View File

@ -629,8 +629,7 @@ public:
/// The instruction is lowered when type index 0 is any type in the given /// The instruction is lowered when type index 0 is any type in the given
/// list. Keep type index 0 as the same type. /// list. Keep type index 0 as the same type.
LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types) { LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types) {
return actionFor(LegalizeAction::Lower, Types, return actionFor(LegalizeAction::Lower, Types);
LegalizeMutations::changeTo(0, 0));
} }
/// The instruction is lowered when type index 0 is any type in the given /// The instruction is lowered when type index 0 is any type in the given
/// list. /// list.
@ -641,8 +640,7 @@ public:
/// The instruction is lowered when type indexes 0 and 1 is any type pair in /// The instruction is lowered when type indexes 0 and 1 is any type pair in
/// the given list. Keep type index 0 as the same type. /// the given list. Keep type index 0 as the same type.
LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types) { LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
return actionFor(LegalizeAction::Lower, Types, return actionFor(LegalizeAction::Lower, Types);
LegalizeMutations::changeTo(0, 0));
} }
/// The instruction is lowered when type indexes 0 and 1 is any type pair in /// The instruction is lowered when type indexes 0 and 1 is any type pair in
/// the given list. /// the given list.

View File

@ -2804,7 +2804,7 @@ void LegalizerHelper::changeOpcode(MachineInstr &MI, unsigned NewOpcode) {
} }
LegalizerHelper::LegalizeResult LegalizerHelper::LegalizeResult
LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
using namespace TargetOpcode; using namespace TargetOpcode;
switch(MI.getOpcode()) { switch(MI.getOpcode()) {
@ -2814,6 +2814,7 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
return lowerBitcast(MI); return lowerBitcast(MI);
case TargetOpcode::G_SREM: case TargetOpcode::G_SREM:
case TargetOpcode::G_UREM: { case TargetOpcode::G_UREM: {
LLT Ty = MRI.getType(MI.getOperand(0).getReg());
auto Quot = auto Quot =
MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty}, MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
{MI.getOperand(1), MI.getOperand(2)}); {MI.getOperand(1), MI.getOperand(2)});
@ -2834,6 +2835,7 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Register Overflow = MI.getOperand(1).getReg(); Register Overflow = MI.getOperand(1).getReg();
Register LHS = MI.getOperand(2).getReg(); Register LHS = MI.getOperand(2).getReg();
Register RHS = MI.getOperand(3).getReg(); Register RHS = MI.getOperand(3).getReg();
LLT Ty = MRI.getType(Res);
unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
? TargetOpcode::G_SMULH ? TargetOpcode::G_SMULH
@ -2862,11 +2864,13 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
return Legalized; return Legalized;
} }
case TargetOpcode::G_FNEG: { case TargetOpcode::G_FNEG: {
Register Res = MI.getOperand(0).getReg();
LLT Ty = MRI.getType(Res);
// TODO: Handle vector types once we are able to // TODO: Handle vector types once we are able to
// represent them. // represent them.
if (Ty.isVector()) if (Ty.isVector())
return UnableToLegalize; return UnableToLegalize;
Register Res = MI.getOperand(0).getReg();
LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Type *ZeroTy = getFloatTypeForLLT(Ctx, Ty); Type *ZeroTy = getFloatTypeForLLT(Ctx, Ty);
if (!ZeroTy) if (!ZeroTy)
@ -2881,12 +2885,14 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
return Legalized; return Legalized;
} }
case TargetOpcode::G_FSUB: { case TargetOpcode::G_FSUB: {
Register Res = MI.getOperand(0).getReg();
LLT Ty = MRI.getType(Res);
// Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)). // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
// First, check if G_FNEG is marked as Lower. If so, we may // First, check if G_FNEG is marked as Lower. If so, we may
// end up with an infinite loop as G_FSUB is used to legalize G_FNEG. // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
if (LI.getAction({G_FNEG, {Ty}}).Action == Lower) if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
return UnableToLegalize; return UnableToLegalize;
Register Res = MI.getOperand(0).getReg();
Register LHS = MI.getOperand(1).getReg(); Register LHS = MI.getOperand(1).getReg();
Register RHS = MI.getOperand(2).getReg(); Register RHS = MI.getOperand(2).getReg();
Register Neg = MRI.createGenericVirtualRegister(Ty); Register Neg = MRI.createGenericVirtualRegister(Ty);
@ -2930,7 +2936,7 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
case TargetOpcode::G_CTLZ: case TargetOpcode::G_CTLZ:
case TargetOpcode::G_CTTZ: case TargetOpcode::G_CTTZ:
case TargetOpcode::G_CTPOP: case TargetOpcode::G_CTPOP:
return lowerBitCount(MI, TypeIdx, Ty); return lowerBitCount(MI);
case G_UADDO: { case G_UADDO: {
Register Res = MI.getOperand(0).getReg(); Register Res = MI.getOperand(0).getReg();
Register CarryOut = MI.getOperand(1).getReg(); Register CarryOut = MI.getOperand(1).getReg();
@ -2992,24 +2998,24 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
return Legalized; return Legalized;
} }
case G_UITOFP: case G_UITOFP:
return lowerUITOFP(MI, TypeIdx, Ty); return lowerUITOFP(MI);
case G_SITOFP: case G_SITOFP:
return lowerSITOFP(MI, TypeIdx, Ty); return lowerSITOFP(MI);
case G_FPTOUI: case G_FPTOUI:
return lowerFPTOUI(MI, TypeIdx, Ty); return lowerFPTOUI(MI);
case G_FPTOSI: case G_FPTOSI:
return lowerFPTOSI(MI); return lowerFPTOSI(MI);
case G_FPTRUNC: case G_FPTRUNC:
return lowerFPTRUNC(MI, TypeIdx, Ty); return lowerFPTRUNC(MI);
case G_FPOWI: case G_FPOWI:
return lowerFPOWI(MI); return lowerFPOWI(MI);
case G_SMIN: case G_SMIN:
case G_SMAX: case G_SMAX:
case G_UMIN: case G_UMIN:
case G_UMAX: case G_UMAX:
return lowerMinMax(MI, TypeIdx, Ty); return lowerMinMax(MI);
case G_FCOPYSIGN: case G_FCOPYSIGN:
return lowerFCopySign(MI, TypeIdx, Ty); return lowerFCopySign(MI);
case G_FMINNUM: case G_FMINNUM:
case G_FMAXNUM: case G_FMAXNUM:
return lowerFMinNumMaxNum(MI); return lowerFMinNumMaxNum(MI);
@ -4758,7 +4764,7 @@ LegalizerHelper::narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx,
} }
LegalizerHelper::LegalizeResult LegalizerHelper::LegalizeResult
LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { LegalizerHelper::lowerBitCount(MachineInstr &MI) {
unsigned Opc = MI.getOpcode(); unsigned Opc = MI.getOpcode();
const auto &TII = MIRBuilder.getTII(); const auto &TII = MIRBuilder.getTII();
auto isSupported = [this](const LegalityQuery &Q) { auto isSupported = [this](const LegalityQuery &Q) {
@ -4848,15 +4854,15 @@ LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
// unless the target has ctlz but not ctpop, in which case we use: // unless the target has ctlz but not ctpop, in which case we use:
// { return 32 - nlz(~x & (x-1)); } // { return 32 - nlz(~x & (x-1)); }
// Ref: "Hacker's Delight" by Henry Warren // Ref: "Hacker's Delight" by Henry Warren
auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1); auto MIBCstNeg1 = MIRBuilder.buildConstant(SrcTy, -1);
auto MIBNot = MIRBuilder.buildXor(Ty, SrcReg, MIBCstNeg1); auto MIBNot = MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
auto MIBTmp = MIRBuilder.buildAnd( auto MIBTmp = MIRBuilder.buildAnd(
Ty, MIBNot, MIRBuilder.buildAdd(Ty, SrcReg, MIBCstNeg1)); SrcTy, MIBNot, MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) && if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) { isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len); auto MIBCstLen = MIRBuilder.buildConstant(SrcTy, Len);
MIRBuilder.buildSub(MI.getOperand(0), MIBCstLen, MIRBuilder.buildSub(MI.getOperand(0), MIBCstLen,
MIRBuilder.buildCTLZ(Ty, MIBTmp)); MIRBuilder.buildCTLZ(SrcTy, MIBTmp));
MI.eraseFromParent(); MI.eraseFromParent();
return Legalized; return Legalized;
} }
@ -4865,6 +4871,8 @@ LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
return Legalized; return Legalized;
} }
case TargetOpcode::G_CTPOP: { case TargetOpcode::G_CTPOP: {
Register SrcReg = MI.getOperand(1).getReg();
LLT Ty = MRI.getType(SrcReg);
unsigned Size = Ty.getSizeInBits(); unsigned Size = Ty.getSizeInBits();
MachineIRBuilder &B = MIRBuilder; MachineIRBuilder &B = MIRBuilder;
@ -4874,11 +4882,11 @@ LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
// B2Count = val - { (val >> 1) & 0x55555555 } // B2Count = val - { (val >> 1) & 0x55555555 }
// since it gives same result in blocks of 2 with one instruction less. // since it gives same result in blocks of 2 with one instruction less.
auto C_1 = B.buildConstant(Ty, 1); auto C_1 = B.buildConstant(Ty, 1);
auto B2Set1LoTo1Hi = B.buildLShr(Ty, MI.getOperand(1).getReg(), C_1); auto B2Set1LoTo1Hi = B.buildLShr(Ty, SrcReg, C_1);
APInt B2Mask1HiTo0 = APInt::getSplat(Size, APInt(8, 0x55)); APInt B2Mask1HiTo0 = APInt::getSplat(Size, APInt(8, 0x55));
auto C_B2Mask1HiTo0 = B.buildConstant(Ty, B2Mask1HiTo0); auto C_B2Mask1HiTo0 = B.buildConstant(Ty, B2Mask1HiTo0);
auto B2Count1Hi = B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0); auto B2Count1Hi = B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
auto B2Count = B.buildSub(Ty, MI.getOperand(1).getReg(), B2Count1Hi); auto B2Count = B.buildSub(Ty, SrcReg, B2Count1Hi);
// In order to get count in blocks of 4 add values from adjacent block of 2. // In order to get count in blocks of 4 add values from adjacent block of 2.
// B4Count = { B2Count & 0x33333333 } + { (B2Count >> 2) & 0x33333333 } // B4Count = { B2Count & 0x33333333 } + { (B2Count >> 2) & 0x33333333 }
@ -4977,8 +4985,7 @@ LegalizerHelper::lowerU64ToF32BitOps(MachineInstr &MI) {
return Legalized; return Legalized;
} }
LegalizerHelper::LegalizeResult LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) {
LegalizerHelper::lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Register Dst = MI.getOperand(0).getReg(); Register Dst = MI.getOperand(0).getReg();
Register Src = MI.getOperand(1).getReg(); Register Src = MI.getOperand(1).getReg();
LLT DstTy = MRI.getType(Dst); LLT DstTy = MRI.getType(Dst);
@ -5006,8 +5013,7 @@ LegalizerHelper::lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
return UnableToLegalize; return UnableToLegalize;
} }
LegalizerHelper::LegalizeResult LegalizerHelper::LegalizeResult LegalizerHelper::lowerSITOFP(MachineInstr &MI) {
LegalizerHelper::lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Register Dst = MI.getOperand(0).getReg(); Register Dst = MI.getOperand(0).getReg();
Register Src = MI.getOperand(1).getReg(); Register Src = MI.getOperand(1).getReg();
LLT DstTy = MRI.getType(Dst); LLT DstTy = MRI.getType(Dst);
@ -5053,8 +5059,7 @@ LegalizerHelper::lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
return UnableToLegalize; return UnableToLegalize;
} }
LegalizerHelper::LegalizeResult LegalizerHelper::LegalizeResult LegalizerHelper::lowerFPTOUI(MachineInstr &MI) {
LegalizerHelper::lowerFPTOUI(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Register Dst = MI.getOperand(0).getReg(); Register Dst = MI.getOperand(0).getReg();
Register Src = MI.getOperand(1).getReg(); Register Src = MI.getOperand(1).getReg();
LLT DstTy = MRI.getType(Dst); LLT DstTy = MRI.getType(Dst);
@ -5271,7 +5276,7 @@ LegalizerHelper::lowerFPTRUNC_F64_TO_F16(MachineInstr &MI) {
} }
LegalizerHelper::LegalizeResult LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFPTRUNC(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { LegalizerHelper::lowerFPTRUNC(MachineInstr &MI) {
Register Dst = MI.getOperand(0).getReg(); Register Dst = MI.getOperand(0).getReg();
Register Src = MI.getOperand(1).getReg(); Register Src = MI.getOperand(1).getReg();
@ -5315,8 +5320,7 @@ static CmpInst::Predicate minMaxToCompare(unsigned Opc) {
} }
} }
LegalizerHelper::LegalizeResult LegalizerHelper::LegalizeResult LegalizerHelper::lowerMinMax(MachineInstr &MI) {
LegalizerHelper::lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Register Dst = MI.getOperand(0).getReg(); Register Dst = MI.getOperand(0).getReg();
Register Src0 = MI.getOperand(1).getReg(); Register Src0 = MI.getOperand(1).getReg();
Register Src1 = MI.getOperand(2).getReg(); Register Src1 = MI.getOperand(2).getReg();
@ -5332,7 +5336,7 @@ LegalizerHelper::lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
} }
LegalizerHelper::LegalizeResult LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { LegalizerHelper::lowerFCopySign(MachineInstr &MI) {
Register Dst = MI.getOperand(0).getReg(); Register Dst = MI.getOperand(0).getReg();
Register Src0 = MI.getOperand(1).getReg(); Register Src0 = MI.getOperand(1).getReg();
Register Src1 = MI.getOperand(2).getReg(); Register Src1 = MI.getOperand(2).getReg();