[SimplifyCFG] FoldTwoEntryPHINode(): consider *total* speculation cost, not per-BB...
[llvm-complete.git] / test / Transforms / InstSimplify / result-of-usub-is-non-zero-and-no-overflow.ll
blob476528f45b9014c07827b7d0bb923adf85545dfc
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -instsimplify -S | FileCheck %s
4 ; Here we subtract two values, check that subtraction did not overflow AND
5 ; that the result is non-zero. This can be simplified just to a comparison
6 ; between the base and offset.
8 declare void @use8(i8)
9 declare void @use64(i64)
10 declare void @use1(i1)
12 declare void @llvm.assume(i1)
14 ; If we are checking that we either did not get null or got no overflow,
15 ; this is tautological and is always true.
17 define i1 @t1(i8 %base, i8 %offset) {
18 ; CHECK-LABEL: @t1(
19 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
20 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
21 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]]
22 ; CHECK-NEXT:    call void @use1(i1 [[NO_UNDERFLOW]])
23 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
24 ; CHECK-NEXT:    call void @use1(i1 [[NOT_NULL]])
25 ; CHECK-NEXT:    ret i1 true
27   %adjusted = sub i8 %base, %offset
28   call void @use8(i8 %adjusted)
29   %no_underflow = icmp uge i8 %base, %offset
30   call void @use1(i1 %no_underflow)
31   %not_null = icmp ne i8 %adjusted, 0
32   call void @use1(i1 %not_null)
33   %r = or i1 %not_null, %no_underflow
34   ret i1 %r
36 define i1 @t1_strict_bad(i8 %base, i8 %offset) {
37 ; CHECK-LABEL: @t1_strict_bad(
38 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
39 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
40 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]
41 ; CHECK-NEXT:    call void @use1(i1 [[NO_UNDERFLOW]])
42 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
43 ; CHECK-NEXT:    call void @use1(i1 [[NOT_NULL]])
44 ; CHECK-NEXT:    [[R:%.*]] = or i1 [[NOT_NULL]], [[NO_UNDERFLOW]]
45 ; CHECK-NEXT:    ret i1 [[R]]
47   %adjusted = sub i8 %base, %offset
48   call void @use8(i8 %adjusted)
49   %no_underflow = icmp ugt i8 %base, %offset ; but not for non-strict predicate
50   call void @use1(i1 %no_underflow)
51   %not_null = icmp ne i8 %adjusted, 0
52   call void @use1(i1 %not_null)
53   %r = or i1 %not_null, %no_underflow
54   ret i1 %r
56 define i1 @t1_commutativity(i8 %base, i8 %offset) {
57 ; CHECK-LABEL: @t1_commutativity(
58 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
59 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
60 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[OFFSET]], [[BASE]]
61 ; CHECK-NEXT:    call void @use1(i1 [[NO_UNDERFLOW]])
62 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
63 ; CHECK-NEXT:    call void @use1(i1 [[NOT_NULL]])
64 ; CHECK-NEXT:    ret i1 true
66   %adjusted = sub i8 %base, %offset
67   call void @use8(i8 %adjusted)
68   %no_underflow = icmp ule i8 %offset, %base
69   call void @use1(i1 %no_underflow)
70   %not_null = icmp ne i8 %adjusted, 0
71   call void @use1(i1 %not_null)
72   %r = or i1 %not_null, %no_underflow
73   ret i1 %r
76 ; Likewise, if we are checking that we both got null and overflow happened,
77 ; it makes no sense and is always false.
79 define i1 @t2(i8 %base, i8 %offset) {
80 ; CHECK-LABEL: @t2(
81 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
82 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
83 ; CHECK-NEXT:    [[UNDERFLOW:%.*]] = icmp ult i8 [[BASE]], [[OFFSET]]
84 ; CHECK-NEXT:    call void @use1(i1 [[UNDERFLOW]])
85 ; CHECK-NEXT:    [[NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0
86 ; CHECK-NEXT:    call void @use1(i1 [[NULL]])
87 ; CHECK-NEXT:    ret i1 false
89   %adjusted = sub i8 %base, %offset
90   call void @use8(i8 %adjusted)
91   %underflow = icmp ult i8 %base, %offset
92   call void @use1(i1 %underflow)
93   %null = icmp eq i8 %adjusted, 0
94   call void @use1(i1 %null)
95   %r = and i1 %null, %underflow
96   ret i1 %r
98 define i1 @t2_nonstrict_bad(i8 %base, i8 %offset) {
99 ; CHECK-LABEL: @t2_nonstrict_bad(
100 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
101 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
102 ; CHECK-NEXT:    [[UNDERFLOW:%.*]] = icmp uge i8 [[ADJUSTED]], [[BASE]]
103 ; CHECK-NEXT:    call void @use1(i1 [[UNDERFLOW]])
104 ; CHECK-NEXT:    [[NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0
105 ; CHECK-NEXT:    call void @use1(i1 [[NULL]])
106 ; CHECK-NEXT:    [[R:%.*]] = and i1 [[NULL]], [[UNDERFLOW]]
107 ; CHECK-NEXT:    ret i1 [[R]]
109   %adjusted = sub i8 %base, %offset
110   call void @use8(i8 %adjusted)
111   %underflow = icmp uge i8 %adjusted, %base ; but not for non-strict predicate
112   call void @use1(i1 %underflow)
113   %null = icmp eq i8 %adjusted, 0
114   call void @use1(i1 %null)
115   %r = and i1 %null, %underflow
116   ret i1 %r
118 define i1 @t2_commutativity(i8 %base, i8 %offset) {
119 ; CHECK-LABEL: @t2_commutativity(
120 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
121 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
122 ; CHECK-NEXT:    [[UNDERFLOW:%.*]] = icmp ugt i8 [[OFFSET]], [[BASE]]
123 ; CHECK-NEXT:    call void @use1(i1 [[UNDERFLOW]])
124 ; CHECK-NEXT:    [[NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0
125 ; CHECK-NEXT:    call void @use1(i1 [[NULL]])
126 ; CHECK-NEXT:    ret i1 false
128   %adjusted = sub i8 %base, %offset
129   call void @use8(i8 %adjusted)
130   %underflow = icmp ugt i8 %offset, %base
131   call void @use1(i1 %underflow)
132   %null = icmp eq i8 %adjusted, 0
133   call void @use1(i1 %null)
134   %r = and i1 %null, %underflow
135   ret i1 %r
138 ; Overflow OR not zero => always true
139 define i1 @t3(i8 %base, i8 %offset) {
140 ; CHECK-LABEL: @t3(
141 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
142 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
143 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[BASE]], [[OFFSET]]
144 ; CHECK-NEXT:    call void @use1(i1 [[NO_UNDERFLOW]])
145 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
146 ; CHECK-NEXT:    call void @use1(i1 [[NOT_NULL]])
147 ; CHECK-NEXT:    ret i1 true
149   %adjusted = sub i8 %base, %offset
150   call void @use8(i8 %adjusted)
151   %no_underflow = icmp ule i8 %base, %offset
152   call void @use1(i1 %no_underflow)
153   %not_null = icmp ne i8 %adjusted, 0
154   call void @use1(i1 %not_null)
155   %r = or i1 %not_null, %no_underflow
156   ret i1 %r
159 ; No overflow and zero => always false
160 define i1 @t4(i8 %base, i8 %offset) {
161 ; CHECK-LABEL: @t4(
162 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
163 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
164 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]
165 ; CHECK-NEXT:    call void @use1(i1 [[NO_UNDERFLOW]])
166 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0
167 ; CHECK-NEXT:    call void @use1(i1 [[NOT_NULL]])
168 ; CHECK-NEXT:    ret i1 false
170   %adjusted = sub i8 %base, %offset
171   call void @use8(i8 %adjusted)
172   %no_underflow = icmp ugt i8 %base, %offset
173   call void @use1(i1 %no_underflow)
174   %not_null = icmp eq i8 %adjusted, 0
175   call void @use1(i1 %not_null)
176   %r = and i1 %not_null, %no_underflow
177   ret i1 %r