Skip to content

Commit 682fa79

Browse files
authored
InstCombine/Select: remove redundant code (NFC) (#112388)
InstCombinerImpl::foldSelectInstWithICmp has some inlined code for select-icmp-xor simplification, but this simplification is already done by other code, via another path: (X & Y) == 0 ? X : X ^ Y -> ((X & Y) == 0 ? 0 : Y) ^ X -> (X & Y) ^ X -> X & ~Y Cover the cases that it claims to simplify, and demonstrate that stripping it doesn't cause test changes.
1 parent 0936195 commit 682fa79

File tree

2 files changed

+190
-50
lines changed

2 files changed

+190
-50
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1954,56 +1954,6 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
19541954
return &SI;
19551955
}
19561956

1957-
// FIXME: This code is nearly duplicated in InstSimplify. Using/refactoring
1958-
// decomposeBitTestICmp() might help.
1959-
if (TrueVal->getType()->isIntOrIntVectorTy()) {
1960-
unsigned BitWidth =
1961-
DL.getTypeSizeInBits(TrueVal->getType()->getScalarType());
1962-
APInt MinSignedValue = APInt::getSignedMinValue(BitWidth);
1963-
Value *X;
1964-
const APInt *Y, *C;
1965-
bool TrueWhenUnset;
1966-
bool IsBitTest = false;
1967-
if (ICmpInst::isEquality(Pred) &&
1968-
match(CmpLHS, m_And(m_Value(X), m_Power2(Y))) &&
1969-
match(CmpRHS, m_Zero())) {
1970-
IsBitTest = true;
1971-
TrueWhenUnset = Pred == ICmpInst::ICMP_EQ;
1972-
} else if (Pred == ICmpInst::ICMP_SLT && match(CmpRHS, m_Zero())) {
1973-
X = CmpLHS;
1974-
Y = &MinSignedValue;
1975-
IsBitTest = true;
1976-
TrueWhenUnset = false;
1977-
} else if (Pred == ICmpInst::ICMP_SGT && match(CmpRHS, m_AllOnes())) {
1978-
X = CmpLHS;
1979-
Y = &MinSignedValue;
1980-
IsBitTest = true;
1981-
TrueWhenUnset = true;
1982-
}
1983-
if (IsBitTest) {
1984-
Value *V = nullptr;
1985-
// (X & Y) == 0 ? X : X ^ Y --> X & ~Y
1986-
if (TrueWhenUnset && TrueVal == X &&
1987-
match(FalseVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C)
1988-
V = Builder.CreateAnd(X, ~(*Y));
1989-
// (X & Y) != 0 ? X ^ Y : X --> X & ~Y
1990-
else if (!TrueWhenUnset && FalseVal == X &&
1991-
match(TrueVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C)
1992-
V = Builder.CreateAnd(X, ~(*Y));
1993-
// (X & Y) == 0 ? X ^ Y : X --> X | Y
1994-
else if (TrueWhenUnset && FalseVal == X &&
1995-
match(TrueVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C)
1996-
V = Builder.CreateOr(X, *Y);
1997-
// (X & Y) != 0 ? X : X ^ Y --> X | Y
1998-
else if (!TrueWhenUnset && TrueVal == X &&
1999-
match(FalseVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C)
2000-
V = Builder.CreateOr(X, *Y);
2001-
2002-
if (V)
2003-
return replaceInstUsesWith(SI, V);
2004-
}
2005-
}
2006-
20071957
if (Instruction *V =
20081958
foldSelectICmpAndAnd(SI.getType(), ICI, TrueVal, FalseVal, Builder))
20091959
return V;
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes=instcombine -S %s | FileCheck %s
3+
4+
define i8 @select_icmp_eq_pow2(i8 %x) {
5+
; CHECK-LABEL: define i8 @select_icmp_eq_pow2(
6+
; CHECK-SAME: i8 [[X:%.*]]) {
7+
; CHECK-NEXT: [[SEL:%.*]] = and i8 [[X]], -5
8+
; CHECK-NEXT: ret i8 [[SEL]]
9+
;
10+
%and = and i8 %x, 4
11+
%icmp = icmp eq i8 %and, 0
12+
%xor = xor i8 %x, 4
13+
%sel = select i1 %icmp, i8 %x, i8 %xor
14+
ret i8 %sel
15+
}
16+
17+
define i8 @select_icmp_eq_pow2_flipped(i8 %x) {
18+
; CHECK-LABEL: define i8 @select_icmp_eq_pow2_flipped(
19+
; CHECK-SAME: i8 [[X:%.*]]) {
20+
; CHECK-NEXT: [[SEL:%.*]] = or i8 [[X]], 4
21+
; CHECK-NEXT: ret i8 [[SEL]]
22+
;
23+
%and = and i8 %x, 4
24+
%icmp = icmp eq i8 %and, 0
25+
%xor = xor i8 %x, 4
26+
%sel = select i1 %icmp, i8 %xor, i8 %x
27+
ret i8 %sel
28+
}
29+
30+
define i8 @select_icmp_eq_not_pow2(i8 %x) {
31+
; CHECK-LABEL: define i8 @select_icmp_eq_not_pow2(
32+
; CHECK-SAME: i8 [[X:%.*]]) {
33+
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], 5
34+
; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i8 [[AND]], 0
35+
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], 5
36+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ICMP]], i8 [[X]], i8 [[XOR]]
37+
; CHECK-NEXT: ret i8 [[SEL]]
38+
;
39+
%and = and i8 %x, 5
40+
%icmp = icmp eq i8 %and, 0
41+
%xor = xor i8 %x, 5
42+
%sel = select i1 %icmp, i8 %x, i8 %xor
43+
ret i8 %sel
44+
}
45+
46+
define i8 @select_icmp_ne_pow2(i8 %x) {
47+
; CHECK-LABEL: define i8 @select_icmp_ne_pow2(
48+
; CHECK-SAME: i8 [[X:%.*]]) {
49+
; CHECK-NEXT: [[SEL:%.*]] = and i8 [[X]], -5
50+
; CHECK-NEXT: ret i8 [[SEL]]
51+
;
52+
%and = and i8 %x, 4
53+
%icmp = icmp ne i8 %and, 0
54+
%xor = xor i8 %x, 4
55+
%sel = select i1 %icmp, i8 %xor, i8 %x
56+
ret i8 %sel
57+
}
58+
59+
define i8 @select_icmp_ne_pow2_flipped(i8 %x) {
60+
; CHECK-LABEL: define i8 @select_icmp_ne_pow2_flipped(
61+
; CHECK-SAME: i8 [[X:%.*]]) {
62+
; CHECK-NEXT: [[SEL:%.*]] = or i8 [[X]], 4
63+
; CHECK-NEXT: ret i8 [[SEL]]
64+
;
65+
%and = and i8 %x, 4
66+
%icmp = icmp ne i8 %and, 0
67+
%xor = xor i8 %x, 4
68+
%sel = select i1 %icmp, i8 %x, i8 %xor
69+
ret i8 %sel
70+
}
71+
72+
define i8 @select_icmp_ne_not_pow2(i8 %x) {
73+
; CHECK-LABEL: define i8 @select_icmp_ne_not_pow2(
74+
; CHECK-SAME: i8 [[X:%.*]]) {
75+
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], 5
76+
; CHECK-NEXT: [[ICMP_NOT:%.*]] = icmp eq i8 [[AND]], 0
77+
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], 5
78+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ICMP_NOT]], i8 [[X]], i8 [[XOR]]
79+
; CHECK-NEXT: ret i8 [[SEL]]
80+
;
81+
%and = and i8 %x, 5
82+
%icmp = icmp ne i8 %and, 0
83+
%xor = xor i8 %x, 5
84+
%sel = select i1 %icmp, i8 %xor, i8 %x
85+
ret i8 %sel
86+
}
87+
88+
define i8 @select_icmp_slt_zero_smin(i8 %x) {
89+
; CHECK-LABEL: define i8 @select_icmp_slt_zero_smin(
90+
; CHECK-SAME: i8 [[X:%.*]]) {
91+
; CHECK-NEXT: [[SEL:%.*]] = or i8 [[X]], -128
92+
; CHECK-NEXT: ret i8 [[SEL]]
93+
;
94+
%icmp = icmp slt i8 %x, 0
95+
%xor = xor i8 %x, -128
96+
%sel = select i1 %icmp, i8 %x, i8 %xor
97+
ret i8 %sel
98+
}
99+
100+
define i8 @select_icmp_slt_zero_smin_flipped(i8 %x) {
101+
; CHECK-LABEL: define i8 @select_icmp_slt_zero_smin_flipped(
102+
; CHECK-SAME: i8 [[X:%.*]]) {
103+
; CHECK-NEXT: [[SEL:%.*]] = and i8 [[X]], 127
104+
; CHECK-NEXT: ret i8 [[SEL]]
105+
;
106+
%icmp = icmp slt i8 %x, 0
107+
%xor = xor i8 %x, -128
108+
%sel = select i1 %icmp, i8 %xor, i8 %x
109+
ret i8 %sel
110+
}
111+
112+
define i8 @select_icmp_slt_not_zero(i8 %x) {
113+
; CHECK-LABEL: define i8 @select_icmp_slt_not_zero(
114+
; CHECK-SAME: i8 [[X:%.*]]) {
115+
; CHECK-NEXT: [[ICMP:%.*]] = icmp slt i8 [[X]], 1
116+
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], -128
117+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ICMP]], i8 [[X]], i8 [[XOR]]
118+
; CHECK-NEXT: ret i8 [[SEL]]
119+
;
120+
%icmp = icmp slt i8 %x, 1
121+
%xor = xor i8 %x, -128
122+
%sel = select i1 %icmp, i8 %x, i8 %xor
123+
ret i8 %sel
124+
}
125+
126+
define i8 @select_icmp_slt_not_smin(i8 %x) {
127+
; CHECK-LABEL: define i8 @select_icmp_slt_not_smin(
128+
; CHECK-SAME: i8 [[X:%.*]]) {
129+
; CHECK-NEXT: [[ICMP:%.*]] = icmp slt i8 [[X]], 0
130+
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], -127
131+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ICMP]], i8 [[X]], i8 [[XOR]]
132+
; CHECK-NEXT: ret i8 [[SEL]]
133+
;
134+
%icmp = icmp slt i8 %x, 0
135+
%xor = xor i8 %x, -127
136+
%sel = select i1 %icmp, i8 %x, i8 %xor
137+
ret i8 %sel
138+
}
139+
140+
define i8 @select_icmp_sgt_allones_smin(i8 %x) {
141+
; CHECK-LABEL: define i8 @select_icmp_sgt_allones_smin(
142+
; CHECK-SAME: i8 [[X:%.*]]) {
143+
; CHECK-NEXT: [[SEL:%.*]] = and i8 [[X]], 127
144+
; CHECK-NEXT: ret i8 [[SEL]]
145+
;
146+
%icmp = icmp sgt i8 %x, 255
147+
%xor = xor i8 %x, -128
148+
%sel = select i1 %icmp, i8 %x, i8 %xor
149+
ret i8 %sel
150+
}
151+
152+
define i8 @select_icmp_sgt_allones_smin_flipped(i8 %x) {
153+
; CHECK-LABEL: define i8 @select_icmp_sgt_allones_smin_flipped(
154+
; CHECK-SAME: i8 [[X:%.*]]) {
155+
; CHECK-NEXT: [[SEL:%.*]] = or i8 [[X]], -128
156+
; CHECK-NEXT: ret i8 [[SEL]]
157+
;
158+
%icmp = icmp sgt i8 %x, 255
159+
%xor = xor i8 %x, -128
160+
%sel = select i1 %icmp, i8 %xor, i8 %x
161+
ret i8 %sel
162+
}
163+
164+
define i8 @select_icmp_sgt_not_allones(i8 %x) {
165+
; CHECK-LABEL: define i8 @select_icmp_sgt_not_allones(
166+
; CHECK-SAME: i8 [[X:%.*]]) {
167+
; CHECK-NEXT: [[ICMP:%.*]] = icmp sgt i8 [[X]], -2
168+
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], -128
169+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ICMP]], i8 [[X]], i8 [[XOR]]
170+
; CHECK-NEXT: ret i8 [[SEL]]
171+
;
172+
%icmp = icmp sgt i8 %x, 254
173+
%xor = xor i8 %x, -128
174+
%sel = select i1 %icmp, i8 %x, i8 %xor
175+
ret i8 %sel
176+
}
177+
178+
define i8 @select_icmp_sgt_not_smin(i8 %x) {
179+
; CHECK-LABEL: define i8 @select_icmp_sgt_not_smin(
180+
; CHECK-SAME: i8 [[X:%.*]]) {
181+
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X]], -127
182+
; CHECK-NEXT: [[ICMP1:%.*]] = icmp slt i8 [[X]], 0
183+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ICMP1]], i8 [[XOR]], i8 [[X]]
184+
; CHECK-NEXT: ret i8 [[SEL]]
185+
;
186+
%icmp = icmp sgt i8 %x, 255
187+
%xor = xor i8 %x, -127
188+
%sel = select i1 %icmp, i8 %x, i8 %xor
189+
ret i8 %sel
190+
}

0 commit comments

Comments
 (0)