Skip to content

Commit b09e63b

Browse files
committed
[AArch64][GlobalISel] Implement combines for boolean G_SELECT->bitwise ops.
Differential Revision: https://reviews.llvm.org/D117160
1 parent fa0f90b commit b09e63b

File tree

5 files changed

+278
-26
lines changed

5 files changed

+278
-26
lines changed

llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,9 @@ class CombinerHelper {
727727
bool matchCombineFSubFpExtFNegFMulToFMadOrFMA(MachineInstr &MI,
728728
BuildFnTy &MatchInfo);
729729

730+
/// Fold boolean selects to logical operations.
731+
bool matchSelectToLogical(MachineInstr &MI, BuildFnTy &MatchInfo);
732+
730733
private:
731734
/// Given a non-indexed load or store instruction \p MI, find an offset that
732735
/// can be usefully and legally folded into it as a post-indexing operation.

llvm/include/llvm/Target/GlobalISel/Combine.td

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,13 @@ def select_constant_cmp: GICombineRule<
284284
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, ${matchinfo}); }])
285285
>;
286286

287+
def select_to_logical : GICombineRule<
288+
(defs root:$root, build_fn_matchinfo:$matchinfo),
289+
(match (wip_match_opcode G_SELECT):$root,
290+
[{ return Helper.matchSelectToLogical(*${root}, ${matchinfo}); }]),
291+
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])
292+
>;
293+
287294
// Fold x op 0 -> x
288295
def right_identity_zero: GICombineRule<
289296
(defs root:$root),
@@ -907,7 +914,8 @@ def width_reduction_combines : GICombineGroup<[reduce_shl_of_extend,
907914

908915
def phi_combines : GICombineGroup<[extend_through_phis]>;
909916

910-
def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp]>;
917+
def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp,
918+
select_to_logical]>;
911919

912920
def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd,
913921
mul_by_neg_one]>;

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5539,6 +5539,63 @@ bool CombinerHelper::matchCombineFSubFpExtFNegFMulToFMadOrFMA(
55395539
return false;
55405540
}
55415541

