1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; It is a miscompile in most of these tests if we 5; execute div/rem without freezing the potentially 6; poison condition value. 7 8define i5 @sdiv_common_divisor(i1 %b, i5 %x, i5 %y, i5 %z) { 9; CHECK-LABEL: @sdiv_common_divisor( 10; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] 11; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] 12; CHECK-NEXT: [[SEL:%.*]] = sdiv i5 [[SEL_V]], [[X:%.*]] 13; CHECK-NEXT: ret i5 [[SEL]] 14; 15 %r1 = sdiv i5 %y, %x 16 %r2 = sdiv i5 %z, %x 17 %sel = select i1 %b, i5 %r2, i5 %r1 18 ret i5 %sel 19} 20 21define i5 @srem_common_divisor(i1 %b, i5 %x, i5 %y, i5 %z) { 22; CHECK-LABEL: @srem_common_divisor( 23; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] 24; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] 25; CHECK-NEXT: [[SEL:%.*]] = srem i5 [[SEL_V]], [[X:%.*]] 26; CHECK-NEXT: ret i5 [[SEL]] 27; 28 %r1 = srem i5 %y, %x 29 %r2 = srem i5 %z, %x 30 %sel = select i1 %b, i5 %r2, i5 %r1 31 ret i5 %sel 32} 33 34; This is ok without freeze because UB can only happen with x==0, 35; and that occurs in the original code. 36 37define i5 @udiv_common_divisor(i1 %b, i5 %x, i5 %y, i5 %z) { 38; CHECK-LABEL: @udiv_common_divisor( 39; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] 40; CHECK-NEXT: [[SEL:%.*]] = udiv i5 [[SEL_V]], [[X:%.*]] 41; CHECK-NEXT: ret i5 [[SEL]] 42; 43 %r1 = udiv i5 %y, %x 44 %r2 = udiv i5 %z, %x 45 %sel = select i1 %b, i5 %r2, i5 %r1 46 ret i5 %sel 47} 48 49; This is ok without freeze because UB can only happen with x==0, 50; and that occurs in the original code. 51 52define i5 @urem_common_divisor(i1 %b, i5 %x, i5 %y, i5 %z) { 53; CHECK-LABEL: @urem_common_divisor( 54; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] 55; CHECK-NEXT: [[SEL:%.*]] = urem i5 [[SEL_V]], [[X:%.*]] 56; CHECK-NEXT: ret i5 [[SEL]] 57; 58 %r1 = urem i5 %y, %x 59 %r2 = urem i5 %z, %x 60 %sel = select i1 %b, i5 %r2, i5 %r1 61 ret i5 %sel 62} 63 64define i5 @sdiv_common_dividend(i1 %b, i5 %x, i5 %y, i5 %z) { 65; CHECK-LABEL: @sdiv_common_dividend( 66; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] 67; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] 68; CHECK-NEXT: [[SEL:%.*]] = sdiv i5 [[X:%.*]], [[SEL_V]] 69; CHECK-NEXT: ret i5 [[SEL]] 70; 71 %r1 = sdiv i5 %x, %y 72 %r2 = sdiv i5 %x, %z 73 %sel = select i1 %b, i5 %r2, i5 %r1 74 ret i5 %sel 75} 76 77define i5 @srem_common_dividend(i1 %b, i5 %x, i5 %y, i5 %z) { 78; CHECK-LABEL: @srem_common_dividend( 79; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] 80; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] 81; CHECK-NEXT: [[SEL:%.*]] = srem i5 [[X:%.*]], [[SEL_V]] 82; CHECK-NEXT: ret i5 [[SEL]] 83; 84 %r1 = srem i5 %x, %y 85 %r2 = srem i5 %x, %z 86 %sel = select i1 %b, i5 %r2, i5 %r1 87 ret i5 %sel 88} 89 90define i5 @udiv_common_dividend(i1 %b, i5 %x, i5 %y, i5 %z) { 91; CHECK-LABEL: @udiv_common_dividend( 92; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] 93; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] 94; CHECK-NEXT: [[SEL:%.*]] = udiv i5 [[X:%.*]], [[SEL_V]] 95; CHECK-NEXT: ret i5 [[SEL]] 96; 97 %r1 = udiv i5 %x, %y 98 %r2 = udiv i5 %x, %z 99 %sel = select i1 %b, i5 %r2, i5 %r1 100 ret i5 %sel 101} 102 103define i5 @urem_common_dividend(i1 %b, i5 %x, i5 %y, i5 %z) { 104; CHECK-LABEL: @urem_common_dividend( 105; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] 106; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] 107; CHECK-NEXT: [[SEL:%.*]] = urem i5 [[X:%.*]], [[SEL_V]] 108; CHECK-NEXT: ret i5 [[SEL]] 109; 110 %r1 = urem i5 %x, %y 111 %r2 = urem i5 %x, %z 112 %sel = select i1 %b, i5 %r2, i5 %r1 113 ret i5 %sel 114} 115 116; Repeat the above tests, but guarantee that the select 117; condition is not poison via argument attribute. That 118; makes it safe to execute the select before div/rem 119; without needing to freeze the condition. 120 121define i5 @sdiv_common_divisor_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { 122; CHECK-LABEL: @sdiv_common_divisor_defined_cond( 123; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] 124; CHECK-NEXT: [[SEL:%.*]] = sdiv i5 [[SEL_V]], [[X:%.*]] 125; CHECK-NEXT: ret i5 [[SEL]] 126; 127 %r1 = sdiv i5 %y, %x 128 %r2 = sdiv i5 %z, %x 129 %sel = select i1 %b, i5 %r2, i5 %r1 130 ret i5 %sel 131} 132 133define i5 @srem_common_divisor_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { 134; CHECK-LABEL: @srem_common_divisor_defined_cond( 135; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] 136; CHECK-NEXT: [[SEL:%.*]] = srem i5 [[SEL_V]], [[X:%.*]] 137; CHECK-NEXT: ret i5 [[SEL]] 138; 139 %r1 = srem i5 %y, %x 140 %r2 = srem i5 %z, %x 141 %sel = select i1 %b, i5 %r2, i5 %r1 142 ret i5 %sel 143} 144 145define i5 @udiv_common_divisor_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { 146; CHECK-LABEL: @udiv_common_divisor_defined_cond( 147; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] 148; CHECK-NEXT: [[SEL:%.*]] = udiv i5 [[SEL_V]], [[X:%.*]] 149; CHECK-NEXT: ret i5 [[SEL]] 150; 151 %r1 = udiv i5 %y, %x 152 %r2 = udiv i5 %z, %x 153 %sel = select i1 %b, i5 %r2, i5 %r1 154 ret i5 %sel 155} 156 157define i5 @urem_common_divisor_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { 158; CHECK-LABEL: @urem_common_divisor_defined_cond( 159; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] 160; CHECK-NEXT: [[SEL:%.*]] = urem i5 [[SEL_V]], [[X:%.*]] 161; CHECK-NEXT: ret i5 [[SEL]] 162; 163 %r1 = urem i5 %y, %x 164 %r2 = urem i5 %z, %x 165 %sel = select i1 %b, i5 %r2, i5 %r1 166 ret i5 %sel 167} 168 169define i5 @sdiv_common_dividend_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { 170; CHECK-LABEL: @sdiv_common_dividend_defined_cond( 171; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] 172; CHECK-NEXT: [[SEL:%.*]] = sdiv i5 [[X:%.*]], [[SEL_V]] 173; CHECK-NEXT: ret i5 [[SEL]] 174; 175 %r1 = sdiv i5 %x, %y 176 %r2 = sdiv i5 %x, %z 177 %sel = select i1 %b, i5 %r2, i5 %r1 178 ret i5 %sel 179} 180 181define i5 @srem_common_dividend_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { 182; CHECK-LABEL: @srem_common_dividend_defined_cond( 183; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] 184; CHECK-NEXT: [[SEL:%.*]] = srem i5 [[X:%.*]], [[SEL_V]] 185; CHECK-NEXT: ret i5 [[SEL]] 186; 187 %r1 = srem i5 %x, %y 188 %r2 = srem i5 %x, %z 189 %sel = select i1 %b, i5 %r2, i5 %r1 190 ret i5 %sel 191} 192 193define i5 @udiv_common_dividend_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { 194; CHECK-LABEL: @udiv_common_dividend_defined_cond( 195; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] 196; CHECK-NEXT: [[SEL:%.*]] = udiv i5 [[X:%.*]], [[SEL_V]] 197; CHECK-NEXT: ret i5 [[SEL]] 198; 199 %r1 = udiv i5 %x, %y 200 %r2 = udiv i5 %x, %z 201 %sel = select i1 %b, i5 %r2, i5 %r1 202 ret i5 %sel 203} 204 205define i5 @urem_common_dividend_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { 206; CHECK-LABEL: @urem_common_dividend_defined_cond( 207; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] 208; CHECK-NEXT: [[SEL:%.*]] = urem i5 [[X:%.*]], [[SEL_V]] 209; CHECK-NEXT: ret i5 [[SEL]] 210; 211 %r1 = urem i5 %x, %y 212 %r2 = urem i5 %x, %z 213 %sel = select i1 %b, i5 %r2, i5 %r1 214 ret i5 %sel 215} 216 217define i32 @rem_euclid_1(i32 %0) { 218; CHECK-LABEL: @rem_euclid_1( 219; CHECK-NEXT: [[SEL:%.*]] = and i32 [[TMP0:%.*]], 7 220; CHECK-NEXT: ret i32 [[SEL]] 221; 222 %rem = srem i32 %0, 8 223 %cond = icmp slt i32 %rem, 0 224 %add = add i32 %rem, 8 225 %sel = select i1 %cond, i32 %add, i32 %rem 226 ret i32 %sel 227} 228 229define i32 @rem_euclid_2(i32 %0) { 230; CHECK-LABEL: @rem_euclid_2( 231; CHECK-NEXT: [[SEL:%.*]] = and i32 [[TMP0:%.*]], 7 232; CHECK-NEXT: ret i32 [[SEL]] 233; 234 %rem = srem i32 %0, 8 235 %cond = icmp sgt i32 %rem, -1 236 %add = add i32 %rem, 8 237 %sel = select i1 %cond, i32 %rem, i32 %add 238 ret i32 %sel 239} 240 241define i32 @rem_euclid_wrong_sign_test(i32 %0) { 242; CHECK-LABEL: @rem_euclid_wrong_sign_test( 243; CHECK-NEXT: [[REM:%.*]] = srem i32 [[TMP0:%.*]], 8 244; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[REM]], 0 245; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[REM]], 8 246; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i32 [[ADD]], i32 [[REM]] 247; CHECK-NEXT: ret i32 [[SEL]] 248; 249 %rem = srem i32 %0, 8 250 %cond = icmp sgt i32 %rem, 0 251 %add = add i32 %rem, 8 252 %sel = select i1 %cond, i32 %add, i32 %rem 253 ret i32 %sel 254} 255 256define i32 @rem_euclid_add_different_const(i32 %0) { 257; CHECK-LABEL: @rem_euclid_add_different_const( 258; CHECK-NEXT: [[REM:%.*]] = srem i32 [[TMP0:%.*]], 8 259; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[REM]], 0 260; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[REM]], 9 261; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i32 [[ADD]], i32 [[REM]] 262; CHECK-NEXT: ret i32 [[SEL]] 263; 264 %rem = srem i32 %0, 8 265 %cond = icmp slt i32 %rem, 0 266 %add = add i32 %rem, 9 267 %sel = select i1 %cond, i32 %add, i32 %rem 268 ret i32 %sel 269} 270 271define i32 @rem_euclid_wrong_operands_select(i32 %0) { 272; CHECK-LABEL: @rem_euclid_wrong_operands_select( 273; CHECK-NEXT: [[REM:%.*]] = srem i32 [[TMP0:%.*]], 8 274; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[REM]], 0 275; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[REM]], 8 276; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i32 [[REM]], i32 [[ADD]] 277; CHECK-NEXT: ret i32 [[SEL]] 278; 279 %rem = srem i32 %0, 8 280 %cond = icmp slt i32 %rem, 0 281 %add = add i32 %rem, 8 282 %sel = select i1 %cond, i32 %rem, i32 %add 283 ret i32 %sel 284} 285 286define <2 x i32> @rem_euclid_vec(<2 x i32> %0) { 287; CHECK-LABEL: @rem_euclid_vec( 288; CHECK-NEXT: [[SEL:%.*]] = and <2 x i32> [[TMP0:%.*]], splat (i32 7) 289; CHECK-NEXT: ret <2 x i32> [[SEL]] 290; 291 %rem = srem <2 x i32> %0, <i32 8, i32 8> 292 %cond = icmp slt <2 x i32> %rem, <i32 0, i32 0> 293 %add = add <2 x i32> %rem, <i32 8, i32 8> 294 %sel = select <2 x i1> %cond, <2 x i32> %add, <2 x i32> %rem 295 ret <2 x i32> %sel 296} 297 298define i128 @rem_euclid_i128(i128 %0) { 299; CHECK-LABEL: @rem_euclid_i128( 300; CHECK-NEXT: [[SEL:%.*]] = and i128 [[TMP0:%.*]], 7 301; CHECK-NEXT: ret i128 [[SEL]] 302; 303 %rem = srem i128 %0, 8 304 %cond = icmp slt i128 %rem, 0 305 %add = add i128 %rem, 8 306 %sel = select i1 %cond, i128 %add, i128 %rem 307 ret i128 %sel 308} 309 310define i8 @rem_euclid_non_const_pow2(i8 %0, i8 %1) { 311; CHECK-LABEL: @rem_euclid_non_const_pow2( 312; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i8 -1, [[TMP0:%.*]] 313; CHECK-NEXT: [[TMP3:%.*]] = xor i8 [[NOTMASK]], -1 314; CHECK-NEXT: [[SEL:%.*]] = and i8 [[TMP1:%.*]], [[TMP3]] 315; CHECK-NEXT: ret i8 [[SEL]] 316; 317 %pow2 = shl i8 1, %0 318 %rem = srem i8 %1, %pow2 319 %cond = icmp slt i8 %rem, 0 320 %add = add i8 %rem, %pow2 321 %sel = select i1 %cond, i8 %add, i8 %rem 322 ret i8 %sel 323} 324 325define i8 @rem_euclid_non_const_pow2_commuted(i8 %0, i8 %1) { 326; CHECK-LABEL: @rem_euclid_non_const_pow2_commuted( 327; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i8 -1, [[TMP0:%.*]] 328; CHECK-NEXT: [[TMP3:%.*]] = xor i8 [[NOTMASK]], -1 329; CHECK-NEXT: [[SEL:%.*]] = and i8 [[TMP1:%.*]], [[TMP3]] 330; CHECK-NEXT: ret i8 [[SEL]] 331; 332 %pow2 = shl i8 1, %0 333 %rem = srem i8 %1, %pow2 334 %cond = icmp slt i8 %rem, 0 335 %add = add i8 %pow2, %rem 336 %sel = select i1 %cond, i8 %add, i8 %rem 337 ret i8 %sel 338} 339 340define i32 @rem_euclid_pow2_true_arm_folded(i32 %n) { 341; CHECK-LABEL: @rem_euclid_pow2_true_arm_folded( 342; CHECK-NEXT: [[RES:%.*]] = and i32 [[N:%.*]], 1 343; CHECK-NEXT: ret i32 [[RES]] 344; 345 %rem = srem i32 %n, 2 346 %neg = icmp slt i32 %rem, 0 347 %res = select i1 %neg, i32 1, i32 %rem 348 ret i32 %res 349} 350 351define i32 @rem_euclid_pow2_false_arm_folded(i32 %n) { 352; CHECK-LABEL: @rem_euclid_pow2_false_arm_folded( 353; CHECK-NEXT: [[RES:%.*]] = and i32 [[N:%.*]], 1 354; CHECK-NEXT: ret i32 [[RES]] 355; 356 %rem = srem i32 %n, 2 357 %nonneg = icmp sge i32 %rem, 0 358 %res = select i1 %nonneg, i32 %rem, i32 1 359 ret i32 %res 360} 361 362define i8 @pr89516(i8 %n, i8 %x) { 363; CHECK-LABEL: @pr89516( 364; CHECK-NEXT: [[COND:%.*]] = icmp slt i8 [[X:%.*]], 0 365; CHECK-NEXT: [[POW2:%.*]] = shl nuw i8 1, [[N:%.*]] 366; CHECK-NEXT: [[SREM:%.*]] = srem i8 1, [[POW2]] 367; CHECK-NEXT: [[ADD:%.*]] = select i1 [[COND]], i8 [[POW2]], i8 0 368; CHECK-NEXT: [[RES:%.*]] = add nuw i8 [[SREM]], [[ADD]] 369; CHECK-NEXT: ret i8 [[RES]] 370; 371 %cond = icmp slt i8 %x, 0 372 %pow2 = shl nuw i8 1, %n 373 %srem = srem i8 1, %pow2 374 %add = add nuw i8 %srem, %pow2 375 %res = select i1 %cond, i8 %add, i8 %srem 376 ret i8 %res 377} 378