diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -143,14 +143,15 @@ Register TruncSrc; if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { LLT DstTy = MRI.getType(DstReg); - if (isInstUnsupported({TargetOpcode::G_SEXT_INREG, {DstTy}})) + LLT SrcTy = MRI.getType(SrcReg); + unsigned SizeInBits = SrcTy.getScalarSizeInBits(); + if (isInstUnsupported( + {TargetOpcode::G_SEXT_INREG, {DstTy}, {}, {SizeInBits}})) return false; LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); - LLT SrcTy = MRI.getType(SrcReg); - uint64_t SizeInBits = SrcTy.getScalarSizeInBits(); Builder.buildInstr( TargetOpcode::G_SEXT_INREG, {DstReg}, - {Builder.buildAnyExtOrTrunc(DstTy, TruncSrc), SizeInBits}); + {Builder.buildAnyExtOrTrunc(DstTy, TruncSrc), uint64_t(SizeInBits)}); markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); return true; } diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -120,6 +120,7 @@ struct LegalityQuery { unsigned Opcode; ArrayRef Types; + ArrayRef Imms; struct MemDesc { uint64_t SizeInBits; @@ -131,11 +132,15 @@ /// memory type for each MMO. ArrayRef MMODescrs; + constexpr LegalityQuery(unsigned Opcode, const ArrayRef Types, + const ArrayRef MMODescrs, + const ArrayRef Imms) + : Opcode(Opcode), Types(Types), Imms(Imms), MMODescrs(MMODescrs) {} constexpr LegalityQuery(unsigned Opcode, const ArrayRef Types, const ArrayRef MMODescrs) - : Opcode(Opcode), Types(Types), MMODescrs(MMODescrs) {} + : LegalityQuery(Opcode, Types, MMODescrs, {}) {} constexpr LegalityQuery(unsigned Opcode, const ArrayRef Types) - : LegalityQuery(Opcode, Types, {}) {} + : LegalityQuery(Opcode, Types, {}, {}) {} raw_ostream &print(raw_ostream &OS) const; }; @@ -214,6 +219,10 @@ LegalityPredicate typePairAndMemDescInSet( unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, std::initializer_list TypesAndMemDescInit); +/// True iff the given type and immediate is one of the specified pairs. +LegalityPredicate +typeAndImmInSet(unsigned TypeIdx0, unsigned ImmIdx, + std::initializer_list> TypesAndImmInit); /// True iff the specified type index is a scalar. LegalityPredicate isScalar(unsigned TypeIdx); /// True iff the specified type index is a vector. @@ -417,6 +426,15 @@ return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types), Mutation); } + /// Use the given action when type index 0 and imm index 0 is any type/imm + /// pair in the given list. Action should not be an action that requires + /// mutation. + LegalizeRuleSet &actionForTypeWithImm( + LegalizeAction Action, + std::initializer_list> TypeAndImm) { + return actionIf(Action, LegalityPredicates::typeAndImmInSet( + typeIdx(0), immIdx(0), TypeAndImm)); + } /// Use the given action when type index 0 is any type in the given list and /// imm index 0 is anything. Action should not be an action that requires /// mutation. @@ -492,7 +510,6 @@ /// The instruction is legal when type index 0 is any type in the given list /// and imm index 0 is anything. LegalizeRuleSet &legalForTypeWithAnyImm(std::initializer_list Types) { - markAllIdxsAsCovered(); return actionForTypeWithAnyImm(LegalizeAction::Legal, Types); } /// The instruction is legal when type indexes 0 and 1 along with the memory @@ -523,6 +540,12 @@ return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1, Types2); } + /// The instruction is legal when type index 0 along with the immediate 0 + /// match any given type and immediate tuple in the given list. + LegalizeRuleSet &legalForTypeWithImm( + std::initializer_list> TypeAndImm) { + return actionForTypeWithImm(LegalizeAction::Legal, TypeAndImm); + } LegalizeRuleSet &alwaysLegal() { using namespace LegalizeMutations; diff --git a/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp b/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp --- a/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp @@ -54,6 +54,17 @@ }; } +LegalityPredicate LegalityPredicates::typeAndImmInSet( + unsigned TypeIdx0, unsigned ImmIdx, + std::initializer_list> TypeAndImmInit) { + SmallVector, 4> TypeAndImm = TypeAndImmInit; + return [=](const LegalityQuery &Query) { + std::pair Match = {Query.Types[TypeIdx0], Query.Imms[ImmIdx]}; + return std::find(TypeAndImm.begin(), TypeAndImm.end(), Match) != + TypeAndImm.end(); + }; +} + LegalityPredicate LegalityPredicates::isScalar(unsigned TypeIdx) { return [=](const LegalityQuery &Query) { return Query.Types[TypeIdx].isScalar(); diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp --- a/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp @@ -86,14 +86,20 @@ for (const auto &Type : Types) { OS << Type << ", "; } - OS << "}, Opcode="; + OS << "}"; - OS << Opcode << ", MMOs={"; + OS << ", MMOs={"; for (const auto &MMODescr : MMODescrs) { OS << MMODescr.SizeInBits << ", "; } OS << "}"; + OS << ", Imms={"; + for (const auto &Imm : Imms) { + OS << Imm << ", "; + } + OS << "}"; + return OS; } @@ -476,10 +482,13 @@ LegalizerInfo::getAction(const MachineInstr &MI, const MachineRegisterInfo &MRI) const { SmallVector Types; + SmallVector Imms; SmallBitVector SeenTypes(8); const MCOperandInfo *OpInfo = MI.getDesc().OpInfo; // FIXME: probably we'll need to cache the results here somehow? for (unsigned i = 0; i < MI.getDesc().getNumOperands(); ++i) { + if (MI.getOperand(i).isImm()) + Imms.push_back(MI.getOperand(i).getImm()); if (!OpInfo[i].isGenericType()) continue; @@ -501,7 +510,7 @@ 8 * MMO->getAlignment(), MMO->getOrdering()}); - return getAction({MI.getOpcode(), Types, MemDescrs}); + return getAction({MI.getOpcode(), Types, MemDescrs, Imms}); } bool LegalizerInfo::isLegal(const MachineInstr &MI, diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp --- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -2051,15 +2051,19 @@ } case TargetOpcode::G_ZEXT: - case TargetOpcode::G_SEXT: { + case TargetOpcode::G_SEXT: + case TargetOpcode::G_SEXT_INREG: { unsigned Opcode = I.getOpcode(); - const bool IsSigned = Opcode == TargetOpcode::G_SEXT; + const bool IsSigned = + Opcode == TargetOpcode::G_SEXT || Opcode == TargetOpcode::G_SEXT_INREG; const Register DefReg = I.getOperand(0).getReg(); const Register SrcReg = I.getOperand(1).getReg(); const LLT DstTy = MRI.getType(DefReg); const LLT SrcTy = MRI.getType(SrcReg); unsigned DstSize = DstTy.getSizeInBits(); - unsigned SrcSize = SrcTy.getSizeInBits(); + unsigned SrcSize = Opcode == TargetOpcode::G_SEXT_INREG + ? I.getOperand(2).getImm() + : SrcTy.getSizeInBits(); assert((*RBI.getRegBank(DefReg, MRI, TRI)).getID() == AArch64::GPRRegBankID && @@ -2101,15 +2105,12 @@ .addUse(SrcReg) .addImm(AArch64::sub_32); - ExtI = MIB.buildInstr(IsSigned ? AArch64::SBFMXri : AArch64::UBFMXri, - {DefReg}, {SubregToReg}) - .addImm(0) - .addImm(SrcSize - 1); + ExtI = + MIB.buildInstr(IsSigned ? AArch64::SBFMXri : AArch64::UBFMXri, + {DefReg}, {SubregToReg, 0ull, uint64_t(SrcSize - 1)}); } else if (DstSize <= 32) { ExtI = MIB.buildInstr(IsSigned ? AArch64::SBFMWri : AArch64::UBFMWri, - {DefReg}, {SrcReg}) - .addImm(0) - .addImm(SrcSize - 1); + {DefReg}, {SrcReg, 0ull, uint64_t(SrcSize - 1)}); } else { return false; } diff --git a/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp @@ -370,7 +370,13 @@ getActionDefinitionsBuilder(G_TRUNC).alwaysLegal(); - getActionDefinitionsBuilder(G_SEXT_INREG).lower(); + getActionDefinitionsBuilder(G_SEXT_INREG) + // It happens that SBFM/UBFM can handle all possible extensions for each + // type so we don't need to check Query.Imm[0]. + .legalForTypeWithAnyImm({s32, s64}) + .clampScalar(0, s32, s64) + .widenScalarToNextPow2(0) + .lower(); // FP conversions getActionDefinitionsBuilder(G_FPTRUNC).legalFor( diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-div.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-div.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-div.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-div.mir @@ -8,25 +8,20 @@ ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 - ; CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[TRUNC]], [[C]](s32) - ; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 24 - ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY [[C1]](s64) - ; CHECK: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[COPY2]](s64) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC]], 8 ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) - ; CHECK: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[TRUNC1]], [[C]](s32) - ; CHECK: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]](s64) - ; CHECK: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[ASHR]], [[ASHR1]] - ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[SDIV]](s32) - ; CHECK: $w0 = COPY [[COPY3]](s32) + ; CHECK: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC1]], 8 + ; CHECK: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[SEXT_INREG]], [[SEXT_INREG1]] + ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY [[SDIV]](s32) + ; CHECK: $w0 = COPY [[COPY2]](s32) ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 ; CHECK: [[TRUNC2:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[TRUNC2]], [[C2]] ; CHECK: [[TRUNC3:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) ; CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[TRUNC3]], [[C2]] ; CHECK: [[UDIV:%[0-9]+]]:_(s32) = G_UDIV [[AND]], [[AND1]] - ; CHECK: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UDIV]](s32) - ; CHECK: $w0 = COPY [[COPY4]](s32) + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[UDIV]](s32) + ; CHECK: $w0 = COPY [[COPY3]](s32) %0:_(s64) = COPY $x0 %1:_(s64) = COPY $x1 %2:_(s8) = G_TRUNC %0(s64) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ext.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ext.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ext.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ext.mir @@ -23,36 +23,28 @@ ; CHECK: [[COPY3:%[0-9]+]]:_(s64) = COPY [[COPY]](s64) ; CHECK: $x0 = COPY [[COPY3]](s64) ; CHECK: [[COPY4:%[0-9]+]]:_(s64) = COPY [[COPY]](s64) - ; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 32 - ; CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[COPY4]], [[C1]](s64) - ; CHECK: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C1]](s64) - ; CHECK: $x0 = COPY [[ASHR]](s64) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[COPY4]], 32 + ; CHECK: $x0 = COPY [[SEXT_INREG]](s64) ; CHECK: [[TRUNC4:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 - ; CHECK: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[TRUNC4]], [[C2]](s32) - ; CHECK: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 31 - ; CHECK: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C3]](s64) - ; CHECK: $w0 = COPY [[ASHR1]](s32) - ; CHECK: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; CHECK: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC4]], 1 + ; CHECK: $w0 = COPY [[SEXT_INREG1]](s32) + ; CHECK: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 ; CHECK: [[TRUNC5:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[TRUNC5]], [[C4]] + ; CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[TRUNC5]], [[C3]] ; CHECK: $w0 = COPY [[AND1]](s32) ; CHECK: [[TRUNC6:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) ; CHECK: $w0 = COPY [[TRUNC6]](s32) - ; CHECK: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; CHECK: [[TRUNC7:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[TRUNC7]], [[C5]] + ; CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[TRUNC7]], [[C4]] ; CHECK: $w0 = COPY [[AND2]](s32) ; CHECK: [[TRUNC8:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) ; CHECK: $w0 = COPY [[TRUNC8]](s32) ; CHECK: [[TRUNC9:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 - ; CHECK: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[TRUNC9]], [[C6]](s32) - ; CHECK: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 16 - ; CHECK: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C7]](s64) - ; CHECK: $w0 = COPY [[ASHR2]](s32) + ; CHECK: [[SEXT_INREG2:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC9]], 16 + ; CHECK: $w0 = COPY [[SEXT_INREG2]](s32) ; CHECK: [[TRUNC10:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: [[AND3:%[0-9]+]]:_(s32) = G_AND [[TRUNC10]], [[C5]] + ; CHECK: [[AND3:%[0-9]+]]:_(s32) = G_AND [[TRUNC10]], [[C4]] ; CHECK: $w0 = COPY [[AND3]](s32) ; CHECK: [[TRUNC11:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) ; CHECK: $w0 = COPY [[TRUNC11]](s32) @@ -60,10 +52,8 @@ ; CHECK: $w0 = COPY [[TRUNC12]](s32) ; CHECK: [[FPEXT:%[0-9]+]]:_(s64) = G_FPEXT [[TRUNC12]](s32) ; CHECK: $x0 = COPY [[FPEXT]](s64) - ; CHECK: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 - ; CHECK: [[COPY5:%[0-9]+]]:_(s32) = COPY [[C8]](s32) - ; CHECK: $w0 = COPY [[COPY5]](s32) - ; CHECK: $w0 = COPY [[C8]](s32) + ; CHECK: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK: $w0 = COPY [[C7]](s32) ; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF ; CHECK: $w0 = COPY [[DEF]](s32) %0:_(s64) = COPY $x0 @@ -143,11 +133,8 @@ ; CHECK-LABEL: name: test_anyext_sext ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 - ; CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C]](s32) - ; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 31 - ; CHECK: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C1]](s64) - ; CHECK: $w0 = COPY [[ASHR]](s32) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY1]], 1 + ; CHECK: $w0 = COPY [[SEXT_INREG]](s32) %0:_(s32) = COPY $w0 %1:_(s1) = G_TRUNC %0(s32) %2:_(s8) = G_SEXT %1(s1) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-gep.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-gep.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-gep.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-gep.mir @@ -8,10 +8,8 @@ ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY [[COPY1]](s64) - ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 56 - ; CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[COPY2]], [[C]](s64) - ; CHECK: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C]](s64) - ; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY]], [[ASHR]](s64) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[COPY2]], 8 + ; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY]], [[SEXT_INREG]](s64) ; CHECK: $x0 = COPY [[GEP]](p0) %0:_(p0) = COPY $x0 %1:_(s64) = COPY $x1 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-itofp.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-itofp.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-itofp.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-itofp.mir @@ -149,11 +149,8 @@ ; CHECK-LABEL: name: test_sitofp_s32_s1 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 - ; CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C]](s32) - ; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 31 - ; CHECK: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C1]](s64) - ; CHECK: [[SITOFP:%[0-9]+]]:_(s32) = G_SITOFP [[ASHR]](s32) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY1]], 1 + ; CHECK: [[SITOFP:%[0-9]+]]:_(s32) = G_SITOFP [[SEXT_INREG]](s32) ; CHECK: $w0 = COPY [[SITOFP]](s32) %0:_(s32) = COPY $w0 %1:_(s1) = G_TRUNC %0 @@ -187,11 +184,8 @@ ; CHECK-LABEL: name: test_sitofp_s64_s8 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 - ; CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C]](s32) - ; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 24 - ; CHECK: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C1]](s64) - ; CHECK: [[SITOFP:%[0-9]+]]:_(s64) = G_SITOFP [[ASHR]](s32) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY1]], 8 + ; CHECK: [[SITOFP:%[0-9]+]]:_(s64) = G_SITOFP [[SEXT_INREG]](s32) ; CHECK: $x0 = COPY [[SITOFP]](s64) %0:_(s32) = COPY $w0 %1:_(s8) = G_TRUNC %0 @@ -253,11 +247,8 @@ ; CHECK-LABEL: name: test_sitofp_s32_s16 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 - ; CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C]](s32) - ; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 16 - ; CHECK: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C1]](s64) - ; CHECK: [[SITOFP:%[0-9]+]]:_(s32) = G_SITOFP [[ASHR]](s32) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY1]], 16 + ; CHECK: [[SITOFP:%[0-9]+]]:_(s32) = G_SITOFP [[SEXT_INREG]](s32) ; CHECK: $w0 = COPY [[SITOFP]](s32) %0:_(s32) = COPY $w0 %1:_(s16) = G_TRUNC %0 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir @@ -46,23 +46,18 @@ ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 - ; CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[TRUNC]], [[C]](s32) - ; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 24 - ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY [[C1]](s64) - ; CHECK: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[COPY2]](s64) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC]], 8 ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) - ; CHECK: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[TRUNC1]], [[C]](s32) - ; CHECK: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]](s64) - ; CHECK: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[ASHR]], [[ASHR1]] - ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[SDIV]](s32) + ; CHECK: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC1]], 8 + ; CHECK: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[SEXT_INREG]], [[SEXT_INREG1]] + ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY [[SDIV]](s32) ; CHECK: [[TRUNC2:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) - ; CHECK: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY3]], [[TRUNC2]] + ; CHECK: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY2]], [[TRUNC2]] ; CHECK: [[TRUNC3:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: [[COPY4:%[0-9]+]]:_(s32) = COPY [[MUL]](s32) - ; CHECK: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[TRUNC3]], [[COPY4]] - ; CHECK: [[COPY5:%[0-9]+]]:_(s32) = COPY [[SUB]](s32) - ; CHECK: $w0 = COPY [[COPY5]](s32) + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[MUL]](s32) + ; CHECK: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[TRUNC3]], [[COPY3]] + ; CHECK: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SUB]](s32) + ; CHECK: $w0 = COPY [[COPY4]](s32) %0:_(s64) = COPY $x0 %1:_(s64) = COPY $x1 %2:_(s8) = G_TRUNC %0(s64) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext.mir @@ -6,13 +6,22 @@ liveins: $w0, $w1 ; CHECK-LABEL: name: test_sext_inreg ; CHECK-DAG: [[COPY:%[0-9]+]]:_(s32) = COPY $w1 - ; CHECK-DAG: [[I25:%[0-9]+]]:_(s32) = G_CONSTANT i32 25 - ; CHECK-DAG: [[SEXT1:%[0-9]+]]:_(s32) = G_SHL [[COPY]], [[I25]] - ; This constant is coming from a custom legalization for G_ASHR rather than G_SEXT_INREG lowering - ; CHECK-DAG: [[I25_64:%[0-9]+]]:_(s64) = G_CONSTANT i64 25 - ; CHECK-DAG: [[SEXT2:%[0-9]+]]:_(s32) = G_ASHR [[SEXT1]], [[I25_64]] + ; CHECK-DAG: [[SEXT2:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY]], 7 ; CHECK-DAG: $w0 = COPY [[SEXT2]](s32) %0:_(s32) = COPY $w1 %2:_(s32) = G_SEXT_INREG %0(s32), 7 $w0 = COPY %2(s32) ... +--- +name: test_sext_inreg_16 +body: | + bb.0.entry: + liveins: $w0, $w1 + ; CHECK-LABEL: name: test_sext_inreg_16 + ; CHECK-DAG: [[COPY:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK-DAG: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY]], 16 + ; CHECK-DAG: $w0 = COPY [[SEXT]](s32) + %0:_(s32) = COPY $w1 + %2:_(s32) = G_SEXT_INREG %0(s32), 16 + $w0 = COPY %2(s32) +... diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shift.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shift.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shift.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shift.mir @@ -11,11 +11,8 @@ ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[TRUNC]], [[C]] ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 - ; CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[TRUNC1]], [[C1]](s32) - ; CHECK: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 24 - ; CHECK: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C2]](s64) - ; CHECK: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[ASHR]], [[AND]](s32) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC1]], 8 + ; CHECK: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SEXT_INREG]], [[AND]](s32) ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ASHR1]](s32) ; CHECK: $w0 = COPY [[COPY2]](s32) ; CHECK: [[TRUNC2:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-undef.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-undef.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-undef.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-undef.mir @@ -25,10 +25,8 @@ ; CHECK-LABEL: name: test_implicit_def_s3 ; CHECK: [[DEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF - ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 61 - ; CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[DEF]], [[C]](s64) - ; CHECK: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C]](s64) - ; CHECK: $x0 = COPY [[ASHR]](s64) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[DEF]], 3 + ; CHECK: $x0 = COPY [[SEXT_INREG]](s64) %0:_(s3) = G_IMPLICIT_DEF %1:_(s64) = G_SEXT %0 $x0 = COPY %1(s64) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-int-ext.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-int-ext.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-int-ext.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-int-ext.mir @@ -20,6 +20,8 @@ define void @sext_s64_from_s32() { ret void } define void @sext_s32_from_s16() { ret void } + define void @sext_s32_from_s16_inreg() { ret void } + define void @sext_s32_from_s3_inreg() { ret void } define void @sext_s32_from_s8() { ret void } define void @sext_s16_from_s8() { ret void } define void @sext_v8s16_from_v8s8() { ret void } @@ -370,6 +372,50 @@ $w0 = COPY %1 ... +--- +name: sext_s32_from_s16_inreg +legalized: true +regBankSelected: true + +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +body: | + bb.0: + liveins: $w0 + + ; CHECK-LABEL: name: sext_s32_from_s16_inreg + ; CHECK: [[COPY:%[0-9]+]]:gpr32 = COPY $w0 + ; CHECK: [[SBFMWri:%[0-9]+]]:gpr32 = SBFMWri [[COPY]], 0, 15 + ; CHECK: $w0 = COPY [[SBFMWri]] + %0:gpr(s32) = COPY $w0 + %1(s32) = G_SEXT_INREG %0, 16 + $w0 = COPY %1 +... + +--- +name: sext_s32_from_s3_inreg +legalized: true +regBankSelected: true + +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +body: | + bb.0: + liveins: $w0 + + ; CHECK-LABEL: name: sext_s32_from_s3_inreg + ; CHECK: [[COPY:%[0-9]+]]:gpr32 = COPY $w0 + ; CHECK: [[SBFMWri:%[0-9]+]]:gpr32 = SBFMWri [[COPY]], 0, 2 + ; CHECK: $w0 = COPY [[SBFMWri]] + %0:gpr(s32) = COPY $w0 + %1(s32) = G_SEXT_INREG %0, 3 + $w0 = COPY %1 +... + --- name: sext_s32_from_s8 legalized: true diff --git a/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp b/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp --- a/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp @@ -1122,9 +1122,14 @@ if (!TM) return; - // Declare your legalization info, these aren't actually relevant to the test. - DefineLegalizerInfo( - A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); }); + // Declare your legalization info, these aren't actually relevant to the + // helper test below. + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_SEXT_INREG) + .legalForTypeWithImm({{s64, 8}}) + .lower(); + }); + // Build Instr auto MIB = B.buildInstr( TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)}, @@ -1155,8 +1160,11 @@ return; // Declare your legalization info, these aren't actually relevant to the test. - DefineLegalizerInfo( - A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); }); + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_SEXT_INREG) + .legalForTypeWithImm({{s64, 8}}) + .lower(); + }); // Build Instr auto MIB = B.buildInstr( TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)}, @@ -1178,5 +1186,13 @@ // Check ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); + + LLT s64 = LLT::scalar(64); + ASSERT_TRUE( + Info.getAction({TargetOpcode::G_SEXT_INREG, {s64}, {}, {8}}).Action == + LegalizeAction::Legal); + ASSERT_TRUE( + Info.getAction({TargetOpcode::G_SEXT_INREG, {s64}, {}, {9}}).Action == + LegalizeAction::Lower); } } // namespace