Skip to content

Commit 902acde

Browse files
committed
[InstCombine] Optimize away certain additions using modular arithmetic
We can turn: ``` %add = add i8 %arg, C1 %and = and i8 %add, C2 %cmp = icmp eq i1 %and, C3 ``` into: ``` %and = and i8 %arg, C2 %cmp = icmp eq i1 %and, (C3 - C1) & C2 ``` This is only worth doing if the sequence is the sole user of the addition operation.
1 parent 034cae4 commit 902acde

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,6 +1976,22 @@ Instruction *InstCombinerImpl::foldICmpAndConstant(ICmpInst &Cmp,
19761976
return new ICmpInst(Pred, LShr, Constant::getNullValue(LShr->getType()));
19771977
}
19781978

1979+
// (icmp eq/ne (and (add A, Addend), Msk), C)
1980+
// -> (icmp eq/ne (and A, Msk), (and (sub C, Addend), Msk))
1981+
{
1982+
Value *A;
1983+
const APInt *Addend, *Msk;
1984+
if (match(And, m_And(m_OneUse(m_Add(m_Value(A), m_APInt(Addend))),
1985+
m_APInt(Msk))) &&
1986+
Msk->isMask() && C.ule(*Msk)) {
1987+
APInt NewComperand = (C - *Addend) & *Msk;
1988+
Value* MaskA = Builder.CreateAnd(A, ConstantInt::get(A->getType(), *Msk));
1989+
return new ICmpInst(
1990+
Pred, MaskA,
1991+
Constant::getIntegerValue(MaskA->getType(), NewComperand));
1992+
}
1993+
}
1994+
19791995
return nullptr;
19801996
}
19811997

llvm/test/Transforms/InstCombine/and-compare.ll

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,87 @@ define i1 @test_ne_cp2_other_okay2(i8 %x, i8 %yy) {
172172
%r = icmp ne i8 %and_x_y, %and_x_neg_y
173173
ret i1 %r
174174
}
175+
176+
define i1 @test_eq_0_and_15_add_1(i8 %a) {
177+
; CHECK-LABEL: @test_eq_0_and_15_add_1(
178+
; CHECK-NEXT: entry:
179+
; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[A:%.*]], 15
180+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP0]], 15
181+
; CHECK-NEXT: ret i1 [[CMP]]
182+
;
183+
entry:
184+
%add = add i8 %a, 1
185+
%and = and i8 %add, 15
186+
%cmp = icmp eq i8 %and, 0
187+
ret i1 %cmp
188+
}
189+
190+
define i1 @test_ne_0_and_15_add_1(i8 %a) {
191+
; CHECK-LABEL: @test_ne_0_and_15_add_1(
192+
; CHECK-NEXT: entry:
193+
; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[A:%.*]], 15
194+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[TMP0]], 15
195+
; CHECK-NEXT: ret i1 [[CMP]]
196+
;
197+
entry:
198+
%add = add i8 %a, 1
199+
%and = and i8 %add, 15
200+
%cmp = icmp ne i8 %and, 0
201+
ret i1 %cmp
202+
}
203+
204+
define i1 @test_eq_0_and_15_add_3(i8 %a) {
205+
; CHECK-LABEL: @test_eq_0_and_15_add_3(
206+
; CHECK-NEXT: entry:
207+
; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[A:%.*]], 15
208+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP0]], 13
209+
; CHECK-NEXT: ret i1 [[CMP]]
210+
;
211+
entry:
212+
%add = add i8 %a, 3
213+
%and = and i8 %add, 15
214+
%cmp = icmp eq i8 %and, 0
215+
ret i1 %cmp
216+
}
217+
218+
define i1 @test_ne_0_and_15_add_3(i8 %a) {
219+
; CHECK-LABEL: @test_ne_0_and_15_add_3(
220+
; CHECK-NEXT: entry:
221+
; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[A:%.*]], 15
222+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[TMP0]], 13
223+
; CHECK-NEXT: ret i1 [[CMP]]
224+
;
225+
entry:
226+
%add = add i8 %a, 3
227+
%and = and i8 %add, 15
228+
%cmp = icmp ne i8 %and, 0
229+
ret i1 %cmp
230+
}
231+
232+
define i1 @test_eq_11_and_15_add_10(i8 %a) {
233+
; CHECK-LABEL: @test_eq_11_and_15_add_10(
234+
; CHECK-NEXT: entry:
235+
; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[A:%.*]], 15
236+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP0]], 1
237+
; CHECK-NEXT: ret i1 [[CMP]]
238+
;
239+
entry:
240+
%add = add i8 %a, 10
241+
%and = and i8 %add, 15
242+
%cmp = icmp eq i8 %and, 11
243+
ret i1 %cmp
244+
}
245+
246+
define i1 @test_ne_11_and_15_add_10(i8 %a) {
247+
; CHECK-LABEL: @test_ne_11_and_15_add_10(
248+
; CHECK-NEXT: entry:
249+
; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[A:%.*]], 15
250+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[TMP0]], 1
251+
; CHECK-NEXT: ret i1 [[CMP]]
252+
;
253+
entry:
254+
%add = add i8 %a, 10
255+
%and = and i8 %add, 15
256+
%cmp = icmp ne i8 %and, 11
257+
ret i1 %cmp
258+
}

0 commit comments

Comments
 (0)