Skip to content

Commit de7881e

Browse files
committed
[DAGCombiner] Combine (select c, (and X, 1), 0) -> (and (zext c), X)
The middle end canonicalizes: `(and (zext c), X)` -> `(select c, (and X, 1), 0)` But the `and` + `zext` form gets better codegen.
1 parent e3e9c94 commit de7881e

File tree

5 files changed

+157
-155
lines changed

5 files changed

+157
-155
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6299,6 +6299,33 @@ static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
62996299
return SDValue();
63006300
}
63016301

6302+
// Combine `(select c, (X & 1), 0)` -> `(and (zext c), X)`.
6303+
// We canonicalize to the `select` form in the middle end, but the `and` form
6304+
// gets better codegen and all tested targets (arm, x86, riscv)
6305+
static SDValue combineSelectAsExtAnd(SDValue Cond, SDValue T, SDValue F,
6306+
const SDLoc &DL, SelectionDAG &DAG) {
6307+
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
6308+
if (!isNullConstant(F))
6309+
return SDValue();
6310+
6311+
EVT CondVT = Cond.getValueType();
6312+
if (TLI.getBooleanContents(CondVT) !=
6313+
TargetLoweringBase::ZeroOrOneBooleanContent)
6314+
return SDValue();
6315+
6316+
if (T.getOpcode() != ISD::AND)
6317+
return SDValue();
6318+
6319+
if (!isOneConstant(T.getOperand(1)))
6320+
return SDValue();
6321+
6322+
EVT OpVT = T.getValueType();
6323+
6324+
SDValue CondMask =
6325+
OpVT == CondVT ? Cond : DAG.getBoolExtOrTrunc(Cond, DL, OpVT, CondVT);
6326+
return DAG.getNode(ISD::AND, DL, OpVT, CondMask, T.getOperand(0));
6327+
}
6328+
63026329
/// This contains all DAGCombine rules which reduce two values combined by
63036330
/// an And operation to a single value. This makes them reusable in the context
63046331
/// of visitSELECT(). Rules involving constants are not included as
@@ -11609,6 +11636,9 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) {
1160911636
if (SDValue BinOp = foldSelectOfBinops(N))
1161011637
return BinOp;
1161111638

11639+
if (SDValue R = combineSelectAsExtAnd(N0, N1, N2, DL, DAG))
11640+
return R;
11641+
1161211642
return SDValue();
1161311643
}
1161411644

