[AArch64][GlobalISel] Implement narrowing of G_SEXT.

We need this to narrow a sext to s128.

Differential Revision: https://reviews.llvm.org/D65357

llvm-svn: 367164
This commit is contained in:
Amara Emerson 2019-07-26 23:46:38 +00:00
parent aa8b9993c2
commit 7bc4fad0fb
3 changed files with 70 additions and 19 deletions

View File

@ -567,6 +567,26 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
MI.eraseFromParent();
return Legalized;
}
case TargetOpcode::G_SEXT: {
if (TypeIdx != 0)
return UnableToLegalize;
if (NarrowTy.getSizeInBits() != SizeOp0 / 2) {
LLVM_DEBUG(dbgs() << "Can't narrow sext to type " << NarrowTy << "\n");
return UnableToLegalize;
}
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)});
MI.eraseFromParent();
return Legalized;
}
case TargetOpcode::G_ADD: {
// FIXME: add support for when SizeOp0 isn't an exact multiple of
// NarrowSize.

View File

@ -340,30 +340,36 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) {
.widenScalarToNextPow2(1);
// Extensions
getActionDefinitionsBuilder({G_ZEXT, G_SEXT, G_ANYEXT})
.legalIf([=](const LegalityQuery &Query) {
unsigned DstSize = Query.Types[0].getSizeInBits();
auto ExtLegalFunc = [=](const LegalityQuery &Query) {
unsigned DstSize = Query.Types[0].getSizeInBits();
// Make sure that we have something that will fit in a register, and
// make sure it's a power of 2.
if (DstSize < 8 || DstSize > 128 || !isPowerOf2_32(DstSize))
return false;
if (DstSize == 128 && !Query.Types[0].isVector())
return false; // Extending to a scalar s128 is not legal.
// Make sure that we have something that will fit in a register, and
// make sure it's a power of 2.
if (DstSize < 8 || DstSize > 128 || !isPowerOf2_32(DstSize))
return false;
const LLT &SrcTy = Query.Types[1];
const LLT &SrcTy = Query.Types[1];
// Special case for s1.
if (SrcTy == s1)
return true;
// Special case for s1.
if (SrcTy == s1)
return true;
// Make sure we fit in a register otherwise. Don't bother checking that
// the source type is below 128 bits. We shouldn't be allowing anything
// through which is wider than the destination in the first place.
unsigned SrcSize = SrcTy.getSizeInBits();
if (SrcSize < 8 || !isPowerOf2_32(SrcSize))
return false;
// Make sure we fit in a register otherwise. Don't bother checking that
// the source type is below 128 bits. We shouldn't be allowing anything
// through which is wider than the destination in the first place.
unsigned SrcSize = SrcTy.getSizeInBits();
if (SrcSize < 8 || !isPowerOf2_32(SrcSize))
return false;
return true;
});
return true;
};
getActionDefinitionsBuilder({G_ZEXT, G_ANYEXT}).legalIf(ExtLegalFunc);
getActionDefinitionsBuilder(G_SEXT)
.legalIf(ExtLegalFunc)
.clampScalar(0, s64, s64); // Just for s128, others are handled above.
getActionDefinitionsBuilder(G_TRUNC).alwaysLegal();

View File

@ -0,0 +1,25 @@
# 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
...