364 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; If we have a relational comparison with a constant, and said comparison is5; used in a select, and there is a constant in select, see if we can make6; those constants match.7 8; We can't ever get non-canonical scalar predicates.9 10; Likewise, while we can get non-canonical vector predicates, there must be an11; extra use on that `icmp`, which precludes the fold from happening.12 13;------------------------------------------------------------------------------;14; Canonical scalar predicates15;------------------------------------------------------------------------------;16 17!0 = !{!"branch_weights", i32 2000, i32 1}18 19define i32 @p0_ult_65536(i32 %x, i32 %y) {20; CHECK-LABEL: @p0_ult_65536(21; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 6553522; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]], !prof [[PROF0:![0-9]+]]23; CHECK-NEXT: ret i32 [[R]]24;25 %t = icmp ult i32 %x, 6553626 %r = select i1 %t, i32 %y, i32 65535, !prof !027 ret i32 %r28}29define i32 @p1_ugt(i32 %x, i32 %y) {30; CHECK-LABEL: @p1_ugt(31; CHECK-NEXT: [[T_INV:%.*]] = icmp ult i32 [[X:%.*]], 6553532; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]33; CHECK-NEXT: ret i32 [[R]]34;35 %t = icmp ugt i32 %x, 6553436 %r = select i1 %t, i32 %y, i32 6553537 ret i32 %r38}39define i32 @p2_slt_65536(i32 %x, i32 %y) {40; CHECK-LABEL: @p2_slt_65536(41; CHECK-NEXT: [[T_INV:%.*]] = icmp sgt i32 [[X:%.*]], 6553542; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]43; CHECK-NEXT: ret i32 [[R]]44;45 %t = icmp slt i32 %x, 6553646 %r = select i1 %t, i32 %y, i32 6553547 ret i32 %r48}49define i32 @p3_sgt(i32 %x, i32 %y) {50; CHECK-LABEL: @p3_sgt(51; CHECK-NEXT: [[T_INV:%.*]] = icmp slt i32 [[X:%.*]], 6553552; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]53; CHECK-NEXT: ret i32 [[R]]54;55 %t = icmp sgt i32 %x, 6553456 %r = select i1 %t, i32 %y, i32 6553557 ret i32 %r58}59 60;------------------------------------------------------------------------------;61; Vectors62;------------------------------------------------------------------------------;63 64define <2 x i32> @p4_vec_splat_ult_65536(<2 x i32> %x, <2 x i32> %y) {65; CHECK-LABEL: @p4_vec_splat_ult_65536(66; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], splat (i32 65535)67; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> splat (i32 65535), <2 x i32> [[Y:%.*]]68; CHECK-NEXT: ret <2 x i32> [[R]]69;70 %t = icmp ult <2 x i32> %x, <i32 65536, i32 65536>71 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>72 ret <2 x i32> %r73}74define <2 x i32> @p5_vec_splat_ugt(<2 x i32> %x, <2 x i32> %y) {75; CHECK-LABEL: @p5_vec_splat_ugt(76; CHECK-NEXT: [[T_INV:%.*]] = icmp ult <2 x i32> [[X:%.*]], splat (i32 65535)77; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> splat (i32 65535), <2 x i32> [[Y:%.*]]78; CHECK-NEXT: ret <2 x i32> [[R]]79;80 %t = icmp ugt <2 x i32> %x, <i32 65534, i32 65534>81 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>82 ret <2 x i32> %r83}84define <2 x i32> @p6_vec_splat_slt_65536(<2 x i32> %x, <2 x i32> %y) {85; CHECK-LABEL: @p6_vec_splat_slt_65536(86; CHECK-NEXT: [[T_INV:%.*]] = icmp sgt <2 x i32> [[X:%.*]], splat (i32 65535)87; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> splat (i32 65535), <2 x i32> [[Y:%.*]]88; CHECK-NEXT: ret <2 x i32> [[R]]89;90 %t = icmp slt <2 x i32> %x, <i32 65536, i32 65536>91 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>92 ret <2 x i32> %r93}94define <2 x i32> @p7_vec_splat_sgt(<2 x i32> %x, <2 x i32> %y) {95; CHECK-LABEL: @p7_vec_splat_sgt(96; CHECK-NEXT: [[T_INV:%.*]] = icmp slt <2 x i32> [[X:%.*]], splat (i32 65535)97; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> splat (i32 65535), <2 x i32> [[Y:%.*]]98; CHECK-NEXT: ret <2 x i32> [[R]]99;100 %t = icmp sgt <2 x i32> %x, <i32 65534, i32 65534>101 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>102 ret <2 x i32> %r103}104 105; Vectors with poison106 107define <2 x i32> @p8_vec_nonsplat_poison0(<2 x i32> %x, <2 x i32> %y) {108; CHECK-LABEL: @p8_vec_nonsplat_poison0(109; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], splat (i32 65535)110; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> splat (i32 65535), <2 x i32> [[Y:%.*]]111; CHECK-NEXT: ret <2 x i32> [[R]]112;113 %t = icmp ult <2 x i32> %x, <i32 65536, i32 poison>114 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>115 ret <2 x i32> %r116}117define <2 x i32> @p9_vec_nonsplat_poison1(<2 x i32> %x, <2 x i32> %y) {118; CHECK-LABEL: @p9_vec_nonsplat_poison1(119; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], splat (i32 65535)120; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 poison>, <2 x i32> [[Y:%.*]]121; CHECK-NEXT: ret <2 x i32> [[R]]122;123 %t = icmp ult <2 x i32> %x, <i32 65536, i32 65536>124 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 poison>125 ret <2 x i32> %r126}127define <2 x i32> @p10_vec_nonsplat_poison2(<2 x i32> %x, <2 x i32> %y) {128; CHECK-LABEL: @p10_vec_nonsplat_poison2(129; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], splat (i32 65535)130; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 poison>, <2 x i32> [[Y:%.*]]131; CHECK-NEXT: ret <2 x i32> [[R]]132;133 %t = icmp ult <2 x i32> %x, <i32 65536, i32 poison>134 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 poison>135 ret <2 x i32> %r136}137 138; Non-splat vectors139 140define <2 x i32> @p11_vec_nonsplat(<2 x i32> %x, <2 x i32> %y) {141; CHECK-LABEL: @p11_vec_nonsplat(142; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65535, i32 32767>143; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 32767>, <2 x i32> [[Y:%.*]]144; CHECK-NEXT: ret <2 x i32> [[R]]145;146 %t = icmp ult <2 x i32> %x, <i32 65536, i32 32768>147 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 32767>148 ret <2 x i32> %r149}150 151;------------------------------------------------------------------------------;152; Extra uses prevent the fold.153;------------------------------------------------------------------------------;154 155declare void @use1(i1)156 157define i32 @n12_extrause(i32 %x, i32 %y) {158; CHECK-LABEL: @n12_extrause(159; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536160; CHECK-NEXT: call void @use1(i1 [[T]])161; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535162; CHECK-NEXT: ret i32 [[R]]163;164 %t = icmp ult i32 %x, 65536165 call void @use1(i1 %t)166 %r = select i1 %t, i32 %y, i32 65535167 ret i32 %r168}169 170;------------------------------------------------------------------------------;171; Commutativity172;------------------------------------------------------------------------------;173 174; We don't care if the constant in select is true value or false value175define i32 @p13_commutativity0(i32 %x, i32 %y) {176; CHECK-LABEL: @p13_commutativity0(177; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535178; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 65535179; CHECK-NEXT: ret i32 [[R]]180;181 %t = icmp ult i32 %x, 65536182 %r = select i1 %t, i32 65535, i32 %y183 ret i32 %r184}185 186; Which means, if both possibilities are constants, we must check both of them.187define i32 @p14_commutativity1(i32 %x, i32 %y) {188; CHECK-LABEL: @p14_commutativity1(189; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535190; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 42, i32 65535191; CHECK-NEXT: ret i32 [[R]]192;193 %t = icmp ult i32 %x, 65536194 %r = select i1 %t, i32 65535, i32 42195 ret i32 %r196}197define i32 @p15_commutativity2(i32 %x, i32 %y) {198; CHECK-LABEL: @p15_commutativity2(199; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535200; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 42201; CHECK-NEXT: ret i32 [[R]]202;203 %t = icmp ult i32 %x, 65536204 %r = select i1 %t, i32 42, i32 65535205 ret i32 %r206}207 208;------------------------------------------------------------------------------;209; Negative tests210;------------------------------------------------------------------------------;211 212; For vectors, make sure we handle edge cases correctly213define <2 x i32> @n17_ult_zero(<2 x i32> %x, <2 x i32> %y) {214; CHECK-LABEL: @n17_ult_zero(215; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> [[X:%.*]], <i32 65536, i32 0>216; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 -1>217; CHECK-NEXT: ret <2 x i32> [[R]]218;219 %t = icmp ult <2 x i32> %x, <i32 65536, i32 0>220 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 -1>221 ret <2 x i32> %r222}223define <2 x i32> @n18_ugt_allones(<2 x i32> %x, <2 x i32> %y) {224; CHECK-LABEL: @n18_ugt_allones(225; CHECK-NEXT: [[T:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65534, i32 -1>226; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 0>227; CHECK-NEXT: ret <2 x i32> [[R]]228;229 %t = icmp ugt <2 x i32> %x, <i32 65534, i32 -1>230 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 0>231 ret <2 x i32> %r232}233define <2 x i32> @n19_slt_int_min(<2 x i32> %x, <2 x i32> %y) {234; CHECK-LABEL: @n19_slt_int_min(235; CHECK-NEXT: [[T:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 65536, i32 -2147483648>236; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 2147483647>237; CHECK-NEXT: ret <2 x i32> [[R]]238;239 %t = icmp slt <2 x i32> %x, <i32 65536, i32 -2147483648>240 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 2147483647>241 ret <2 x i32> %r242}243define <2 x i32> @n20_sgt_int_max(<2 x i32> %x, <2 x i32> %y) {244; CHECK-LABEL: @n20_sgt_int_max(245; CHECK-NEXT: [[T:%.*]] = icmp sgt <2 x i32> [[X:%.*]], <i32 65534, i32 2147483647>246; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 -2147483648>247; CHECK-NEXT: ret <2 x i32> [[R]]248;249 %t = icmp sgt <2 x i32> %x, <i32 65534, i32 2147483647>250 %r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 -2147483648>251 ret <2 x i32> %r252}253 254; We don't do anything for non-relational comparisons.255define i32 @n21_equality(i32 %x, i32 %y) {256; CHECK-LABEL: @n21_equality(257; CHECK-NEXT: [[T:%.*]] = icmp eq i32 [[X:%.*]], -2147483648258; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 2147483647, i32 [[Y:%.*]]259; CHECK-NEXT: ret i32 [[R]]260;261 %t = icmp eq i32 %x, -2147483648262 %r = select i1 %t, i32 2147483647, i32 %y263 ret i32 %r264}265 266; There is nothing special about sign-bit-tests, we can fold them.267define i32 @t22_sign_check(i32 %x, i32 %y) {268; CHECK-LABEL: @t22_sign_check(269; CHECK-NEXT: [[T_INV:%.*]] = icmp sgt i32 [[X:%.*]], -1270; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 -1271; CHECK-NEXT: ret i32 [[R]]272;273 %t = icmp slt i32 %x, 0274 %r = select i1 %t, i32 -1, i32 %y275 ret i32 %r276}277define i32 @t22_sign_check2(i32 %x, i32 %y) {278; CHECK-LABEL: @t22_sign_check2(279; CHECK-NEXT: [[T_INV:%.*]] = icmp slt i32 [[X:%.*]], 0280; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 0281; CHECK-NEXT: ret i32 [[R]]282;283 %t = icmp sgt i32 %x, -1284 %r = select i1 %t, i32 0, i32 %y285 ret i32 %r286}287 288; If the types don't match we currently don't do anything.289define i32 @n23_type_mismatch(i64 %x, i32 %y) {290; CHECK-LABEL: @n23_type_mismatch(291; CHECK-NEXT: [[T:%.*]] = icmp ult i64 [[X:%.*]], 65536292; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535293; CHECK-NEXT: ret i32 [[R]]294;295 %t = icmp ult i64 %x, 65536296 %r = select i1 %t, i32 %y, i32 65535297 ret i32 %r298}299 300; Don't do wrong tranform301define i32 @n24_ult_65534(i32 %x, i32 %y) {302; CHECK-LABEL: @n24_ult_65534(303; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65534304; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535305; CHECK-NEXT: ret i32 [[R]]306;307 %t = icmp ult i32 %x, 65534308 %r = select i1 %t, i32 %y, i32 65535309 ret i32 %r310}311 312; If we already have a match, it's good enough.313define i32 @n25_all_good0(i32 %x, i32 %y) {314; CHECK-LABEL: @n25_all_good0(315; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536316; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 65535, i32 65536317; CHECK-NEXT: ret i32 [[R]]318;319 %t = icmp ult i32 %x, 65536320 %r = select i1 %t, i32 65535, i32 65536321 ret i32 %r322}323define i32 @n26_all_good1(i32 %x, i32 %y) {324; CHECK-LABEL: @n26_all_good1(325; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536326; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 65536, i32 65535327; CHECK-NEXT: ret i32 [[R]]328;329 %t = icmp ult i32 %x, 65536330 %r = select i1 %t, i32 65536, i32 65535331 ret i32 %r332}333 334; https://llvm.org/PR52684335; Do not infinite loop by opposing 'ult' canonicalization.336 337define i32 @ult_inf_loop(i32 %x) {338; CHECK-LABEL: @ult_inf_loop(339; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X:%.*]], -1340; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 2341; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 1, i32 -3342; CHECK-NEXT: ret i32 [[SEL]]343;344 %add = add i32 %x, -1345 %cmp = icmp ult i32 %add, 2346 %sel = select i1 %cmp, i32 1, i32 -3347 ret i32 %sel348}349 350define <2 x i32> @ult_inf_loop_vec(<2 x i32> %x) {351; CHECK-LABEL: @ult_inf_loop_vec(352; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], splat (i32 38)353; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[TMP1]], splat (i32 -4)354; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[CMP]], <2 x i32> splat (i32 -5), <2 x i32> splat (i32 3)355; CHECK-NEXT: ret <2 x i32> [[SEL]]356;357 %add = add <2 x i32> %x, <i32 42, i32 42>358 %cmp = icmp ugt <2 x i32> %add, <i32 3, i32 3>359 %sel = select <2 x i1> %cmp, <2 x i32> <i32 -5, i32 -5>, <2 x i32> <i32 3, i32 3>360 ret <2 x i32> %sel361}362 363; CHECK: !0 = !{!"branch_weights", i32 1, i32 2000}364