llvm/test/CodeGen/AArch64/select-to-and-zext.ll

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ define i32 @from_cmpeq_fail_bad_andmask(i32 %xx, i32 %y) {
3131
define i32 @from_i1(i1 %x, i32 %y) {
3232
; CHECK-LABEL: from_i1:
3333
; CHECK: // %bb.0:
34-
; CHECK-NEXT: and w8, w1, #0x1
35-
; CHECK-NEXT: tst w0, #0x1
36-
; CHECK-NEXT: csel w0, w8, wzr, ne
34+
; CHECK-NEXT: and w8, w0, w1
35+
; CHECK-NEXT: and w0, w8, #0x1
3736
; CHECK-NEXT: ret
3837
%masked = and i32 %y, 1
3938
%r = select i1 %x, i32 %masked, i32 0
@@ -43,9 +42,8 @@ define i32 @from_i1(i1 %x, i32 %y) {
4342
define i32 @from_trunc_i8(i8 %xx, i32 %y) {
4443
; CHECK-LABEL: from_trunc_i8:
4544
; CHECK: // %bb.0:
46-
; CHECK-NEXT: and w8, w1, #0x1
47-
; CHECK-NEXT: tst w0, #0x1
48-
; CHECK-NEXT: csel w0, w8, wzr, ne
45+
; CHECK-NEXT: and w8, w0, w1
46+
; CHECK-NEXT: and w0, w8, #0x1
4947
; CHECK-NEXT: ret
5048
%masked = and i32 %y, 1
5149
%x = trunc i8 %xx to i1
@@ -56,9 +54,8 @@ define i32 @from_trunc_i8(i8 %xx, i32 %y) {
5654
define i32 @from_trunc_i64(i64 %xx, i32 %y) {
5755
; CHECK-LABEL: from_trunc_i64:
5856
; CHECK: // %bb.0:
59-
; CHECK-NEXT: and w8, w1, #0x1
60-
; CHECK-NEXT: tst w0, #0x1
61-
; CHECK-NEXT: csel w0, w8, wzr, ne
57+
; CHECK-NEXT: and w8, w0, w1
58+
; CHECK-NEXT: and w0, w8, #0x1
6259
; CHECK-NEXT: ret
6360
%masked = and i32 %y, 1
6461
%x = trunc i64 %xx to i1

llvm/test/CodeGen/RISCV/select-to-and-zext.ll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ define i32 @from_cmpeq(i32 %xx, i32 %y) {
1010
; RV32I: # %bb.0:
1111
; RV32I-NEXT: addi a0, a0, -9
1212
; RV32I-NEXT: seqz a0, a0
13-
; RV32I-NEXT: and a0, a1, a0
13+
; RV32I-NEXT: and a0, a0, a1
1414
; RV32I-NEXT: ret
1515
;
1616
; RV64I-LABEL: from_cmpeq:
1717
; RV64I: # %bb.0:
1818
; RV64I-NEXT: sext.w a0, a0
1919
; RV64I-NEXT: addi a0, a0, -9
2020
; RV64I-NEXT: seqz a0, a0
21-
; RV64I-NEXT: and a0, a1, a0
21+
; RV64I-NEXT: and a0, a0, a1
2222
; RV64I-NEXT: ret
2323
%x = icmp eq i32 %xx, 9
2424
%masked = and i32 %y, 1
@@ -55,13 +55,13 @@ define i32 @from_cmpeq_fail_bad_andmask(i32 %xx, i32 %y) {
5555
define i32 @from_i1(i1 %x, i32 %y) {
5656
; RV32I-LABEL: from_i1:
5757
; RV32I: # %bb.0:
58-
; RV32I-NEXT: and a0, a1, a0
58+
; RV32I-NEXT: and a0, a0, a1
5959
; RV32I-NEXT: andi a0, a0, 1
6060
; RV32I-NEXT: ret
6161
;
6262
; RV64I-LABEL: from_i1:
6363
; RV64I: # %bb.0:
64-
; RV64I-NEXT: and a0, a1, a0
64+
; RV64I-NEXT: and a0, a0, a1
6565
; RV64I-NEXT: andi a0, a0, 1
6666
; RV64I-NEXT: ret
6767
%masked = and i32 %y, 1
@@ -72,13 +72,13 @@ define i32 @from_i1(i1 %x, i32 %y) {
7272
define i32 @from_trunc_i8(i8 %xx, i32 %y) {
7373
; RV32I-LABEL: from_trunc_i8:
7474
; RV32I: # %bb.0:
75-
; RV32I-NEXT: and a0, a1, a0
75+
; RV32I-NEXT: and a0, a0, a1
7676
; RV32I-NEXT: andi a0, a0, 1
7777
; RV32I-NEXT: ret
7878
;
7979
; RV64I-LABEL: from_trunc_i8:
8080
; RV64I: # %bb.0:
81-
; RV64I-NEXT: and a0, a1, a0
81+
; RV64I-NEXT: and a0, a0, a1
8282
; RV64I-NEXT: andi a0, a0, 1
8383
; RV64I-NEXT: ret
8484
%masked = and i32 %y, 1
@@ -90,13 +90,13 @@ define i32 @from_trunc_i8(i8 %xx, i32 %y) {
9090
define i32 @from_trunc_i64(i64 %xx, i32 %y) {
9191
; RV32I-LABEL: from_trunc_i64:
9292
; RV32I: # %bb.0:
93-
; RV32I-NEXT: and a0, a2, a0
93+
; RV32I-NEXT: and a0, a0, a2
9494
; RV32I-NEXT: andi a0, a0, 1
9595
; RV32I-NEXT: ret
9696
;
9797
; RV64I-LABEL: from_trunc_i64:
9898
; RV64I: # %bb.0:
99-
; RV64I-NEXT: and a0, a1, a0
99+
; RV64I-NEXT: and a0, a0, a1
100100
; RV64I-NEXT: andi a0, a0, 1
101101
; RV64I-NEXT: ret
102102
%masked = and i32 %y, 1

llvm/test/CodeGen/SystemZ/pr60413.ll

Lines changed: 95 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -13,118 +13,114 @@ declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #0
1313
define dso_local void @m() local_unnamed_addr #1 {
1414
; CHECK-LABEL: m:
1515
; CHECK: # %bb.0: # %entry
16-
; CHECK-NEXT: stmg %r13, %r15, 104(%r15)
16+
; CHECK-NEXT: stmg %r12, %r15, 96(%r15)
1717
; CHECK-NEXT: aghi %r15, -168
18-
; CHECK-NEXT: llhrl %r1, f+4
19-
; CHECK-NEXT: sll %r1, 8
20-
; CHECK-NEXT: larl %r2, f
21-
; CHECK-NEXT: ic %r1, 6(%r2)
22-
; CHECK-NEXT: lr %r0, %r1
23-
; CHECK-NEXT: nilh %r0, 255
24-
; CHECK-NEXT: vlvgp %v1, %r1, %r0
25-
; CHECK-NEXT: vlvgf %v1, %r1, 0
26-
; CHECK-NEXT: vlvgf %v1, %r1, 2
27-
; CHECK-NEXT: vlvgp %v0, %r0, %r1
18+
; CHECK-NEXT: llhrl %r2, f+4
19+
; CHECK-NEXT: sll %r2, 8
20+
; CHECK-NEXT: larl %r1, f
21+
; CHECK-NEXT: ic %r2, 6(%r1)
22+
; CHECK-NEXT: larl %r1, e
23+
; CHECK-NEXT: lb %r0, 3(%r1)
24+
; CHECK-NEXT: clfi %r2, 128
25+
; CHECK-NEXT: ipm %r1
26+
; CHECK-NEXT: risbg %r1, %r1, 63, 191, 36
27+
; CHECK-NEXT: vlvgp %v1, %r2, %r0
28+
; CHECK-NEXT: vlvgf %v1, %r2, 0
29+
; CHECK-NEXT: vlvgf %v1, %r2, 2
30+
; CHECK-NEXT: vlvgp %v0, %r0, %r2
31+
; CHECK-NEXT: vlvgp %v2, %r2, %r2
32+
; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d
33+
; CHECK-NEXT: nilh %r2, 255
34+
; CHECK-NEXT: chi %r2, 128
35+
; CHECK-NEXT: ipm %r2
36+
; CHECK-NEXT: risbg %r2, %r2, 63, 191, 36
2837
; CHECK-NEXT: vlvgf %v0, %r0, 0
2938
; CHECK-NEXT: vlvgf %v0, %r0, 2
30-
; CHECK-NEXT: vlvgp %v2, %r1, %r1
3139
; CHECK-NEXT: vrepf %v2, %v2, 1
3240
; CHECK-NEXT: vgbm %v3, 30583
3341
; CHECK-NEXT: vn %v0, %v0, %v3
3442
; CHECK-NEXT: vn %v1, %v1, %v3
3543
; CHECK-NEXT: vn %v2, %v2, %v3
3644
; CHECK-NEXT: vrepif %v3, 127
3745
; CHECK-NEXT: vchlf %v1, %v1, %v3
38-
; CHECK-NEXT: vlgvf %r13, %v1, 0
46+
; CHECK-NEXT: vlgvf %r12, %v1, 0
3947
; CHECK-NEXT: vchlf %v2, %v2, %v3
40-
; CHECK-NEXT: vlgvf %r3, %v2, 1
41-
; CHECK-NEXT: nilf %r3, 1
42-
; CHECK-NEXT: vlgvf %r4, %v2, 0
43-
; CHECK-NEXT: risbg %r2, %r4, 48, 176, 15
44-
; CHECK-NEXT: rosbg %r2, %r3, 32, 49, 14
45-
; CHECK-NEXT: vlgvf %r5, %v2, 2
46-
; CHECK-NEXT: nilf %r5, 1
47-
; CHECK-NEXT: rosbg %r2, %r5, 32, 50, 13
48-
; CHECK-NEXT: vlgvf %r14, %v2, 3
48+
; CHECK-NEXT: vlgvf %r4, %v2, 1
49+
; CHECK-NEXT: nilf %r4, 1
50+
; CHECK-NEXT: vlgvf %r5, %v2, 0
51+
; CHECK-NEXT: risbg %r3, %r5, 48, 176, 15
52+
; CHECK-NEXT: rosbg %r3, %r4, 32, 49, 14
53+
; CHECK-NEXT: vlgvf %r14, %v2, 2
4954
; CHECK-NEXT: nilf %r14, 1
50-
; CHECK-NEXT: rosbg %r2, %r14, 32, 51, 12
51-
; CHECK-NEXT: rosbg %r2, %r13, 52, 52, 11
52-
; CHECK-NEXT: vlgvf %r13, %v1, 1
53-
; CHECK-NEXT: rosbg %r2, %r13, 53, 53, 10
54-
; CHECK-NEXT: vlgvf %r13, %v1, 2
55-
; CHECK-NEXT: rosbg %r2, %r13, 54, 54, 9
56-
; CHECK-NEXT: vlgvf %r13, %v1, 3
57-
; CHECK-NEXT: rosbg %r2, %r13, 55, 55, 8
55+
; CHECK-NEXT: rosbg %r3, %r14, 32, 50, 13
56+
; CHECK-NEXT: vlgvf %r13, %v2, 3
57+
; CHECK-NEXT: nilf %r13, 1
58+
; CHECK-NEXT: rosbg %r3, %r13, 32, 51, 12
59+
; CHECK-NEXT: rosbg %r3, %r12, 52, 52, 11
60+
; CHECK-NEXT: vlgvf %r12, %v1, 1
61+
; CHECK-NEXT: rosbg %r3, %r12, 53, 53, 10
62+
; CHECK-NEXT: vlgvf %r12, %v1, 2
63+
; CHECK-NEXT: rosbg %r3, %r12, 54, 54, 9
64+
; CHECK-NEXT: vlgvf %r12, %v1, 3
65+
; CHECK-NEXT: rosbg %r3, %r12, 55, 55, 8
5866
; CHECK-NEXT: vchlf %v0, %v0, %v3
59-
; CHECK-NEXT: vlgvf %r13, %v0, 0
60-
; CHECK-NEXT: rosbg %r2, %r13, 56, 56, 7
61-
; CHECK-NEXT: vlgvf %r13, %v0, 1
62-
; CHECK-NEXT: rosbg %r2, %r13, 57, 57, 6
63-
; CHECK-NEXT: vlgvf %r13, %v0, 2
64-
; CHECK-NEXT: rosbg %r2, %r13, 58, 58, 5
65-
; CHECK-NEXT: vlgvf %r13, %v0, 3
66-
; CHECK-NEXT: rosbg %r2, %r13, 59, 59, 4
67-
; CHECK-NEXT: nilf %r4, 1
68-
; CHECK-NEXT: rosbg %r2, %r4, 32, 60, 3
69-
; CHECK-NEXT: rosbg %r2, %r3, 32, 61, 2
70-
; CHECK-NEXT: rosbg %r2, %r5, 32, 62, 1
71-
; CHECK-NEXT: or %r2, %r14
72-
; CHECK-NEXT: vlgvb %r4, %v0, 1
73-
; CHECK-NEXT: vlgvb %r3, %v0, 0
74-
; CHECK-NEXT: risbg %r3, %r3, 48, 176, 15
75-
; CHECK-NEXT: rosbg %r3, %r4, 49, 49, 14
76-
; CHECK-NEXT: vlgvb %r4, %v0, 2
77-
; CHECK-NEXT: rosbg %r3, %r4, 50, 50, 13
78-
; CHECK-NEXT: vlgvb %r4, %v0, 3
79-
; CHECK-NEXT: rosbg %r3, %r4, 51, 51, 12
80-
; CHECK-NEXT: vlgvb %r4, %v0, 4
81-
; CHECK-NEXT: rosbg %r3, %r4, 52, 52, 11
82-
; CHECK-NEXT: vlgvb %r4, %v0, 5
83-
; CHECK-NEXT: rosbg %r3, %r4, 53, 53, 10
84-
; CHECK-NEXT: vlgvb %r4, %v0, 6
85-
; CHECK-NEXT: rosbg %r3, %r4, 54, 54, 9
86-
; CHECK-NEXT: vlgvb %r4, %v0, 7
87-
; CHECK-NEXT: rosbg %r3, %r4, 55, 55, 8
88-
; CHECK-NEXT: vlgvb %r4, %v0, 8
89-
; CHECK-NEXT: rosbg %r3, %r4, 56, 56, 7
90-
; CHECK-NEXT: vlgvb %r4, %v0, 9
91-
; CHECK-NEXT: rosbg %r3, %r4, 57, 57, 6
92-
; CHECK-NEXT: vlgvb %r4, %v0, 10
93-
; CHECK-NEXT: rosbg %r3, %r4, 58, 58, 5
94-
; CHECK-NEXT: vlgvb %r4, %v0, 11
95-
; CHECK-NEXT: rosbg %r3, %r4, 59, 59, 4
96-
; CHECK-NEXT: vlgvb %r4, %v0, 12
97-
; CHECK-NEXT: rosbg %r3, %r4, 60, 60, 3
98-
; CHECK-NEXT: vlgvb %r4, %v0, 13
99-
; CHECK-NEXT: rosbg %r3, %r4, 61, 61, 2
100-
; CHECK-NEXT: vlgvb %r4, %v0, 14
101-
; CHECK-NEXT: rosbg %r3, %r4, 62, 62, 1
102-
; CHECK-NEXT: vlgvb %r4, %v0, 15
103-
; CHECK-NEXT: rosbg %r3, %r4, 63, 63, 0
104-
; CHECK-NEXT: xilf %r3, 4294967295
105-
; CHECK-NEXT: clijhe %r1, 128, .LBB0_2
106-
; CHECK-NEXT: # %bb.1:
107-
; CHECK-NEXT: larl %r1, e
108-
; CHECK-NEXT: llc %r1, 3(%r1)
109-
; CHECK-NEXT: nilf %r1, 1
110-
; CHECK-NEXT: j .LBB0_3
111-
; CHECK-NEXT: .LBB0_2: # %entry
112-
; CHECK-NEXT: lhi %r1, 0
113-
; CHECK-NEXT: .LBB0_3: # %entry
114-
; CHECK-NEXT: or %r2, %r3
115-
; CHECK-NEXT: chi %r0, 128
116-
; CHECK-NEXT: jl .LBB0_5
117-
; CHECK-NEXT: # %bb.4: # %entry
118-
; CHECK-NEXT: lhi %r1, 0
119-
; CHECK-NEXT: .LBB0_5: # %entry
120-
; CHECK-NEXT: tmll %r2, 65535
121-
; CHECK-NEXT: je .LBB0_7
122-
; CHECK-NEXT: # %bb.6: # %entry
123-
; CHECK-NEXT: lhi %r1, 0
124-
; CHECK-NEXT: .LBB0_7: # %entry
125-
; CHECK-NEXT: larl %r2, g
126-
; CHECK-NEXT: stc %r1, 0(%r2)
127-
; CHECK-NEXT: lmg %r13, %r15, 272(%r15)
67+
; CHECK-NEXT: vlgvf %r12, %v0, 0
68+
; CHECK-NEXT: rosbg %r3, %r12, 56, 56, 7
69+
; CHECK-NEXT: vlgvf %r12, %v0, 1
70+
; CHECK-NEXT: rosbg %r3, %r12, 57, 57, 6
71+
; CHECK-NEXT: vlgvf %r12, %v0, 2
72+
; CHECK-NEXT: rosbg %r3, %r12, 58, 58, 5
73+
; CHECK-NEXT: vlgvf %r12, %v0, 3
74+
; CHECK-NEXT: rosbg %r3, %r12, 59, 59, 4
75+
; CHECK-NEXT: nilf %r5, 1
76+
; CHECK-NEXT: rosbg %r3, %r5, 32, 60, 3
77+
; CHECK-NEXT: rosbg %r3, %r4, 32, 61, 2
78+
; CHECK-NEXT: rosbg %r3, %r14, 32, 62, 1
79+
; CHECK-NEXT: or %r3, %r13
80+
; CHECK-NEXT: vlgvb %r5, %v0, 1
81+
; CHECK-NEXT: vlgvb %r4, %v0, 0
82+
; CHECK-NEXT: risbg %r4, %r4, 48, 176, 15
83+
; CHECK-NEXT: rosbg %r4, %r5, 49, 49, 14
84+
; CHECK-NEXT: vlgvb %r5, %v0, 2
85+
; CHECK-NEXT: rosbg %r4, %r5, 50, 50, 13
86+
; CHECK-NEXT: vlgvb %r5, %v0, 3
87+
; CHECK-NEXT: rosbg %r4, %r5, 51, 51, 12
88+
; CHECK-NEXT: vlgvb %r5, %v0, 4
89+
; CHECK-NEXT: rosbg %r4, %r5, 52, 52, 11
90+
; CHECK-NEXT: vlgvb %r5, %v0, 5
91+
; CHECK-NEXT: rosbg %r4, %r5, 53, 53, 10
92+
; CHECK-NEXT: vlgvb %r5, %v0, 6
93+
; CHECK-NEXT: rosbg %r4, %r5, 54, 54, 9
94+
; CHECK-NEXT: vlgvb %r5, %v0, 7
95+
; CHECK-NEXT: rosbg %r4, %r5, 55, 55, 8
96+
; CHECK-NEXT: vlgvb %r5, %v0, 8
97+
; CHECK-NEXT: rosbg %r4, %r5, 56, 56, 7
98+
; CHECK-NEXT: vlgvb %r5, %v0, 9
99+
; CHECK-NEXT: rosbg %r4, %r5, 57, 57, 6
100+
; CHECK-NEXT: vlgvb %r5, %v0, 10
101+
; CHECK-NEXT: rosbg %r4, %r5, 58, 58, 5
102+
; CHECK-NEXT: vlgvb %r5, %v0, 11
103+
; CHECK-NEXT: rosbg %r4, %r5, 59, 59, 4
104+
; CHECK-NEXT: vlgvb %r5, %v0, 12
105+
; CHECK-NEXT: rosbg %r4, %r5, 60, 60, 3
106+
; CHECK-NEXT: vlgvb %r5, %v0, 13
107+
; CHECK-NEXT: rosbg %r4, %r5, 61, 61, 2
108+
; CHECK-NEXT: vlgvb %r5, %v0, 14
109+
; CHECK-NEXT: rosbg %r4, %r5, 62, 62, 1
110+
; CHECK-NEXT: vlgvb %r5, %v0, 15
111+
; CHECK-NEXT: rosbg %r4, %r5, 63, 63, 0
112+
; CHECK-NEXT: xilf %r4, 4294967295
113+
; CHECK-NEXT: or %r4, %r3
114+
; CHECK-NEXT: tmll %r4, 65535
115+
; CHECK-NEXT: ipm %r3
116+
; CHECK-NEXT: afi %r3, -268435456
117+
; CHECK-NEXT: srl %r3, 31
118+
; CHECK-NEXT: nr %r2, %r1
119+
; CHECK-NEXT: nr %r2, %r3
120+
; CHECK-NEXT: nr %r2, %r0
121+
; CHECK-NEXT: larl %r1, g
122+
; CHECK-NEXT: stc %r2, 0(%r1)
123+
; CHECK-NEXT: lmg %r12, %r15, 264(%r15)
128124
; CHECK-NEXT: br %r14
129125
entry:
130126
%n = alloca i32, align 4

0 commit comments

Comments
 (0)