5542+
bool CombinerHelper::matchSelectToLogical(MachineInstr &MI,
5543+
BuildFnTy &MatchInfo) {
5544+
GSelect &Sel = cast<GSelect>(MI);
5545+
Register DstReg = Sel.getReg(0);
5546+
Register Cond = Sel.getCondReg();
5547+
Register TrueReg = Sel.getTrueReg();
5548+
Register FalseReg = Sel.getFalseReg();
5549+
5550+
auto *TrueDef = getDefIgnoringCopies(TrueReg, MRI);
5551+
auto *FalseDef = getDefIgnoringCopies(FalseReg, MRI);
5552+
5553+
const LLT CondTy = MRI.getType(Cond);
5554+
const LLT OpTy = MRI.getType(TrueReg);
5555+
if (CondTy != OpTy || OpTy.getScalarSizeInBits() != 1)
5556+
return false;
5557+
5558+
// We have a boolean select.
5559+
5560+
// select Cond, Cond, F --> or Cond, F
5561+
// select Cond, 1, F --> or Cond, F
5562+
auto MaybeCstTrue = isConstantOrConstantSplatVector(*TrueDef, MRI);
5563+
if (Cond == TrueReg || (MaybeCstTrue && MaybeCstTrue->isOne())) {
5564+
MatchInfo = [=](MachineIRBuilder &MIB) {
5565+
MIB.buildOr(DstReg, Cond, FalseReg);
5566+
};
5567+
return true;
5568+
}
5569+
5570+
// select Cond, T, Cond --> and Cond, T
5571+
// select Cond, T, 0 --> and Cond, T
5572+
auto MaybeCstFalse = isConstantOrConstantSplatVector(*FalseDef, MRI);
5573+
if (Cond == FalseReg || (MaybeCstFalse && MaybeCstFalse->isZero())) {
5574+
MatchInfo = [=](MachineIRBuilder &MIB) {
5575+
MIB.buildAnd(DstReg, Cond, TrueReg);
5576+
};
5577+
return true;
5578+
}
5579+
5580+
// select Cond, T, 1 --> or (not Cond), T
5581+
if (MaybeCstFalse && MaybeCstFalse->isOne()) {
5582+
MatchInfo = [=](MachineIRBuilder &MIB) {
5583+
MIB.buildOr(DstReg, MIB.buildNot(OpTy, Cond), TrueReg);
5584+
};
5585+
return true;
5586+
}
5587+
5588+
// select Cond, 0, F --> and (not Cond), F
5589+
if (MaybeCstTrue && MaybeCstTrue->isZero()) {
5590+
MatchInfo = [=](MachineIRBuilder &MIB) {
5591+
MIB.buildAnd(DstReg, MIB.buildNot(OpTy, Cond), FalseReg);
5592+
};
5593+
return true;
5594+
}
5595+
return false;
5596+
}
5597+
5598+
55425599
bool CombinerHelper::tryCombine(MachineInstr &MI) {
55435600
if (tryCombineCopy(MI))
55445601
return true;

llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir

Lines changed: 181 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2-
# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
2+
# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown- --aarch64postlegalizercombinerhelper-only-enable-rule="select_to_logical" %s -o - | FileCheck %s
33
# RUN: llc -debugify-and-strip-all-safe -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
4+
# REQUIRES: asserts
45
---
56
# select (c, x, x) -> x
67
name: test_combine_select_same_res
@@ -92,3 +93,182 @@ body: |
9293
%3:_(<4 x s32>) = G_SELECT %condvec, %0, %1
9394
$q0 = COPY %3(<4 x s32>)
9495
...
96+
---
97+
# select Cond, Cond, F --> or Cond, F
98+
name: bool_cond_cond_false
99+
body: |
100+
bb.1:
101+
liveins: $x0, $x1, $x2
102+
; CHECK-LABEL: name: bool_cond_cond_false
103+
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
104+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x2
105+
; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
106+
; CHECK-NEXT: %f:_(s1) = G_TRUNC [[COPY1]](s64)
107+
; CHECK-NEXT: %sel:_(s1) = G_OR %c, %f
108+
; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
109+
; CHECK-NEXT: $w0 = COPY %ext(s32)
110+
%0:_(s64) = COPY $x0
111+
%1:_(s64) = COPY $x1
112+
%2:_(s64) = COPY $x2
113+
%c:_(s1) = G_TRUNC %0
114+
%t:_(s1) = G_TRUNC %1
115+
%f:_(s1) = G_TRUNC %2
116+
%sel:_(s1) = G_SELECT %c, %c, %f
117+
%ext:_(s32) = G_ANYEXT %sel
118+
$w0 = COPY %ext(s32)
119+
...
120+
---
121+
# select Cond, 1, F --> or Cond, F
122+
name: bool_cond_one_false
123+
body: |
124+
bb.1:
125+
liveins: $x0, $x1, $x2
126+
; CHECK-LABEL: name: bool_cond_one_false
127+
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
128+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x2
129+
; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
130+
; CHECK-NEXT: %f:_(s1) = G_TRUNC [[COPY1]](s64)
131+
; CHECK-NEXT: %sel:_(s1) = G_OR %c, %f
132+
; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
133+
; CHECK-NEXT: $w0 = COPY %ext(s32)
134+
%0:_(s64) = COPY $x0
135+
%1:_(s64) = COPY $x1
136+
%2:_(s64) = COPY $x2
137+
%c:_(s1) = G_TRUNC %0
138+
%t:_(s1) = G_TRUNC %1
139+
%f:_(s1) = G_TRUNC %2
140+
%one:_(s1) = G_CONSTANT i1 1
141+
%sel:_(s1) = G_SELECT %c, %one, %f
142+
%ext:_(s32) = G_ANYEXT %sel
143+
$w0 = COPY %ext(s32)
144+
...
145+
---
146+
# select Cond, 1, F --> or Cond, F
147+
name: bool_cond_one_false_vector
148+
body: |
149+
bb.1:
150+
liveins: $d0, $d1, $d2
151+
; CHECK-LABEL: name: bool_cond_one_false_vector
152+
; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
153+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $d2
154+
; CHECK-NEXT: %c:_(<2 x s1>) = G_TRUNC [[COPY]](<2 x s32>)
155+
; CHECK-NEXT: %f:_(<2 x s1>) = G_TRUNC [[COPY1]](<2 x s32>)
156+
; CHECK-NEXT: %sel:_(<2 x s1>) = G_OR %c, %f
157+
; CHECK-NEXT: %ext:_(<2 x s32>) = G_ANYEXT %sel(<2 x s1>)
158+
; CHECK-NEXT: $d0 = COPY %ext(<2 x s32>)
159+
%0:_(<2 x s32>) = COPY $d0
160+
%1:_(<2 x s32>) = COPY $d1
161+
%2:_(<2 x s32>) = COPY $d2
162+
%c:_(<2 x s1>) = G_TRUNC %0
163+
%t:_(<2 x s1>) = G_TRUNC %1
164+
%f:_(<2 x s1>) = G_TRUNC %2
165+
%one:_(s1) = G_CONSTANT i1 1
166+
%one_vec:_(<2 x s1>) = G_BUILD_VECTOR %one, %one
167+
%sel:_(<2 x s1>) = G_SELECT %c, %one_vec, %f
168+
%ext:_(<2 x s32>) = G_ANYEXT %sel
169+
$d0 = COPY %ext(<2 x s32>)
170+
...
171+
---
172+
# select Cond, T, Cond --> and Cond, T
173+
name: bool_cond_true_cond
174+
body: |
175+
bb.1:
176+
liveins: $x0, $x1, $x2
177+
; CHECK-LABEL: name: bool_cond_true_cond
178+
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
179+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
180+
; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
181+
; CHECK-NEXT: %t:_(s1) = G_TRUNC [[COPY1]](s64)
182+
; CHECK-NEXT: %sel:_(s1) = G_AND %c, %t
183+
; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
184+
; CHECK-NEXT: $w0 = COPY %ext(s32)
185+
%0:_(s64) = COPY $x0
186+
%1:_(s64) = COPY $x1
187+
%2:_(s64) = COPY $x2
188+
%c:_(s1) = G_TRUNC %0
189+
%t:_(s1) = G_TRUNC %1
190+
%f:_(s1) = G_TRUNC %2
191+
%one:_(s1) = G_CONSTANT i1 1
192+
%sel:_(s1) = G_SELECT %c, %t, %c
193+
%ext:_(s32) = G_ANYEXT %sel
194+
$w0 = COPY %ext(s32)
195+
...
196+
---
197+
# select Cond, T, 0 --> and Cond, T
198+
name: bool_cond_true_zero
199+
body: |
200+
bb.1:
201+
liveins: $x0, $x1, $x2
202+
; CHECK-LABEL: name: bool_cond_true_zero
203+
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
204+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
205+
; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
206+
; CHECK-NEXT: %t:_(s1) = G_TRUNC [[COPY1]](s64)
207+
; CHECK-NEXT: %sel:_(s1) = G_AND %c, %t
208+
; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
209+
; CHECK-NEXT: $w0 = COPY %ext(s32)
210+
%0:_(s64) = COPY $x0
211+
%1:_(s64) = COPY $x1
212+
%2:_(s64) = COPY $x2
213+
%c:_(s1) = G_TRUNC %0
214+
%t:_(s1) = G_TRUNC %1
215+
%f:_(s1) = G_TRUNC %2
216+
%zero:_(s1) = G_CONSTANT i1 0
217+
%sel:_(s1) = G_SELECT %c, %t, %zero
218+
%ext:_(s32) = G_ANYEXT %sel
219+
$w0 = COPY %ext(s32)
220+
...
221+
---
222+
# select Cond, T, 1 --> or (not Cond), T
223+
name: bool_cond_true_one
224+
body: |
225+
bb.1:
226+
liveins: $x0, $x1, $x2
227+
; CHECK-LABEL: name: bool_cond_true_one
228+
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
229+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
230+
; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
231+
; CHECK-NEXT: %t:_(s1) = G_TRUNC [[COPY1]](s64)
232+
; CHECK-NEXT: %one:_(s1) = G_CONSTANT i1 true
233+
; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR %c, %one
234+
; CHECK-NEXT: %sel:_(s1) = G_OR [[XOR]], %t
235+
; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
236+
; CHECK-NEXT: $w0 = COPY %ext(s32)
237+
%0:_(s64) = COPY $x0
238+
%1:_(s64) = COPY $x1
239+
%2:_(s64) = COPY $x2
240+
%c:_(s1) = G_TRUNC %0
241+
%t:_(s1) = G_TRUNC %1
242+
%f:_(s1) = G_TRUNC %2
243+
%one:_(s1) = G_CONSTANT i1 1
244+
%sel:_(s1) = G_SELECT %c, %t, %one
245+
%ext:_(s32) = G_ANYEXT %sel
246+
$w0 = COPY %ext(s32)
247+
...
248+
---
249+
# select Cond, 0, F --> and (not Cond), F
250+
name: bool_cond_zero_false
251+
body: |
252+
bb.1:
253+
liveins: $x0, $x1, $x2
254+
; CHECK-LABEL: name: bool_cond_zero_false
255+
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
256+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x2
257+
; CHECK-NEXT: %c:_(s1) = G_TRUNC [[COPY]](s64)
258+
; CHECK-NEXT: %f:_(s1) = G_TRUNC [[COPY1]](s64)
259+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s1) = G_CONSTANT i1 true
260+
; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR %c, [[C]]
261+
; CHECK-NEXT: %sel:_(s1) = G_AND [[XOR]], %f
262+
; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %sel(s1)
263+
; CHECK-NEXT: $w0 = COPY %ext(s32)
264+
%0:_(s64) = COPY $x0
265+
%1:_(s64) = COPY $x1
266+
%2:_(s64) = COPY $x2
267+
%c:_(s1) = G_TRUNC %0
268+
%t:_(s1) = G_TRUNC %1
269+
%f:_(s1) = G_TRUNC %2
270+
%zero:_(s1) = G_CONSTANT i1 0
271+
%sel:_(s1) = G_SELECT %c, %zero, %f
272+
%ext:_(s32) = G_ANYEXT %sel
273+
$w0 = COPY %ext(s32)
274+
...

0 commit comments

Comments
 (0)