[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / unsigned_saturated_sub.ll
blob44aa7deb4acc5e51b7689a4cefdb0ca112e3e790
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -instcombine -S < %s | FileCheck %s
4 ; Canonicalization of unsigned saturated subtraction idioms to
5 ; usub.sat() intrinsics is tested here.
7 declare void @use(i64)
9 ; (a > b) ? a - b : 0 -> usub.sat(a, b)
11 define i64 @max_sub_ugt(i64 %a, i64 %b) {
12 ; CHECK-LABEL: @max_sub_ugt(
13 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
14 ; CHECK-NEXT:    ret i64 [[TMP1]]
16   %cmp = icmp ugt i64 %a, %b
17   %sub = sub i64 %a, %b
18   %sel = select i1 %cmp, i64 %sub ,i64 0
19   ret i64 %sel
22 ; (a >= b) ? a - b : 0 -> usub.sat(a, b)
24 define i64 @max_sub_uge(i64 %a, i64 %b) {
25 ; CHECK-LABEL: @max_sub_uge(
26 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
27 ; CHECK-NEXT:    ret i64 [[TMP1]]
29   %cmp = icmp uge i64 %a, %b
30   %sub = sub i64 %a, %b
31   %sel = select i1 %cmp, i64 %sub ,i64 0
32   ret i64 %sel
35 ; Again, with vectors:
36 ; (a > b) ? a - b : 0 -> usub.sat(a, b)
38 define <4 x i32> @max_sub_ugt_vec(<4 x i32> %a, <4 x i32> %b) {
39 ; CHECK-LABEL: @max_sub_ugt_vec(
40 ; CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]])
41 ; CHECK-NEXT:    ret <4 x i32> [[TMP1]]
43   %cmp = icmp ugt <4 x i32> %a, %b
44   %sub = sub <4 x i32> %a, %b
45   %sel = select <4 x i1> %cmp, <4 x i32> %sub, <4 x i32> zeroinitializer
46   ret <4 x i32> %sel
49 ; Use extra ops to thwart icmp swapping canonicalization.
50 ; (b < a) ? a - b : 0 -> usub.sat(a, b)
52 define i64 @max_sub_ult(i64 %a, i64 %b) {
53 ; CHECK-LABEL: @max_sub_ult(
54 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
55 ; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[B]], [[A]]
56 ; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
57 ; CHECK-NEXT:    ret i64 [[TMP1]]
59   %cmp = icmp ult i64 %b, %a
60   %sub = sub i64 %a, %b
61   %sel = select i1 %cmp, i64 %sub ,i64 0
62   %extrasub = sub i64 %b, %a
63   call void @use(i64 %extrasub)
64   ret i64 %sel
67 ; (b > a) ? 0 : a - b -> usub.sat(a, b)
69 define i64 @max_sub_ugt_sel_swapped(i64 %a, i64 %b) {
70 ; CHECK-LABEL: @max_sub_ugt_sel_swapped(
71 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
72 ; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[B]], [[A]]
73 ; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
74 ; CHECK-NEXT:    ret i64 [[TMP1]]
76   %cmp = icmp ugt i64 %b, %a
77   %sub = sub i64 %a, %b
78   %sel = select i1 %cmp, i64 0 ,i64 %sub
79   %extrasub = sub i64 %b, %a
80   call void @use(i64 %extrasub)
81   ret i64 %sel
84 ; (a < b) ? 0 : a - b -> usub.sat(a, b)
86 define i64 @max_sub_ult_sel_swapped(i64 %a, i64 %b) {
87 ; CHECK-LABEL: @max_sub_ult_sel_swapped(
88 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
89 ; CHECK-NEXT:    ret i64 [[TMP1]]
91   %cmp = icmp ult i64 %a, %b
92   %sub = sub i64 %a, %b
93   %sel = select i1 %cmp, i64 0 ,i64 %sub
94   ret i64 %sel
97 ; ((a > b) ? b - a : 0) -> -usub.sat(a, b)
99 define i64 @neg_max_sub_ugt(i64 %a, i64 %b) {
100 ; CHECK-LABEL: @neg_max_sub_ugt(
101 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
102 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 0, [[TMP1]]
103 ; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[A]], [[B]]
104 ; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
105 ; CHECK-NEXT:    ret i64 [[TMP2]]
107   %cmp = icmp ugt i64 %a, %b
108   %sub = sub i64 %b, %a
109   %sel = select i1 %cmp, i64 %sub ,i64 0
110   %extrasub = sub i64 %a, %b
111   call void @use(i64 %extrasub)
112   ret i64 %sel
115 ; ((b < a) ? b - a : 0) -> -usub.sat(a, b)
117 define i64 @neg_max_sub_ult(i64 %a, i64 %b) {
118 ; CHECK-LABEL: @neg_max_sub_ult(
119 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
120 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 0, [[TMP1]]
121 ; CHECK-NEXT:    ret i64 [[TMP2]]
123   %cmp = icmp ult i64 %b, %a
124   %sub = sub i64 %b, %a
125   %sel = select i1 %cmp, i64 %sub ,i64 0
126   ret i64 %sel
129 ; ((b > a) ? 0 : b - a) -> -usub.sat(a, b)
131 define i64 @neg_max_sub_ugt_sel_swapped(i64 %a, i64 %b) {
132 ; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped(
133 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
134 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 0, [[TMP1]]
135 ; CHECK-NEXT:    ret i64 [[TMP2]]
137   %cmp = icmp ugt i64 %b, %a
138   %sub = sub i64 %b, %a
139   %sel = select i1 %cmp, i64 0 ,i64 %sub
140   ret i64 %sel
143 ; ((a < b) ? 0 : b - a) -> -usub.sat(a, b)
145 define i64 @neg_max_sub_ult_sel_swapped(i64 %a, i64 %b) {
146 ; CHECK-LABEL: @neg_max_sub_ult_sel_swapped(
147 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
148 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 0, [[TMP1]]
149 ; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[A]], [[B]]
150 ; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
151 ; CHECK-NEXT:    ret i64 [[TMP2]]
153   %cmp = icmp ult i64 %a, %b
154   %sub = sub i64 %b, %a
155   %sel = select i1 %cmp, i64 0 ,i64 %sub
156   %extrasub = sub i64 %a, %b
157   call void @use(i64 %extrasub)
158   ret i64 %sel