Skip to content

Commit 6f0a946

Browse files
committed
[InstCombine] Fold reconstruction across select
1 parent 683da5c commit 6f0a946

File tree

2 files changed

+40
-24
lines changed

2 files changed

+40
-24
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,37 @@ Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
13491349
return nullptr;
13501350
};
13511351

1352+
// Special case for reconstructing across a select:
1353+
// (Cond ? V1 : (X & Mask)) op
1354+
// zext (Cond ? V2 : trunc X)
1355+
// -> (Cond ? (V1 op zext V2) : ((X & Mask) op zext trunc X))
1356+
auto foldReconstruction = [&](Value *V1, Value *Masked,
1357+
Value *ZExtSel) -> Value * {
1358+
Value *X;
1359+
if (!match(Masked, m_OneUse(m_And(m_Value(X), m_Constant()))))
1360+
return nullptr;
1361+
1362+
Value *V2, *Trunc;
1363+
if (!match(ZExtSel, m_ZExt(m_OneUse(m_Select(m_Specific(Cond), m_Value(V2),
1364+
m_Value(Trunc))))))
1365+
return nullptr;
1366+
1367+
if (!match(Trunc, m_Trunc(m_Specific(X))))
1368+
return nullptr;
1369+
1370+
Value *ZExtTrue = Builder.CreateZExt(V2, V1->getType());
1371+
Value *True;
1372+
if (!(True = simplifyBinOp(Opcode, V1, ZExtTrue, FMF, Q)))
1373+
True = Builder.CreateOr(V1, ZExtTrue);
1374+
1375+
Value *ZExtFalse = Builder.CreateZExt(Trunc, V1->getType());
1376+
Value *False;
1377+
if (!(False = simplifyBinOp(Opcode, Masked, ZExtFalse, FMF, Q)))
1378+
False = Builder.CreateOr(Masked, ZExtFalse);
1379+
1380+
return Builder.CreateSelect(Cond, True, False, I.getName());
1381+
};
1382+
13521383
if (LHSIsSelect && RHSIsSelect && A == D) {
13531384
// (A ? B : C) op (A ? E : F) -> A ? (B op E) : (C op F)
13541385
Cond = A;
@@ -1368,13 +1399,17 @@ Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
13681399
False = simplifyBinOp(Opcode, C, RHS, FMF, Q);
13691400
if (Value *NewSel = foldAddNegate(B, C, RHS))
13701401
return NewSel;
1402+
if (Value *NewSel = foldReconstruction(B, C, RHS))
1403+
return NewSel;
13711404
} else if (RHSIsSelect && RHS->hasOneUse()) {
13721405
// X op (D ? E : F) -> D ? (X op E) : (X op F)
13731406
Cond = D;
13741407
True = simplifyBinOp(Opcode, LHS, E, FMF, Q);
13751408
False = simplifyBinOp(Opcode, LHS, F, FMF, Q);
13761409
if (Value *NewSel = foldAddNegate(E, F, LHS))
13771410
return NewSel;
1411+
if (Value *NewSel = foldReconstruction(E, F, LHS))
1412+
return NewSel;
13781413
}
13791414

13801415
if (!True || !False)

