forked from OSchip/llvm-project
[AArch64][GlobalISel] Port buildvector -> dup pattern from AArch64ISelLowering
Given this: ``` %x:_(<n x sK>) = G_BUILD_VECTOR %lane, ... ... %y:_(<n x sK>) = G_SHUFFLE_VECTOR %x(<n x sK>), %foo, shufflemask(0, 0, ...) ``` We can produce: ``` %y:_(<n x sK) = G_DUP %lane(sK) ``` Doesn't seem to be too common, but AArch64ISelLowering attempts to do this before trying to produce a DUPLANE. Might as well port it. Also make it so that when the splat has an undef mask, we try setting it to 0. SDAG does this, and it makes sure that when we get the build vector operand, we actually get a source operand. Differential Revision: https://reviews.llvm.org/D81979
This commit is contained in:
parent
2c09e91054
commit
7fb84dff69
|
@ -271,11 +271,11 @@ static bool matchZip(MachineInstr &MI, MachineRegisterInfo &MRI,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool matchDup(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
ShuffleVectorPseudo &MatchInfo) {
|
||||
assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
|
||||
auto Lane = getSplatIndex(MI);
|
||||
if (!Lane || *Lane != 0)
|
||||
/// Helper function for matchDup.
|
||||
static bool matchDupFromInsertVectorElt(int Lane, MachineInstr &MI,
|
||||
MachineRegisterInfo &MRI,
|
||||
ShuffleVectorPseudo &MatchInfo) {
|
||||
if (Lane != 0)
|
||||
return false;
|
||||
|
||||
// Try to match a vector splat operation into a dup instruction.
|
||||
|
@ -296,10 +296,9 @@ static bool matchDup(MachineInstr &MI, MachineRegisterInfo &MRI,
|
|||
MI.getOperand(1).getReg(), MRI);
|
||||
if (!InsMI)
|
||||
return false;
|
||||
|
||||
// Match the undef vector operand.
|
||||
if (!getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
|
||||
InsMI->getOperand(1).getReg(), MRI))
|
||||
if (!getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, InsMI->getOperand(1).getReg(),
|
||||
MRI))
|
||||
return false;
|
||||
|
||||
// Match the index constant 0.
|
||||
|
@ -307,12 +306,45 @@ static bool matchDup(MachineInstr &MI, MachineRegisterInfo &MRI,
|
|||
if (!mi_match(InsMI->getOperand(3).getReg(), MRI, m_ICst(Index)) || Index)
|
||||
return false;
|
||||
|
||||
Register Dst = MI.getOperand(0).getReg();
|
||||
MatchInfo =
|
||||
ShuffleVectorPseudo(AArch64::G_DUP, Dst, {InsMI->getOperand(2).getReg()});
|
||||
MatchInfo = ShuffleVectorPseudo(AArch64::G_DUP, MI.getOperand(0).getReg(),
|
||||
{InsMI->getOperand(2).getReg()});
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Helper function for matchDup.
|
||||
static bool matchDupFromBuildVector(int Lane, MachineInstr &MI,
|
||||
MachineRegisterInfo &MRI,
|
||||
ShuffleVectorPseudo &MatchInfo) {
|
||||
assert(Lane >= 0 && "Expected positive lane?");
|
||||
// Test if the LHS is a BUILD_VECTOR. If it is, then we can just reference the
|
||||
// lane's definition directly.
|
||||
auto *BuildVecMI = getOpcodeDef(TargetOpcode::G_BUILD_VECTOR,
|
||||
MI.getOperand(1).getReg(), MRI);
|
||||
if (!BuildVecMI)
|
||||
return false;
|
||||
Register Reg = BuildVecMI->getOperand(Lane + 1).getReg();
|
||||
MatchInfo =
|
||||
ShuffleVectorPseudo(AArch64::G_DUP, MI.getOperand(0).getReg(), {Reg});
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool matchDup(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
ShuffleVectorPseudo &MatchInfo) {
|
||||
assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
|
||||
auto MaybeLane = getSplatIndex(MI);
|
||||
if (!MaybeLane)
|
||||
return false;
|
||||
int Lane = *MaybeLane;
|
||||
// If this is undef splat, generate it via "just" vdup, if possible.
|
||||
if (Lane < 0)
|
||||
Lane = 0;
|
||||
if (matchDupFromInsertVectorElt(Lane, MI, MRI, MatchInfo))
|
||||
return true;
|
||||
if (matchDupFromBuildVector(Lane, MI, MRI, MatchInfo))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool matchEXT(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
ShuffleVectorPseudo &MatchInfo) {
|
||||
assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
|
||||
|
|
|
@ -328,3 +328,31 @@ body: |
|
|||
%splat:_(<8 x s8>) = G_SHUFFLE_VECTOR %ins(<8 x s8>), %undef, shufflemask(0, 0, 0, 0, 0, 0, 0, 0)
|
||||
$d0 = COPY %splat(<8 x s8>)
|
||||
RET_ReallyLR implicit $d0
|
||||
|
||||
...
|
||||
---
|
||||
name: build_vector
|
||||
alignment: 4
|
||||
legalized: true
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $w0, $w1, $w2, $w3
|
||||
; The G_SHUFFLE_VECTOR is fed by a G_BUILD_VECTOR, and the 0th input
|
||||
; operand is not a constant. We should get a G_DUP.
|
||||
;
|
||||
; CHECK-LABEL: name: build_vector
|
||||
; CHECK: liveins: $w0, $w1, $w2, $w3
|
||||
; CHECK: %lane:_(s32) = COPY $w0
|
||||
; CHECK: %shuf:_(<4 x s32>) = G_DUP %lane(s32)
|
||||
; CHECK: $q0 = COPY %shuf(<4 x s32>)
|
||||
; CHECK: RET_ReallyLR implicit $q0
|
||||
%lane:_(s32) = COPY $w0
|
||||
%b:_(s32) = COPY $w1
|
||||
%c:_(s32) = COPY $w2
|
||||
%d:_(s32) = COPY $w3
|
||||
%undef:_(<4 x s32>) = G_IMPLICIT_DEF
|
||||
%buildvec:_(<4 x s32>) = G_BUILD_VECTOR %lane, %b, %c, %d
|
||||
%shuf:_(<4 x s32>) = G_SHUFFLE_VECTOR %buildvec(<4 x s32>), %undef, shufflemask(0, 0, 0, 0)
|
||||
$q0 = COPY %shuf(<4 x s32>)
|
||||
RET_ReallyLR implicit $q0
|
||||
|
|
Loading…
Reference in New Issue