1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 declare { i64, i1 } @llvm.usub.with.overflow.i64(i64, i64)
5 declare { i8, i1 } @llvm.usub.with.overflow.i8(i8, i8)
9 define i1 @test_generic(i64 %a, i64 %b) {
10 ; CHECK-LABEL: @test_generic(
11 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ult i64 [[A:%.*]], [[B:%.*]]
12 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
14 %res = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
15 %overflow = extractvalue { i64, i1 } %res, 1
19 define i1 @test_constant0(i8 %a) {
20 ; CHECK-LABEL: @test_constant0(
21 ; CHECK-NEXT: ret i1 false
23 %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 0)
24 %overflow = extractvalue { i8, i1 } %res, 1
28 define i1 @test_constant1(i8 %a) {
29 ; CHECK-LABEL: @test_constant1(
30 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], 0
31 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
33 %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 1)
34 %overflow = extractvalue { i8, i1 } %res, 1
38 define i1 @test_constant2(i8 %a) {
39 ; CHECK-LABEL: @test_constant2(
40 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ult i8 [[A:%.*]], 2
41 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
43 %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 2)
44 %overflow = extractvalue { i8, i1 } %res, 1
48 define i1 @test_constant3(i8 %a) {
49 ; CHECK-LABEL: @test_constant3(
50 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ult i8 [[A:%.*]], 3
51 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
53 %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 3)
54 %overflow = extractvalue { i8, i1 } %res, 1
58 define i1 @test_constant4(i8 %a) {
59 ; CHECK-LABEL: @test_constant4(
60 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ult i8 [[A:%.*]], 4
61 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
63 %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 4)
64 %overflow = extractvalue { i8, i1 } %res, 1
69 define i1 @test_constant127(i8 %a) {
70 ; CHECK-LABEL: @test_constant127(
71 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ult i8 [[A:%.*]], 127
72 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
74 %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 127)
75 %overflow = extractvalue { i8, i1 } %res, 1
79 define i1 @test_constant128(i8 %a) {
80 ; CHECK-LABEL: @test_constant128(
81 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp sgt i8 [[A:%.*]], -1
82 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
84 %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 128)
85 %overflow = extractvalue { i8, i1 } %res, 1
89 define i1 @test_constant255(i8 %a) {
90 ; CHECK-LABEL: @test_constant255(
91 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ne i8 [[A:%.*]], -1
92 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
94 %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 255)
95 %overflow = extractvalue { i8, i1 } %res, 1
99 define i1 @sub_eq0(i8 %x, i8 %y, i1 %b) {
100 ; CHECK-LABEL: @sub_eq0(
101 ; CHECK-NEXT: [[OV:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]]
102 ; CHECK-NEXT: call void @use(i1 [[OV]])
103 ; CHECK-NEXT: [[EQ0:%.*]] = icmp eq i8 [[X]], [[Y]]
104 ; CHECK-NEXT: ret i1 [[EQ0]]
106 %us = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %x, i8 %y)
107 %ov = extractvalue { i8, i1 } %us, 1
108 call void @use(i1 %ov)
109 %sub = extractvalue { i8, i1 } %us, 0
110 %eq0 = icmp eq i8 %sub, 0
114 define i1 @sub_ne0(i8 %x, i8 %y, i1 %b) {
115 ; CHECK-LABEL: @sub_ne0(
116 ; CHECK-NEXT: [[OV:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]]
117 ; CHECK-NEXT: call void @use(i1 [[OV]])
118 ; CHECK-NEXT: [[NE0:%.*]] = icmp ne i8 [[X]], [[Y]]
119 ; CHECK-NEXT: ret i1 [[NE0]]
121 %us = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %x, i8 %y)
122 %ov = extractvalue { i8, i1 } %us, 1
123 call void @use(i1 %ov)
124 %sub = extractvalue { i8, i1 } %us, 0
125 %ne0 = icmp ne i8 %sub, 0
129 ; negative test - need zero
131 define i1 @sub_eq1(i8 %x, i8 %y, i1 %b) {
132 ; CHECK-LABEL: @sub_eq1(
133 ; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
134 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1
135 ; CHECK-NEXT: call void @use(i1 [[OV]])
136 ; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SS]], 0
137 ; CHECK-NEXT: [[EQ1:%.*]] = icmp eq i8 [[SUB]], 1
138 ; CHECK-NEXT: ret i1 [[EQ1]]
140 %ss = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %x, i8 %y)
141 %ov = extractvalue { i8, i1 } %ss, 1
142 call void @use(i1 %ov)
143 %sub = extractvalue { i8, i1 } %ss, 0
144 %eq1 = icmp eq i8 %sub, 1
148 ; negative test - need equality pred
150 define i1 @sub_sgt0(i8 %x, i8 %y, i1 %b) {
151 ; CHECK-LABEL: @sub_sgt0(
152 ; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
153 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1
154 ; CHECK-NEXT: call void @use(i1 [[OV]])
155 ; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SS]], 0
156 ; CHECK-NEXT: [[SGT0:%.*]] = icmp sgt i8 [[SUB]], 0
157 ; CHECK-NEXT: ret i1 [[SGT0]]
159 %ss = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %x, i8 %y)
160 %ov = extractvalue { i8, i1 } %ss, 1
161 call void @use(i1 %ov)
162 %sub = extractvalue { i8, i1 } %ss, 0
163 %sgt0 = icmp sgt i8 %sub, 0