llvm/test/Transforms/InstCombine/select-reconstruction.ll

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ define i40 @select_reconstruction_i40(i40 %arg0) {
66
; CHECK-SAME: i40 [[ARG0:%.*]]) {
77
; CHECK-NEXT: [[TMP1:%.*]] = trunc i40 [[ARG0]] to i8
88
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 2
9-
; CHECK-NEXT: [[TMP7:%.*]] = and i40 [[ARG0]], -256
10-
; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i8 0, i8 [[TMP1]]
11-
; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], i40 0, i40 [[TMP7]]
12-
; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP4]] to i40
13-
; CHECK-NEXT: [[TMP3:%.*]] = or disjoint i40 [[TMP5]], [[TMP6]]
9+
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i40 0, i40 [[ARG0]]
1410
; CHECK-NEXT: ret i40 [[TMP3]]
1511
;
1612
%1 = trunc i40 %arg0 to i8
@@ -28,11 +24,7 @@ define i40 @select_reconstruction_any_cmp_val(i40 %arg0, i8 %arg1) {
2824
; CHECK-SAME: i40 [[ARG0:%.*]], i8 [[ARG1:%.*]]) {
2925
; CHECK-NEXT: [[TMP1:%.*]] = trunc i40 [[ARG0]] to i8
3026
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[ARG1]], [[TMP1]]
31-
; CHECK-NEXT: [[TMP7:%.*]] = and i40 [[ARG0]], -256
32-
; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i8 0, i8 [[TMP1]]
33-
; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], i40 0, i40 [[TMP7]]
34-
; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP4]] to i40
35-
; CHECK-NEXT: [[TMP3:%.*]] = or disjoint i40 [[TMP5]], [[TMP6]]
27+
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i40 0, i40 [[ARG0]]
3628
; CHECK-NEXT: ret i40 [[TMP3]]
3729
;
3830
%1 = trunc i40 %arg0 to i8
@@ -51,11 +43,8 @@ define i40 @select_reconstruction_257_mask(i40 %arg0) {
5143
; CHECK-NEXT: [[TMP1:%.*]] = trunc i40 [[ARG0]] to i8
5244
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 2
5345
; CHECK-NEXT: [[TMP3:%.*]] = and i40 [[ARG0]], -257
54-
; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], i8 0, i8 [[TMP1]]
5546
; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i40 0, i40 [[TMP3]]
56-
; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i40
57-
; CHECK-NEXT: [[TMP7:%.*]] = or disjoint i40 [[TMP4]], [[TMP6]]
58-
; CHECK-NEXT: ret i40 [[TMP7]]
47+
; CHECK-NEXT: ret i40 [[TMP4]]
5948
;
6049
%1 = trunc i40 %arg0 to i8
6150
%2 = icmp eq i8 %1, 2
@@ -72,11 +61,7 @@ define i40 @select_reconstruction_i16_mask(i40 %arg0) {
7261
; CHECK-SAME: i40 [[ARG0:%.*]]) {
7362
; CHECK-NEXT: [[TMP1:%.*]] = trunc i40 [[ARG0]] to i16
7463
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i16 [[TMP1]], 2
75-
; CHECK-NEXT: [[TMP7:%.*]] = and i40 [[ARG0]], -65356
76-
; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i16 0, i16 [[TMP1]]
77-
; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], i40 0, i40 [[TMP7]]
78-
; CHECK-NEXT: [[TMP6:%.*]] = zext i16 [[TMP4]] to i40
79-
; CHECK-NEXT: [[TMP3:%.*]] = or disjoint i40 [[TMP5]], [[TMP6]]
64+
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i40 0, i40 [[ARG0]]
8065
; CHECK-NEXT: ret i40 [[TMP3]]
8166
;
8267
%1 = trunc i40 %arg0 to i16
@@ -94,11 +79,7 @@ define <2 x i32> @select_reconstruction_vec_any_cmp_val(<2 x i32> %arg0, <2 x i8
9479
; CHECK-SAME: <2 x i32> [[ARG0:%.*]], <2 x i8> [[ARG1:%.*]]) {
9580
; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[ARG0]] to <2 x i8>
9681
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i8> [[ARG1]], [[TMP1]]
97-
; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[ARG0]], splat (i32 -256)
98-
; CHECK-NEXT: [[TMP4:%.*]] = select <2 x i1> [[TMP2]], <2 x i8> zeroinitializer, <2 x i8> [[TMP1]]
99-
; CHECK-NEXT: [[TMP5:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> zeroinitializer, <2 x i32> [[TMP3]]
100-
; CHECK-NEXT: [[TMP6:%.*]] = zext <2 x i8> [[TMP4]] to <2 x i32>
101-
; CHECK-NEXT: [[TMP7:%.*]] = or disjoint <2 x i32> [[TMP5]], [[TMP6]]
82+
; CHECK-NEXT: [[TMP7:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> zeroinitializer, <2 x i32> [[ARG0]]
10283
; CHECK-NEXT: ret <2 x i32> [[TMP7]]
10384
;
10485
%1 = trunc <2 x i32> %arg0 to <2 x i8>

0 commit comments

Comments
 (0)