1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; Given a pattern like: 5; %old_cmp1 = icmp slt i32 %x, C2 6; %old_replacement = select i1 %old_cmp1, i32 %target_low, i32 %target_high 7; %old_x_offseted = add i32 %x, C1 8; %old_cmp0 = icmp ult i32 %old_x_offseted, C0 9; %r = select i1 %old_cmp0, i32 %x, i32 %old_replacement 10; it can be rewriten as more canonical pattern: 11; %new_cmp1 = icmp slt i32 %x, -C1 12; %new_cmp2 = icmp sge i32 %x, C0-C1 13; %new_clamped_low = select i1 %new_cmp1, i32 %target_low, i32 %x 14; %r = select i1 %new_cmp2, i32 %target_high, i32 %new_clamped_low 15; Iff -C1 s<= C2 s<= C0-C1 16; Also, ULT predicate can also be UGE; or UGT iff C0 != -1 (+invert result) 17; Also, SLT predicate can also be SGE; or SGT iff C2 != INT_MAX (+invert res.) 18 19;------------------------------------------------------------------------------- 20 21; Basic pattern. There is no 'and', so lower threshold is 0 (inclusive). 22; The upper threshold is 127 (inclusive). 23; There are 2 icmp's so for scalars there are 4 possible combinations. 24; The constant in %t0 has to be between the thresholds, i.e 128 <= Ct0 <= 0. 25 26define i32 @t0_ult_slt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) { 27; CHECK-LABEL: @t0_ult_slt_128( 28; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 29; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], 127 30; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] 31; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]] 32; CHECK-NEXT: ret i32 [[R]] 33; 34 %t0 = icmp slt i32 %x, 128 35 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 36 %t2 = add i32 %x, 16 37 %t3 = icmp ult i32 %t2, 144 38 %r = select i1 %t3, i32 %x, i32 %t1 39 ret i32 %r 40} 41define i32 @t1_ult_slt_0(i32 %x, i32 %replacement_low, i32 %replacement_high) { 42; CHECK-LABEL: @t1_ult_slt_0( 43; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 44; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], 127 45; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] 46; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]] 47; CHECK-NEXT: ret i32 [[R]] 48; 49 %t0 = icmp slt i32 %x, -16 50 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 51 %t2 = add i32 %x, 16 52 %t3 = icmp ult i32 %t2, 144 53 %r = select i1 %t3, i32 %x, i32 %t1 54 ret i32 %r 55} 56 57define i32 @t2_ult_sgt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) { 58; CHECK-LABEL: @t2_ult_sgt_128( 59; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 60; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], 127 61; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] 62; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]] 63; CHECK-NEXT: ret i32 [[R]] 64; 65 %t0 = icmp sgt i32 %x, 127 66 %t1 = select i1 %t0, i32 %replacement_high, i32 %replacement_low 67 %t2 = add i32 %x, 16 68 %t3 = icmp ult i32 %t2, 144 69 %r = select i1 %t3, i32 %x, i32 %t1 70 ret i32 %r 71} 72define i32 @t3_ult_sgt_neg1(i32 %x, i32 %replacement_low, i32 %replacement_high) { 73; CHECK-LABEL: @t3_ult_sgt_neg1( 74; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 75; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], 127 76; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] 77; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]] 78; CHECK-NEXT: ret i32 [[R]] 79; 80 %t0 = icmp sgt i32 %x, -17 81 %t1 = select i1 %t0, i32 %replacement_high, i32 %replacement_low 82 %t2 = add i32 %x, 16 83 %t3 = icmp ult i32 %t2, 144 84 %r = select i1 %t3, i32 %x, i32 %t1 85 ret i32 %r 86} 87 88define i32 @t4_ugt_slt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) { 89; CHECK-LABEL: @t4_ugt_slt_128( 90; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 91; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], 127 92; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] 93; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]] 94; CHECK-NEXT: ret i32 [[R]] 95; 96 %t0 = icmp slt i32 %x, 128 97 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 98 %t2 = add i32 %x, 16 99 %t3 = icmp ugt i32 %t2, 143 100 %r = select i1 %t3, i32 %t1, i32 %x 101 ret i32 %r 102} 103define i32 @t5_ugt_slt_0(i32 %x, i32 %replacement_low, i32 %replacement_high) { 104; CHECK-LABEL: @t5_ugt_slt_0( 105; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 106; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], 127 107; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] 108; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]] 109; CHECK-NEXT: ret i32 [[R]] 110; 111 %t0 = icmp slt i32 %x, -16 112 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 113 %t2 = add i32 %x, 16 114 %t3 = icmp ugt i32 %t2, 143 115 %r = select i1 %t3, i32 %t1, i32 %x 116 ret i32 %r 117} 118 119define i32 @t6_ugt_sgt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) { 120; CHECK-LABEL: @t6_ugt_sgt_128( 121; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 122; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], 127 123; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] 124; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]] 125; CHECK-NEXT: ret i32 [[R]] 126; 127 %t0 = icmp sgt i32 %x, 127 128 %t1 = select i1 %t0, i32 %replacement_high, i32 %replacement_low 129 %t2 = add i32 %x, 16 130 %t3 = icmp ugt i32 %t2, 143 131 %r = select i1 %t3, i32 %t1, i32 %x 132 ret i32 %r 133} 134 135define i32 @t7_ugt_sgt_neg1(i32 %x, i32 %replacement_low, i32 %replacement_high) { 136; CHECK-LABEL: @t7_ugt_sgt_neg1( 137; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 138; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], 127 139; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] 140; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]] 141; CHECK-NEXT: ret i32 [[R]] 142; 143 %t0 = icmp sgt i32 %x, -17 144 %t1 = select i1 %t0, i32 %replacement_high, i32 %replacement_low 145 %t2 = add i32 %x, 16 146 %t3 = icmp ugt i32 %t2, 143 147 %r = select i1 %t3, i32 %t1, i32 %x 148 ret i32 %r 149} 150 151;------------------------------------------------------------------------------- 152 153; So Ct0 can not be s> 128, or s< -16 154 155define i32 @n8_ult_slt_129(i32 %x, i32 %replacement_low, i32 %replacement_high) { 156; CHECK-LABEL: @n8_ult_slt_129( 157; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 129 158; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] 159; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 160; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 161; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] 162; CHECK-NEXT: ret i32 [[R]] 163; 164 %t0 = icmp slt i32 %x, 129 165 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 166 %t2 = add i32 %x, 16 167 %t3 = icmp ult i32 %t2, 144 168 %r = select i1 %t3, i32 %x, i32 %t1 169 ret i32 %r 170} 171 172define i32 @n9_ult_slt_neg17(i32 %x, i32 %replacement_low, i32 %replacement_high) { 173; CHECK-LABEL: @n9_ult_slt_neg17( 174; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], -17 175; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] 176; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 177; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 178; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] 179; CHECK-NEXT: ret i32 [[R]] 180; 181 %t0 = icmp slt i32 %x, -17 182 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 183 %t2 = add i32 %x, 16 184 %t3 = icmp ult i32 %t2, 144 185 %r = select i1 %t3, i32 %x, i32 %t1 186 ret i32 %r 187} 188 189; Regression test for PR53252. 190define i32 @n10_ugt_slt(i32 %x, i32 %replacement_low, i32 %replacement_high) { 191; CHECK-LABEL: @n10_ugt_slt( 192; CHECK-NEXT: [[T2:%.*]] = icmp ugt i32 [[X:%.*]], 128 193; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32 [[X]], i32 [[REPLACEMENT_HIGH:%.*]] 194; CHECK-NEXT: ret i32 [[R]] 195; 196 %t0 = icmp slt i32 %x, 0 197 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 198 %t2 = icmp ugt i32 %x, 128 199 %r = select i1 %t2, i32 %x, i32 %t1 200 ret i32 %r 201} 202 203define i32 @n11_uge_slt(i32 %x, i32 %replacement_low, i32 %replacement_high) { 204; CHECK-LABEL: @n11_uge_slt( 205; CHECK-NEXT: [[T2:%.*]] = icmp ult i32 [[X:%.*]], 129 206; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[X]] 207; CHECK-NEXT: ret i32 [[R]] 208; 209 %t0 = icmp slt i32 %x, 0 210 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 211 %t2 = icmp ult i32 %x, 129 212 %r = select i1 %t2, i32 %t1, i32 %x 213 ret i32 %r 214} 215 216define i32 @n12_ule_slt(i32 %x, i32 %replacement_low, i32 %replacement_high) { 217; CHECK-LABEL: @n12_ule_slt( 218; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], -1 219; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] 220; CHECK-NEXT: [[T2:%.*]] = icmp ugt i32 [[X]], 127 221; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32 [[T1]], i32 [[X]] 222; CHECK-NEXT: ret i32 [[R]] 223; 224 %t0 = icmp slt i32 %x, -1 225 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 226 %t2 = icmp ugt i32 %x, 127 227 %r = select i1 %t2, i32 %t1, i32 %x 228 ret i32 %r 229} 230 231;------------------------------------------------------------------------------- 232 233declare void @use32(i32) 234declare void @use1(i1) 235 236; One-use restrictions: here the entire pattern needs to be one-use. 237; FIXME: if %t0 could be reused then it's less restrictive. 238 239; This one is ok. 240define i32 @t10_oneuse0(i32 %x, i32 %replacement_low, i32 %replacement_high) { 241; CHECK-LABEL: @t10_oneuse0( 242; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64 243; CHECK-NEXT: call void @use1(i1 [[T0]]) 244; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X]], -16 245; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], 127 246; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] 247; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]] 248; CHECK-NEXT: ret i32 [[R]] 249; 250 %t0 = icmp slt i32 %x, 64 251 call void @use1(i1 %t0) 252 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 253 %t2 = add i32 %x, 16 254 %t3 = icmp ult i32 %t2, 144 255 %r = select i1 %t3, i32 %x, i32 %t1 256 ret i32 %r 257} 258define i32 @n11_oneuse1(i32 %x, i32 %replacement_low, i32 %replacement_high) { 259; CHECK-LABEL: @n11_oneuse1( 260; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64 261; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] 262; CHECK-NEXT: call void @use32(i32 [[T1]]) 263; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 264; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 265; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] 266; CHECK-NEXT: ret i32 [[R]] 267; 268 %t0 = icmp slt i32 %x, 64 269 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 270 call void @use32(i32 %t1) 271 %t2 = add i32 %x, 16 272 %t3 = icmp ult i32 %t2, 144 273 %r = select i1 %t3, i32 %x, i32 %t1 274 ret i32 %r 275} 276 277; This one is ok. 278define i32 @t12_oneuse2(i32 %x, i32 %replacement_low, i32 %replacement_high) { 279; CHECK-LABEL: @t12_oneuse2( 280; CHECK-NEXT: [[T2:%.*]] = add i32 [[X:%.*]], 16 281; CHECK-NEXT: call void @use32(i32 [[T2]]) 282; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X]], -16 283; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], 127 284; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] 285; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[TMP3]] 286; CHECK-NEXT: ret i32 [[R]] 287; 288 %t0 = icmp slt i32 %x, 64 289 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 290 %t2 = add i32 %x, 16 291 call void @use32(i32 %t2) 292 %t3 = icmp ult i32 %t2, 144 293 %r = select i1 %t3, i32 %x, i32 %t1 294 ret i32 %r 295} 296 297define i32 @n13_oneuse3(i32 %x, i32 %replacement_low, i32 %replacement_high) { 298; CHECK-LABEL: @n13_oneuse3( 299; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64 300; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] 301; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 302; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 303; CHECK-NEXT: call void @use1(i1 [[T3]]) 304; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] 305; CHECK-NEXT: ret i32 [[R]] 306; 307 %t0 = icmp slt i32 %x, 64 308 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 309 %t2 = add i32 %x, 16 310 %t3 = icmp ult i32 %t2, 144 311 call void @use1(i1 %t3) 312 %r = select i1 %t3, i32 %x, i32 %t1 313 ret i32 %r 314} 315 316define i32 @n14_oneuse4(i32 %x, i32 %replacement_low, i32 %replacement_high) { 317; CHECK-LABEL: @n14_oneuse4( 318; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64 319; CHECK-NEXT: call void @use1(i1 [[T0]]) 320; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] 321; CHECK-NEXT: call void @use32(i32 [[T1]]) 322; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 323; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 324; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] 325; CHECK-NEXT: ret i32 [[R]] 326; 327 %t0 = icmp slt i32 %x, 64 328 call void @use1(i1 %t0) 329 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 330 call void @use32(i32 %t1) 331 %t2 = add i32 %x, 16 332 %t3 = icmp ult i32 %t2, 144 333 %r = select i1 %t3, i32 %x, i32 %t1 334 ret i32 %r 335} 336define i32 @n15_oneuse5(i32 %x, i32 %replacement_low, i32 %replacement_high) { 337; CHECK-LABEL: @n15_oneuse5( 338; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64 339; CHECK-NEXT: call void @use1(i1 [[T0]]) 340; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] 341; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 342; CHECK-NEXT: call void @use32(i32 [[T2]]) 343; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 344; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] 345; CHECK-NEXT: ret i32 [[R]] 346; 347 %t0 = icmp slt i32 %x, 64 348 call void @use1(i1 %t0) 349 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 350 %t2 = add i32 %x, 16 351 call void @use32(i32 %t2) 352 %t3 = icmp ult i32 %t2, 144 353 %r = select i1 %t3, i32 %x, i32 %t1 354 ret i32 %r 355} 356define i32 @n16_oneuse6(i32 %x, i32 %replacement_low, i32 %replacement_high) { 357; CHECK-LABEL: @n16_oneuse6( 358; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64 359; CHECK-NEXT: call void @use1(i1 [[T0]]) 360; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] 361; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 362; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 363; CHECK-NEXT: call void @use1(i1 [[T3]]) 364; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] 365; CHECK-NEXT: ret i32 [[R]] 366; 367 %t0 = icmp slt i32 %x, 64 368 call void @use1(i1 %t0) 369 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 370 %t2 = add i32 %x, 16 371 %t3 = icmp ult i32 %t2, 144 372 call void @use1(i1 %t3) 373 %r = select i1 %t3, i32 %x, i32 %t1 374 ret i32 %r 375} 376 377define i32 @n17_oneuse7(i32 %x, i32 %replacement_low, i32 %replacement_high) { 378; CHECK-LABEL: @n17_oneuse7( 379; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64 380; CHECK-NEXT: call void @use1(i1 [[T0]]) 381; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] 382; CHECK-NEXT: call void @use32(i32 [[T1]]) 383; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 384; CHECK-NEXT: call void @use32(i32 [[T2]]) 385; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 386; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] 387; CHECK-NEXT: ret i32 [[R]] 388; 389 %t0 = icmp slt i32 %x, 64 390 call void @use1(i1 %t0) 391 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 392 call void @use32(i32 %t1) 393 %t2 = add i32 %x, 16 394 call void @use32(i32 %t2) 395 %t3 = icmp ult i32 %t2, 144 396 %r = select i1 %t3, i32 %x, i32 %t1 397 ret i32 %r 398} 399define i32 @n18_oneuse8(i32 %x, i32 %replacement_low, i32 %replacement_high) { 400; CHECK-LABEL: @n18_oneuse8( 401; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64 402; CHECK-NEXT: call void @use1(i1 [[T0]]) 403; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] 404; CHECK-NEXT: call void @use32(i32 [[T1]]) 405; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 406; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 407; CHECK-NEXT: call void @use1(i1 [[T3]]) 408; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] 409; CHECK-NEXT: ret i32 [[R]] 410; 411 %t0 = icmp slt i32 %x, 64 412 call void @use1(i1 %t0) 413 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 414 call void @use32(i32 %t1) 415 %t2 = add i32 %x, 16 416 %t3 = icmp ult i32 %t2, 144 417 call void @use1(i1 %t3) 418 %r = select i1 %t3, i32 %x, i32 %t1 419 ret i32 %r 420} 421 422define i32 @n19_oneuse9(i32 %x, i32 %replacement_low, i32 %replacement_high) { 423; CHECK-LABEL: @n19_oneuse9( 424; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64 425; CHECK-NEXT: call void @use1(i1 [[T0]]) 426; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] 427; CHECK-NEXT: call void @use32(i32 [[T1]]) 428; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 429; CHECK-NEXT: call void @use32(i32 [[T2]]) 430; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 431; CHECK-NEXT: call void @use1(i1 [[T3]]) 432; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] 433; CHECK-NEXT: ret i32 [[R]] 434; 435 %t0 = icmp slt i32 %x, 64 436 call void @use1(i1 %t0) 437 %t1 = select i1 %t0, i32 %replacement_low, i32 %replacement_high 438 call void @use32(i32 %t1) 439 %t2 = add i32 %x, 16 440 call void @use32(i32 %t2) 441 %t3 = icmp ult i32 %t2, 144 442 call void @use1(i1 %t3) 443 %r = select i1 %t3, i32 %x, i32 %t1 444 ret i32 %r 445} 446 447;------------------------------------------------------------------------------- 448 449; Vectors 450 451define <2 x i32> @t20_ult_slt_vec_splat(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) { 452; CHECK-LABEL: @t20_ult_slt_vec_splat( 453; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], splat (i32 -16) 454; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt <2 x i32> [[X]], splat (i32 127) 455; CHECK-NEXT: [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]] 456; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[REPLACEMENT_HIGH:%.*]], <2 x i32> [[TMP3]] 457; CHECK-NEXT: ret <2 x i32> [[R]] 458; 459 %t0 = icmp slt <2 x i32> %x, <i32 128, i32 128> 460 %t1 = select <2 x i1> %t0, <2 x i32> %replacement_low, <2 x i32> %replacement_high 461 %t2 = add <2 x i32> %x, <i32 16, i32 16> 462 %t3 = icmp ult <2 x i32> %t2, <i32 144, i32 144> 463 %r = select <2 x i1> %t3, <2 x i32> %x, <2 x i32> %t1 464 ret <2 x i32> %r 465} 466define <2 x i32> @t21_ult_slt_vec_nonsplat(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) { 467; CHECK-LABEL: @t21_ult_slt_vec_nonsplat( 468; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 -16, i32 -8> 469; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt <2 x i32> [[X]], <i32 127, i32 255> 470; CHECK-NEXT: [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]] 471; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[REPLACEMENT_HIGH:%.*]], <2 x i32> [[TMP3]] 472; CHECK-NEXT: ret <2 x i32> [[R]] 473; 474 %t0 = icmp slt <2 x i32> %x, <i32 128, i32 64> 475 %t1 = select <2 x i1> %t0, <2 x i32> %replacement_low, <2 x i32> %replacement_high 476 %t2 = add <2 x i32> %x, <i32 16, i32 8> 477 %t3 = icmp ult <2 x i32> %t2, <i32 144, i32 264> 478 %r = select <2 x i1> %t3, <2 x i32> %x, <2 x i32> %t1 479 ret <2 x i32> %r 480} 481 482; Non-canonical predicates 483 484declare void @use2xi1(<2 x i1>) 485 486declare void @use(<2 x i1>) 487define <2 x i32> @t22_uge_slt(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) { 488; CHECK-LABEL: @t22_uge_slt( 489; CHECK-NEXT: [[T0:%.*]] = icmp slt <2 x i32> [[X:%.*]], splat (i32 128) 490; CHECK-NEXT: [[T1:%.*]] = select <2 x i1> [[T0]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[REPLACEMENT_HIGH:%.*]] 491; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[X]], splat (i32 16) 492; CHECK-NEXT: [[T3:%.*]] = icmp uge <2 x i32> [[T2]], <i32 144, i32 0> 493; CHECK-NEXT: call void @use2xi1(<2 x i1> [[T3]]) 494; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T3]], <2 x i32> [[T1]], <2 x i32> [[X]] 495; CHECK-NEXT: ret <2 x i32> [[R]] 496; 497 %t0 = icmp slt <2 x i32> %x, <i32 128, i32 128> 498 %t1 = select <2 x i1> %t0, <2 x i32> %replacement_low, <2 x i32> %replacement_high 499 %t2 = add <2 x i32> %x, <i32 16, i32 16> 500 %t3 = icmp uge <2 x i32> %t2, <i32 144, i32 0> 501 call void @use2xi1(<2 x i1> %t3) 502 %r = select <2 x i1> %t3, <2 x i32> %t1, <2 x i32> %x 503 ret <2 x i32> %r 504} 505 506define <2 x i32> @t23_ult_sge(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) { 507; CHECK-LABEL: @t23_ult_sge( 508; CHECK-NEXT: [[T0:%.*]] = icmp sge <2 x i32> [[X:%.*]], <i32 128, i32 -2147483648> 509; CHECK-NEXT: call void @use2xi1(<2 x i1> [[T0]]) 510; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> [[X]], <i32 -16, i32 -2147483648> 511; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt <2 x i32> [[X]], <i32 127, i32 2147483646> 512; CHECK-NEXT: [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]] 513; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[REPLACEMENT_HIGH:%.*]], <2 x i32> [[TMP3]] 514; CHECK-NEXT: ret <2 x i32> [[R]] 515; 516 %t0 = icmp sge <2 x i32> %x, <i32 128, i32 -2147483648> 517 call void @use2xi1(<2 x i1> %t0) 518 %t1 = select <2 x i1> %t0, <2 x i32> %replacement_high, <2 x i32> %replacement_low 519 %t2 = add <2 x i32> %x, <i32 16, i32 -2147483648> 520 %t3 = icmp ult <2 x i32> %t2, <i32 144, i32 -1> 521 %r = select <2 x i1> %t3, <2 x i32> %x, <2 x i32> %t1 522 ret <2 x i32> %r 523} 524