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.
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
18 %sel = select i1 %cmp, i64 %sub ,i64 0
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
31 %sel = select i1 %cmp, i64 %sub ,i64 0
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
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
61 %sel = select i1 %cmp, i64 %sub ,i64 0
62 %extrasub = sub i64 %b, %a
63 call void @use(i64 %extrasub)
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
78 %sel = select i1 %cmp, i64 0 ,i64 %sub
79 %extrasub = sub i64 %b, %a
80 call void @use(i64 %extrasub)
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
93 %sel = select i1 %cmp, i64 0 ,i64 %sub
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)
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
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
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)