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.ssub.with.overflow.i64(i64, i64)
5 declare { i8, i1 } @llvm.ssub.with.overflow.i8(i8, i8)
9 define i1 @test_generic(i64 %a, i64 %b) {
10 ; CHECK-LABEL: @test_generic(
11 ; CHECK-NEXT: [[RES:%.*]] = tail call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])
12 ; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 1
13 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
15 %res = tail call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
16 %overflow = extractvalue { i64, i1 } %res, 1
20 define i1 @test_constant0(i8 %a) {
21 ; CHECK-LABEL: @test_constant0(
22 ; CHECK-NEXT: ret i1 false
24 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 0)
25 %overflow = extractvalue { i8, i1 } %res, 1
29 define i1 @test_constant1(i8 %a) {
30 ; CHECK-LABEL: @test_constant1(
31 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], -128
32 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
34 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 1)
35 %overflow = extractvalue { i8, i1 } %res, 1
39 define i1 @test_constant2(i8 %a) {
40 ; CHECK-LABEL: @test_constant2(
41 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -126
42 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
44 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 2)
45 %overflow = extractvalue { i8, i1 } %res, 1
49 define i1 @test_constant3(i8 %a) {
50 ; CHECK-LABEL: @test_constant3(
51 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -125
52 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
54 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 3)
55 %overflow = extractvalue { i8, i1 } %res, 1
59 define i1 @test_constant4(i8 %a) {
60 ; CHECK-LABEL: @test_constant4(
61 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -124
62 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
64 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 4)
65 %overflow = extractvalue { i8, i1 } %res, 1
70 define i1 @test_constant127(i8 %a) {
71 ; CHECK-LABEL: @test_constant127(
72 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -1
73 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
75 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 127)
76 %overflow = extractvalue { i8, i1 } %res, 1
80 define i1 @test_constant128(i8 %a) {
81 ; CHECK-LABEL: @test_constant128(
82 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp sgt i8 [[A:%.*]], -1
83 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
85 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 128)
86 %overflow = extractvalue { i8, i1 } %res, 1
90 define i1 @test_constant255(i8 %a) {
91 ; CHECK-LABEL: @test_constant255(
92 ; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], 127
93 ; CHECK-NEXT: ret i1 [[OVERFLOW]]
95 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 255)
96 %overflow = extractvalue { i8, i1 } %res, 1
100 define i1 @sub_eq0(i8 %x, i8 %y, i1 %b) {
101 ; CHECK-LABEL: @sub_eq0(
102 ; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
103 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1
104 ; CHECK-NEXT: call void @use(i1 [[OV]])
105 ; CHECK-NEXT: [[EQ0:%.*]] = icmp eq i8 [[X]], [[Y]]
106 ; CHECK-NEXT: ret i1 [[EQ0]]
108 %ss = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y)
109 %ov = extractvalue { i8, i1 } %ss, 1
110 call void @use(i1 %ov)
111 %sub = extractvalue { i8, i1 } %ss, 0
112 %eq0 = icmp eq i8 %sub, 0
116 define i1 @sub_ne0(i8 %x, i8 %y, i1 %b) {
117 ; CHECK-LABEL: @sub_ne0(
118 ; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
119 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1
120 ; CHECK-NEXT: call void @use(i1 [[OV]])
121 ; CHECK-NEXT: [[NE0:%.*]] = icmp ne i8 [[X]], [[Y]]
122 ; CHECK-NEXT: ret i1 [[NE0]]
124 %ss = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y)
125 %ov = extractvalue { i8, i1 } %ss, 1
126 call void @use(i1 %ov)
127 %sub = extractvalue { i8, i1 } %ss, 0
128 %ne0 = icmp ne i8 %sub, 0
132 ; negative test - need zero
134 define i1 @sub_eq1(i8 %x, i8 %y, i1 %b) {
135 ; CHECK-LABEL: @sub_eq1(
136 ; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
137 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1
138 ; CHECK-NEXT: call void @use(i1 [[OV]])
139 ; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SS]], 0
140 ; CHECK-NEXT: [[EQ1:%.*]] = icmp eq i8 [[SUB]], 1
141 ; CHECK-NEXT: ret i1 [[EQ1]]
143 %ss = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y)
144 %ov = extractvalue { i8, i1 } %ss, 1
145 call void @use(i1 %ov)
146 %sub = extractvalue { i8, i1 } %ss, 0
147 %eq1 = icmp eq i8 %sub, 1
151 ; negative test - need equality pred
153 define i1 @sub_sgt0(i8 %x, i8 %y, i1 %b) {
154 ; CHECK-LABEL: @sub_sgt0(
155 ; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
156 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1
157 ; CHECK-NEXT: call void @use(i1 [[OV]])
158 ; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SS]], 0
159 ; CHECK-NEXT: [[SGT0:%.*]] = icmp sgt i8 [[SUB]], 0
160 ; CHECK-NEXT: ret i1 [[SGT0]]
162 %ss = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y)
163 %ov = extractvalue { i8, i1 } %ss, 1
164 call void @use(i1 %ov)
165 %sub = extractvalue { i8, i1 } %ss, 0
166 %sgt0 = icmp sgt i8 %sub, 0