xref: /llvm-project/llvm/test/Analysis/ValueTracking/knownbits-trunc-with-min-max-clamp.ll (revision 088d636136a42d738e15f2f0a85e1b77a8f2de35)
16d7cf520Sadam-bzowski; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
26d7cf520Sadam-bzowski; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s
36d7cf520Sadam-bzowski
46d7cf520Sadam-bzowski; The LIT tests rely on i32, i16 and i8 being valid machine types.
5*088d6361Sadam-bzowski; The bounds checking tests require also i64 and i128.
6*088d6361Sadam-bzowskitarget datalayout = "n8:16:32:64:128"
76d7cf520Sadam-bzowski
86d7cf520Sadam-bzowski; This LIT test checks if TruncInstCombine pass correctly recognizes the
96d7cf520Sadam-bzowski; constraints from a signed min-max clamp. The clamp is a sequence of smin and
106d7cf520Sadam-bzowski; smax instructions limiting a variable into a range, smin <= x <= smax.
116d7cf520Sadam-bzowski;
126d7cf520Sadam-bzowski; Each LIT test (except the last ones) has two versions depending on the order
136d7cf520Sadam-bzowski; of smin and smax:
146d7cf520Sadam-bzowski; a) y = smax(smin(x, upper_limit), lower_limit)
156d7cf520Sadam-bzowski; b) y = smin(smax(x, lower_limit), upper_limit)
16*088d6361Sadam-bzowski;
17*088d6361Sadam-bzowski; The clamp is used in TruncInstCombine.cpp pass (as part of aggressive-instcombine)
18*088d6361Sadam-bzowski; to optimize extensions and truncations of lshr. This is what is tested here.
19*088d6361Sadam-bzowski; The pass also optimizes extensions and truncations of other binary operators,
20*088d6361Sadam-bzowski; but in such cases the smin-smax clamp may not be used.
216d7cf520Sadam-bzowski
226d7cf520Sadam-bzowskidefine i8 @test_0a(i16 %x) {
236d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_0a(
246d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
256d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smin.i16(i16 [[X]], i16 31)
266d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smax.i16(i16 [[TMP1]], i16 0)
276d7cf520Sadam-bzowski; CHECK-NEXT:    [[A:%.*]] = trunc i16 [[TMP2]] to i8
286d7cf520Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i8 [[A]], 2
296d7cf520Sadam-bzowski; CHECK-NEXT:    ret i8 [[B]]
306d7cf520Sadam-bzowski;
316d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smin.i16(i16 %x, i16 31)
326d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 0)
336d7cf520Sadam-bzowski  %a = sext i16 %2 to i32
346d7cf520Sadam-bzowski  %b = lshr i32 %a, 2
356d7cf520Sadam-bzowski  %b.trunc = trunc i32 %b to i8
366d7cf520Sadam-bzowski  ret i8 %b.trunc
376d7cf520Sadam-bzowski}
386d7cf520Sadam-bzowski
396d7cf520Sadam-bzowskidefine i8 @test_0b(i16 %x) {
406d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_0b(
416d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
426d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smax.i16(i16 [[X]], i16 0)
436d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smin.i16(i16 [[TMP1]], i16 31)
446d7cf520Sadam-bzowski; CHECK-NEXT:    [[A:%.*]] = trunc i16 [[TMP2]] to i8
456d7cf520Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i8 [[A]], 2
466d7cf520Sadam-bzowski; CHECK-NEXT:    ret i8 [[B]]
476d7cf520Sadam-bzowski;
486d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smax.i16(i16 %x, i16 0)
496d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smin.i16(i16 %1, i16 31)
506d7cf520Sadam-bzowski  %a = sext i16 %2 to i32
516d7cf520Sadam-bzowski  %b = lshr i32 %a, 2
526d7cf520Sadam-bzowski  %b.trunc = trunc i32 %b to i8
536d7cf520Sadam-bzowski  ret i8 %b.trunc
546d7cf520Sadam-bzowski}
556d7cf520Sadam-bzowski
56*088d6361Sadam-bzowski; The following two tests contain add instead of lshr.
57*088d6361Sadam-bzowski; The optimization works here as well.
586d7cf520Sadam-bzowskidefine i8 @test_1a(i16 %x) {
596d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_1a(
606d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
616d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smin.i16(i16 [[X]], i16 31)
626d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smax.i16(i16 [[TMP1]], i16 0)
636d7cf520Sadam-bzowski; CHECK-NEXT:    [[A:%.*]] = trunc i16 [[TMP2]] to i8
646d7cf520Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = add i8 [[A]], 2
656d7cf520Sadam-bzowski; CHECK-NEXT:    ret i8 [[B]]
666d7cf520Sadam-bzowski;
676d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smin.i16(i16 %x, i16 31)
686d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 0)
696d7cf520Sadam-bzowski  %a = sext i16 %2 to i32
706d7cf520Sadam-bzowski  %b = add i32 %a, 2
716d7cf520Sadam-bzowski  %b.trunc = trunc i32 %b to i8
726d7cf520Sadam-bzowski  ret i8 %b.trunc
736d7cf520Sadam-bzowski}
746d7cf520Sadam-bzowski
756d7cf520Sadam-bzowskidefine i8 @test_1b(i16 %x) {
766d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_1b(
776d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
786d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smax.i16(i16 [[X]], i16 0)
796d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smin.i16(i16 [[TMP1]], i16 31)
806d7cf520Sadam-bzowski; CHECK-NEXT:    [[A:%.*]] = trunc i16 [[TMP2]] to i8
816d7cf520Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = add i8 [[A]], 2
826d7cf520Sadam-bzowski; CHECK-NEXT:    ret i8 [[B]]
836d7cf520Sadam-bzowski;
846d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smax.i16(i16 %x, i16 0)
856d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smin.i16(i16 %1, i16 31)
866d7cf520Sadam-bzowski  %a = sext i16 %2 to i32
876d7cf520Sadam-bzowski  %b = add i32 %a, 2
886d7cf520Sadam-bzowski  %b.trunc = trunc i32 %b to i8
896d7cf520Sadam-bzowski  ret i8 %b.trunc
906d7cf520Sadam-bzowski}
916d7cf520Sadam-bzowski
92*088d6361Sadam-bzowski; Tests for clamping with negative min and max.
93*088d6361Sadam-bzowski
94*088d6361Sadam-bzowski; With sext no optimization occurs.
956d7cf520Sadam-bzowskidefine i8 @test_2a(i16 %x) {
966d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_2a(
976d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
986d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smin.i16(i16 [[X]], i16 -1)
996d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smax.i16(i16 [[TMP1]], i16 -31)
100*088d6361Sadam-bzowski; CHECK-NEXT:    [[A:%.*]] = sext i16 [[TMP2]] to i32
101*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i32 [[A]], 2
102*088d6361Sadam-bzowski; CHECK-NEXT:    [[B_TRUNC:%.*]] = trunc i32 [[B]] to i8
103*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B_TRUNC]]
1046d7cf520Sadam-bzowski;
1056d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smin.i16(i16 %x, i16 -1)
1066d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 -31)
1076d7cf520Sadam-bzowski  %a = sext i16 %2 to i32
108*088d6361Sadam-bzowski  %b = lshr i32 %a, 2
1096d7cf520Sadam-bzowski  %b.trunc = trunc i32 %b to i8
1106d7cf520Sadam-bzowski  ret i8 %b.trunc
1116d7cf520Sadam-bzowski}
1126d7cf520Sadam-bzowski
1136d7cf520Sadam-bzowskidefine i8 @test_2b(i16 %x) {
1146d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_2b(
1156d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
1166d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smax.i16(i16 [[X]], i16 -31)
1176d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smin.i16(i16 [[TMP1]], i16 -1)
118*088d6361Sadam-bzowski; CHECK-NEXT:    [[A:%.*]] = sext i16 [[TMP2]] to i32
119*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i32 [[A]], 2
120*088d6361Sadam-bzowski; CHECK-NEXT:    [[B_TRUNC:%.*]] = trunc i32 [[B]] to i8
121*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B_TRUNC]]
1226d7cf520Sadam-bzowski;
1236d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smax.i16(i16 %x, i16 -31)
1246d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smin.i16(i16 %1, i16 -1)
1256d7cf520Sadam-bzowski  %a = sext i16 %2 to i32
126*088d6361Sadam-bzowski  %b = lshr i32 %a, 2
1276d7cf520Sadam-bzowski  %b.trunc = trunc i32 %b to i8
1286d7cf520Sadam-bzowski  ret i8 %b.trunc
1296d7cf520Sadam-bzowski}
1306d7cf520Sadam-bzowski
131*088d6361Sadam-bzowski; With zext the optimization occurs.
132*088d6361Sadam-bzowskidefine i8 @test_2c(i16 %x) {
133*088d6361Sadam-bzowski; CHECK-LABEL: define i8 @test_2c(
134*088d6361Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
135*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smin.i16(i16 [[X]], i16 -1)
136*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smax.i16(i16 [[TMP1]], i16 -31)
137*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i16 [[TMP2]], 2
138*088d6361Sadam-bzowski; CHECK-NEXT:    [[B_TRUNC:%.*]] = trunc i16 [[B]] to i8
139*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B_TRUNC]]
140*088d6361Sadam-bzowski;
141*088d6361Sadam-bzowski  %1 = tail call i16 @llvm.smin.i16(i16 %x, i16 -1)
142*088d6361Sadam-bzowski  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 -31)
143*088d6361Sadam-bzowski  %a = zext i16 %2 to i32
144*088d6361Sadam-bzowski  %b = lshr i32 %a, 2
145*088d6361Sadam-bzowski  %b.trunc = trunc i32 %b to i8
146*088d6361Sadam-bzowski  ret i8 %b.trunc
147*088d6361Sadam-bzowski}
148*088d6361Sadam-bzowski
149*088d6361Sadam-bzowskidefine i8 @test_2d(i16 %x) {
150*088d6361Sadam-bzowski; CHECK-LABEL: define i8 @test_2d(
151*088d6361Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
152*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smax.i16(i16 [[X]], i16 -31)
153*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smin.i16(i16 [[TMP1]], i16 -1)
154*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i16 [[TMP2]], 2
155*088d6361Sadam-bzowski; CHECK-NEXT:    [[B_TRUNC:%.*]] = trunc i16 [[B]] to i8
156*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B_TRUNC]]
157*088d6361Sadam-bzowski;
158*088d6361Sadam-bzowski  %1 = tail call i16 @llvm.smax.i16(i16 %x, i16 -31)
159*088d6361Sadam-bzowski  %2 = tail call i16 @llvm.smin.i16(i16 %1, i16 -1)
160*088d6361Sadam-bzowski  %a = zext i16 %2 to i32
161*088d6361Sadam-bzowski  %b = lshr i32 %a, 2
162*088d6361Sadam-bzowski  %b.trunc = trunc i32 %b to i8
163*088d6361Sadam-bzowski  ret i8 %b.trunc
164*088d6361Sadam-bzowski}
165*088d6361Sadam-bzowski
166*088d6361Sadam-bzowski; Tests for clamping with mixed-signed min and max.
167*088d6361Sadam-bzowski; With zext the optimization occurs.
1686d7cf520Sadam-bzowskidefine i8 @test_3a(i16 %x) {
1696d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_3a(
1706d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
1716d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smin.i16(i16 [[X]], i16 31)
1726d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smax.i16(i16 [[TMP1]], i16 -31)
173*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i16 [[TMP2]], 2
174*088d6361Sadam-bzowski; CHECK-NEXT:    [[B_TRUNC:%.*]] = trunc i16 [[B]] to i8
175*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B_TRUNC]]
1766d7cf520Sadam-bzowski;
1776d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smin.i16(i16 %x, i16 31)
1786d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 -31)
179*088d6361Sadam-bzowski  %a = zext i16 %2 to i32
180*088d6361Sadam-bzowski  %b = lshr i32 %a, 2
1816d7cf520Sadam-bzowski  %b.trunc = trunc i32 %b to i8
1826d7cf520Sadam-bzowski  ret i8 %b.trunc
1836d7cf520Sadam-bzowski}
1846d7cf520Sadam-bzowski
1856d7cf520Sadam-bzowskidefine i8 @test_3b(i16 %x) {
1866d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_3b(
1876d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
1886d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smax.i16(i16 [[X]], i16 -31)
1896d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smin.i16(i16 [[TMP1]], i16 31)
190*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i16 [[TMP2]], 2
191*088d6361Sadam-bzowski; CHECK-NEXT:    [[B_TRUNC:%.*]] = trunc i16 [[B]] to i8
192*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B_TRUNC]]
1936d7cf520Sadam-bzowski;
1946d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smax.i16(i16 %x, i16 -31)
1956d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smin.i16(i16 %1, i16 31)
196*088d6361Sadam-bzowski  %a = zext i16 %2 to i32
197*088d6361Sadam-bzowski  %b = lshr i32 %a, 2
1986d7cf520Sadam-bzowski  %b.trunc = trunc i32 %b to i8
1996d7cf520Sadam-bzowski  ret i8 %b.trunc
2006d7cf520Sadam-bzowski}
2016d7cf520Sadam-bzowski
202*088d6361Sadam-bzowski; Optimizations with vector types.
2036d7cf520Sadam-bzowskidefine <16 x i8> @test_vec_1a(<16 x i16> %x) {
2046d7cf520Sadam-bzowski; CHECK-LABEL: define <16 x i8> @test_vec_1a(
2056d7cf520Sadam-bzowski; CHECK-SAME: <16 x i16> [[X:%.*]]) {
2066d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call <16 x i16> @llvm.smin.v16i16(<16 x i16> [[X]], <16 x i16> splat (i16 127))
2076d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call <16 x i16> @llvm.smax.v16i16(<16 x i16> [[TMP1]], <16 x i16> zeroinitializer)
2086d7cf520Sadam-bzowski; CHECK-NEXT:    [[A:%.*]] = trunc <16 x i16> [[TMP2]] to <16 x i8>
209*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr <16 x i8> [[A]], splat (i8 2)
2106d7cf520Sadam-bzowski; CHECK-NEXT:    ret <16 x i8> [[B]]
2116d7cf520Sadam-bzowski;
2126d7cf520Sadam-bzowski  %1 = tail call <16 x i16> @llvm.smin.v16i16(<16 x i16> %x, <16 x i16> splat (i16 127))
2136d7cf520Sadam-bzowski  %2 = tail call <16 x i16> @llvm.smax.v16i16(<16 x i16> %1, <16 x i16> zeroinitializer)
2146d7cf520Sadam-bzowski  %a = sext <16 x i16> %2 to <16 x i32>
215*088d6361Sadam-bzowski  %b = lshr <16 x i32> %a, splat (i32 2)
2166d7cf520Sadam-bzowski  %b.trunc = trunc <16 x i32> %b to <16 x i8>
2176d7cf520Sadam-bzowski  ret <16 x i8> %b.trunc
2186d7cf520Sadam-bzowski}
2196d7cf520Sadam-bzowski
2206d7cf520Sadam-bzowskidefine <16 x i8> @test_vec_1b(<16 x i16> %x) {
2216d7cf520Sadam-bzowski; CHECK-LABEL: define <16 x i8> @test_vec_1b(
2226d7cf520Sadam-bzowski; CHECK-SAME: <16 x i16> [[X:%.*]]) {
2236d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call <16 x i16> @llvm.smax.v16i16(<16 x i16> [[X]], <16 x i16> zeroinitializer)
2246d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call <16 x i16> @llvm.smin.v16i16(<16 x i16> [[TMP1]], <16 x i16> splat (i16 127))
2256d7cf520Sadam-bzowski; CHECK-NEXT:    [[A:%.*]] = trunc <16 x i16> [[TMP2]] to <16 x i8>
226*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr <16 x i8> [[A]], splat (i8 2)
2276d7cf520Sadam-bzowski; CHECK-NEXT:    ret <16 x i8> [[B]]
2286d7cf520Sadam-bzowski;
2296d7cf520Sadam-bzowski  %1 = tail call <16 x i16> @llvm.smax.v16i16(<16 x i16> %x, <16 x i16> zeroinitializer)
2306d7cf520Sadam-bzowski  %2 = tail call <16 x i16> @llvm.smin.v16i16(<16 x i16> %1, <16 x i16> splat (i16 127))
2316d7cf520Sadam-bzowski  %a = sext <16 x i16> %2 to <16 x i32>
232*088d6361Sadam-bzowski  %b = lshr <16 x i32> %a, splat (i32 2)
2336d7cf520Sadam-bzowski  %b.trunc = trunc <16 x i32> %b to <16 x i8>
2346d7cf520Sadam-bzowski  ret <16 x i8> %b.trunc
2356d7cf520Sadam-bzowski}
2366d7cf520Sadam-bzowski
2376d7cf520Sadam-bzowski; A longer test that was the original motivation for the smin-smax clamping.
2386d7cf520Sadam-bzowskidefine i8 @test_final(i16 %x, i16 %y) {
2396d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_final(
2406d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]], i16 [[Y:%.*]]) {
2416d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smin.i16(i16 [[X]], i16 127)
2426d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smax.i16(i16 [[TMP1]], i16 0)
2436d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP3:%.*]] = tail call i16 @llvm.smax.i16(i16 [[Y]], i16 0)
2446d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP4:%.*]] = tail call i16 @llvm.smin.i16(i16 [[TMP3]], i16 127)
2456d7cf520Sadam-bzowski; CHECK-NEXT:    [[MUL:%.*]] = mul i16 [[TMP2]], [[TMP4]]
2466d7cf520Sadam-bzowski; CHECK-NEXT:    [[SHR:%.*]] = lshr i16 [[MUL]], 7
2476d7cf520Sadam-bzowski; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i16 [[SHR]] to i8
2486d7cf520Sadam-bzowski; CHECK-NEXT:    ret i8 [[TRUNC]]
2496d7cf520Sadam-bzowski;
2506d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smin.i16(i16 %x, i16 127)
2516d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 0)
2526d7cf520Sadam-bzowski  %x.clamp = zext nneg i16 %2 to i32
2536d7cf520Sadam-bzowski  %3 = tail call i16 @llvm.smax.i16(i16 %y, i16 0)
2546d7cf520Sadam-bzowski  %4 = tail call i16 @llvm.smin.i16(i16 %3, i16 127)
2556d7cf520Sadam-bzowski  %y.clamp = zext nneg i16 %4 to i32
2566d7cf520Sadam-bzowski  %mul = mul nuw nsw i32 %x.clamp, %y.clamp
2576d7cf520Sadam-bzowski  %shr = lshr i32 %mul, 7
2586d7cf520Sadam-bzowski  %trunc= trunc nuw nsw i32 %shr to i8
2596d7cf520Sadam-bzowski  ret i8 %trunc
2606d7cf520Sadam-bzowski}
2616d7cf520Sadam-bzowski
2626d7cf520Sadam-bzowski; Range tests below check if the bounds are dealt with correctly.
2636d7cf520Sadam-bzowski
2646d7cf520Sadam-bzowski; This gets optimized.
2656d7cf520Sadam-bzowskidefine i8 @test_bounds_1(i16 %x) {
2666d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_bounds_1(
2676d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
2686d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smin.i16(i16 [[X]], i16 127)
2696d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smax.i16(i16 [[TMP1]], i16 0)
2706d7cf520Sadam-bzowski; CHECK-NEXT:    [[A:%.*]] = trunc i16 [[TMP2]] to i8
271*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i8 [[A]], 7
272*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B]]
2736d7cf520Sadam-bzowski;
2746d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smin.i16(i16 %x, i16 127)
2756d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 0)
2766d7cf520Sadam-bzowski  %a = sext i16 %2 to i32
277*088d6361Sadam-bzowski  %b = lshr i32 %a, 7
278*088d6361Sadam-bzowski  %b.trunc = trunc i32 %b to i8
2796d7cf520Sadam-bzowski  ret i8 %b.trunc
2806d7cf520Sadam-bzowski}
2816d7cf520Sadam-bzowski
2826d7cf520Sadam-bzowski; While this does not.
2836d7cf520Sadam-bzowskidefine i8 @test_bounds_2(i16 %x) {
2846d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_bounds_2(
2856d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
2866d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smin.i16(i16 [[X]], i16 128)
2876d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smax.i16(i16 [[TMP1]], i16 0)
288*088d6361Sadam-bzowski; CHECK-NEXT:    [[A:%.*]] = trunc i16 [[TMP2]] to i8
289*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i8 [[A]], 7
290*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B]]
2916d7cf520Sadam-bzowski;
2926d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smin.i16(i16 %x, i16 128)
2936d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 0)
2946d7cf520Sadam-bzowski  %a = sext i16 %2 to i32
295*088d6361Sadam-bzowski  %b = lshr i32 %a, 7
296*088d6361Sadam-bzowski  %b.trunc = trunc i32 %b to i8
2976d7cf520Sadam-bzowski  ret i8 %b.trunc
2986d7cf520Sadam-bzowski}
2996d7cf520Sadam-bzowski
3006d7cf520Sadam-bzowski; This should get optimized. We test here if the optimization works correctly
3016d7cf520Sadam-bzowski; if the upper limit is signed max int.
3026d7cf520Sadam-bzowskidefine i8 @test_bounds_3(i16 %x) {
3036d7cf520Sadam-bzowski; CHECK-LABEL: define i8 @test_bounds_3(
3046d7cf520Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
3056d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smin.i16(i16 [[X]], i16 32767)
3066d7cf520Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smax.i16(i16 [[TMP1]], i16 32752)
307*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i16 [[TMP2]], 2
308*088d6361Sadam-bzowski; CHECK-NEXT:    [[B_TRUNC:%.*]] = trunc i16 [[B]] to i8
309*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B_TRUNC]]
3106d7cf520Sadam-bzowski;
3116d7cf520Sadam-bzowski  %1 = tail call i16 @llvm.smin.i16(i16 %x, i16 32767)
3126d7cf520Sadam-bzowski  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 32752)
3136d7cf520Sadam-bzowski  %a = sext i16 %2 to i32
314*088d6361Sadam-bzowski  %b = lshr i32 %a, 2
315*088d6361Sadam-bzowski  %b.trunc = trunc i32 %b to i8
316*088d6361Sadam-bzowski  ret i8 %b.trunc
317*088d6361Sadam-bzowski}
318*088d6361Sadam-bzowski
319*088d6361Sadam-bzowski; Here min = 128 is greater than max = 0.
320*088d6361Sadam-bzowskidefine i8 @test_bounds_4(i16 %x) {
321*088d6361Sadam-bzowski; CHECK-LABEL: define i8 @test_bounds_4(
322*088d6361Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
323*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smin.i16(i16 [[X]], i16 0)
324*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smax.i16(i16 [[TMP1]], i16 128)
325*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i16 [[TMP2]], 2
326*088d6361Sadam-bzowski; CHECK-NEXT:    [[B_TRUNC:%.*]] = trunc i16 [[B]] to i8
327*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B_TRUNC]]
328*088d6361Sadam-bzowski;
329*088d6361Sadam-bzowski  %1 = tail call i16 @llvm.smin.i16(i16 %x, i16 0)
330*088d6361Sadam-bzowski  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 128)
331*088d6361Sadam-bzowski  %a = sext i16 %2 to i32
332*088d6361Sadam-bzowski  %b = lshr i32 %a, 2
333*088d6361Sadam-bzowski  %b.trunc = trunc i32 %b to i8
334*088d6361Sadam-bzowski  ret i8 %b.trunc
335*088d6361Sadam-bzowski}
336*088d6361Sadam-bzowski
337*088d6361Sadam-bzowski; The following 3 tests check the situation where min and max are minimal and
338*088d6361Sadam-bzowski; maximal signed values. No transformations should occur here.
339*088d6361Sadam-bzowskidefine i8 @test_bounds_5(i16 %x) {
340*088d6361Sadam-bzowski; CHECK-LABEL: define i8 @test_bounds_5(
341*088d6361Sadam-bzowski; CHECK-SAME: i16 [[X:%.*]]) {
342*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i16 @llvm.smin.i16(i16 [[X]], i16 32767)
343*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i16 @llvm.smax.i16(i16 [[TMP1]], i16 -32768)
344*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i16 [[TMP2]], 2
345*088d6361Sadam-bzowski; CHECK-NEXT:    [[B_TRUNC:%.*]] = trunc i16 [[B]] to i8
346*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B_TRUNC]]
347*088d6361Sadam-bzowski;
348*088d6361Sadam-bzowski  %1 = tail call i16 @llvm.smin.i16(i16 %x, i16 32767)
349*088d6361Sadam-bzowski  %2 = tail call i16 @llvm.smax.i16(i16 %1, i16 -32768)
350*088d6361Sadam-bzowski  %a = zext i16 %2 to i32
351*088d6361Sadam-bzowski  %b = lshr i32 %a, 2
352*088d6361Sadam-bzowski  %b.trunc = trunc i32 %b to i8
353*088d6361Sadam-bzowski  ret i8 %b.trunc
354*088d6361Sadam-bzowski}
355*088d6361Sadam-bzowski
356*088d6361Sadam-bzowskidefine i8 @test_bounds_6(i32 %x) {
357*088d6361Sadam-bzowski; CHECK-LABEL: define i8 @test_bounds_6(
358*088d6361Sadam-bzowski; CHECK-SAME: i32 [[X:%.*]]) {
359*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i32 @llvm.smin.i32(i32 [[X]], i32 2147483647)
360*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 -2147483648)
361*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i32 [[TMP2]], 2
362*088d6361Sadam-bzowski; CHECK-NEXT:    [[B_TRUNC:%.*]] = trunc i32 [[B]] to i8
363*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B_TRUNC]]
364*088d6361Sadam-bzowski;
365*088d6361Sadam-bzowski  %1 = tail call i32 @llvm.smin.i32(i32 %x, i32 2147483647)
366*088d6361Sadam-bzowski  %2 = tail call i32 @llvm.smax.i32(i32 %1, i32 -2147483648)
367*088d6361Sadam-bzowski  %a = zext i32 %2 to i64
368*088d6361Sadam-bzowski  %b = lshr i64 %a, 2
369*088d6361Sadam-bzowski  %b.trunc = trunc i64 %b to i8
370*088d6361Sadam-bzowski  ret i8 %b.trunc
371*088d6361Sadam-bzowski}
372*088d6361Sadam-bzowski
373*088d6361Sadam-bzowskidefine i8 @test_bounds_7(i64 %x) {
374*088d6361Sadam-bzowski; CHECK-LABEL: define i8 @test_bounds_7(
375*088d6361Sadam-bzowski; CHECK-SAME: i64 [[X:%.*]]) {
376*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP1:%.*]] = tail call i64 @llvm.smin.i64(i64 [[X]], i64 9223372036854775807)
377*088d6361Sadam-bzowski; CHECK-NEXT:    [[TMP2:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP1]], i64 -9223372036854775808)
378*088d6361Sadam-bzowski; CHECK-NEXT:    [[B:%.*]] = lshr i64 [[TMP2]], 2
379*088d6361Sadam-bzowski; CHECK-NEXT:    [[B_TRUNC:%.*]] = trunc i64 [[B]] to i8
380*088d6361Sadam-bzowski; CHECK-NEXT:    ret i8 [[B_TRUNC]]
381*088d6361Sadam-bzowski;
382*088d6361Sadam-bzowski  %1 = tail call i64 @llvm.smin.i64(i64 %x, i64 9223372036854775807)
383*088d6361Sadam-bzowski  %2 = tail call i64 @llvm.smax.i64(i64 %1, i64 -9223372036854775808)
384*088d6361Sadam-bzowski  %a = zext i64 %2 to i128
385*088d6361Sadam-bzowski  %b = lshr i128 %a, 2
386*088d6361Sadam-bzowski  %b.trunc = trunc i128 %b to i8
3876d7cf520Sadam-bzowski  ret i8 %b.trunc
3886d7cf520Sadam-bzowski}
389