1; RUN: opt < %s -instcombine -S | FileCheck %s
2; These should be InstSimplify checks, but most of the code
3; is currently only in InstCombine.  TODO: move supporting code
4
5; Definitely out of range
6define i1 @test_nonzero(i32* nocapture readonly %arg) {
7; CHECK-LABEL:test_nonzero
8; CHECK: ret i1 true
9  %val = load i32, i32* %arg, !range !0
10  %rval = icmp ne i32 %val, 0
11  ret i1 %rval
12}
13define i1 @test_nonzero2(i32* nocapture readonly %arg) {
14; CHECK-LABEL:test_nonzero2
15; CHECK: ret i1 false
16  %val = load i32, i32* %arg, !range !0
17  %rval = icmp eq i32 %val, 0
18  ret i1 %rval
19}
20
21; Potentially in range
22define i1 @test_nonzero3(i32* nocapture readonly %arg) {
23; CHECK-LABEL: test_nonzero3
24; Check that this does not trigger - it wouldn't be legal
25; CHECK: icmp
26  %val = load i32, i32* %arg, !range !1
27  %rval = icmp ne i32 %val, 0
28  ret i1 %rval
29}
30
31; Definitely in range
32define i1 @test_nonzero4(i8* nocapture readonly %arg) {
33; CHECK-LABEL: test_nonzero4
34; CHECK: ret i1 false
35  %val = load i8, i8* %arg, !range !2
36  %rval = icmp ne i8 %val, 0
37  ret i1 %rval
38}
39
40define i1 @test_nonzero5(i8* nocapture readonly %arg) {
41; CHECK-LABEL: test_nonzero5
42; CHECK: ret i1 false
43  %val = load i8, i8* %arg, !range !2
44  %rval = icmp ugt i8 %val, 0
45  ret i1 %rval
46}
47
48; Cheaper checks (most values in range meet requirements)
49define i1 @test_nonzero6(i8* %argw) {
50; CHECK-LABEL: test_nonzero6
51; CHECK: icmp ne i8 %val, 0
52  %val = load i8, i8* %argw, !range !3
53  %rval = icmp sgt i8 %val, 0
54  ret i1 %rval
55}
56
57; Constant not in range, should return true.
58define i1 @test_not_in_range(i32* nocapture readonly %arg) {
59; CHECK-LABEL: test_not_in_range
60; CHECK: ret i1 true
61  %val = load i32, i32* %arg, !range !0
62  %rval = icmp ne i32 %val, 6
63  ret i1 %rval
64}
65
66; Constant in range, can not fold.
67define i1 @test_in_range(i32* nocapture readonly %arg) {
68; CHECK-LABEL: test_in_range
69; CHECK: icmp ne i32 %val, 3
70  %val = load i32, i32* %arg, !range !0
71  %rval = icmp ne i32 %val, 3
72  ret i1 %rval
73}
74
75; Values in range greater than constant.
76define i1 @test_range_sgt_constant(i32* nocapture readonly %arg) {
77; CHECK-LABEL: test_range_sgt_constant
78; CHECK: ret i1 true
79  %val = load i32, i32* %arg, !range !0
80  %rval = icmp sgt i32 %val, 0
81  ret i1 %rval
82}
83
84; Values in range less than constant.
85define i1 @test_range_slt_constant(i32* nocapture readonly %arg) {
86; CHECK-LABEL: test_range_slt_constant
87; CHECK: ret i1 false
88  %val = load i32, i32* %arg, !range !0
89  %rval = icmp sgt i32 %val, 6
90  ret i1 %rval
91}
92
93; Values in union of multiple sub ranges not equal to constant.
94define i1 @test_multi_range1(i32* nocapture readonly %arg) {
95; CHECK-LABEL: test_multi_range1
96; CHECK: ret i1 true
97  %val = load i32, i32* %arg, !range !4
98  %rval = icmp ne i32 %val, 0
99  ret i1 %rval
100}
101
102; Values in multiple sub ranges not equal to constant, but in
103; union of sub ranges could possibly equal to constant. This
104; in theory could also be folded and might be implemented in
105; the future if shown profitable in practice.
106define i1 @test_multi_range2(i32* nocapture readonly %arg) {
107; CHECK-LABEL: test_multi_range2
108; CHECK: icmp ne i32 %val, 7
109  %val = load i32, i32* %arg, !range !4
110  %rval = icmp ne i32 %val, 7
111  ret i1 %rval
112}
113
114; Values' ranges overlap each other, so it can not be simplified.
115define i1 @test_two_ranges(i32* nocapture readonly %arg1, i32* nocapture readonly %arg2) {
116; CHECK-LABEL: test_two_ranges
117; CHECK: icmp ult i32 %val2, %val1
118  %val1 = load i32, i32* %arg1, !range !5
119  %val2 = load i32, i32* %arg2, !range !6
120  %rval = icmp ult i32 %val2, %val1
121  ret i1 %rval
122}
123
124; Values' ranges do not overlap each other, so it can simplified to false.
125define i1 @test_two_ranges2(i32* nocapture readonly %arg1, i32* nocapture readonly %arg2) {
126; CHECK-LABEL: test_two_ranges2
127; CHECK: ret i1 false
128  %val1 = load i32, i32* %arg1, !range !0
129  %val2 = load i32, i32* %arg2, !range !6
130  %rval = icmp ult i32 %val2, %val1
131  ret i1 %rval
132}
133
134; Values' ranges do not overlap each other, so it can simplified to true.
135define i1 @test_two_ranges3(i32* nocapture readonly %arg1, i32* nocapture readonly %arg2) {
136; CHECK-LABEL: test_two_ranges3
137; CHECK: ret i1 true
138  %val1 = load i32, i32* %arg1, !range !0
139  %val2 = load i32, i32* %arg2, !range !6
140  %rval = icmp ugt i32 %val2, %val1
141  ret i1 %rval
142}
143
144!0 = !{i32 1, i32 6}
145!1 = !{i32 0, i32 6}
146!2 = !{i8 0, i8 1}
147!3 = !{i8 0, i8 6}
148!4 = !{i32 1, i32 6, i32 8, i32 10}
149!5 = !{i32 5, i32 10}
150!6 = !{i32 8, i32 16}
151