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 @@ -596,7 +596,9 @@ MI.eraseFromParent(); return Legalized; } - case TargetOpcode::G_SEXT: { + case TargetOpcode::G_ZEXT: { + LLVM_FALLTHROUGH; + case TargetOpcode::G_SEXT: if (TypeIdx != 0) return UnableToLegalize; @@ -606,16 +608,21 @@ } Register SrcReg = MI.getOperand(1).getReg(); - - // Shift the sign bit of the low register through the high register. - auto ShiftAmt = - MIRBuilder.buildConstant(LLT::scalar(64), NarrowTy.getSizeInBits() - 1); - auto Shift = MIRBuilder.buildAShr(NarrowTy, SrcReg, ShiftAmt); - MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {SrcReg, Shift.getReg(0)}); + Register HighReg; + + // SEXT: shift the sign bit of the low register through the high register. + // ZEXT: merge with 0 in the high bits. + if (MI.getOpcode() == TargetOpcode::G_SEXT) { + auto ShiftAmt = MIRBuilder.buildConstant(LLT::scalar(64), + NarrowTy.getSizeInBits() - 1); + HighReg = MIRBuilder.buildAShr(NarrowTy, SrcReg, ShiftAmt).getReg(0); + } else { + HighReg = MIRBuilder.buildConstant(NarrowTy, 0).getReg(0); + } + MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {SrcReg, HighReg}); MI.eraseFromParent(); return Legalized; } - case TargetOpcode::G_ADD: { // FIXME: add support for when SizeOp0 isn't an exact multiple of // NarrowSize. 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-zext-128.mir rename from llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext-128.mir rename to llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext-zext-128.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext-128.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sext-zext-128.mir @@ -1,13 +1,13 @@ # 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 +name: narrow_sext_s128 tracksRegLiveness: true body: | bb.1: liveins: $x0, $x1 - ; CHECK-LABEL: name: narrow_s128 + ; CHECK-LABEL: name: narrow_sext_s128 ; CHECK: liveins: $x0, $x1 ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 ; CHECK: [[COPY1:%[0-9]+]]:_(p0) = COPY $x1 @@ -23,3 +23,25 @@ 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 + +... 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