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