diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -615,6 +615,24 @@ MI.eraseFromParent(); return Legalized; } + case TargetOpcode::G_ZEXT: { + if (TypeIdx != 0) + return UnableToLegalize; + + if (SizeOp0 % NarrowTy.getSizeInBits() != 0) + return UnableToLegalize; + + // Generate a merge where the bottom bits are taken from the source, and + // zero everything else. + Register ZeroReg = MIRBuilder.buildConstant(NarrowTy, 0).getReg(0); + unsigned NumParts = SizeOp0 / NarrowTy.getSizeInBits(); + SmallVector Srcs = {MI.getOperand(1).getReg()}; + for (unsigned Part = 1; Part < NumParts; ++Part) + Srcs.push_back(ZeroReg); + MIRBuilder.buildMerge(MI.getOperand(0).getReg(), Srcs); + MI.eraseFromParent(); + return Legalized; + } case TargetOpcode::G_ADD: { // FIXME: add support for when SizeOp0 isn't an exact multiple of 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 @@ -341,7 +341,7 @@ unsigned DstSize = Query.Types[0].getSizeInBits(); if (DstSize == 128 && !Query.Types[0].isVector()) - return false; // Extending to a scalar s128 is not legal. + return false; // Extending to a scalar s128 needs narrowing. // Make sure that we have something that will fit in a register, and // make sure it's a power of 2. @@ -363,8 +363,7 @@ return true; }; - getActionDefinitionsBuilder({G_ZEXT, G_ANYEXT}).legalIf(ExtLegalFunc); - getActionDefinitionsBuilder(G_SEXT) + getActionDefinitionsBuilder({G_ZEXT, G_SEXT, G_ANYEXT}) .legalIf(ExtLegalFunc) .clampScalar(0, s64, s64); // Just for s128, others are handled above. diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext-128.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext-128.mir deleted file mode 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext-128.mir +++ /dev/null @@ -1,25 +0,0 @@ -# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -march=aarch64 -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s ---- -name: narrow_s128 -tracksRegLiveness: true -body: | - bb.1: - liveins: $x0, $x1 - - ; CHECK-LABEL: name: narrow_s128 - ; CHECK: liveins: $x0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:_(p0) = COPY $x1 - ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63 - ; CHECK: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY]], [[C]](s64) - ; CHECK: [[MV:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY]](s64), [[ASHR]](s64) - ; CHECK: G_STORE [[MV]](s128), [[COPY1]](p0) :: (store 16) - ; CHECK: RET_ReallyLR - %0:_(s64) = COPY $x0 - %1:_(p0) = COPY $x1 - %2:_(s128) = G_SEXT %0(s64) - G_STORE %2(s128), %1(p0) :: (store 16) - RET_ReallyLR - -... diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext-zext-128.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext-zext-128.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext-zext-128.mir @@ -0,0 +1,71 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=aarch64 -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s +--- +name: narrow_sext_s128 +tracksRegLiveness: true +body: | + bb.1: + liveins: $x0, $x1 + + ; CHECK-LABEL: name: narrow_sext_s128 + ; CHECK: liveins: $x0, $x1 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:_(p0) = COPY $x1 + ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63 + ; CHECK: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY]], [[C]](s64) + ; CHECK: [[MV:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY]](s64), [[ASHR]](s64) + ; CHECK: G_STORE [[MV]](s128), [[COPY1]](p0) :: (store 16) + ; CHECK: RET_ReallyLR + %0:_(s64) = COPY $x0 + %1:_(p0) = COPY $x1 + %2:_(s128) = G_SEXT %0(s64) + G_STORE %2(s128), %1(p0) :: (store 16) + RET_ReallyLR + +... +--- +name: narrow_zext_s128 +tracksRegLiveness: true +body: | + bb.1: + liveins: $x0, $x1 + + ; CHECK-LABEL: name: narrow_zext_s128 + ; CHECK: liveins: $x0, $x1 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:_(p0) = COPY $x1 + ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK: [[MV:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY]](s64), [[C]](s64) + ; CHECK: G_STORE [[MV]](s128), [[COPY1]](p0) :: (store 16) + ; CHECK: RET_ReallyLR + %0:_(s64) = COPY $x0 + %1:_(p0) = COPY $x1 + %2:_(s128) = G_ZEXT %0(s64) + G_STORE %2(s128), %1(p0) :: (store 16) + RET_ReallyLR + +... +--- +name: narrow_zext_s192 +tracksRegLiveness: true +body: | + bb.1: + liveins: $x0, $x1 + + ; CHECK-LABEL: name: narrow_zext_s192 + ; CHECK: liveins: $x0, $x1 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:_(p0) = COPY $x1 + ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK: [[MV:%[0-9]+]]:_(s192) = G_MERGE_VALUES [[COPY]](s64), [[C]](s64), [[C]](s64) + ; CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64), [[UV2:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[MV]](s192) + ; CHECK: G_STORE [[UV]](s64), [[COPY1]](p0) :: (store 8) + ; CHECK: RET_ReallyLR + %0:_(s64) = COPY $x0 + %1:_(p0) = COPY $x1 + %2:_(s192) = G_ZEXT %0(s64) + %3:_(s64), %4:_(s64), %5:_(s64) = G_UNMERGE_VALUES %2(s192) + G_STORE %3, %1(p0) :: (store 8) + RET_ReallyLR + +... diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -227,6 +227,7 @@ # DEBUG-NEXT: .. the first uncovered type index: 2, OK # DEBUG-NEXT: .. the first uncovered imm index: 0, OK # DEBUG-NEXT: G_SEXT (opcode {{[0-9]+}}): 2 type indices, 0 imm indices +# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}} # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: G_SEXT_INREG (opcode {{[0-9]+}}): 1 type index, 1 imm index