unsigned-range-checks.ll
3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt %s -instsimplify -S | FileCheck %s
; Here we add unsigned two values, check that addition did not underflow AND
; that the result is non-zero. This can be simplified just to a comparison
; between the base and negated offset.
; If we are checking that the result is not null or no underflow happened,
; it is tautological (always-true).
define i1 @t1(i8 %x, i8 %y) {
; CHECK-LABEL: @t1(
; CHECK-NEXT: ret i1 true
;
%not_null = icmp ne i8 %y, 0
%no_underflow = icmp ule i8 %y, %x
%r = or i1 %not_null, %no_underflow
ret i1 %r
}
define i1 @t2_commutative(i8 %x, i8 %y) {
; CHECK-LABEL: @t2_commutative(
; CHECK-NEXT: ret i1 true
;
%not_null = icmp ne i8 %y, 0
%no_underflow = icmp uge i8 %x, %y ; swapped
%r = or i1 %not_null, %no_underflow
ret i1 %r
}
define i1 @t3_commutative(i8 %x, i8 %y) {
; CHECK-LABEL: @t3_commutative(
; CHECK-NEXT: ret i1 true
;
%not_null = icmp ne i8 %y, 0
%no_underflow = icmp ule i8 %y, %x
%r = or i1 %no_underflow, %not_null ; swapped
ret i1 %r
}
define i1 @t4_commutative(i8 %x, i8 %y) {
; CHECK-LABEL: @t4_commutative(
; CHECK-NEXT: ret i1 true
;
%not_null = icmp ne i8 %y, 0
%no_underflow = icmp uge i8 %x, %y ; swapped
%r = or i1 %no_underflow, %not_null ; swapped
ret i1 %r
}
; If we are checking that the result is null and underflow happened,
; it is tautological (always-false).
define i1 @t5(i8 %x, i8 %y) {
; CHECK-LABEL: @t5(
; CHECK-NEXT: ret i1 false
;
%not_null = icmp eq i8 %y, 0
%no_underflow = icmp ugt i8 %y, %x
%r = and i1 %not_null, %no_underflow
ret i1 %r
}
define i1 @t6_commutative(i8 %x, i8 %y) {
; CHECK-LABEL: @t6_commutative(
; CHECK-NEXT: ret i1 false
;
%not_null = icmp eq i8 %y, 0
%no_underflow = icmp ult i8 %x, %y ; swapped
%r = and i1 %not_null, %no_underflow
ret i1 %r
}
; We only need to know that any of the 'add' operands is non-zero,
; not necessarily the one used in the comparison.
define i1 @t7(i8 %x, i8 %y) {
; CHECK-LABEL: @t7(
; CHECK-NEXT: ret i1 true
;
%cmp = icmp slt i8 %y, 0
%not_null = icmp ne i8 %y, 0
%no_underflow = icmp ule i8 %y, %x
%r = or i1 %not_null, %no_underflow
ret i1 %r
}
; If we check that no underflow happened and that the result is null,
; we can just check for null.
define i1 @t8(i8 %x, i8 %y) {
; CHECK-LABEL: @t8(
; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq i8 [[Y:%.*]], 0
; CHECK-NEXT: ret i1 [[NOT_NULL]]
;
%not_null = icmp eq i8 %y, 0
%no_underflow = icmp ule i8 %y, %x
%r = and i1 %not_null, %no_underflow
ret i1 %r
}
; Likewise, if we check that result is non-null or underflow happened,
; we can just check for null.
define i1 @t9(i8 %x, i8 %y) {
; CHECK-LABEL: @t9(
; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[Y:%.*]], 0
; CHECK-NEXT: ret i1 [[NOT_NULL]]
;
%not_null = icmp ne i8 %y, 0
%no_underflow = icmp ugt i8 %y, %x
%r = or i1 %not_null, %no_underflow
ret i1 %r
}
; If we check that no underflow happened or that the result is not null,
; we can just check for lack of underflow.
define i1 @t10(i8 %x, i8 %y) {
; CHECK-LABEL: @t10(
; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[NO_UNDERFLOW]]
;
%not_null = icmp eq i8 %y, 0
%no_underflow = icmp ule i8 %y, %x
%r = or i1 %not_null, %no_underflow
ret i1 %r
}
; Likewise, if we check that underflow happened and that the result is not null,
; we can just check for lack of underflow.
define i1 @t11(i8 %x, i8 %y) {
; CHECK-LABEL: @t11(
; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ugt i8 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[NO_UNDERFLOW]]
;
%not_null = icmp ne i8 %y, 0
%no_underflow = icmp ugt i8 %y, %x
%r = and i1 %not_null, %no_underflow
ret i1 %r
}