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 @@ -108,10 +108,13 @@ unsigned 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); + if (isInstUnsupported({TargetOpcode::G_SEXT_INREG, + {DstTy}, + {}, + {SrcTy.getScalarSizeInBits()}})) return false; LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); - LLT SrcTy = MRI.getType(SrcReg); unsigned SizeInBits = SrcTy.getScalarSizeInBits(); Builder.buildInstr( TargetOpcode::G_SEXT_INREG, {DstReg}, 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. @@ -494,6 +503,14 @@ 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 actionIf(LegalizeAction::Legal, + LegalityPredicates::typeAndImmInSet( + typeIdx(0), /*ImmIdx*/ 0, 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; } @@ -455,10 +461,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; @@ -480,7 +489,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 @@ -1616,15 +1616,21 @@ } case TargetOpcode::G_ZEXT: - case TargetOpcode::G_SEXT: { + case TargetOpcode::G_SEXT: + case TargetOpcode::G_SEXT_INREG: { unsigned Opcode = I.getOpcode(); - const LLT DstTy = MRI.getType(I.getOperand(0).getReg()), - SrcTy = MRI.getType(I.getOperand(1).getReg()); - const bool isSigned = Opcode == TargetOpcode::G_SEXT; + const LLT DstTy = MRI.getType(I.getOperand(0).getReg()); + const bool isSigned = + Opcode == TargetOpcode::G_SEXT || Opcode == TargetOpcode::G_SEXT_INREG; const unsigned DefReg = I.getOperand(0).getReg(); const unsigned SrcReg = I.getOperand(1).getReg(); const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI); + unsigned SrcSizeInBits = + Opcode == TargetOpcode::G_SEXT_INREG + ? I.getOperand(2).getImm() + : MRI.getType(I.getOperand(1).getReg()).getSizeInBits(); + if (RB.getID() != AArch64::GPRRegBankID) { LLVM_DEBUG(dbgs() << TII.getName(I.getOpcode()) << " on bank: " << RB << ", expected: GPR\n"); @@ -1653,14 +1659,14 @@ .addDef(DefReg) .addUse(SrcXReg) .addImm(0) - .addImm(SrcTy.getSizeInBits() - 1); + .addImm(SrcSizeInBits - 1); } else if (DstTy.isScalar() && DstTy.getSizeInBits() <= 32) { const unsigned NewOpc = isSigned ? AArch64::SBFMWri : AArch64::UBFMWri; ExtI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc)) .addDef(DefReg) .addUse(SrcReg) .addImm(0) - .addImm(SrcTy.getSizeInBits() - 1); + .addImm(SrcSizeInBits - 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 @@ -347,7 +347,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]. + .legalFor({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 @@ -7,14 +7,11 @@ ; CHECK-LABEL: name: test_div ; CHECK-DAG: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 ; CHECK-DAG: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 - ; CHECK-DAG: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 ; CHECK-DAG: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK-DAG: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[TRUNC]], [[C]](s32) - ; CHECK-DAG: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) + ; CHECK-DAG: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC]], 8 ; CHECK-DAG: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) - ; CHECK-DAG: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[TRUNC1]], [[C]](s32) - ; CHECK-DAG: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) - ; CHECK-DAG: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[ASHR]], [[ASHR1]] + ; CHECK-DAG: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC1]], 8 + ; CHECK-DAG: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[SEXT_INREG]], [[SEXT_INREG1]] ; CHECK-DAG: [[COPY2:%[0-9]+]]:_(s32) = COPY [[SDIV]](s32) ; CHECK-DAG: $w0 = COPY [[COPY2]](s32) ; CHECK-DAG: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 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 @@ -22,16 +22,12 @@ ; CHECK-DAG: $x0 = COPY [[AND]](s64) ; CHECK-DAG: [[COPY3:%[0-9]+]]:_(s64) = COPY [[COPY]](s64) ; CHECK-DAG: $x0 = COPY [[COPY3]](s64) - ; CHECK-DAG: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 32 ; CHECK-DAG: [[COPY4:%[0-9]+]]:_(s64) = COPY [[COPY]](s64) - ; CHECK-DAG: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[COPY4]], [[C1]] - ; CHECK-DAG: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C1]] - ; CHECK-DAG: $x0 = COPY [[ASHR]](s64) - ; CHECK-DAG: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 + ; CHECK-DAG: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[COPY4]], 32 + ; CHECK-DAG: $x0 = COPY [[SEXT_INREG]](s64) ; CHECK-DAG: [[TRUNC4:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK-DAG: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[TRUNC4]], [[C2]] - ; CHECK-DAG: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C2]] - ; CHECK-DAG: $w0 = COPY [[ASHR1]](s32) + ; CHECK-DAG: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC4]], 1 + ; CHECK-DAG: $w0 = COPY [[SEXT_INREG1]](s32) ; CHECK-DAG: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 ; CHECK-DAG: [[TRUNC5:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) ; CHECK-DAG: [[AND1:%[0-9]+]]:_(s32) = G_AND [[TRUNC5]], [[C3]] @@ -44,11 +40,9 @@ ; CHECK-DAG: $w0 = COPY [[AND2]](s32) ; CHECK-DAG: [[TRUNC8:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) ; CHECK-DAG: $w0 = COPY [[TRUNC8]](s32) - ; CHECK-DAG: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 ; CHECK-DAG: [[TRUNC9:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK-DAG: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[TRUNC9]], [[C5]] - ; CHECK-DAG: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C5]] - ; CHECK-DAG: $w0 = COPY [[ASHR2]](s32) + ; CHECK-DAG: [[SEXT_INREG2:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC9]], 16 + ; CHECK-DAG: $w0 = COPY [[SEXT_INREG2]](s32) ; CHECK-DAG: [[TRUNC10:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) ; CHECK-DAG: [[AND3:%[0-9]+]]:_(s32) = G_AND [[TRUNC10]], [[C4]] ; CHECK-DAG: $w0 = COPY [[AND3]](s32) @@ -138,11 +132,9 @@ ; CHECK-LABEL: name: test_anyext_sext ; CHECK-DAG: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 - ; CHECK-DAG: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 ; CHECK-DAG: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) - ; CHECK-DAG: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C]] - ; CHECK-DAG: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]] - ; CHECK-DAG: $w0 = COPY [[ASHR]](s32) + ; CHECK-DAG: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY1]], 1 + ; CHECK-DAG: $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 @@ -7,11 +7,9 @@ ; CHECK-LABEL: name: test_gep_small ; CHECK-DAG: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 ; CHECK-DAG: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 - ; CHECK-DAG: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 56 ; CHECK-DAG: [[COPY2:%[0-9]+]]:_(s64) = COPY [[COPY1]](s64) - ; CHECK-DAG: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[COPY2]], [[C]] - ; CHECK-DAG: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C]] - ; CHECK-DAG: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY]], [[ASHR]](s64) + ; CHECK-DAG: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[COPY2]], 8 + ; CHECK-DAG: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY]], [[SEXT_INREG]](s64) ; CHECK-DAG: $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 @@ -148,11 +148,9 @@ liveins: $w0 ; CHECK-LABEL: name: test_sitofp_s32_s1 ; CHECK-DAG: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 - ; CHECK-DAG: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 ; CHECK-DAG: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) - ; CHECK-DAG: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C]](s32) - ; CHECK-DAG: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) - ; CHECK-DAG: [[SITOFP:%[0-9]+]]:_(s32) = G_SITOFP [[ASHR]](s32) + ; CHECK-DAG: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY1]], 1 + ; CHECK-DAG: [[SITOFP:%[0-9]+]]:_(s32) = G_SITOFP [[SEXT_INREG]](s32) ; CHECK-DAG: $w0 = COPY [[SITOFP]](s32) %0:_(s32) = COPY $w0 %1:_(s1) = G_TRUNC %0 @@ -185,11 +183,9 @@ liveins: $w0 ; CHECK-LABEL: name: test_sitofp_s64_s8 ; CHECK-DAG: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 - ; CHECK-DAG: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 ; CHECK-DAG: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) - ; CHECK-DAG: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C]](s32) - ; CHECK-DAG: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) - ; CHECK-DAG: [[SITOFP:%[0-9]+]]:_(s64) = G_SITOFP [[ASHR]](s32) + ; CHECK-DAG: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY1]], 8 + ; CHECK-DAG: [[SITOFP:%[0-9]+]]:_(s64) = G_SITOFP [[SEXT_INREG]](s32) ; CHECK-DAG: $x0 = COPY [[SITOFP]](s64) %0:_(s32) = COPY $w0 %1:_(s8) = G_TRUNC %0 @@ -250,11 +246,9 @@ liveins: $w0 ; CHECK-LABEL: name: test_sitofp_s32_s16 ; CHECK-DAG: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 - ; CHECK-DAG: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 ; CHECK-DAG: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) - ; CHECK-DAG: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C]](s32) - ; CHECK-DAG: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) - ; CHECK-DAG: [[SITOFP:%[0-9]+]]:_(s32) = G_SITOFP [[ASHR]](s32) + ; CHECK-DAG: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY1]], 16 + ; CHECK-DAG: [[SITOFP:%[0-9]+]]:_(s32) = G_SITOFP [[SEXT_INREG]](s32) ; CHECK-DAG: $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 @@ -45,14 +45,11 @@ ; CHECK-LABEL: name: test_srem_8 ; CHECK-DAG: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 ; CHECK-DAG: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 - ; CHECK-DAG: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 ; CHECK-DAG: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK-DAG: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[TRUNC]], [[C]] - ; CHECK-DAG: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]] + ; CHECK-DAG: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC]], 8 ; CHECK-DAG: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) - ; CHECK-DAG: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[TRUNC1]], [[C]] - ; CHECK-DAG: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]] - ; CHECK-DAG: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[ASHR]], [[ASHR1]] + ; CHECK-DAG: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC1]], 8 + ; CHECK-DAG: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[SEXT_INREG]], [[SEXT_INREG1]] ; CHECK-DAG: [[COPY2:%[0-9]+]]:_(s32) = COPY [[SDIV]](s32) ; CHECK-DAG: [[TRUNC2:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) ; CHECK-DAG: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY2]], [[TRUNC2]] 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,11 +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]] - ; CHECK-DAG: [[SEXT2:%[0-9]+]]:_(s32) = G_ASHR [[SEXT1]], [[I25]] + ; 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 @@ -10,11 +10,9 @@ ; CHECK-DAG: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 ; CHECK-DAG: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) ; CHECK-DAG: [[AND:%[0-9]+]]:_(s32) = G_AND [[TRUNC]], [[C]] - ; CHECK-DAG: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 ; CHECK-DAG: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK-DAG: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[TRUNC1]], [[C1]](s32) - ; CHECK-DAG: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C1]](s32) - ; CHECK-DAG: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[ASHR]], [[AND]](s32) + ; CHECK-DAG: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC1]], 8 + ; CHECK-DAG: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SEXT_INREG]], [[AND]](s32) ; CHECK-DAG: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ASHR1]](s32) ; CHECK-DAG: $w0 = COPY [[COPY2]](s32) ; CHECK-DAG: [[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 @@ -24,11 +24,9 @@ liveins: ; CHECK-LABEL: name: test_implicit_def_s3 - ; CHECK-DAG: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 61 ; CHECK-DAG: [[DEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF - ; CHECK-DAG: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[DEF]], [[C]](s64) - ; CHECK-DAG: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C]](s64) - ; CHECK-DAG: $x0 = COPY [[ASHR]](s64) + ; CHECK-DAG: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[DEF]], 3 + ; CHECK-DAG: $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/test/CodeGen/AArch64/arm64-fastisel-gep-promote-before-add.ll b/llvm/test/CodeGen/AArch64/arm64-fastisel-gep-promote-before-add.ll --- a/llvm/test/CodeGen/AArch64/arm64-fastisel-gep-promote-before-add.ll +++ b/llvm/test/CodeGen/AArch64/arm64-fastisel-gep-promote-before-add.ll @@ -1,5 +1,6 @@ ; fastisel should not fold add with non-pointer bitwidth ; sext(a) + sext(b) != sext(a + b) +; FIXME: This test isn't fastisel anymore. It's GlobalISel ; RUN: llc -mtriple=arm64-apple-darwin %s -O0 -o - | FileCheck %s define zeroext i8 @gep_promotion(i8* %ptr) nounwind uwtable ssp { @@ -9,7 +10,7 @@ %0 = load i8*, i8** %ptr.addr, align 8 ; CHECK-LABEL: _gep_promotion: - ; CHECK: ldrb {{[a-z][0-9]+}}, {{\[[a-z][0-9]+\]}} + ; CHECK: ldurb {{[a-z][0-9]+}}, [{{[a-z][0-9]+}}, #-128] %arrayidx = getelementptr inbounds i8, i8* %0, i8 %add %1 = load i8, i8* %arrayidx, align 1 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 @@ -796,9 +796,14 @@ if (!TM) return; - // Declare your legalization info, these aren't actually relevant to the test. - DefineLegalizerInfo( - A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalFor({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)}, @@ -830,8 +835,11 @@ return; // Declare your legalization info, these aren't actually relevant to the test. - DefineLegalizerInfo( - A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalFor({s64}); }); + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_SEXT_INREG) + .legalForTypeWithImm({{s64, 8}}) + .lower(); + }); // Build Instr auto MIB = B.buildInstr( TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)}, @@ -854,5 +862,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