[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / result-of-add-of-negative-or-zero-is-non-zero-and-no-underflow.ll
blobb8a29e4fab25ecff4f7e5a301f38779513fa4c49
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -instcombine -S | FileCheck %s
4 declare void @use8(i8)
6 declare void @use1(i1)
7 declare void @llvm.assume(i1)
9 define i1 @t0(i8 %base, i8 %offset) {
10 ; CHECK-LABEL: @t0(
11 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
12 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
13 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
14 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
15 ; CHECK-NEXT:    ret i1 [[TMP2]]
17   %adjusted = add i8 %base, %offset
18   call void @use8(i8 %adjusted)
19   %not_null = icmp ne i8 %adjusted, 0
20   %no_underflow = icmp ule i8 %adjusted, %base
21   %r = and i1 %not_null, %no_underflow
22   ret i1 %r
25 ; We need to produce extra instruction, so one of icmp's must go away.
26 define i1 @t1_oneuse0(i8 %base, i8 %offset) {
27 ; CHECK-LABEL: @t1_oneuse0(
28 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
29 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
30 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
31 ; CHECK-NEXT:    call void @use1(i1 [[NOT_NULL]])
32 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
33 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
34 ; CHECK-NEXT:    ret i1 [[TMP2]]
36   %adjusted = add i8 %base, %offset
37   call void @use8(i8 %adjusted)
38   %not_null = icmp ne i8 %adjusted, 0
39   call void @use1(i1 %not_null)
40   %no_underflow = icmp ule i8 %adjusted, %base
41   %r = and i1 %not_null, %no_underflow
42   ret i1 %r
44 define i1 @t2_oneuse1(i8 %base, i8 %offset) {
45 ; CHECK-LABEL: @t2_oneuse1(
46 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
47 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
48 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[ADJUSTED]], [[BASE]]
49 ; CHECK-NEXT:    call void @use1(i1 [[NO_UNDERFLOW]])
50 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
51 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
52 ; CHECK-NEXT:    ret i1 [[TMP2]]
54   %adjusted = add i8 %base, %offset
55   call void @use8(i8 %adjusted)
56   %not_null = icmp ne i8 %adjusted, 0
57   %no_underflow = icmp ule i8 %adjusted, %base
58   call void @use1(i1 %no_underflow)
59   %r = and i1 %not_null, %no_underflow
60   ret i1 %r
62 define i1 @n3_oneuse2_bad(i8 %base, i8 %offset) {
63 ; CHECK-LABEL: @n3_oneuse2_bad(
64 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
65 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
66 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
67 ; CHECK-NEXT:    call void @use1(i1 [[NOT_NULL]])
68 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[ADJUSTED]], [[BASE]]
69 ; CHECK-NEXT:    call void @use1(i1 [[NO_UNDERFLOW]])
70 ; CHECK-NEXT:    [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]
71 ; CHECK-NEXT:    ret i1 [[R]]
73   %adjusted = add i8 %base, %offset
74   call void @use8(i8 %adjusted)
75   %not_null = icmp ne i8 %adjusted, 0
76   call void @use1(i1 %not_null)
77   %no_underflow = icmp ule i8 %adjusted, %base
78   call void @use1(i1 %no_underflow)
79   %r = and i1 %not_null, %no_underflow
80   ret i1 %r
83 define i1 @t4_commutativity0(i8 %base, i8 %offset) {
84 ; CHECK-LABEL: @t4_commutativity0(
85 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
86 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
87 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
88 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
89 ; CHECK-NEXT:    ret i1 [[TMP2]]
91   %adjusted = add i8 %base, %offset
92   call void @use8(i8 %adjusted)
93   %not_null = icmp ne i8 %adjusted, 0
94   %no_underflow = icmp ule i8 %adjusted, %base
95   %r = and i1 %no_underflow, %not_null ; swapped
96   ret i1 %r
98 define i1 @t5_commutativity1(i8 %base, i8 %offset) {
99 ; CHECK-LABEL: @t5_commutativity1(
100 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
101 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
102 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
103 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
104 ; CHECK-NEXT:    ret i1 [[TMP2]]
106   %adjusted = add i8 %base, %offset
107   call void @use8(i8 %adjusted)
108   %not_null = icmp ne i8 %adjusted, 0
109   %no_underflow = icmp uge i8 %base, %adjusted ; swapped
110   %r = and i1 %not_null, %no_underflow
111   ret i1 %r
113 define i1 @t6_commutativity3(i8 %base, i8 %offset) {
114 ; CHECK-LABEL: @t6_commutativity3(
115 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
116 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
117 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
118 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
119 ; CHECK-NEXT:    ret i1 [[TMP2]]
121   %adjusted = add i8 %base, %offset
122   call void @use8(i8 %adjusted)
123   %not_null = icmp ne i8 %adjusted, 0
124   %no_underflow = icmp uge i8 %base, %adjusted ; swapped
125   %r = and i1 %no_underflow, %not_null ; swapped
126   ret i1 %r
129 ; We could have the opposite question, did we get null or overflow happened?
130 define i1 @t7(i8 %base, i8 %offset) {
131 ; CHECK-LABEL: @t7(
132 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
133 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
134 ; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[ADJUSTED]], -1
135 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i8 [[TMP1]], [[BASE]]
136 ; CHECK-NEXT:    ret i1 [[TMP2]]
138   %adjusted = add i8 %base, %offset
139   call void @use8(i8 %adjusted)
140   %not_null = icmp eq i8 %adjusted, 0
141   %no_underflow = icmp ugt i8 %adjusted, %base
142   %r = or i1 %not_null, %no_underflow
143   ret i1 %r
146 ; The comparison can be with any of the values being added.
147 define i1 @t8(i8 %base, i8 %offset) {
148 ; CHECK-LABEL: @t8(
149 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
150 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
151 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 0, [[BASE]]
152 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
153 ; CHECK-NEXT:    ret i1 [[TMP2]]
155   %adjusted = add i8 %base, %offset
156   call void @use8(i8 %adjusted)
157   %not_null = icmp ne i8 %adjusted, 0
158   %no_underflow = icmp ule i8 %adjusted, %offset
159   %r = and i1 %not_null, %no_underflow
160   ret i1 %r