Skip to content

[GlobalIsel] Push cast through build vector #104634

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,9 @@ class CombinerHelper {
bool matchExtOfExt(const MachineInstr &FirstMI, const MachineInstr &SecondMI,
BuildFnTy &MatchInfo);

bool matchCastOfBuildVector(const MachineInstr &CastMI,
const MachineInstr &BVMI, BuildFnTy &MatchInfo);

private:
/// Checks for legality of an indexed variant of \p LdSt.
bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;
Expand Down
13 changes: 12 additions & 1 deletion llvm/include/llvm/Target/GlobalISel/Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -1857,6 +1857,16 @@ def anyext_of_anyext : ext_of_ext_opcodes<G_ANYEXT, G_ANYEXT>;
def anyext_of_zext : ext_of_ext_opcodes<G_ANYEXT, G_ZEXT>;
def anyext_of_sext : ext_of_ext_opcodes<G_ANYEXT, G_SEXT>;

// Push cast through build vector.
class buildvector_of_opcode<Instruction castOpcode> : GICombineRule <
(defs root:$root, build_fn_matchinfo:$matchinfo),
(match (G_BUILD_VECTOR $bv, GIVariadic<>:$unused):$Build,
(castOpcode $root, $bv):$Cast,
[{ return Helper.matchCastOfBuildVector(*${Cast}, *${Build}, ${matchinfo}); }]),
(apply [{ Helper.applyBuildFn(*${Cast}, ${matchinfo}); }])>;

def buildvector_of_truncate : buildvector_of_opcode<G_TRUNC>;

def cast_combines: GICombineGroup<[
truncate_of_zext,
truncate_of_sext,
Expand All @@ -1870,7 +1880,8 @@ def cast_combines: GICombineGroup<[
sext_of_anyext,
anyext_of_anyext,
anyext_of_zext,
anyext_of_sext
anyext_of_sext,
buildvector_of_truncate
]>;


Expand Down
40 changes: 40 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,43 @@ bool CombinerHelper::matchExtOfExt(const MachineInstr &FirstMI,

return false;
}

bool CombinerHelper::matchCastOfBuildVector(const MachineInstr &CastMI,
const MachineInstr &BVMI,
BuildFnTy &MatchInfo) {
const GExtOrTruncOp *Cast = cast<GExtOrTruncOp>(&CastMI);
const GBuildVector *BV = cast<GBuildVector>(&BVMI);

if (!MRI.hasOneNonDBGUse(BV->getReg(0)))
return false;

Register Dst = Cast->getReg(0);
// The type of the new build vector.
LLT DstTy = MRI.getType(Dst);
// The scalar or element type of the new build vector.
LLT ElemTy = DstTy.getScalarType();
// The scalar or element type of the old build vector.
LLT InputElemTy = MRI.getType(BV->getReg(0)).getElementType();

// Check legality of new build vector, the scalar casts, and profitability of
// the many casts.
if (!isLegalOrBeforeLegalizer(
{TargetOpcode::G_BUILD_VECTOR, {DstTy, ElemTy}}) ||
!isLegalOrBeforeLegalizer({Cast->getOpcode(), {ElemTy, InputElemTy}}) ||
!isCastFree(Cast->getOpcode(), ElemTy, InputElemTy))
return false;

MatchInfo = [=](MachineIRBuilder &B) {
SmallVector<Register> Casts;
unsigned Elements = BV->getNumSources();
for (unsigned I = 0; I < Elements; ++I) {
auto CastI =
B.buildInstr(Cast->getOpcode(), {ElemTy}, {BV->getSourceReg(I)});
Casts.push_back(CastI.getReg(0));
}

B.buildBuildVector(Dst, Casts);
};

return true;
}
1 change: 1 addition & 0 deletions llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
.clampNumElements(0, v2s64, v2s64)
.minScalarOrElt(0, s8)
.widenVectorEltsToVectorMinSize(0, 64)
.widenScalarOrEltToNextPow2(0)
.minScalarSameAs(1, 0);

getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC).lower();
Expand Down
95 changes: 95 additions & 0 deletions llvm/test/CodeGen/AArch64/GlobalISel/combine-cast.mir
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,98 @@ body: |
%res:_(<2 x s64>) = G_SELECT %cond(<2 x s32>), %bv, %bv2
%small:_(<2 x s32>) = G_TRUNC %res(<2 x s64>)
$x0 = COPY %small(<2 x s32>)
...
---
name: test_combine_trunc_build_vector
legalized: true
body: |
bb.1:
; CHECK-PRE-LABEL: name: test_combine_trunc_build_vector
; CHECK-PRE: %arg1:_(s64) = COPY $x0
; CHECK-PRE-NEXT: %arg2:_(s64) = COPY $x0
; CHECK-PRE-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC %arg1(s64)
; CHECK-PRE-NEXT: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC %arg2(s64)
; CHECK-PRE-NEXT: %small:_(<2 x s32>) = G_BUILD_VECTOR [[TRUNC]](s32), [[TRUNC1]](s32)
; CHECK-PRE-NEXT: $x0 = COPY %small(<2 x s32>)
;
; CHECK-POST-LABEL: name: test_combine_trunc_build_vector
; CHECK-POST: %arg1:_(s64) = COPY $x0
; CHECK-POST-NEXT: %arg2:_(s64) = COPY $x0
; CHECK-POST-NEXT: %bv:_(<2 x s64>) = G_BUILD_VECTOR %arg1(s64), %arg2(s64)
; CHECK-POST-NEXT: %small:_(<2 x s32>) = G_TRUNC %bv(<2 x s64>)
; CHECK-POST-NEXT: $x0 = COPY %small(<2 x s32>)
%arg1:_(s64) = COPY $x0
%arg2:_(s64) = COPY $x0
%bv:_(<2 x s64>) = G_BUILD_VECTOR %arg1(s64), %arg2(s64)
%small:_(<2 x s32>) = G_TRUNC %bv(<2 x s64>)
$x0 = COPY %small(<2 x s32>)
...
---
name: test_combine_zext_build_vector
legalized: true
body: |
bb.1:
; CHECK-LABEL: name: test_combine_zext_build_vector
; CHECK: %arg1:_(s32) = COPY $w0
; CHECK-NEXT: %arg2:_(s32) = COPY $w0
; CHECK-NEXT: %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32)
; CHECK-NEXT: %large:_(<2 x s64>) = G_ZEXT %bv(<2 x s32>)
; CHECK-NEXT: $q0 = COPY %large(<2 x s64>)
%arg1:_(s32) = COPY $w0
%arg2:_(s32) = COPY $w0
%bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32)
%large:_(<2 x s64>) = G_ZEXT %bv(<2 x s32>)
$q0 = COPY %large(<2 x s64>)
...
---
name: test_combine_anyext_build_vector
legalized: true
body: |
bb.1:
; CHECK-LABEL: name: test_combine_anyext_build_vector
; CHECK: %arg1:_(s32) = COPY $w0
; CHECK-NEXT: %arg2:_(s32) = COPY $w0
; CHECK-NEXT: %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32)
; CHECK-NEXT: %large:_(<2 x s64>) = G_ANYEXT %bv(<2 x s32>)
; CHECK-NEXT: $q0 = COPY %large(<2 x s64>)
%arg1:_(s32) = COPY $w0
%arg2:_(s32) = COPY $w0
%bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32)
%large:_(<2 x s64>) = G_ANYEXT %bv(<2 x s32>)
$q0 = COPY %large(<2 x s64>)
...
---
name: test_combine_sext_build_vector
legalized: true
body: |
bb.1:
; CHECK-LABEL: name: test_combine_sext_build_vector
; CHECK: %arg1:_(s32) = COPY $w0
; CHECK-NEXT: %arg2:_(s32) = COPY $w0
; CHECK-NEXT: %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32)
; CHECK-NEXT: %large:_(<2 x s64>) = G_SEXT %bv(<2 x s32>)
; CHECK-NEXT: $q0 = COPY %large(<2 x s64>)
%arg1:_(s32) = COPY $w0
%arg2:_(s32) = COPY $w0
%bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32)
%large:_(<2 x s64>) = G_SEXT %bv(<2 x s32>)
$q0 = COPY %large(<2 x s64>)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Negative check for the hasOneUse case? Legality would be nice too, but that's more labor

