Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / InstCombine / ssubo.ll
blob30749afdfc570aa096aea1f670dee1f1ea7be2b2
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)
7 declare void @use(i1)
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
17   ret i1 %overflow
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
26   ret i1 %overflow
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
36   ret i1 %overflow
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
46   ret i1 %overflow
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
56   ret i1 %overflow
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
66   ret i1 %overflow
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
77   ret i1 %overflow
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
87   ret i1 %overflow
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
97   ret i1 %overflow
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
113   ret i1 %eq0
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
129   ret i1 %ne0
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
148   ret i1 %eq1
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
167   ret i1 %sgt0