1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 declare void @use(i8 %value)
6 define i1 @ucmp_eq_0(i32 %x, i32 %y) {
7 ; CHECK-LABEL: define i1 @ucmp_eq_0(
8 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
9 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[X]], [[Y]]
10 ; CHECK-NEXT: ret i1 [[TMP2]]
12 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
17 define i1 @ucmp_ne_0(i32 %x, i32 %y) {
18 ; CHECK-LABEL: define i1 @ucmp_ne_0(
19 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
20 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[X]], [[Y]]
21 ; CHECK-NEXT: ret i1 [[TMP2]]
23 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
28 define i1 @ucmp_eq_1(i32 %x, i32 %y) {
29 ; CHECK-LABEL: define i1 @ucmp_eq_1(
30 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
31 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]]
32 ; CHECK-NEXT: ret i1 [[TMP2]]
34 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
39 define i1 @ucmp_ne_1(i32 %x, i32 %y) {
40 ; CHECK-LABEL: define i1 @ucmp_ne_1(
41 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
42 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]]
43 ; CHECK-NEXT: ret i1 [[TMP2]]
45 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
50 define i1 @ucmp_eq_negative_1(i32 %x, i32 %y) {
51 ; CHECK-LABEL: define i1 @ucmp_eq_negative_1(
52 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
53 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]]
54 ; CHECK-NEXT: ret i1 [[TMP2]]
56 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
57 %2 = icmp eq i8 %1, -1
61 define i1 @ucmp_ne_negative_1(i32 %x, i32 %y) {
62 ; CHECK-LABEL: define i1 @ucmp_ne_negative_1(
63 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
64 ; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]]
65 ; CHECK-NEXT: ret i1 [[TMP2]]
67 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
68 %2 = icmp ne i8 %1, -1
72 define i1 @ucmp_sgt_0(i32 %x, i32 %y) {
73 ; CHECK-LABEL: define i1 @ucmp_sgt_0(
74 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
75 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]]
76 ; CHECK-NEXT: ret i1 [[TMP2]]
78 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
79 %2 = icmp sgt i8 %1, 0
83 define i1 @ucmp_sgt_neg_1(i32 %x, i32 %y) {
84 ; CHECK-LABEL: define i1 @ucmp_sgt_neg_1(
85 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
86 ; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]]
87 ; CHECK-NEXT: ret i1 [[TMP2]]
89 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
90 %2 = icmp sgt i8 %1, -1
94 define i1 @ucmp_sge_0(i32 %x, i32 %y) {
95 ; CHECK-LABEL: define i1 @ucmp_sge_0(
96 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
97 ; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]]
98 ; CHECK-NEXT: ret i1 [[TMP2]]
100 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
101 %2 = icmp sge i8 %1, 0
105 define i1 @ucmp_sge_1(i32 %x, i32 %y) {
106 ; CHECK-LABEL: define i1 @ucmp_sge_1(
107 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
108 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]]
109 ; CHECK-NEXT: ret i1 [[TMP2]]
111 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
112 %2 = icmp sge i8 %1, 1
116 define i1 @ucmp_slt_0(i32 %x, i32 %y) {
117 ; CHECK-LABEL: define i1 @ucmp_slt_0(
118 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
119 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]]
120 ; CHECK-NEXT: ret i1 [[TMP2]]
122 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
123 %2 = icmp slt i8 %1, 0
127 define i1 @ucmp_slt_1(i32 %x, i32 %y) {
128 ; CHECK-LABEL: define i1 @ucmp_slt_1(
129 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
130 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]]
131 ; CHECK-NEXT: ret i1 [[TMP2]]
133 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
134 %2 = icmp slt i8 %1, 1
138 define i1 @ucmp_sle_0(i32 %x, i32 %y) {
139 ; CHECK-LABEL: define i1 @ucmp_sle_0(
140 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
141 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]]
142 ; CHECK-NEXT: ret i1 [[TMP2]]
144 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
145 %2 = icmp sle i8 %1, 0
149 define i1 @ucmp_sle_neg_1(i32 %x, i32 %y) {
150 ; CHECK-LABEL: define i1 @ucmp_sle_neg_1(
151 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
152 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]]
153 ; CHECK-NEXT: ret i1 [[TMP2]]
155 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
156 %2 = icmp sle i8 %1, -1
160 ; ========== Fold -ucmp(x, y) => ucmp(y, x) ==========
161 define i8 @ucmp_negated(i32 %x, i32 %y) {
162 ; CHECK-LABEL: define i8 @ucmp_negated(
163 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
164 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[Y]], i32 [[X]])
165 ; CHECK-NEXT: ret i8 [[TMP2]]
167 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
172 ; Negative test: do not fold if the original ucmp result is already used
173 define i8 @ucmp_negated_multiuse(i32 %x, i32 %y) {
174 ; CHECK-LABEL: define i8 @ucmp_negated_multiuse(
175 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
176 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
177 ; CHECK-NEXT: call void @use(i8 [[TMP1]])
178 ; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i8 0, [[TMP1]]
179 ; CHECK-NEXT: ret i8 [[TMP2]]
181 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
182 call void @use(i8 %1)