...
---
name: test_combine_anyext_build_vector_multi_use
legalized: true
body: |
bb.1:
; CHECK-LABEL: name: test_combine_anyext_build_vector_multi_use
; CHECK: %arg1:_(s32) = COPY $w0
; CHECK-NEXT: %arg2:_(s32) = COPY $w0
; CHECK-NEXT: %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32)
; CHECK-NEXT: %large:_(<2 x s64>) = G_ANYEXT %bv(<2 x s32>)
; CHECK-NEXT: $q0 = COPY %large(<2 x s64>)
; CHECK-NEXT: $d0 = COPY %bv(<2 x s32>)
%arg1:_(s32) = COPY $w0
%arg2:_(s32) = COPY $w0
%bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32)
%large:_(<2 x s64>) = G_ANYEXT %bv(<2 x s32>)
$q0 = COPY %large(<2 x s64>)
$d0 = COPY %bv(<2 x s32>)
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ body: |
; CHECK: liveins: $x0, $x1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %arg1:_(s64) = COPY $x0
; CHECK-NEXT: %extract:_(s32) = G_TRUNC %arg1(s64)
; CHECK-NEXT: %zext:_(s64) = G_ZEXT %extract(s32)
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC %arg1(s64)
; CHECK-NEXT: %zext:_(s64) = G_ZEXT [[TRUNC]](s32)
; CHECK-NEXT: $x0 = COPY %zext(s64)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%arg1:_(s64) = COPY $x0
Expand Down
45 changes: 33 additions & 12 deletions llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY]](s32), [[COPY1]](s32)
; CHECK-NEXT: $q0 = COPY %bv0(<4 x s32>)
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32)
; CHECK-NEXT: %trunc:_(<4 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC]](s16), [[TRUNC1]](s16)
; CHECK-NEXT: %zext:_(<4 x s32>) = G_ZEXT %trunc(<4 x s16>)
; CHECK-NEXT: $q0 = COPY %zext(<4 x s32>)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%0:_(s32) = COPY $w0
%1:_(s32) = COPY $w1
Expand Down Expand Up @@ -165,8 +168,13 @@ body: |
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32)
; CHECK-NEXT: $q0 = COPY %bv0(<4 x s32>)
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32)
; CHECK-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32)
; CHECK-NEXT: [[TRUNC3:%[0-9]+]]:_(s16) = G_TRUNC [[COPY3]](s32)
; CHECK-NEXT: %t:_(<4 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16), [[TRUNC3]](s16)
; CHECK-NEXT: %s:_(<4 x s32>) = G_SEXT %t(<4 x s16>)
; CHECK-NEXT: $q0 = COPY %s(<4 x s32>)
%0:_(s32) = COPY $w0
%1:_(s32) = COPY $w1
%2:_(s32) = COPY $w2
Expand All @@ -188,8 +196,11 @@ body: |
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32)
; CHECK-NEXT: %t:_(<4 x s16>) = G_TRUNC %bv0(<4 x s32>)
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32)
; CHECK-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32)
; CHECK-NEXT: [[TRUNC3:%[0-9]+]]:_(s16) = G_TRUNC [[COPY3]](s32)
; CHECK-NEXT: %t:_(<4 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16), [[TRUNC3]](s16)
; CHECK-NEXT: %z:_(<4 x s32>) = G_ZEXT %t(<4 x s16>)
; CHECK-NEXT: $q0 = COPY %z(<4 x s32>)
%0:_(s32) = COPY $w0
Expand All @@ -213,8 +224,11 @@ body: |
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32)
; CHECK-NEXT: %t:_(<4 x s16>) = nsw G_TRUNC %bv0(<4 x s32>)
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32)
; CHECK-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32)
; CHECK-NEXT: [[TRUNC3:%[0-9]+]]:_(s16) = G_TRUNC [[COPY3]](s32)
; CHECK-NEXT: %t:_(<4 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16), [[TRUNC3]](s16)
; CHECK-NEXT: %z:_(<4 x s32>) = G_ZEXT %t(<4 x s16>)
; CHECK-NEXT: $q0 = COPY %z(<4 x s32>)
%0:_(s32) = COPY $w0
Expand All @@ -238,8 +252,13 @@ body: |
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32)
; CHECK-NEXT: $q0 = COPY %bv0(<4 x s32>)
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32)
; CHECK-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32)
; CHECK-NEXT: [[TRUNC3:%[0-9]+]]:_(s16) = G_TRUNC [[COPY3]](s32)
; CHECK-NEXT: %t:_(<4 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16), [[TRUNC3]](s16)
; CHECK-NEXT: %z:_(<4 x s32>) = G_ZEXT %t(<4 x s16>)
; CHECK-NEXT: $q0 = COPY %z(<4 x s32>)
%0:_(s32) = COPY $w0
%1:_(s32) = COPY $w1
%2:_(s32) = COPY $w2
Expand All @@ -259,8 +278,10 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
; CHECK-NEXT: %bv0:_(<2 x s64>) = G_BUILD_VECTOR [[COPY]](s64), [[COPY1]](s64)
; CHECK-NEXT: %z:_(<2 x s32>) = nuw G_TRUNC %bv0(<2 x s64>)
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s64)
; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s64)
; CHECK-NEXT: %t:_(<2 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16)
; CHECK-NEXT: %z:_(<2 x s32>) = G_ZEXT %t(<2 x s16>)
; CHECK-NEXT: $d0 = COPY %z(<2 x s32>)
%0:_(s64) = COPY $x0
%1:_(s64) = COPY $x1
Expand Down
Loading
Loading