339 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; Given pattern:5; (x shiftopcode Q) shiftopcode K6; we should rewrite it as7; x shiftopcode (Q+K) iff (Q+K) u< bitwidth(x)8; This is valid for any shift, but they must be identical.9; THIS FOLD DOES *NOT* REQUIRE ANY 'exact'/'nuw'/`nsw` FLAGS!10 11; Basic scalar test12 13define i32 @t0(i32 %x, i32 %y) {14; CHECK-LABEL: @t0(15; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[X:%.*]], 3016; CHECK-NEXT: ret i32 [[T3]]17;18 %t0 = sub i32 32, %y19 %t1 = lshr i32 %x, %t020 %t2 = add i32 %y, -221 %t3 = lshr exact i32 %t1, %t2 ; while there, test that we don't propagate partial 'exact' flag22 ret i32 %t323}24 25define <2 x i32> @t1_vec_splat(<2 x i32> %x, <2 x i32> %y) {26; CHECK-LABEL: @t1_vec_splat(27; CHECK-NEXT: [[T3:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 30)28; CHECK-NEXT: ret <2 x i32> [[T3]]29;30 %t0 = sub <2 x i32> <i32 32, i32 32>, %y31 %t1 = lshr <2 x i32> %x, %t032 %t2 = add <2 x i32> %y, <i32 -2, i32 -2>33 %t3 = lshr <2 x i32> %t1, %t234 ret <2 x i32> %t335}36 37define <2 x i32> @t2_vec_nonsplat(<2 x i32> %x, <2 x i32> %y) {38; CHECK-LABEL: @t2_vec_nonsplat(39; CHECK-NEXT: [[T3:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 30)40; CHECK-NEXT: ret <2 x i32> [[T3]]41;42 %t0 = sub <2 x i32> <i32 32, i32 30>, %y43 %t1 = lshr <2 x i32> %x, %t044 %t2 = add <2 x i32> %y, <i32 -2, i32 0>45 %t3 = lshr <2 x i32> %t1, %t246 ret <2 x i32> %t347}48 49; Basic vector tests50 51define <3 x i32> @t3_vec_nonsplat_poison0(<3 x i32> %x, <3 x i32> %y) {52; CHECK-LABEL: @t3_vec_nonsplat_poison0(53; CHECK-NEXT: [[T3:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 30, i32 poison, i32 30>54; CHECK-NEXT: ret <3 x i32> [[T3]]55;56 %t0 = sub <3 x i32> <i32 32, i32 poison, i32 32>, %y57 %t1 = lshr <3 x i32> %x, %t058 %t2 = add <3 x i32> %y, <i32 -2, i32 -2, i32 -2>59 %t3 = lshr <3 x i32> %t1, %t260 ret <3 x i32> %t361}62 63define <3 x i32> @t4_vec_nonsplat_poison1(<3 x i32> %x, <3 x i32> %y) {64; CHECK-LABEL: @t4_vec_nonsplat_poison1(65; CHECK-NEXT: [[T3:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 30, i32 poison, i32 30>66; CHECK-NEXT: ret <3 x i32> [[T3]]67;68 %t0 = sub <3 x i32> <i32 32, i32 32, i32 32>, %y69 %t1 = lshr <3 x i32> %x, %t070 %t2 = add <3 x i32> %y, <i32 -2, i32 poison, i32 -2>71 %t3 = lshr <3 x i32> %t1, %t272 ret <3 x i32> %t373}74 75define <3 x i32> @t5_vec_nonsplat_poison1(<3 x i32> %x, <3 x i32> %y) {76; CHECK-LABEL: @t5_vec_nonsplat_poison1(77; CHECK-NEXT: [[T3:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 30, i32 poison, i32 30>78; CHECK-NEXT: ret <3 x i32> [[T3]]79;80 %t0 = sub <3 x i32> <i32 32, i32 poison, i32 32>, %y81 %t1 = lshr <3 x i32> %x, %t082 %t2 = add <3 x i32> %y, <i32 -2, i32 poison, i32 -2>83 %t3 = lshr <3 x i32> %t1, %t284 ret <3 x i32> %t385}86 87; Some other shift opcodes88define i32 @t6_shl(i32 %x, i32 %y) {89; CHECK-LABEL: @t6_shl(90; CHECK-NEXT: [[T3:%.*]] = shl i32 [[X:%.*]], 3091; CHECK-NEXT: ret i32 [[T3]]92;93 %t0 = sub i32 32, %y94 %t1 = shl nuw i32 %x, %t0 ; while there, test that we don't propagate partial 'nuw' flag95 %t2 = add i32 %y, -296 %t3 = shl nsw i32 %t1, %t2 ; while there, test that we don't propagate partial 'nsw' flag97 ret i32 %t398}99define i32 @t7_ashr(i32 %x, i32 %y) {100; CHECK-LABEL: @t7_ashr(101; CHECK-NEXT: [[T3:%.*]] = ashr i32 [[X:%.*]], 30102; CHECK-NEXT: ret i32 [[T3]]103;104 %t0 = sub i32 32, %y105 %t1 = ashr exact i32 %x, %t0 ; while there, test that we don't propagate partial 'exact' flag106 %t2 = add i32 %y, -2107 %t3 = ashr i32 %t1, %t2108 ret i32 %t3109}110 111; If the same flag is present on both shifts, it can be kept.112define i32 @t8_lshr_exact_flag_preservation(i32 %x, i32 %y) {113; CHECK-LABEL: @t8_lshr_exact_flag_preservation(114; CHECK-NEXT: [[T3:%.*]] = lshr exact i32 [[X:%.*]], 30115; CHECK-NEXT: ret i32 [[T3]]116;117 %t0 = sub i32 32, %y118 %t1 = lshr exact i32 %x, %t0119 %t2 = add i32 %y, -2120 %t3 = lshr exact i32 %t1, %t2121 ret i32 %t3122}123define i32 @t9_ashr_exact_flag_preservation(i32 %x, i32 %y) {124; CHECK-LABEL: @t9_ashr_exact_flag_preservation(125; CHECK-NEXT: [[T3:%.*]] = ashr exact i32 [[X:%.*]], 30126; CHECK-NEXT: ret i32 [[T3]]127;128 %t0 = sub i32 32, %y129 %t1 = ashr exact i32 %x, %t0130 %t2 = add i32 %y, -2131 %t3 = ashr exact i32 %t1, %t2132 ret i32 %t3133}134define i32 @t10_shl_nuw_flag_preservation(i32 %x, i32 %y) {135; CHECK-LABEL: @t10_shl_nuw_flag_preservation(136; CHECK-NEXT: [[T3:%.*]] = shl nuw i32 [[X:%.*]], 30137; CHECK-NEXT: ret i32 [[T3]]138;139 %t0 = sub i32 32, %y140 %t1 = shl nuw i32 %x, %t0141 %t2 = add i32 %y, -2142 %t3 = shl nuw nsw i32 %t1, %t2 ; only 'nuw' should be propagated.143 ret i32 %t3144}145define i32 @t11_shl_nsw_flag_preservation(i32 %x, i32 %y) {146; CHECK-LABEL: @t11_shl_nsw_flag_preservation(147; CHECK-NEXT: [[T3:%.*]] = shl nsw i32 [[X:%.*]], 30148; CHECK-NEXT: ret i32 [[T3]]149;150 %t0 = sub i32 32, %y151 %t1 = shl nsw i32 %x, %t0152 %t2 = add i32 %y, -2153 %t3 = shl nsw nuw i32 %t1, %t2 ; only 'nuw' should be propagated.154 ret i32 %t3155}156 157; Reduced from https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=15587158@X = external global i32159define i64 @constantexpr(ptr %A) {160; CHECK-LABEL: @constantexpr(ptr %A) {161; CHECK-NEXT: ret i64 0162;163 %L = load i64, ptr %A164 %V = add i64 ptrtoint (ptr @X to i64), 0165 %B2 = shl i64 %V, 0166 %B4 = ashr i64 %B2, %L167 %B = and i64 undef, %B4168 ret i64 %B169}170 171; No one-use tests since we will only produce a single instruction here.172 173; Negative tests174 175; Can't fold, total shift would be 32176define i32 @n12(i32 %x, i32 %y) {177; CHECK-LABEL: @n12(178; CHECK-NEXT: [[T0:%.*]] = sub i32 30, [[Y:%.*]]179; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]180; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], 2181; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T1]], [[T2]]182; CHECK-NEXT: ret i32 [[T3]]183;184 %t0 = sub i32 30, %y185 %t1 = lshr i32 %x, %t0186 %t2 = add i32 %y, 2187 %t3 = lshr i32 %t1, %t2188 ret i32 %t3189}190; Can't fold, for second channel the shift would 32191define <2 x i32> @t13_vec(<2 x i32> %x, <2 x i32> %y) {192; CHECK-LABEL: @t13_vec(193; CHECK-NEXT: [[T0:%.*]] = sub <2 x i32> <i32 32, i32 30>, [[Y:%.*]]194; CHECK-NEXT: [[T1:%.*]] = lshr <2 x i32> [[X:%.*]], [[T0]]195; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[Y]], <i32 -2, i32 2>196; CHECK-NEXT: [[T3:%.*]] = lshr <2 x i32> [[T1]], [[T2]]197; CHECK-NEXT: ret <2 x i32> [[T3]]198;199 %t0 = sub <2 x i32> <i32 32, i32 30>, %y200 %t1 = lshr <2 x i32> %x, %t0201 %t2 = add <2 x i32> %y, <i32 -2, i32 2>202 %t3 = lshr <2 x i32> %t1, %t2203 ret <2 x i32> %t3204}205 206; If we have different right-shifts, in general, we can't do anything with it.207define i32 @n13(i32 %x, i32 %y) {208; CHECK-LABEL: @n13(209; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]210; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]211; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -2212; CHECK-NEXT: [[T3:%.*]] = ashr i32 [[T1]], [[T2]]213; CHECK-NEXT: ret i32 [[T3]]214;215 %t0 = sub i32 32, %y216 %t1 = lshr i32 %x, %t0217 %t2 = add i32 %y, -2218 %t3 = ashr i32 %t1, %t2219 ret i32 %t3220}221define i32 @n14(i32 %x, i32 %y) {222; CHECK-LABEL: @n14(223; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]224; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]225; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1226; CHECK-NEXT: [[T3:%.*]] = ashr i32 [[T1]], [[T2]]227; CHECK-NEXT: ret i32 [[T3]]228;229 %t0 = sub i32 32, %y230 %t1 = lshr i32 %x, %t0231 %t2 = add i32 %y, -1232 %t3 = ashr i32 %t1, %t2233 ret i32 %t3234}235define i32 @n15(i32 %x, i32 %y) {236; CHECK-LABEL: @n15(237; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]238; CHECK-NEXT: [[T1:%.*]] = ashr i32 [[X:%.*]], [[T0]]239; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -2240; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T1]], [[T2]]241; CHECK-NEXT: ret i32 [[T3]]242;243 %t0 = sub i32 32, %y244 %t1 = ashr i32 %x, %t0245 %t2 = add i32 %y, -2246 %t3 = lshr i32 %t1, %t2247 ret i32 %t3248}249define i32 @n16(i32 %x, i32 %y) {250; CHECK-LABEL: @n16(251; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]252; CHECK-NEXT: [[T1:%.*]] = ashr i32 [[X:%.*]], [[T0]]253; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1254; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T1]], [[T2]]255; CHECK-NEXT: ret i32 [[T3]]256;257 %t0 = sub i32 32, %y258 %t1 = ashr i32 %x, %t0259 %t2 = add i32 %y, -1260 %t3 = lshr i32 %t1, %t2261 ret i32 %t3262}263 264; If the shift direction is different, then this should be handled elsewhere.265define i32 @n17(i32 %x, i32 %y) {266; CHECK-LABEL: @n17(267; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]268; CHECK-NEXT: [[T1:%.*]] = shl i32 [[X:%.*]], [[T0]]269; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1270; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T1]], [[T2]]271; CHECK-NEXT: ret i32 [[T3]]272;273 %t0 = sub i32 32, %y274 %t1 = shl i32 %x, %t0275 %t2 = add i32 %y, -1276 %t3 = lshr i32 %t1, %t2277 ret i32 %t3278}279define i32 @n18(i32 %x, i32 %y) {280; CHECK-LABEL: @n18(281; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]282; CHECK-NEXT: [[T1:%.*]] = shl i32 [[X:%.*]], [[T0]]283; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1284; CHECK-NEXT: [[T3:%.*]] = ashr i32 [[T1]], [[T2]]285; CHECK-NEXT: ret i32 [[T3]]286;287 %t0 = sub i32 32, %y288 %t1 = shl i32 %x, %t0289 %t2 = add i32 %y, -1290 %t3 = ashr i32 %t1, %t2291 ret i32 %t3292}293define i32 @n19(i32 %x, i32 %y) {294; CHECK-LABEL: @n19(295; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]296; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]297; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1298; CHECK-NEXT: [[T3:%.*]] = shl i32 [[T1]], [[T2]]299; CHECK-NEXT: ret i32 [[T3]]300;301 %t0 = sub i32 32, %y302 %t1 = lshr i32 %x, %t0303 %t2 = add i32 %y, -1304 %t3 = shl i32 %t1, %t2305 ret i32 %t3306}307define i32 @n20(i32 %x, i32 %y) {308; CHECK-LABEL: @n20(309; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[Y:%.*]]310; CHECK-NEXT: [[T1:%.*]] = ashr i32 [[X:%.*]], [[T0]]311; CHECK-NEXT: [[T2:%.*]] = add i32 [[Y]], -1312; CHECK-NEXT: [[T3:%.*]] = shl i32 [[T1]], [[T2]]313; CHECK-NEXT: ret i32 [[T3]]314;315 %t0 = sub i32 32, %y316 %t1 = ashr i32 %x, %t0317 %t2 = add i32 %y, -1318 %t3 = shl i32 %t1, %t2319 ret i32 %t3320}321 322; See https://bugs.llvm.org/show_bug.cgi?id=44802323define i3 @pr44802(i3 %t0) {324; CHECK-LABEL: @pr44802(325; CHECK-NEXT: [[T1:%.*]] = sub i3 0, [[T0:%.*]]326; CHECK-NEXT: [[T2:%.*]] = icmp ne i3 [[T0]], 0327; CHECK-NEXT: [[T3:%.*]] = zext i1 [[T2]] to i3328; CHECK-NEXT: [[T4:%.*]] = lshr i3 [[T1]], [[T3]]329; CHECK-NEXT: [[T5:%.*]] = lshr i3 [[T4]], [[T3]]330; CHECK-NEXT: ret i3 [[T5]]331;332 %t1 = sub i3 0, %t0333 %t2 = icmp ne i3 %t0, 0334 %t3 = zext i1 %t2 to i3335 %t4 = lshr i3 %t1, %t3336 %t5 = lshr i3 %t4, %t3337 ret i3 %t5338}339