Index: include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h =================================================================== --- include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -87,8 +87,8 @@ MI.getOperand(1).getReg(), MRI)) { unsigned DstReg = MI.getOperand(0).getReg(); LLT DstTy = MRI.getType(DstReg); - if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy}}) || - isInstUnsupported({TargetOpcode::G_ASHR, {DstTy}}) || + if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy, DstTy}}) || + isInstUnsupported({TargetOpcode::G_ASHR, {DstTy, DstTy}}) || isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) return false; DEBUG(dbgs() << ".. Combine MI: " << MI;); Index: include/llvm/Target/GenericOpcodes.td =================================================================== --- include/llvm/Target/GenericOpcodes.td +++ include/llvm/Target/GenericOpcodes.td @@ -213,21 +213,21 @@ // Generic left-shift. def G_SHL : GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); + let InOperandList = (ins type0:$src1, type1:$src2); let hasSideEffects = 0; } // Generic logical right-shift. def G_LSHR : GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); + let InOperandList = (ins type0:$src1, type1:$src2); let hasSideEffects = 0; } // Generic arithmetic right-shift. def G_ASHR : GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); + let InOperandList = (ins type0:$src1, type1:$src2); let hasSideEffects = 0; } Index: lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -631,11 +631,14 @@ return Legalized; case TargetOpcode::G_SHL: - widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); // The "number of bits to shift" operand must preserve its value as an // unsigned integer: - widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); - widenScalarDst(MI, WideTy); + if (TypeIdx == 1) + widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); + else { + widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); + widenScalarDst(MI, WideTy); + } MIRBuilder.recordInsertion(&MI); return Legalized; @@ -648,23 +651,35 @@ return Legalized; case TargetOpcode::G_ASHR: - widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT); // The "number of bits to shift" operand must preserve its value as an // unsigned integer: - widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); - widenScalarDst(MI, WideTy); + if (TypeIdx == 1) + widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); + else { + widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT); + widenScalarDst(MI, WideTy); + } MIRBuilder.recordInsertion(&MI); return Legalized; case TargetOpcode::G_UDIV: case TargetOpcode::G_UREM: - case TargetOpcode::G_LSHR: widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); widenScalarDst(MI, WideTy); MIRBuilder.recordInsertion(&MI); return Legalized; + case TargetOpcode::G_LSHR: + if (TypeIdx == 1) + widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); + else { + widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); + widenScalarDst(MI, WideTy); + } + MIRBuilder.recordInsertion(&MI); + return Legalized; + case TargetOpcode::G_SELECT: if (TypeIdx != 0) return UnableToLegalize; Index: lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- lib/Target/AArch64/AArch64InstrFormats.td +++ lib/Target/AArch64/AArch64InstrFormats.td @@ -1695,9 +1695,9 @@ let Inst{31} = 1; } - def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)), + def : Pat<(i32 (OpNode GPR32:$Rn, GPR64:$Rm)), (!cast(NAME # "Wr") GPR32:$Rn, - (EXTRACT_SUBREG i64:$Rm, sub_32))>; + (EXTRACT_SUBREG GPR64:$Rm, sub_32))>; def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))), (!cast(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>; @@ -1707,6 +1707,9 @@ def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))), (!cast(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>; + + def : Pat<(i32 (OpNode GPR32:$Rn, GPR32:$Rm)), + (!cast(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>; } class ShiftAlias Index: lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.td +++ lib/Target/AArch64/AArch64InstrInfo.td @@ -319,6 +319,9 @@ def AArch64smaxv : SDNode<"AArch64ISD::SMAXV", SDT_AArch64UnaryVec>; def AArch64umaxv : SDNode<"AArch64ISD::UMAXV", SDT_AArch64UnaryVec>; + +def : GINodeEquiv; + //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// Index: lib/Target/AArch64/AArch64InstructionSelector.cpp =================================================================== --- lib/Target/AArch64/AArch64InstructionSelector.cpp +++ lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -1084,15 +1084,19 @@ // operands to use appropriate classes. return constrainSelectedInstRegOperands(I, TII, TRI, RBI); } + case TargetOpcode::G_SHL: + llvm_unreachable("G_SHL is expected to be tablegen-selectable"); + case TargetOpcode::G_LSHR: + llvm_unreachable("G_LSHR is expected to be tablegen-selectable"); + case TargetOpcode::G_ASHR: + llvm_unreachable("G_ASHR is expected to be tablegen-selectable"); + case TargetOpcode::G_FADD: case TargetOpcode::G_FSUB: case TargetOpcode::G_FMUL: case TargetOpcode::G_FDIV: case TargetOpcode::G_OR: - case TargetOpcode::G_SHL: - case TargetOpcode::G_LSHR: - case TargetOpcode::G_ASHR: case TargetOpcode::G_GEP: { // Reject the various things we don't support yet. if (unsupportedBinOp(I, RBI, MRI, TRI)) Index: lib/Target/AArch64/AArch64LegalizerInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64LegalizerInfo.cpp +++ lib/Target/AArch64/AArch64LegalizerInfo.cpp @@ -24,6 +24,7 @@ using namespace llvm; using namespace LegalizeActions; +using namespace LegalizeMutations; using namespace LegalityPredicates; AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) { @@ -62,7 +63,7 @@ .clampScalar(0, s16, s64) .widenScalarToNextPow2(0); - getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SHL}) + getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) .legalFor({s32, s64, v2s32, v4s32, v2s64}) .clampScalar(0, s32, s64) .widenScalarToNextPow2(0) @@ -76,11 +77,27 @@ getActionDefinitionsBuilder(G_PTR_MASK).legalFor({p0}); - getActionDefinitionsBuilder({G_LSHR, G_ASHR, G_SDIV, G_UDIV}) + getActionDefinitionsBuilder({G_SDIV, G_UDIV}) .legalFor({s32, s64}) .clampScalar(0, s32, s64) .widenScalarToNextPow2(0); + getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR}) + .legalFor({{s32, s32}, {s32, s64}, {s64, s64}, {v4s32, s32}}) + .clampScalar(0, s32, s64) + .widenScalarToNextPow2(0) + .maxScalar(1, s64) + .widenScalarIf( + [s64](const LegalityQuery &Query) { + return Query.Types[0] != Query.Types[1] && Query.Types[1] != s64; + }, + [s64](const LegalityQuery &Query) { + return ((Query.Types[0].getSizeInBits() < + Query.Types[1].getSizeInBits()) + ? changeTo(1, s64) + : changeTo(1, 0))(Query); + }); + getActionDefinitionsBuilder({G_SREM, G_UREM}) .lowerFor({s1, s8, s16, s32, s64}); @@ -212,7 +229,8 @@ // Extensions getActionDefinitionsBuilder({G_ZEXT, G_SEXT, G_ANYEXT}) - .legalForCartesianProduct({s8, s16, s32, s64}, {s1, s8, s16, s32}); + .legalForCartesianProduct({s8, s16, s32, s64}, {s1, s8, s16, s32}) + .legalFor({{v4s32, v4s16}}); // FP conversions getActionDefinitionsBuilder(G_FPTRUNC).legalFor( Index: lib/Target/AArch64/AArch64RegisterBankInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64RegisterBankInfo.cpp +++ lib/Target/AArch64/AArch64RegisterBankInfo.cpp @@ -469,10 +469,6 @@ case TargetOpcode::G_AND: case TargetOpcode::G_OR: case TargetOpcode::G_XOR: - // Shifts. - case TargetOpcode::G_SHL: - case TargetOpcode::G_LSHR: - case TargetOpcode::G_ASHR: // Floating point ops. case TargetOpcode::G_FADD: case TargetOpcode::G_FSUB: Index: lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -134,6 +134,7 @@ setAction({G_SELECT, 1, S1}, Legal); setAction({G_SHL, S32}, Legal); + setAction({G_SHL, 1, S32}, Legal); // FIXME: When RegBankSelect inserts copies, it will only create new Index: lib/Target/ARM/ARMLegalizerInfo.cpp =================================================================== --- lib/Target/ARM/ARMLegalizerInfo.cpp +++ lib/Target/ARM/ARMLegalizerInfo.cpp @@ -107,7 +107,7 @@ getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s32}}); getActionDefinitionsBuilder(G_PTRTOINT).legalFor({{s32, p0}}); - getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL}).legalFor({s32}); + getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL}).legalFor({{s32, s32}}); getActionDefinitionsBuilder(G_GEP).legalFor({{p0, s32}}); Index: lib/Target/X86/X86LegalizerInfo.cpp =================================================================== --- lib/Target/X86/X86LegalizerInfo.cpp +++ lib/Target/X86/X86LegalizerInfo.cpp @@ -132,8 +132,14 @@ .widenScalarToNextPow2(0, /*Min*/ 8); getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s32}}); - // Shifts and SDIV - getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR, G_SDIV}) + // Shifts + getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR}) + .legalFor({{s8, s8}, {s16, s16}, {s32, s32}}) + .clampScalar(0, s8, s32) + .clampScalar(1, s8, s32); + + // SDIV + getActionDefinitionsBuilder(G_SDIV) .legalFor({s8, s16, s32}) .clampScalar(0, s8, s32); } @@ -215,8 +221,14 @@ // Comparison setAction({G_ICMP, 1, s64}, Legal); - // Shifts and SDIV - getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR, G_SDIV}) + // Shifts + getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR}) + .legalFor({{s8, s8}, {s16, s16}, {s32, s32}, {s64, s64}}) + .clampScalar(0, s8, s64) + .clampScalar(1, s8, s64); + + // SDIV + getActionDefinitionsBuilder(G_SDIV) .legalFor({s8, s16, s32, s64}) .clampScalar(0, s8, s64); Index: test/CodeGen/AArch64/GlobalISel/legalize-shift.mir =================================================================== --- test/CodeGen/AArch64/GlobalISel/legalize-shift.mir +++ test/CodeGen/AArch64/GlobalISel/legalize-shift.mir @@ -1,4 +1,3 @@ -# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -O0 -run-pass=legalizer %s -o - | FileCheck %s --- | @@ -8,6 +7,10 @@ entry: ret void } + define void @test_vector_shift() { + entry: + ret void + } ... --- @@ -20,53 +23,109 @@ - { id: 4, class: _ } - { id: 5, class: _ } - { id: 6, class: _ } + - { id: 7, class: _ } + - { id: 8, class: _ } + - { id: 9, class: _ } + - { id: 10, class: _ } + - { id: 11, class: _ } +tracksRegLiveness: true body: | bb.0.entry: - liveins: $x0, $x1, $x2, $x3 + liveins: $x0, $w1, $w2 + ; CHECK-LABEL: name: test_shift + ; CHECK-NOT: failedISel: true + ; CHECK: liveins: $x0, $w1, $w2 ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 - ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[TRUNC]], [[C]] - ; CHECK: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]] + ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2 + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY2]](s32) + ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; CHECK: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY1]], [[AND]](s32) + ; CHECK: $w1 = COPY [[ASHR]](s32) ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 - ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) - ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[TRUNC1]], [[C1]] - ; CHECK: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[ASHR]], [[AND]] - ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ASHR1]](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: [[AND1:%[0-9]+]]:_(s32) = G_AND [[TRUNC2]], [[C2]] + ; CHECK: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY2]](s32) + ; CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C1]] + ; CHECK: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND1]], [[COPY]](s64) + ; CHECK: [[COPY5:%[0-9]+]]:_(s32) = COPY [[LSHR]](s32) + ; CHECK: $w1 = COPY [[COPY5]](s32) + ; CHECK: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 255 + ; CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[COPY2]](s32) + ; CHECK: [[AND2:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C2]] + ; CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[COPY]], [[AND2]](s64) + ; CHECK: $x0 = COPY [[SHL]](s64) + ; CHECK: [[COPY6:%[0-9]+]]:_(s32) = COPY [[COPY2]](s32) + ; CHECK: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY6]], [[COPY1]](s32) + ; CHECK: [[COPY7:%[0-9]+]]:_(s32) = COPY [[SHL1]](s32) + ; CHECK: $w1 = COPY [[COPY7]](s32) + ; CHECK: [[COPY8:%[0-9]+]]:_(s32) = COPY [[COPY2]](s32) ; CHECK: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 - ; CHECK: [[TRUNC3:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) - ; CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[TRUNC3]], [[C3]] - ; CHECK: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND1]], [[AND2]] - ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[LSHR]](s32) - ; CHECK: $w0 = COPY [[COPY3]](s32) - ; CHECK: [[TRUNC4:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 - ; CHECK: [[TRUNC5:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) - ; CHECK: [[AND3:%[0-9]+]]:_(s32) = G_AND [[TRUNC5]], [[C4]] - ; CHECK: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[TRUNC4]], [[AND3]] - ; CHECK: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SHL1]](s32) - ; CHECK: $w0 = COPY [[COPY4]](s32) + ; CHECK: [[COPY9:%[0-9]+]]:_(s32) = COPY [[COPY2]](s32) + ; CHECK: [[AND3:%[0-9]+]]:_(s32) = G_AND [[COPY9]], [[C3]] + ; CHECK: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[COPY8]], [[AND3]](s32) + ; CHECK: [[COPY10:%[0-9]+]]:_(s32) = COPY [[SHL2]](s32) + ; CHECK: $w1 = COPY [[COPY10]](s32) %0(s64) = COPY $x0 - %1(s64) = COPY $x1 - %2(s8) = G_TRUNC %0 - %3(s8) = G_TRUNC %1 + %1(s32) = COPY $w1 + %2(s32) = COPY $w2 + %3(s8) = G_TRUNC %2 + + %4(s32) = G_ASHR %1, %3(s8) + $w1 = COPY %4 + + %5(s8) = G_LSHR %3, %0(s64) + %6(s32) = G_ANYEXT %5 + $w1 = COPY %6 - %4(s8) = G_ASHR %2, %3 - %7:_(s32) = G_ANYEXT %4 - $w0 = COPY %7 + %7(s64) = G_SHL %0, %3(s8) + $x0 = COPY %7 + + %8(s8) = G_SHL %3, %1(s32) + %9(s32) = G_ANYEXT %8 + $w1 = COPY %9 + + %10(s8) = G_SHL %3, %3(s8) + %11(s32) = G_ANYEXT %10 + $w1 = COPY %11 +... + +--- +name: test_vector_shift +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } + - { id: 3, class: _ } + - { id: 4, class: _ } + - { id: 5, class: _ } + - { id: 6, class: _ } +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $q0, $d0 + ; CHECK-LABEL: name: test_vector_shift + ; CHECK-NOT: failedISel: true + ; CHECK: liveins: $q0, $d0 + ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0 + ; CHECK: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $d0 + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK: [[SHL:%[0-9]+]]:_(<4 x s32>) = G_SHL [[COPY]], [[C]](s32) + ; CHECK: $q1 = COPY [[SHL]](<4 x s32>) + ; CHECK: [[SEXT:%[0-9]+]]:_(<4 x s32>) = G_SEXT [[COPY1]](<4 x s16>) + ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; CHECK: [[SHL1:%[0-9]+]]:_(<4 x s32>) = G_SHL [[SEXT]], [[C1]](s32) + ; CHECK: $q2 = COPY [[SHL1]](<4 x s32>) + %0(<4 x s32>) = COPY $q0 + %5(<4 x s16>) = COPY $d0 - %5(s8) = G_LSHR %2, %3 - %8:_(s32) = G_ANYEXT %5 - $w0 = COPY %8 + %1(s32) = G_CONSTANT i32 3 + %2(<4 x s32>) = G_SHL %0, %1(s32) + $q1 = COPY %2 - %6(s8) = G_SHL %2, %3 - %9:_(s32) = G_ANYEXT %6 - $w0 = COPY %9 + %6(<4 x s32>) = G_SEXT %5(<4 x s16>) + %3(s32) = G_CONSTANT i32 16 + %4(<4 x s32>) = G_SHL %6, %3(s32) + $q2 = COPY %4 ... Index: test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir =================================================================== --- test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -165,14 +165,14 @@ # DEBUG-NEXT: G_ZEXT (opcode {{[0-9]+}}): 2 type indices # DEBUG: .. the first uncovered type index: 2, OK # -# DEBUG-NEXT: G_SHL (opcode {{[0-9]+}}): 1 type index -# DEBUG: .. the first uncovered type index: 1, OK +# DEBUG-NEXT: G_SHL (opcode {{[0-9]+}}): 2 type indices +# DEBUG: .. type index coverage check SKIPPED: user-defined predicate detected # -# DEBUG-NEXT: G_LSHR (opcode {{[0-9]+}}): 1 type index -# DEBUG: .. the first uncovered type index: 1, OK +# DEBUG-NEXT: G_LSHR (opcode {{[0-9]+}}): 2 type indices +# DEBUG: .. type index coverage check SKIPPED: user-defined predicate detected # -# DEBUG-NEXT: G_ASHR (opcode {{[0-9]+}}): 1 type index -# DEBUG: .. the first uncovered type index: 1, OK +# DEBUG-NEXT: G_ASHR (opcode {{[0-9]+}}): 2 type indices +# DEBUG: .. type index coverage check SKIPPED: user-defined predicate detected # # DEBUG-NEXT: G_ICMP (opcode {{[0-9]+}}): 2 type indices # DEBUG: .. the first uncovered type index: 2, OK Index: test/CodeGen/AArch64/GlobalISel/regbankselect-default.mir =================================================================== --- test/CodeGen/AArch64/GlobalISel/regbankselect-default.mir +++ test/CodeGen/AArch64/GlobalISel/regbankselect-default.mir @@ -1,5 +1,5 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -O0 -mtriple arm64-- -run-pass=regbankselect %s -o - | FileCheck %s +# RUN: llc -O0 -mtriple arm64-- -run-pass=regbankselect -disable-gisel-legality-check %s -o - | FileCheck %s # Check the default mappings for various instructions. Index: test/CodeGen/AArch64/GlobalISel/regbankselect-shift.mir =================================================================== --- /dev/null +++ test/CodeGen/AArch64/GlobalISel/regbankselect-shift.mir @@ -0,0 +1,113 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -run-pass=regbankselect %s -o - | FileCheck %s +--- | + target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_shift() { + entry: + ret void + } + define void @test_vector_shift() { + entry: + ret void + } +... + +--- +name: test_shift +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x0, $w1, $w2 + + ; CHECK-LABEL: name: test_shift + ; CHECK-NOT: failedISel: true + ; CHECK: liveins: $x0, $w1, $w2 + ; CHECK: [[COPY:%[0-9]+]]:gpr(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:gpr(s32) = COPY $w1 + ; CHECK: [[COPY2:%[0-9]+]]:gpr(s32) = COPY $w2 + ; CHECK: [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 255 + ; CHECK: [[AND:%[0-9]+]]:gpr(s32) = G_AND [[COPY2]], [[C]] + ; CHECK: [[ASHR:%[0-9]+]]:gpr(s32) = G_ASHR [[COPY1]], [[AND]](s32) + ; CHECK: $w1 = COPY [[ASHR]](s32) + ; CHECK: [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 255 + ; CHECK: [[AND1:%[0-9]+]]:gpr(s32) = G_AND [[COPY2]], [[C1]] + ; CHECK: [[LSHR:%[0-9]+]]:gpr(s32) = G_LSHR [[AND1]], [[COPY]](s64) + ; CHECK: $w1 = COPY [[LSHR]](s32) + ; CHECK: [[C2:%[0-9]+]]:gpr(s64) = G_CONSTANT i64 255 + ; CHECK: [[ANYEXT:%[0-9]+]]:gpr(s64) = G_ANYEXT [[COPY2]](s32) + ; CHECK: [[AND2:%[0-9]+]]:gpr(s64) = G_AND [[ANYEXT]], [[C2]] + ; CHECK: [[SHL:%[0-9]+]]:gpr(s64) = G_SHL [[COPY]], [[AND2]](s64) + ; CHECK: $x0 = COPY [[SHL]](s64) + ; CHECK: [[COPY3:%[0-9]+]]:gpr(s32) = COPY [[COPY2]](s32) + ; CHECK: [[SHL1:%[0-9]+]]:gpr(s32) = G_SHL [[COPY3]], [[COPY1]](s32) + ; CHECK: $w1 = COPY [[SHL1]](s32) + ; CHECK: [[C3:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 255 + ; CHECK: [[COPY4:%[0-9]+]]:gpr(s32) = COPY [[COPY2]](s32) + ; CHECK: [[AND3:%[0-9]+]]:gpr(s32) = G_AND [[COPY4]], [[C3]] + ; CHECK: [[SHL2:%[0-9]+]]:gpr(s32) = G_SHL [[COPY2]], [[AND3]](s32) + ; CHECK: $w1 = COPY [[SHL2]](s32) + %0:_(s64) = COPY $x0 + %1:_(s32) = COPY $w1 + %2:_(s32) = COPY $w2 + + %21:_(s32) = G_CONSTANT i32 255 + %20:_(s32) = G_AND %2, %21 + %4:_(s32) = G_ASHR %1, %20(s32) + $w1 = COPY %4(s32) + + %23:_(s32) = G_CONSTANT i32 255 + %18:_(s32) = G_AND %2, %23 + %19:_(s32) = G_LSHR %18, %0(s64) + $w1 = COPY %19(s32) + + %25:_(s64) = G_CONSTANT i64 255 + %24:_(s64) = G_ANYEXT %2(s32) + %17:_(s64) = G_AND %24, %25 + %7:_(s64) = G_SHL %0, %17(s64) + $x0 = COPY %7(s64) + + %15:_(s32) = COPY %2(s32) + %16:_(s32) = G_SHL %15, %1(s32) + $w1 = COPY %16(s32) + + %27:_(s32) = G_CONSTANT i32 255 + %28:_(s32) = COPY %2(s32) + %14:_(s32) = G_AND %28, %27 + %13:_(s32) = G_SHL %2, %14(s32) + $w1 = COPY %13(s32) +... + +--- +name: test_vector_shift +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $q0, $d0 + + ; CHECK-LABEL: name: test_vector_shift + ; CHECK-NOT: failedISel: true + ; CHECK: liveins: $q0, $d0 + ; CHECK: [[COPY:%[0-9]+]]:fpr(<4 x s32>) = COPY $q0 + ; CHECK: [[COPY1:%[0-9]+]]:fpr(<4 x s16>) = COPY $d0 + ; CHECK: [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 3 + ; CHECK: [[SHL:%[0-9]+]]:fpr(<4 x s32>) = G_SHL [[COPY]], [[C]](s32) + ; CHECK: $q1 = COPY [[SHL]](<4 x s32>) + ; CHECK: [[SEXT:%[0-9]+]]:fpr(<4 x s32>) = G_SEXT [[COPY1]](<4 x s16>) + ; CHECK: [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 16 + ; CHECK: [[SHL1:%[0-9]+]]:fpr(<4 x s32>) = G_SHL [[SEXT]], [[C1]](s32) + ; CHECK: $q2 = COPY [[SHL1]](<4 x s32>) + %0:_(<4 x s32>) = COPY $q0 + %5:_(<4 x s16>) = COPY $d0 + + %1:_(s32) = G_CONSTANT i32 3 + %2:_(<4 x s32>) = G_SHL %0, %1(s32) + $q1 = COPY %2(<4 x s32>) + + %6:_(<4 x s32>) = G_SEXT %5(<4 x s16>) + %3:_(s32) = G_CONSTANT i32 16 + %4:_(<4 x s32>) = G_SHL %6, %3(s32) + $q2 = COPY %4(<4 x s32>) +... Index: test/CodeGen/AArch64/GlobalISel/select-shift.mir =================================================================== --- /dev/null +++ test/CodeGen/AArch64/GlobalISel/select-shift.mir @@ -0,0 +1,118 @@ +# RUN: llc -O0 -run-pass=instruction-select %s -o - | FileCheck %s +# RUN: llc -O0 -start-before=instruction-select %s -o - | FileCheck %s --check-prefix=ASM + +--- | + target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_shift() { + entry: + ret void + } + define void @test_vector_shift() { + entry: + ret void + } +... + +--- +name: test_shift +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x0, $w1, $w2 + + ; CHECK-LABEL: name: test_shift + ; CHECK-NOT: failedISel: true + ; CHECK: liveins: $x0, $w1, $w2 + ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY $w1 + ; CHECK: [[COPY2:%[0-9]+]]:gpr32 = COPY $w2 + ; CHECK: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 255 + ; CHECK: [[ANDWrr:%[0-9]+]]:gpr32 = ANDWrr [[COPY2]], [[MOVi32imm]] + ; CHECK: [[ASRVWr:%[0-9]+]]:gpr32 = ASRVWr [[COPY1]], [[ANDWrr]] + ; CHECK: $w1 = COPY [[ASRVWr]] + ; CHECK: [[MOVi32imm1:%[0-9]+]]:gpr32 = MOVi32imm 255 + ; CHECK: [[ANDWrr1:%[0-9]+]]:gpr32 = ANDWrr [[COPY2]], [[MOVi32imm1]] + ; CHECK: [[COPY3:%[0-9]+]]:gpr32 = COPY [[COPY]].sub_32 + ; CHECK: [[LSRVWr:%[0-9]+]]:gpr32 = LSRVWr [[ANDWrr1]], [[COPY3]] + ; CHECK: $w1 = COPY [[LSRVWr]] + ; CHECK: [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm 255 + ; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gpr64all = SUBREG_TO_REG 0, [[COPY2]], %subreg.sub_32 + ; CHECK: [[COPY4:%[0-9]+]]:gpr64 = COPY [[SUBREG_TO_REG]] + ; CHECK: [[ANDXrr:%[0-9]+]]:gpr64 = ANDXrr [[COPY4]], [[MOVi64imm]] + ; CHECK: [[LSLVXr:%[0-9]+]]:gpr64 = LSLVXr [[COPY]], [[ANDXrr]] + ; CHECK: $x0 = COPY [[LSLVXr]] + ; CHECK: [[LSLVWr:%[0-9]+]]:gpr32 = LSLVWr [[COPY2]], [[COPY1]] + ; CHECK: $w1 = COPY [[LSLVWr]] + ; CHECK: [[MOVi32imm2:%[0-9]+]]:gpr32 = MOVi32imm 255 + ; CHECK: [[ANDWrr2:%[0-9]+]]:gpr32 = ANDWrr [[COPY2]], [[MOVi32imm2]] + ; CHECK: [[LSLVWr1:%[0-9]+]]:gpr32 = LSLVWr [[COPY2]], [[ANDWrr2]] + ; CHECK: $w1 = COPY [[LSLVWr1]] + %0:gpr(s64) = COPY $x0 + %1:gpr(s32) = COPY $w1 + %2:gpr(s32) = COPY $w2 + + %3:gpr(s32) = G_CONSTANT i32 255 + %4:gpr(s32) = G_AND %2, %3 + %5:gpr(s32) = G_ASHR %1, %4(s32) + $w1 = COPY %5(s32) + + %6:gpr(s32) = G_CONSTANT i32 255 + %7:gpr(s32) = G_AND %2, %6 + %8:gpr(s32) = G_LSHR %7, %0(s64) + $w1 = COPY %8(s32) + + %9:gpr(s64) = G_CONSTANT i64 255 + %10:gpr(s64) = G_ANYEXT %2(s32) + %11:gpr(s64) = G_AND %10, %9 + %12:gpr(s64) = G_SHL %0, %11(s64) + $x0 = COPY %12(s64) + + %13:gpr(s32) = COPY %2(s32) + %14:gpr(s32) = G_SHL %13, %1(s32) + $w1 = COPY %14(s32) + + %15:gpr(s32) = G_CONSTANT i32 255 + %16:gpr(s32) = COPY %2(s32) + %17:gpr(s32) = G_AND %16, %15 + %18:gpr(s32) = G_SHL %2, %17(s32) + $w1 = COPY %18(s32) +... + +--- +name: test_vector_shift +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $q0, $d6 + + ; CHECK-LABEL: name: test_vector_shift + ; CHECK-NOT: failedISel: true + ; CHECK: liveins: $q0, $d6 + ; CHECK: [[COPY:%[0-9]+]]:fpr128 = COPY $q0 + ; CHECK: [[COPY1:%[0-9]+]]:fpr64 = COPY $d6 + ; CHECK: [[SHLv4i32_shift:%[0-9]+]]:fpr128 = SHLv4i32_shift [[COPY]], 3 + ; CHECK: $q1 = COPY [[SHLv4i32_shift]] + ; CHECK: [[SHLLv4i16_:%[0-9]+]]:fpr128 = SHLLv4i16 [[COPY1]] + ; CHECK: $q2 = COPY [[SHLLv4i16_]] + + ; ASM-LABEL: test_vector_shift: + ; ASM: shl v1.4s, v0.4s, #3 + ; ASM-NEXT: shll v2.4s, v6.4h, #16 + + %0:fpr(<4 x s32>) = COPY $q0 + %1:fpr(<4 x s16>) = COPY $d6 + + %2:gpr(s32) = G_CONSTANT i32 3 + %3:fpr(<4 x s32>) = G_SHL %0, %2(s32) + $q1 = COPY %3(<4 x s32>) + + %4:fpr(<4 x s32>) = G_SEXT %1(<4 x s16>) + %5:gpr(s32) = G_CONSTANT i32 16 + %6:fpr(<4 x s32>) = G_SHL %4, %5(s32) + $q2 = COPY %6(<4 x s32>) +...