1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; and enhanced to include metadata checking. 3 4; RUN: opt < %s -instcombine -S | FileCheck %s 5 6define i32 @foo(i32) local_unnamed_addr #0 { 7; CHECK-LABEL: @foo( 8; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 %0, 2 9; CHECK-NEXT: [[DOTV:%.*]] = select i1 [[TMP2]], i32 20, i32 -20, !prof ![[MD1:[0-9]+]] 10; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[DOTV]], %0 11; CHECK-NEXT: ret i32 [[TMP3]] 12; 13 %2 = icmp sgt i32 %0, 2 14 %3 = add nsw i32 %0, 20 15 %4 = add nsw i32 %0, -20 16 select i1 %2, i32 %3, i32 %4, !prof !1 17 ret i32 %5 18} 19 20define i8 @shrink_select(i1 %cond, i32 %x) { 21; CHECK-LABEL: @shrink_select( 22; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %x to i8 23; CHECK-NEXT: [[TRUNC:%.*]] = select i1 %cond, i8 [[TMP1]], i8 42, !prof ![[MD1]] 24; CHECK-NEXT: ret i8 [[TRUNC]] 25; 26 %sel = select i1 %cond, i32 %x, i32 42, !prof !1 27 %trunc = trunc i32 %sel to i8 28 ret i8 %trunc 29} 30 31define void @min_max_bitcast(<4 x float> %a, <4 x float> %b, <4 x i32>* %ptr1, <4 x i32>* %ptr2) { 32; CHECK-LABEL: @min_max_bitcast( 33; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <4 x float> %a, %b 34; CHECK-NEXT: [[SEL1_V:%.*]] = select <4 x i1> [[CMP]], <4 x float> %a, <4 x float> %b, !prof ![[MD1]] 35; CHECK-NEXT: [[SEL2_V:%.*]] = select <4 x i1> [[CMP]], <4 x float> %b, <4 x float> %a, !prof ![[MD1]] 36; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32>* %ptr1 to <4 x float>* 37; CHECK-NEXT: store <4 x float> [[SEL1_V]], <4 x float>* [[TMP1]], align 16 38; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i32>* %ptr2 to <4 x float>* 39; CHECK-NEXT: store <4 x float> [[SEL2_V]], <4 x float>* [[TMP2]], align 16 40; CHECK-NEXT: ret void 41; 42 %cmp = fcmp olt <4 x float> %a, %b 43 %bc1 = bitcast <4 x float> %a to <4 x i32> 44 %bc2 = bitcast <4 x float> %b to <4 x i32> 45 %sel1 = select <4 x i1> %cmp, <4 x i32> %bc1, <4 x i32> %bc2, !prof !1 46 %sel2 = select <4 x i1> %cmp, <4 x i32> %bc2, <4 x i32> %bc1, !prof !1 47 store <4 x i32> %sel1, <4 x i32>* %ptr1 48 store <4 x i32> %sel2, <4 x i32>* %ptr2 49 ret void 50} 51 52define i32 @foo2(i32, i32) local_unnamed_addr #0 { 53; CHECK-LABEL: @foo2( 54; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 %0, 2 55; CHECK-NEXT: [[TMP4:%.*]] = sub i32 0, %1 56; CHECK-NEXT: [[DOTP:%.*]] = select i1 [[TMP3]], i32 %1, i32 [[TMP4]], !prof ![[MD1]] 57; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[DOTP]], %0 58; CHECK-NEXT: ret i32 [[TMP5]] 59; 60 %3 = icmp sgt i32 %0, 2 61 %4 = add nsw i32 %0, %1 62 %5 = sub nsw i32 %0, %1 63 select i1 %3, i32 %4, i32 %5, !prof !1 64 ret i32 %6 65} 66 67define i64 @test43(i32 %a) nounwind { 68; CHECK-LABEL: @test43( 69; CHECK-NEXT: [[A_EXT:%.*]] = sext i32 %a to i64 70; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[A_EXT]], 0 71; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 [[A_EXT]], i64 0, !prof ![[MD1]] 72; CHECK-NEXT: ret i64 [[MAX]] 73; 74 %a_ext = sext i32 %a to i64 75 %is_a_nonnegative = icmp sgt i32 %a, -1 76 %max = select i1 %is_a_nonnegative, i64 %a_ext, i64 0, !prof !1 77 ret i64 %max 78} 79 80define <2 x i32> @scalar_select_of_vectors_sext(<2 x i1> %cca, i1 %ccb) { 81; CHECK-LABEL: @scalar_select_of_vectors_sext( 82; CHECK-NEXT: [[NARROW:%.*]] = select i1 %ccb, <2 x i1> %cca, <2 x i1> zeroinitializer, !prof ![[MD1]] 83; CHECK-NEXT: [[R:%.*]] = sext <2 x i1> [[NARROW]] to <2 x i32> 84; CHECK-NEXT: ret <2 x i32> [[R]] 85; 86 %ccax = sext <2 x i1> %cca to <2 x i32> 87 %r = select i1 %ccb, <2 x i32> %ccax, <2 x i32> <i32 0, i32 0>, !prof !1 88 ret <2 x i32> %r 89} 90 91 92define i16 @t7(i32 %a) { 93; CHECK-LABEL: @t7( 94; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 %a, -32768 95; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 %a, i32 -32768, !prof ![[MD1]] 96; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16 97; CHECK-NEXT: ret i16 [[TMP3]] 98; 99 %1 = icmp slt i32 %a, -32768 100 %2 = trunc i32 %a to i16 101 %3 = select i1 %1, i16 %2, i16 -32768, !prof !1 102 ret i16 %3 103} 104 105define i32 @abs_nabs_x01(i32 %x) { 106; CHECK-LABEL: @abs_nabs_x01( 107; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, -1 108; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, %x 109; CHECK-NEXT: [[COND1:%.*]] = select i1 [[CMP]], i32 %x, i32 [[SUB]], !prof ![[MD1]] 110; CHECK-NEXT: ret i32 [[COND1]] 111; 112 %cmp = icmp sgt i32 %x, -1 113 %sub = sub nsw i32 0, %x 114 %cond = select i1 %cmp, i32 %sub, i32 %x, !prof !1 115 %cmp1 = icmp sgt i32 %cond, -1 116 %sub16 = sub nsw i32 0, %cond 117 %cond18 = select i1 %cmp1, i32 %cond, i32 %sub16, !prof !2 118 ret i32 %cond18 119} 120 121define <2 x i32> @abs_nabs_x01_vec(<2 x i32> %x) { 122; CHECK-LABEL: @abs_nabs_x01_vec( 123; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> %x, <i32 -1, i32 -1> 124; CHECK-NEXT: [[SUB:%.*]] = sub nsw <2 x i32> zeroinitializer, %x 125; CHECK-NEXT: [[COND1:%.*]] = select <2 x i1> [[CMP]], <2 x i32> %x, <2 x i32> [[SUB]], !prof ![[MD1]] 126; CHECK-NEXT: ret <2 x i32> [[COND1]] 127; 128 %cmp = icmp sgt <2 x i32> %x, <i32 -1, i32 -1> 129 %sub = sub nsw <2 x i32> zeroinitializer, %x 130 %cond = select <2 x i1> %cmp, <2 x i32> %sub, <2 x i32> %x, !prof !1 131 %cmp1 = icmp sgt <2 x i32> %cond, <i32 -1, i32 -1> 132 %sub16 = sub nsw <2 x i32> zeroinitializer, %cond 133 %cond18 = select <2 x i1> %cmp1, <2 x i32> %cond, <2 x i32> %sub16, !prof !2 134 ret <2 x i32> %cond18 135} 136 137; SMAX(SMAX(x, y), x) -> SMAX(x, y) 138define i32 @test30(i32 %x, i32 %y) { 139; CHECK-LABEL: @test30( 140; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, %y 141; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 %x, i32 %y, !prof ![[MD1]] 142; CHECK-NEXT: ret i32 [[COND]] 143; 144 %cmp = icmp sgt i32 %x, %y 145 %cond = select i1 %cmp, i32 %x, i32 %y, !prof !1 146 %cmp5 = icmp sgt i32 %cond, %x 147 %retval = select i1 %cmp5, i32 %cond, i32 %x, !prof !2 148 ret i32 %retval 149} 150 151; Swap predicate / metadata order 152; SMAX(SMAX(X, 75), 36) -> SMAX(X, 75) 153define i32 @test70(i32 %x) { 154; CHECK-LABEL: @test70( 155; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 %x, 75 156; CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP1]], i32 %x, i32 75, !prof ![[MD3:[0-9]+]] 157; CHECK-NEXT: ret i32 [[COND]] 158; 159 %cmp = icmp slt i32 %x, 75 160 %cond = select i1 %cmp, i32 75, i32 %x, !prof !1 161 %cmp3 = icmp slt i32 %cond, 36 162 %retval = select i1 %cmp3, i32 36, i32 %cond, !prof !2 163 ret i32 %retval 164} 165 166; Swap predicate / metadata order 167; SMIN(SMIN(X, 92), 11) -> SMIN(X, 11) 168define i32 @test72(i32 %x) { 169; CHECK-LABEL: @test72( 170; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 %x, 11 171; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[TMP1]], i32 %x, i32 11, !prof ![[MD4:[0-9]+]] 172; CHECK-NEXT: ret i32 [[RETVAL]] 173; 174 %cmp = icmp sgt i32 %x, 92 175 %cond = select i1 %cmp, i32 92, i32 %x, !prof !1 176 %cmp3 = icmp sgt i32 %cond, 11 177 %retval = select i1 %cmp3, i32 11, i32 %cond, !prof !2 178 ret i32 %retval 179} 180 181; Swap predicate / metadata order 182; SMAX(SMAX(X, 36), 75) -> SMAX(X, 75) 183define i32 @test74(i32 %x) { 184; CHECK-LABEL: @test74( 185; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 %x, 75 186; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[TMP1]], i32 %x, i32 75, !prof ![[MD4]] 187; CHECK-NEXT: ret i32 [[RETVAL]] 188; 189 %cmp = icmp slt i32 %x, 36 190 %cond = select i1 %cmp, i32 36, i32 %x, !prof !1 191 %cmp3 = icmp slt i32 %cond, 75 192 %retval = select i1 %cmp3, i32 75, i32 %cond, !prof !2 193 ret i32 %retval 194} 195 196; FIXME: 197; The compare should change, but the metadata remains the same because the select operands are not swapped. 198define i32 @smin1(i32 %x) { 199; CHECK-LABEL: @smin1( 200; CHECK-NEXT: [[NOT_X:%.*]] = xor i32 %x, -1 201; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, 0 202; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[NOT_X]], i32 -1, !prof ![[MD1]] 203; CHECK-NEXT: ret i32 [[SEL]] 204; 205 %not_x = xor i32 %x, -1 206 %cmp = icmp sgt i32 %x, 0 207 %sel = select i1 %cmp, i32 %not_x, i32 -1, !prof !1 208 ret i32 %sel 209} 210 211; FIXME: 212; The compare should change, and the metadata is swapped because the select operands are swapped. 213define i32 @smin2(i32 %x) { 214; CHECK-LABEL: @smin2( 215; CHECK-NEXT: [[NOT_X:%.*]] = xor i32 %x, -1 216; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %x, 0 217; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 -1, i32 [[NOT_X]], !prof ![[MD1]] 218; CHECK-NEXT: ret i32 [[SEL]] 219; 220 %not_x = xor i32 %x, -1 221 %cmp = icmp slt i32 %x, 0 222 %sel = select i1 %cmp, i32 -1, i32 %not_x, !prof !1 223 ret i32 %sel 224} 225 226; FIXME: 227; The compare should change, but the metadata remains the same because the select operands are not swapped. 228define i32 @smax1(i32 %x) { 229; CHECK-LABEL: @smax1( 230; CHECK-NEXT: [[NOT_X:%.*]] = xor i32 %x, -1 231; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %x, 0 232; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[NOT_X]], i32 -1, !prof ![[MD1]] 233; CHECK-NEXT: ret i32 [[SEL]] 234; 235 %not_x = xor i32 %x, -1 236 %cmp = icmp slt i32 %x, 0 237 %sel = select i1 %cmp, i32 %not_x, i32 -1, !prof !1 238 ret i32 %sel 239} 240 241; FIXME: 242; The compare should change, and the metadata is swapped because the select operands are swapped. 243define i32 @smax2(i32 %x) { 244; CHECK-LABEL: @smax2( 245; CHECK-NEXT: [[NOT_X:%.*]] = xor i32 %x, -1 246; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, 0 247; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 -1, i32 [[NOT_X]], !prof ![[MD1]] 248; CHECK-NEXT: ret i32 [[SEL]] 249; 250 %not_x = xor i32 %x, -1 251 %cmp = icmp sgt i32 %x, 0 252 %sel = select i1 %cmp, i32 -1, i32 %not_x, !prof !1 253 ret i32 %sel 254} 255 256; FIXME: 257; The compare should change, but the metadata remains the same because the select operands are not swapped. 258define i32 @umin1(i32 %x) { 259; CHECK-LABEL: @umin1( 260; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, -1 261; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 %x, i32 -2147483648, !prof ![[MD1]] 262; CHECK-NEXT: ret i32 [[SEL]] 263; 264 %cmp = icmp sgt i32 %x, -1 265 %sel = select i1 %cmp, i32 %x, i32 -2147483648, !prof !1 266 ret i32 %sel 267} 268 269; FIXME: 270; The compare should change, and the metadata is swapped because the select operands are swapped. 271define i32 @umin2(i32 %x) { 272; CHECK-LABEL: @umin2( 273; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %x, 0 274; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 2147483647, i32 %x, !prof ![[MD1]] 275; CHECK-NEXT: ret i32 [[SEL]] 276; 277 %cmp = icmp slt i32 %x, 0 278 %sel = select i1 %cmp, i32 2147483647, i32 %x, !prof !1 279 ret i32 %sel 280} 281 282; FIXME: 283; The compare should change, but the metadata remains the same because the select operands are not swapped. 284define i32 @umax1(i32 %x) { 285; CHECK-LABEL: @umax1( 286; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %x, 0 287; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 %x, i32 2147483647, !prof ![[MD1]] 288; CHECK-NEXT: ret i32 [[SEL]] 289; 290 %cmp = icmp slt i32 %x, 0 291 %sel = select i1 %cmp, i32 %x, i32 2147483647, !prof !1 292 ret i32 %sel 293} 294 295; FIXME: 296; The compare should change, and the metadata is swapped because the select operands are swapped. 297define i32 @umax2(i32 %x) { 298; CHECK-LABEL: @umax2( 299; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, -1 300; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 -2147483648, i32 %x, !prof ![[MD1]] 301; CHECK-NEXT: ret i32 [[SEL]] 302; 303 %cmp = icmp sgt i32 %x, -1 304 %sel = select i1 %cmp, i32 -2147483648, i32 %x, !prof !1 305 ret i32 %sel 306} 307 308!1 = !{!"branch_weights", i32 2, i32 10} 309!2 = !{!"branch_weights", i32 3, i32 10} 310 311; CHECK-DAG: ![[MD1]] = !{!"branch_weights", i32 2, i32 10} 312; CHECK-DAG: ![[MD3]] = !{!"branch_weights", i32 10, i32 2} 313; CHECK-DAG: ![[MD4]] = !{!"branch_weights", i32 10, i32 3} 314 315