1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -instcombine -S | FileCheck %s
7 declare void @llvm.assume(i1)
9 define i1 @t0(i8 %base, i8 %offset) {
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
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
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
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
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
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
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
129 ; We could have the opposite question, did we get null or overflow happened?
130 define i1 @t7(i8 %base, i8 %offset) {
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
146 ; The comparison can be with any of the values being added.
147 define i1 @t8(i8 %base, i8 %offset) {
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