Index: llvm/docs/GlobalISel/Legalizer.rst =================================================================== --- llvm/docs/GlobalISel/Legalizer.rst +++ llvm/docs/GlobalISel/Legalizer.rst @@ -176,10 +176,12 @@ elements in one of the types to a specific type would make it more legal. This action supports vectors. -* ``lowerIf()``, ``lowerFor()``, etc. declare an instruction to be illegal if the - predicate is satisfied and indicates that replacing it with equivalent - instruction(s) would make it more legal. Support for this action differs for - each opcode. +* ``lowerIf()``, ``lowerFor()``, etc. declare an instruction to be + illegal if the predicate is satisfied and indicates that replacing + it with equivalent instruction(s) would make it more legal. Support + 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 predicate is satisfied and indicates that replacing it with a libcall would Index: llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -616,8 +616,7 @@ /// The instruction is lowered when type index 0 is any type in the given /// list. Keep type index 0 as the same type. LegalizeRuleSet &lowerFor(std::initializer_list Types) { - return actionFor(LegalizeAction::Lower, Types, - LegalizeMutations::changeTo(0, 0)); + return actionFor(LegalizeAction::Lower, Types); } /// The instruction is lowered when type index 0 is any type in the given /// list. @@ -628,8 +627,7 @@ /// 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. LegalizeRuleSet &lowerFor(std::initializer_list> Types) { - return actionFor(LegalizeAction::Lower, Types, - LegalizeMutations::changeTo(0, 0)); + return actionFor(LegalizeAction::Lower, Types); } /// The instruction is lowered when type indexes 0 and 1 is any type pair in /// the given list. Index: llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -2327,7 +2327,7 @@ } LegalizerHelper::LegalizeResult -LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { +LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerTy) { using namespace TargetOpcode; switch(MI.getOpcode()) { @@ -2337,6 +2337,7 @@ return lowerBitcast(MI); case TargetOpcode::G_SREM: case TargetOpcode::G_UREM: { + LLT Ty = MRI.getType(MI.getOperand(0).getReg()); auto Quot = MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty}, {MI.getOperand(1), MI.getOperand(2)}); @@ -2357,6 +2358,7 @@ Register Overflow = MI.getOperand(1).getReg(); Register LHS = MI.getOperand(2).getReg(); Register RHS = MI.getOperand(3).getReg(); + LLT Ty = MRI.getType(Res); unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO ? TargetOpcode::G_SMULH @@ -2385,11 +2387,13 @@ return Legalized; } case TargetOpcode::G_FNEG: { + Register Res = MI.getOperand(0).getReg(); + LLT Ty = MRI.getType(Res); + // TODO: Handle vector types once we are able to // represent them. if (Ty.isVector()) return UnableToLegalize; - Register Res = MI.getOperand(0).getReg(); LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); Type *ZeroTy = getFloatTypeForLLT(Ctx, Ty); if (!ZeroTy) @@ -2404,12 +2408,14 @@ return Legalized; } 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)). // 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. if (LI.getAction({G_FNEG, {Ty}}).Action == Lower) return UnableToLegalize; - Register Res = MI.getOperand(0).getReg(); Register LHS = MI.getOperand(1).getReg(); Register RHS = MI.getOperand(2).getReg(); Register Neg = MRI.createGenericVirtualRegister(Ty); @@ -2576,7 +2582,7 @@ case TargetOpcode::G_CTLZ: case TargetOpcode::G_CTTZ: case TargetOpcode::G_CTPOP: - return lowerBitCount(MI, TypeIdx, Ty); + return lowerBitCount(MI, TypeIdx, LowerTy); case G_UADDO: { Register Res = MI.getOperand(0).getReg(); Register CarryOut = MI.getOperand(1).getReg(); @@ -2638,22 +2644,22 @@ return Legalized; } case G_UITOFP: - return lowerUITOFP(MI, TypeIdx, Ty); + return lowerUITOFP(MI, TypeIdx, LowerTy); case G_SITOFP: - return lowerSITOFP(MI, TypeIdx, Ty); + return lowerSITOFP(MI, TypeIdx, LowerTy); case G_FPTOUI: - return lowerFPTOUI(MI, TypeIdx, Ty); + return lowerFPTOUI(MI, TypeIdx, LowerTy); case G_FPTOSI: return lowerFPTOSI(MI); case G_FPTRUNC: - return lowerFPTRUNC(MI, TypeIdx, Ty); + return lowerFPTRUNC(MI, TypeIdx, LowerTy); case G_SMIN: case G_SMAX: case G_UMIN: case G_UMAX: - return lowerMinMax(MI, TypeIdx, Ty); + return lowerMinMax(MI, TypeIdx, LowerTy); case G_FCOPYSIGN: - return lowerFCopySign(MI, TypeIdx, Ty); + return lowerFCopySign(MI, TypeIdx, LowerTy); case G_FMINNUM: case G_FMAXNUM: return lowerFMinNumMaxNum(MI); @@ -4288,7 +4294,8 @@ } LegalizerHelper::LegalizeResult -LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { +LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, + LLT LowerTy) { unsigned Opc = MI.getOpcode(); auto &TII = *MI.getMF()->getSubtarget().getInstrInfo(); auto isSupported = [this](const LegalityQuery &Q) { @@ -4378,15 +4385,15 @@ // unless the target has ctlz but not ctpop, in which case we use: // { return 32 - nlz(~x & (x-1)); } // Ref: "Hacker's Delight" by Henry Warren - auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1); - auto MIBNot = MIRBuilder.buildXor(Ty, SrcReg, MIBCstNeg1); + auto MIBCstNeg1 = MIRBuilder.buildConstant(SrcTy, -1); + auto MIBNot = MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1); auto MIBTmp = MIRBuilder.buildAnd( - Ty, MIBNot, MIRBuilder.buildAdd(Ty, SrcReg, MIBCstNeg1)); - if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) && - isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) { - auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len); + SrcTy, MIBNot, MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1)); + if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) && + isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) { + auto MIBCstLen = MIRBuilder.buildConstant(SrcTy, Len); MIRBuilder.buildSub(MI.getOperand(0), MIBCstLen, - MIRBuilder.buildCTLZ(Ty, MIBTmp)); + MIRBuilder.buildCTLZ(SrcTy, MIBTmp)); MI.eraseFromParent(); return Legalized; } @@ -4395,6 +4402,8 @@ return Legalized; } case TargetOpcode::G_CTPOP: { + Register SrcReg = MI.getOperand(1).getReg(); + LLT Ty = MRI.getType(SrcReg); unsigned Size = Ty.getSizeInBits(); MachineIRBuilder &B = MIRBuilder; @@ -4404,11 +4413,11 @@ // B2Count = val - { (val >> 1) & 0x55555555 } // since it gives same result in blocks of 2 with one instruction less. 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)); auto C_B2Mask1HiTo0 = B.buildConstant(Ty, 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. // B4Count = { B2Count & 0x33333333 } + { (B2Count >> 2) & 0x33333333 }