Skip to content

Commit bc5dbb0

Browse files
author
Abinav Puthan Purayil
committed
[GlobalISel] Add matchers for constant splat.
This change exposes isBuildVectorConstantSplat() to the llvm namespace and uses it to implement the constant splat versions of m_SpecificICst(). CombinerHelper::matchOrShiftToFunnelShift() can now work with vector types and CombinerHelper::matchMulOBy2()'s match for a constant splat is simplified. Differential Revision: https://reviews.llvm.org/D114625
1 parent 5d60212 commit bc5dbb0

File tree

7 files changed

+189
-31
lines changed

7 files changed

+189
-31
lines changed

llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,43 @@ inline SpecificConstantMatch m_SpecificICst(int64_t RequestedValue) {
129129
return SpecificConstantMatch(RequestedValue);
130130
}
131131

132+
/// Matcher for a specific constant splat.
133+
struct SpecificConstantSplatMatch {
134+
int64_t RequestedVal;
135+
SpecificConstantSplatMatch(int64_t RequestedVal)
136+
: RequestedVal(RequestedVal) {}
137+
bool match(const MachineRegisterInfo &MRI, Register Reg) {
138+
return isBuildVectorConstantSplat(Reg, MRI, RequestedVal,
139+
/* AllowUndef */ false);
140+
}
141+
};
142+
143+
/// Matches a constant splat of \p RequestedValue.
144+
inline SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue) {
145+
return SpecificConstantSplatMatch(RequestedValue);
146+
}
147+
148+
/// Matcher for a specific constant or constant splat.
149+
struct SpecificConstantOrSplatMatch {
150+
int64_t RequestedVal;
151+
SpecificConstantOrSplatMatch(int64_t RequestedVal)
152+
: RequestedVal(RequestedVal) {}
153+
bool match(const MachineRegisterInfo &MRI, Register Reg) {
154+
int64_t MatchedVal;
155+
if (mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal)
156+
return true;
157+
return isBuildVectorConstantSplat(Reg, MRI, RequestedVal,
158+
/* AllowUndef */ false);
159+
}
160+
};
161+
162+
/// Matches a \p RequestedValue constant or a constant splat of \p
163+
/// RequestedValue.
164+
inline SpecificConstantOrSplatMatch
165+
m_SpecificICstOrSplat(int64_t RequestedValue) {
166+
return SpecificConstantOrSplatMatch(RequestedValue);
167+
}
168+
132169
///{
133170
/// Convenience matchers for specific integer values.
134171
inline SpecificConstantMatch m_ZeroInt() { return SpecificConstantMatch(0); }

llvm/include/llvm/CodeGen/GlobalISel/Utils.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,18 @@ Optional<FPValueAndVReg> getFConstantSplat(Register VReg,
378378
const MachineRegisterInfo &MRI,
379379
bool AllowUndef = true);
380380

