[PATCH] D141902: [GlobalISel] Detect splats built with G_CONCAT_VECTORS
Diana Picus via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 17 00:48:00 PST 2023
rovka created this revision.
Herald added subscribers: kosarev, hiraditya, tpr.
Herald added a project: All.
rovka requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
Add support to the MI matching of vector splats for patterns that
consist of `G_CONCAT_VECTORS` of smaller splats with the same constant
value. With this, we would consider the following pseudo-MIR to be a splat:
%0 = G_[F]CONSTANT [...]
%1 = G_BUILD_VECTOR %0, %0, ..., %0
%2 = G_CONCAT_VECTORS %1, %1, ..., %1
Since it uses recursion for matching splats, it could match pretty
complicated patterns with all sorts of combinations of `G_BUILD_VECTOR`
and `G_CONCAT_VECTORS` (e.g. a `G_CONCAT_VECTORS` with
a `G_BUILD_VECTOR_TRUNC` and another `G_CONCAT_VECTORS` as operands),
and it should also look through copies etc.
This should make it easier to match complex immediates for certain
instructions on AMDGPU, where for instance a <8 x s16> will be split
before instruction selection into a `G_CONCAT_VECTORS` of <2 x s16>
splats.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D141902
Files:
llvm/lib/CodeGen/GlobalISel/Utils.cpp
llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp
Index: llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp
===================================================================
--- llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp
+++ llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp
@@ -57,6 +57,7 @@
return;
LLT s64 = LLT::scalar(64);
+ LLT v2s64 = LLT::fixed_vector(2, s64);
LLT v4s64 = LLT::fixed_vector(4, s64);
MachineInstrBuilder FortyTwoSplat =
@@ -68,6 +69,11 @@
MachineInstrBuilder NonConstantSplat =
B.buildBuildVector(v4s64, {Copies[0], Copies[0], Copies[0], Copies[0]});
EXPECT_FALSE(mi_match(NonConstantSplat.getReg(0), *MRI, m_ICstOrSplat(Cst)));
+
+ auto ICst = B.buildConstant(s64, 15).getReg(0);
+ auto SmallSplat = B.buildBuildVector(v2s64, {ICst, ICst}).getReg(0);
+ auto LargeSplat = B.buildConcatVectors(v4s64, {SmallSplat, SmallSplat});
+ EXPECT_TRUE(mi_match(LargeSplat.getReg(0), *MRI, m_ICstOrSplat(Cst)));
}
TEST_F(AArch64GISelMITest, MachineInstrPtrBind) {
@@ -718,6 +724,7 @@
return;
LLT s64 = LLT::scalar(64);
+ LLT v2s64 = LLT::fixed_vector(2, 64);
LLT v4s64 = LLT::fixed_vector(4, 64);
Register FPOne = B.buildFConstant(s64, 1.0).getReg(0);
@@ -761,6 +768,33 @@
auto Mixed = B.buildBuildVector(v4s64, {FPZero, FPZero, FPZero, Copies[0]});
EXPECT_FALSE(
mi_match(Mixed.getReg(0), *MRI, GFCstOrSplatGFCstMatch(FValReg)));
+
+ // Look through G_CONCAT_VECTORS.
+ auto SmallZeroSplat = B.buildBuildVector(v2s64, {FPZero, FPZero}).getReg(0);
+ auto LargeZeroSplat =
+ B.buildConcatVectors(v4s64, {SmallZeroSplat, SmallZeroSplat});
+ EXPECT_TRUE(mi_match(LargeZeroSplat.getReg(0), *MRI,
+ GFCstOrSplatGFCstMatch(FValReg)));
+
+ auto SmallZeroSplat2 = B.buildBuildVector(v2s64, {FPZero, FPZero}).getReg(0);
+ auto SmallZeroSplat3 = B.buildCopy(v2s64, SmallZeroSplat).getReg(0);
+ auto LargeZeroSplat2 =
+ B.buildConcatVectors(v4s64, {SmallZeroSplat2, SmallZeroSplat3});
+ EXPECT_TRUE(mi_match(LargeZeroSplat2.getReg(0), *MRI,
+ GFCstOrSplatGFCstMatch(FValReg)));
+
+ // Not all G_CONCAT_VECTORS are splats.
+ auto SmallOneSplat = B.buildBuildVector(v2s64, {FPOne, FPOne}).getReg(0);
+ auto LargeMixedSplat =
+ B.buildConcatVectors(v4s64, {SmallZeroSplat, SmallOneSplat});
+ EXPECT_FALSE(mi_match(LargeMixedSplat.getReg(0), *MRI,
+ GFCstOrSplatGFCstMatch(FValReg)));
+
+ auto SmallMixedSplat = B.buildBuildVector(v2s64, {FPOne, FPZero}).getReg(0);
+ auto LargeSplat =
+ B.buildConcatVectors(v4s64, {SmallMixedSplat, SmallMixedSplat});
+ EXPECT_FALSE(
+ mi_match(LargeSplat.getReg(0), *MRI, GFCstOrSplatGFCstMatch(FValReg)));
}
TEST_F(AArch64GISelMITest, MatchNeg) {
Index: llvm/lib/CodeGen/GlobalISel/Utils.cpp
===================================================================
--- llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -1035,14 +1035,19 @@
if (!MI)
return std::nullopt;
- if (!isBuildVectorOp(MI->getOpcode()))
+ bool isConcatVectorsOp = MI->getOpcode() == TargetOpcode::G_CONCAT_VECTORS;
+ if (!isBuildVectorOp(MI->getOpcode()) && !isConcatVectorsOp)
return std::nullopt;
std::optional<ValueAndVReg> SplatValAndReg;
for (MachineOperand &Op : MI->uses()) {
Register Element = Op.getReg();
+ // If we have a G_CONCAT_VECTOR, we recursively look into the
+ // vectors that we're concatenating to see if they're splats.
auto ElementValAndReg =
- getAnyConstantVRegValWithLookThrough(Element, MRI, true, true);
+ isConcatVectorsOp
+ ? getAnyConstantSplat(Element, MRI, AllowUndef)
+ : getAnyConstantVRegValWithLookThrough(Element, MRI, true, true);
// If AllowUndef, treat undef as value that will result in a constant splat.
if (!ElementValAndReg) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D141902.489723.patch
Type: text/x-patch
Size: 3855 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230117/faa4bca4/attachment.bin>
More information about the llvm-commits
mailing list