381+
/// Return true if the specified register is defined by G_BUILD_VECTOR or
382+
/// G_BUILD_VECTOR_TRUNC where all of the elements are \p SplatValue or undef.
383+
bool isBuildVectorConstantSplat(const Register Reg,
384+
const MachineRegisterInfo &MRI,
385+
int64_t SplatValue, bool AllowUndef);
386+
387+
/// Return true if the specified instruction is a G_BUILD_VECTOR or
388+
/// G_BUILD_VECTOR_TRUNC where all of the elements are \p SplatValue or undef.
389+
bool isBuildVectorConstantSplat(const MachineInstr &MI,
390+
const MachineRegisterInfo &MRI,
391+
int64_t SplatValue, bool AllowUndef);
392+
381393
/// Return true if the specified instruction is a G_BUILD_VECTOR or
382394
/// G_BUILD_VECTOR_TRUNC where all of the elements are 0 or undef.
383395
bool isBuildVectorAllZeros(const MachineInstr &MI,

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3878,21 +3878,21 @@ bool CombinerHelper::matchOrShiftToFunnelShift(MachineInstr &MI,
38783878
Register ShlSrc, ShlAmt, LShrSrc, LShrAmt;
38793879
unsigned FshOpc = 0;
38803880

3881-
// TODO: Handle vector types.
38823881
// Match (or (shl x, amt), (lshr y, sub(bw, amt))).
3883-
if (mi_match(Dst, MRI,
3884-
// m_GOr() handles the commuted version as well.
3885-
m_GOr(m_GShl(m_Reg(ShlSrc), m_Reg(ShlAmt)),
3886-
m_GLShr(m_Reg(LShrSrc), m_GSub(m_SpecificICst(BitWidth),
3887-
m_Reg(LShrAmt)))))) {
3882+
if (mi_match(
3883+
Dst, MRI,
3884+
// m_GOr() handles the commuted version as well.
3885+
m_GOr(m_GShl(m_Reg(ShlSrc), m_Reg(ShlAmt)),
3886+
m_GLShr(m_Reg(LShrSrc), m_GSub(m_SpecificICstOrSplat(BitWidth),
3887+
m_Reg(LShrAmt)))))) {
38883888
FshOpc = TargetOpcode::G_FSHL;
38893889

38903890
// Match (or (shl x, sub(bw, amt)), (lshr y, amt)).
3891-
} else if (mi_match(
3892-
Dst, MRI,
3893-
m_GOr(m_GLShr(m_Reg(LShrSrc), m_Reg(LShrAmt)),
3894-
m_GShl(m_Reg(ShlSrc), m_GSub(m_SpecificICst(BitWidth),
3895-
m_Reg(ShlAmt)))))) {
3891+
} else if (mi_match(Dst, MRI,
3892+
m_GOr(m_GLShr(m_Reg(LShrSrc), m_Reg(LShrAmt)),
3893+
m_GShl(m_Reg(ShlSrc),
3894+
m_GSub(m_SpecificICstOrSplat(BitWidth),
3895+
m_Reg(ShlAmt)))))) {
38963896
FshOpc = TargetOpcode::G_FSHR;
38973897

38983898
} else {
@@ -4543,20 +4543,9 @@ bool CombinerHelper::matchNarrowBinopFeedingAnd(
45434543
bool CombinerHelper::matchMulOBy2(MachineInstr &MI, BuildFnTy &MatchInfo) {
45444544
unsigned Opc = MI.getOpcode();
45454545
assert(Opc == TargetOpcode::G_UMULO || Opc == TargetOpcode::G_SMULO);
4546-
// Check for a constant 2 or a splat of 2 on the RHS.
4547-
auto RHS = MI.getOperand(3).getReg();
4548-
bool IsVector = MRI.getType(RHS).isVector();
4549-
if (!IsVector && !mi_match(MI.getOperand(3).getReg(), MRI, m_SpecificICst(2)))
4550-
return false;
4551-
if (IsVector) {
4552-
// FIXME: There's no mi_match pattern for this yet.
4553-
auto *RHSDef = getDefIgnoringCopies(RHS, MRI);
4554-
if (!RHSDef)
4555-
return false;
4556-
auto Splat = getBuildVectorConstantSplat(*RHSDef, MRI);
4557-
if (!Splat || *Splat != 2)
4558-
return false;
4559-
}
4546+
4547+
if (!mi_match(MI.getOperand(3).getReg(), MRI, m_SpecificICstOrSplat(2)))
4548+
return false;
45604549

45614550
MatchInfo = [=, &MI](MachineIRBuilder &B) {
45624551
Observer.changingInstr(MI);

llvm/lib/CodeGen/GlobalISel/Utils.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,16 +1030,22 @@ Optional<ValueAndVReg> getAnyConstantSplat(Register VReg,
10301030
return SplatValAndReg;
10311031
}
10321032

1033-
bool isBuildVectorConstantSplat(const MachineInstr &MI,
1034-
const MachineRegisterInfo &MRI,
1035-
int64_t SplatValue, bool AllowUndef) {
1036-
if (auto SplatValAndReg =
1037-
getAnyConstantSplat(MI.getOperand(0).getReg(), MRI, AllowUndef))
1033+
} // end anonymous namespace
1034+
1035+
bool llvm::isBuildVectorConstantSplat(const Register Reg,
1036+
const MachineRegisterInfo &MRI,
1037+
int64_t SplatValue, bool AllowUndef) {
1038+
if (auto SplatValAndReg = getAnyConstantSplat(Reg, MRI, AllowUndef))
10381039
return mi_match(SplatValAndReg->VReg, MRI, m_SpecificICst(SplatValue));
10391040
return false;
10401041
}
10411042

1042-
} // end anonymous namespace
1043+
bool llvm::isBuildVectorConstantSplat(const MachineInstr &MI,
1044+
const MachineRegisterInfo &MRI,
1045+
int64_t SplatValue, bool AllowUndef) {
1046+
return isBuildVectorConstantSplat(MI.getOperand(0).getReg(), MRI, SplatValue,
1047+
AllowUndef);
1048+
}
10431049

10441050
Optional<int64_t>
10451051
llvm::getBuildVectorConstantSplat(const MachineInstr &MI,

llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fsh.mir

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,33 @@ body: |
2727
$vgpr3 = COPY %or
2828
...
2929

30+
---
31+
name: fshl_v2i32
32+
tracksRegLiveness: true
33+
body: |
34+
bb.0:
35+
liveins: $vgpr0_vgpr1, $vgpr2_vgpr3, $vgpr4_vgpr5, $vgpr6_vgpr7
36+
37+
; CHECK-LABEL: name: fshl_v2i32
38+
; CHECK: liveins: $vgpr0_vgpr1, $vgpr2_vgpr3, $vgpr4_vgpr5, $vgpr6_vgpr7
39+
; CHECK-NEXT: {{ $}}
40+
; CHECK-NEXT: %a:_(<2 x s32>) = COPY $vgpr0_vgpr1
41+
; CHECK-NEXT: %b:_(<2 x s32>) = COPY $vgpr2_vgpr3
42+
; CHECK-NEXT: %amt:_(<2 x s32>) = COPY $vgpr4_vgpr5
43+
; CHECK-NEXT: %or:_(<2 x s32>) = G_FSHL %a, %b, %amt(<2 x s32>)
44+
; CHECK-NEXT: $vgpr6_vgpr7 = COPY %or(<2 x s32>)
45+
%a:_(<2 x s32>) = COPY $vgpr0_vgpr1
46+
%b:_(<2 x s32>) = COPY $vgpr2_vgpr3
47+
%amt:_(<2 x s32>) = COPY $vgpr4_vgpr5
48+
%scalar_bw:_(s32) = G_CONSTANT i32 32
49+
%bw:_(<2 x s32>) = G_BUILD_VECTOR %scalar_bw(s32), %scalar_bw(s32)
50+
%shl:_(<2 x s32>) = G_SHL %a:_, %amt:_(<2 x s32>)
51+
%sub:_(<2 x s32>) = G_SUB %bw:_, %amt:_
52+
%lshr:_(<2 x s32>) = G_LSHR %b:_, %sub:_(<2 x s32>)
53+
%or:_(<2 x s32>) = G_OR %shl:_, %lshr:_
54+
$vgpr6_vgpr7 = COPY %or
55+
...
56+
3057
---
3158
name: fshl_commute_i32
3259
tracksRegLiveness: true

llvm/test/CodeGen/AMDGPU/GlobalISel/combine-rot.mir

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,31 @@ body: |
2525
$vgpr2 = COPY %or
2626
...
2727

28+
---
29+
name: rotl_v2i32
30+
tracksRegLiveness: true
31+
body: |
32+
bb.0:
33+
liveins: $vgpr0_vgpr1, $vgpr2_vgpr3, $vgpr4_vgpr5
34+
35+
; CHECK-LABEL: name: rotl_v2i32
36+
; CHECK: liveins: $vgpr0_vgpr1, $vgpr2_vgpr3, $vgpr4_vgpr5
37+
; CHECK-NEXT: {{ $}}
38+
; CHECK-NEXT: %a:_(<2 x s32>) = COPY $vgpr0_vgpr1
39+
; CHECK-NEXT: %amt:_(<2 x s32>) = COPY $vgpr2_vgpr3
40+
; CHECK-NEXT: %or:_(<2 x s32>) = G_ROTL %a, %amt(<2 x s32>)
41+
; CHECK-NEXT: $vgpr4_vgpr5 = COPY %or(<2 x s32>)
42+
%a:_(<2 x s32>) = COPY $vgpr0_vgpr1
43+
%amt:_(<2 x s32>) = COPY $vgpr2_vgpr3
44+
%scalar_bw:_(s32) = G_CONSTANT i32 32
45+
%bw:_(<2 x s32>) = G_BUILD_VECTOR %scalar_bw(s32), %scalar_bw(s32)
46+
%shl:_(<2 x s32>) = G_SHL %a:_, %amt:_(<2 x s32>)
47+
%sub:_(<2 x s32>) = G_SUB %bw:_, %amt:_
48+
%lshr:_(<2 x s32>) = G_LSHR %a:_, %sub:_(<2 x s32>)
49+
%or:_(<2 x s32>) = G_OR %shl:_, %lshr:_
50+
$vgpr4_vgpr5 = COPY %or
51+
...
52+
2853
---
2954
name: rotl_commute_i32
3055
tracksRegLiveness: true
@@ -55,6 +80,7 @@ tracksRegLiveness: true
5580
body: |
5681
bb.0:
5782
liveins: $vgpr0, $vgpr1, $vgpr2
83+
5884
; CHECK-LABEL: name: rotr_i32
5985
; CHECK: liveins: $vgpr0, $vgpr1, $vgpr2
6086
; CHECK-NEXT: {{ $}}

llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,67 @@ TEST_F(AArch64GISelMITest, MatchSpecificConstant) {
533533
EXPECT_FALSE(mi_match(MIBAdd.getReg(1), *MRI, m_SpecificICst(42)));
534534
}
535535

536+
TEST_F(AArch64GISelMITest, MatchSpecificConstantSplat) {
537+
setUp();
538+
if (!TM)
539+
return;
540+
541+
LLT s64 = LLT::scalar(64);
542+
LLT v4s64 = LLT::fixed_vector(4, s64);
543+
544+
MachineInstrBuilder FortyTwoSplat =
545+
B.buildSplatVector(v4s64, B.buildConstant(s64, 42));
546+
MachineInstrBuilder FortyTwo = B.buildConstant(s64, 42);
547+
548+
EXPECT_TRUE(mi_match(FortyTwoSplat.getReg(0), *MRI, m_SpecificICstSplat(42)));
549+
EXPECT_FALSE(
550+
mi_match(FortyTwoSplat.getReg(0), *MRI, m_SpecificICstSplat(43)));
551+
EXPECT_FALSE(mi_match(FortyTwo.getReg(0), *MRI, m_SpecificICstSplat(42)));
552+
553+
MachineInstrBuilder NonConstantSplat =
554+
B.buildBuildVector(v4s64, {Copies[0], Copies[0], Copies[0], Copies[0]});
555+
556+
MachineInstrBuilder AddSplat =
557+
B.buildAdd(v4s64, NonConstantSplat, FortyTwoSplat);
558+
EXPECT_TRUE(mi_match(AddSplat.getReg(2), *MRI, m_SpecificICstSplat(42)));
559+
EXPECT_FALSE(mi_match(AddSplat.getReg(2), *MRI, m_SpecificICstSplat(43)));
560+
EXPECT_FALSE(mi_match(AddSplat.getReg(1), *MRI, m_SpecificICstSplat(42)));
561+
562+
MachineInstrBuilder Add = B.buildAdd(s64, Copies[0], FortyTwo);
563+
EXPECT_FALSE(mi_match(Add.getReg(2), *MRI, m_SpecificICstSplat(42)));
564+
}
565+
566+
TEST_F(AArch64GISelMITest, MatchSpecificConstantOrSplat) {
567+
setUp();
568+
if (!TM)
569+
return;
570+
571+
LLT s64 = LLT::scalar(64);
572+
LLT v4s64 = LLT::fixed_vector(4, s64);
573+
574+
MachineInstrBuilder FortyTwoSplat =
575+
B.buildSplatVector(v4s64, B.buildConstant(s64, 42));
576+
MachineInstrBuilder FortyTwo = B.buildConstant(s64, 42);
577+
578+
EXPECT_TRUE(
579+
mi_match(FortyTwoSplat.getReg(0), *MRI, m_SpecificICstOrSplat(42)));
580+
EXPECT_FALSE(
581+
mi_match(FortyTwoSplat.getReg(0), *MRI, m_SpecificICstOrSplat(43)));
582+
EXPECT_TRUE(mi_match(FortyTwo.getReg(0), *MRI, m_SpecificICstOrSplat(42)));
583+
584+
MachineInstrBuilder NonConstantSplat =
585+
B.buildBuildVector(v4s64, {Copies[0], Copies[0], Copies[0], Copies[0]});
586+
587+
MachineInstrBuilder AddSplat =
588+
B.buildAdd(v4s64, NonConstantSplat, FortyTwoSplat);
589+
EXPECT_TRUE(mi_match(AddSplat.getReg(2), *MRI, m_SpecificICstOrSplat(42)));
590+
EXPECT_FALSE(mi_match(AddSplat.getReg(2), *MRI, m_SpecificICstOrSplat(43)));
591+
EXPECT_FALSE(mi_match(AddSplat.getReg(1), *MRI, m_SpecificICstOrSplat(42)));
592+
593+
MachineInstrBuilder Add = B.buildAdd(s64, Copies[0], FortyTwo);
594+
EXPECT_TRUE(mi_match(Add.getReg(2), *MRI, m_SpecificICstOrSplat(42)));
595+
}
596+
536597
TEST_F(AArch64GISelMITest, MatchZeroInt) {
537598
setUp();
538599
if (!TM)

0 commit comments

Comments
 (0)