1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -passes=instcombine -S < %s | FileCheck %s 3 4declare float @llvm.maxnum.f32(float %a, float %b) 5declare float @llvm.minnum.f32(float %a, float %b) 6declare float @llvm.maximum.f32(float %a, float %b) 7declare float @llvm.minimum.f32(float %a, float %b) 8declare i32 @llvm.smax.i32(i32 %a, i32 %b) 9declare i32 @llvm.smin.i32(i32 %a, i32 %b) 10declare i32 @llvm.umax.i32(i32 %a, i32 %b) 11declare i32 @llvm.umin.i32(i32 %a, i32 %b) 12declare i16 @llvm.sadd.sat.i16(i16 %a, i16 %b) 13declare i16 @llvm.uadd.sat.i16(i16 %a, i16 %b) 14declare {i16, i1} @llvm.sadd.with.overflow.i16(i16 %a, i16 %b) 15declare {i16, i1} @llvm.uadd.with.overflow.i16(i16 %a, i16 %b) 16declare {i16, i1} @llvm.smul.with.overflow.i16(i16 %a, i16 %b) 17declare {i16, i1} @llvm.umul.with.overflow.i16(i16 %a, i16 %b) 18declare i16 @llvm.smul.fix.i16(i16 %a, i16 %b, i32 %scale) 19declare i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 %scale) 20declare i16 @llvm.smul.fix.sat.i16(i16 %a, i16 %b, i32 %scale) 21declare i16 @llvm.umul.fix.sat.i16(i16 %a, i16 %b, i32 %scale) 22declare float @llvm.fma.f32(float %a, float %b, float %c) 23declare float @llvm.fmuladd.f32(float %a, float %b, float %c) 24 25define i8 @fold_select_mul(i1 %c, i8 %a, i8 %b) { 26; CHECK-LABEL: define i8 @fold_select_mul( 27; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) { 28; CHECK-NEXT: [[RET:%.*]] = mul i8 [[B]], [[A]] 29; CHECK-NEXT: ret i8 [[RET]] 30; 31 %s0 = select i1 %c, i8 %a, i8 %b 32 %s1 = select i1 %c, i8 %b, i8 %a 33 %ret = mul i8 %s1, %s0 34 ret i8 %ret 35} 36 37define i8 @fold_select_mul_nsw_nuw_preserve(i1 %c, i8 %a, i8 %b) { 38; CHECK-LABEL: define i8 @fold_select_mul_nsw_nuw_preserve( 39; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) { 40; CHECK-NEXT: [[RET:%.*]] = mul nuw nsw i8 [[B]], [[A]] 41; CHECK-NEXT: ret i8 [[RET]] 42; 43 %s0 = select i1 %c, i8 %a, i8 %b 44 %s1 = select i1 %c, i8 %b, i8 %a 45 %ret = mul nsw nuw i8 %s1, %s0 46 ret i8 %ret 47} 48 49define <2 x i4> @fold_select_mul_vec2(i1 %c, <2 x i4> %a, <2 x i4> %b) { 50; CHECK-LABEL: define <2 x i4> @fold_select_mul_vec2( 51; CHECK-SAME: i1 [[C:%.*]], <2 x i4> [[A:%.*]], <2 x i4> [[B:%.*]]) { 52; CHECK-NEXT: [[RET:%.*]] = mul <2 x i4> [[B]], [[A]] 53; CHECK-NEXT: ret <2 x i4> [[RET]] 54; 55 %s0 = select i1 %c, <2 x i4> %a, <2 x i4> %b 56 %s1 = select i1 %c, <2 x i4> %b, <2 x i4> %a 57 %ret = mul <2 x i4> %s1, %s0 58 ret <2 x i4> %ret 59} 60 61define i8 @fold_select_add(i1 %c, i8 %a, i8 %b) { 62; CHECK-LABEL: define i8 @fold_select_add( 63; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) { 64; CHECK-NEXT: [[RET:%.*]] = add i8 [[B]], [[A]] 65; CHECK-NEXT: ret i8 [[RET]] 66; 67 %s0 = select i1 %c, i8 %a, i8 %b 68 %s1 = select i1 %c, i8 %b, i8 %a 69 %ret = add i8 %s1, %s0 70 ret i8 %ret 71} 72 73define <2 x i4> @fold_select_add_vec2(i1 %c, <2 x i4> %a, <2 x i4> %b) { 74; CHECK-LABEL: define <2 x i4> @fold_select_add_vec2( 75; CHECK-SAME: i1 [[C:%.*]], <2 x i4> [[A:%.*]], <2 x i4> [[B:%.*]]) { 76; CHECK-NEXT: [[RET:%.*]] = add <2 x i4> [[B]], [[A]] 77; CHECK-NEXT: ret <2 x i4> [[RET]] 78; 79 %s0 = select i1 %c, <2 x i4> %a, <2 x i4> %b 80 %s1 = select i1 %c, <2 x i4> %b, <2 x i4> %a 81 %ret = add <2 x i4> %s1, %s0 82 ret <2 x i4> %ret 83} 84 85define i8 @fold_select_and(i1 %c, i8 %a, i8 %b) { 86; CHECK-LABEL: define i8 @fold_select_and( 87; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) { 88; CHECK-NEXT: [[RET:%.*]] = and i8 [[B]], [[A]] 89; CHECK-NEXT: ret i8 [[RET]] 90; 91 %s0 = select i1 %c, i8 %a, i8 %b 92 %s1 = select i1 %c, i8 %b, i8 %a 93 %ret = and i8 %s1, %s0 94 ret i8 %ret 95} 96 97define <2 x i4> @fold_select_and_vec2(i1 %c, <2 x i4> %a, <2 x i4> %b) { 98; CHECK-LABEL: define <2 x i4> @fold_select_and_vec2( 99; CHECK-SAME: i1 [[C:%.*]], <2 x i4> [[A:%.*]], <2 x i4> [[B:%.*]]) { 100; CHECK-NEXT: [[RET:%.*]] = and <2 x i4> [[B]], [[A]] 101; CHECK-NEXT: ret <2 x i4> [[RET]] 102; 103 %s0 = select i1 %c, <2 x i4> %a, <2 x i4> %b 104 %s1 = select i1 %c, <2 x i4> %b, <2 x i4> %a 105 %ret = and <2 x i4> %s1, %s0 106 ret <2 x i4> %ret 107} 108 109define i8 @fold_select_or(i1 %c, i8 %a, i8 %b) { 110; CHECK-LABEL: define i8 @fold_select_or( 111; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) { 112; CHECK-NEXT: [[RET:%.*]] = or i8 [[B]], [[A]] 113; CHECK-NEXT: ret i8 [[RET]] 114; 115 %s0 = select i1 %c, i8 %a, i8 %b 116 %s1 = select i1 %c, i8 %b, i8 %a 117 %ret = or i8 %s1, %s0 118 ret i8 %ret 119} 120 121define <2 x i4> @fold_select_or_vec2(i1 %c, <2 x i4> %a, <2 x i4> %b) { 122; CHECK-LABEL: define <2 x i4> @fold_select_or_vec2( 123; CHECK-SAME: i1 [[C:%.*]], <2 x i4> [[A:%.*]], <2 x i4> [[B:%.*]]) { 124; CHECK-NEXT: [[RET:%.*]] = or <2 x i4> [[B]], [[A]] 125; CHECK-NEXT: ret <2 x i4> [[RET]] 126; 127 %s0 = select i1 %c, <2 x i4> %a, <2 x i4> %b 128 %s1 = select i1 %c, <2 x i4> %b, <2 x i4> %a 129 %ret = or <2 x i4> %s1, %s0 130 ret <2 x i4> %ret 131} 132 133define i8 @fold_select_xor(i1 %c, i8 %a, i8 %b) { 134; CHECK-LABEL: define i8 @fold_select_xor( 135; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) { 136; CHECK-NEXT: [[RET:%.*]] = xor i8 [[B]], [[A]] 137; CHECK-NEXT: ret i8 [[RET]] 138; 139 %s0 = select i1 %c, i8 %a, i8 %b 140 %s1 = select i1 %c, i8 %b, i8 %a 141 %ret = xor i8 %s1, %s0 142 ret i8 %ret 143} 144 145define <2 x i4> @fold_select_xor_vec2(i1 %c, <2 x i4> %a, <2 x i4> %b) { 146; CHECK-LABEL: define <2 x i4> @fold_select_xor_vec2( 147; CHECK-SAME: i1 [[C:%.*]], <2 x i4> [[A:%.*]], <2 x i4> [[B:%.*]]) { 148; CHECK-NEXT: [[RET:%.*]] = xor <2 x i4> [[B]], [[A]] 149; CHECK-NEXT: ret <2 x i4> [[RET]] 150; 151 %s0 = select i1 %c, <2 x i4> %a, <2 x i4> %b 152 %s1 = select i1 %c, <2 x i4> %b, <2 x i4> %a 153 %ret = xor <2 x i4> %s1, %s0 154 ret <2 x i4> %ret 155} 156 157define float @fold_select_fadd(i1 %c, float %a, float %b) { 158; CHECK-LABEL: define float @fold_select_fadd( 159; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) { 160; CHECK-NEXT: [[RET:%.*]] = fadd float [[B]], [[A]] 161; CHECK-NEXT: ret float [[RET]] 162; 163 %s0 = select i1 %c, float %a, float %b 164 %s1 = select i1 %c, float %b, float %a 165 %ret = fadd float %s1, %s0 166 ret float %ret 167} 168 169define float @fold_select_fadd_nnan(i1 %c, float %a, float %b) { 170; CHECK-LABEL: define float @fold_select_fadd_nnan( 171; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) { 172; CHECK-NEXT: [[RET:%.*]] = fadd nnan float [[B]], [[A]] 173; CHECK-NEXT: ret float [[RET]] 174; 175 %s0 = select i1 %c, float %a, float %b 176 %s1 = select i1 %c, float %b, float %a 177 %ret = fadd nnan float %s1, %s0 178 ret float %ret 179} 180 181define <2 x float> @fold_select_fadd_vec2(i1 %c, <2 x float> %a, <2 x float> %b) { 182; CHECK-LABEL: define <2 x float> @fold_select_fadd_vec2( 183; CHECK-SAME: i1 [[C:%.*]], <2 x float> [[A:%.*]], <2 x float> [[B:%.*]]) { 184; CHECK-NEXT: [[RET:%.*]] = fadd <2 x float> [[B]], [[A]] 185; CHECK-NEXT: ret <2 x float> [[RET]] 186; 187 %s0 = select i1 %c, <2 x float> %a, <2 x float> %b 188 %s1 = select i1 %c, <2 x float> %b, <2 x float> %a 189 %ret = fadd <2 x float> %s1, %s0 190 ret <2 x float> %ret 191} 192 193define float @fold_select_fmul(i1 %c, float %a, float %b) { 194; CHECK-LABEL: define float @fold_select_fmul( 195; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) { 196; CHECK-NEXT: [[RET:%.*]] = fmul float [[B]], [[A]] 197; CHECK-NEXT: ret float [[RET]] 198; 199 %s0 = select i1 %c, float %a, float %b 200 %s1 = select i1 %c, float %b, float %a 201 %ret = fmul float %s1, %s0 202 ret float %ret 203} 204 205define <2 x float> @fold_select_fmul_vec2(i1 %c, <2 x float> %a, <2 x float> %b) { 206; CHECK-LABEL: define <2 x float> @fold_select_fmul_vec2( 207; CHECK-SAME: i1 [[C:%.*]], <2 x float> [[A:%.*]], <2 x float> [[B:%.*]]) { 208; CHECK-NEXT: [[RET:%.*]] = fmul <2 x float> [[B]], [[A]] 209; CHECK-NEXT: ret <2 x float> [[RET]] 210; 211 %s0 = select i1 %c, <2 x float> %a, <2 x float> %b 212 %s1 = select i1 %c, <2 x float> %b, <2 x float> %a 213 %ret = fmul <2 x float> %s1, %s0 214 ret <2 x float> %ret 215} 216 217; 218 219define float @fold_select_maxnum(i1 %c, float %a, float %b) { 220; CHECK-LABEL: define float @fold_select_maxnum( 221; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) { 222; CHECK-NEXT: [[RET:%.*]] = call float @llvm.maxnum.f32(float [[B]], float [[A]]) 223; CHECK-NEXT: ret float [[RET]] 224; 225 %s0 = select i1 %c, float %a, float %b 226 %s1 = select i1 %c, float %b, float %a 227 %ret = call float @llvm.maxnum.f32(float %s1, float %s0) 228 ret float %ret 229} 230 231define float @fold_select_minnum(i1 %c, float %a, float %b) { 232; CHECK-LABEL: define float @fold_select_minnum( 233; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) { 234; CHECK-NEXT: [[RET:%.*]] = call float @llvm.minnum.f32(float [[B]], float [[A]]) 235; CHECK-NEXT: ret float [[RET]] 236; 237 %s0 = select i1 %c, float %a, float %b 238 %s1 = select i1 %c, float %b, float %a 239 %ret = call float @llvm.minnum.f32(float %s1, float %s0) 240 ret float %ret 241} 242 243define float @fold_select_maximum(i1 %c, float %a, float %b) { 244; CHECK-LABEL: define float @fold_select_maximum( 245; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) { 246; CHECK-NEXT: [[RET:%.*]] = call float @llvm.maximum.f32(float [[B]], float [[A]]) 247; CHECK-NEXT: ret float [[RET]] 248; 249 %s0 = select i1 %c, float %a, float %b 250 %s1 = select i1 %c, float %b, float %a 251 %ret = call float @llvm.maximum.f32(float %s1, float %s0) 252 ret float %ret 253} 254 255define float @fold_select_minimum(i1 %c, float %a, float %b) { 256; CHECK-LABEL: define float @fold_select_minimum( 257; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]]) { 258; CHECK-NEXT: [[RET:%.*]] = call float @llvm.minimum.f32(float [[B]], float [[A]]) 259; CHECK-NEXT: ret float [[RET]] 260; 261 %s0 = select i1 %c, float %a, float %b 262 %s1 = select i1 %c, float %b, float %a 263 %ret = call float @llvm.minimum.f32(float %s1, float %s0) 264 ret float %ret 265} 266 267define i32 @fold_select_smax(i1 %c, i32 %a, i32 %b) { 268; CHECK-LABEL: define i32 @fold_select_smax( 269; CHECK-SAME: i1 [[C:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { 270; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 [[A]]) 271; CHECK-NEXT: ret i32 [[RET]] 272; 273 %s0 = select i1 %c, i32 %a, i32 %b 274 %s1 = select i1 %c, i32 %b, i32 %a 275 %ret = call i32 @llvm.smax.i32(i32 %s1, i32 %s0) 276 ret i32 %ret 277} 278 279define i32 @fold_select_smin(i1 %c, i32 %a, i32 %b) { 280; CHECK-LABEL: define i32 @fold_select_smin( 281; CHECK-SAME: i1 [[C:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { 282; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.smin.i32(i32 [[B]], i32 [[A]]) 283; CHECK-NEXT: ret i32 [[RET]] 284; 285 %s0 = select i1 %c, i32 %a, i32 %b 286 %s1 = select i1 %c, i32 %b, i32 %a 287 %ret = call i32 @llvm.smin.i32(i32 %s1, i32 %s0) 288 ret i32 %ret 289} 290 291define i32 @fold_select_umax(i1 %c, i32 %a, i32 %b) { 292; CHECK-LABEL: define i32 @fold_select_umax( 293; CHECK-SAME: i1 [[C:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { 294; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.umax.i32(i32 [[B]], i32 [[A]]) 295; CHECK-NEXT: ret i32 [[RET]] 296; 297 %s0 = select i1 %c, i32 %a, i32 %b 298 %s1 = select i1 %c, i32 %b, i32 %a 299 %ret = call i32 @llvm.umax.i32(i32 %s1, i32 %s0) 300 ret i32 %ret 301} 302 303define i32 @fold_select_umin(i1 %c, i32 %a, i32 %b) { 304; CHECK-LABEL: define i32 @fold_select_umin( 305; CHECK-SAME: i1 [[C:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { 306; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.umin.i32(i32 [[B]], i32 [[A]]) 307; CHECK-NEXT: ret i32 [[RET]] 308; 309 %s0 = select i1 %c, i32 %a, i32 %b 310 %s1 = select i1 %c, i32 %b, i32 %a 311 %ret = call i32 @llvm.umin.i32(i32 %s1, i32 %s0) 312 ret i32 %ret 313} 314 315define i16 @fold_select_sadd_sat(i1 %c, i16 %a, i16 %b) { 316; CHECK-LABEL: define i16 @fold_select_sadd_sat( 317; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) { 318; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[B]], i16 [[A]]) 319; CHECK-NEXT: ret i16 [[RET]] 320; 321 %s0 = select i1 %c, i16 %a, i16 %b 322 %s1 = select i1 %c, i16 %b, i16 %a 323 %ret = call i16 @llvm.sadd.sat.i16(i16 %s1, i16 %s0) 324 ret i16 %ret 325} 326 327define i16 @fold_select_uadd_sat(i1 %c, i16 %a, i16 %b) { 328; CHECK-LABEL: define i16 @fold_select_uadd_sat( 329; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) { 330; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[B]], i16 [[A]]) 331; CHECK-NEXT: ret i16 [[RET]] 332; 333 %s0 = select i1 %c, i16 %a, i16 %b 334 %s1 = select i1 %c, i16 %b, i16 %a 335 %ret = call i16 @llvm.uadd.sat.i16(i16 %s1, i16 %s0) 336 ret i16 %ret 337} 338 339define i16 @fold_select_sadd_with_overflow(i1 %c, i16 %a, i16 %b) { 340; CHECK-LABEL: define i16 @fold_select_sadd_with_overflow( 341; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) { 342; CHECK-NEXT: [[RES:%.*]] = call { i16, i1 } @llvm.sadd.with.overflow.i16(i16 [[B]], i16 [[A]]) 343; CHECK-NEXT: [[OBIT:%.*]] = extractvalue { i16, i1 } [[RES]], 1 344; CHECK-NEXT: br i1 [[OBIT]], label [[OVERFLOW:%.*]], label [[NORMAL:%.*]] 345; CHECK: overflow: 346; CHECK-NEXT: ret i16 0 347; CHECK: normal: 348; CHECK-NEXT: [[SUM:%.*]] = extractvalue { i16, i1 } [[RES]], 0 349; CHECK-NEXT: ret i16 [[SUM]] 350; 351 %s0 = select i1 %c, i16 %a, i16 %b 352 %s1 = select i1 %c, i16 %b, i16 %a 353 %res = call {i16, i1} @llvm.sadd.with.overflow.i16(i16 %s1, i16 %s0) 354 %obit = extractvalue {i16, i1} %res, 1 355 br i1 %obit, label %overflow, label %normal 356overflow: 357 ret i16 0 358normal: 359 %sum = extractvalue {i16, i1} %res, 0 360 ret i16 %sum 361} 362 363define i16 @fold_select_uadd_with_overflow(i1 %c, i16 %a, i16 %b) { 364; CHECK-LABEL: define i16 @fold_select_uadd_with_overflow( 365; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) { 366; CHECK-NEXT: [[RES:%.*]] = call { i16, i1 } @llvm.uadd.with.overflow.i16(i16 [[B]], i16 [[A]]) 367; CHECK-NEXT: [[OBIT:%.*]] = extractvalue { i16, i1 } [[RES]], 1 368; CHECK-NEXT: br i1 [[OBIT]], label [[OVERFLOW:%.*]], label [[NORMAL:%.*]] 369; CHECK: overflow: 370; CHECK-NEXT: ret i16 0 371; CHECK: normal: 372; CHECK-NEXT: [[SUM:%.*]] = extractvalue { i16, i1 } [[RES]], 0 373; CHECK-NEXT: ret i16 [[SUM]] 374; 375 %s0 = select i1 %c, i16 %a, i16 %b 376 %s1 = select i1 %c, i16 %b, i16 %a 377 %res = call {i16, i1} @llvm.uadd.with.overflow.i16(i16 %s1, i16 %s0) 378 %obit = extractvalue {i16, i1} %res, 1 379 br i1 %obit, label %overflow, label %normal 380overflow: 381 ret i16 0 382normal: 383 %sum = extractvalue {i16, i1} %res, 0 384 ret i16 %sum 385} 386 387define i16 @fold_select_smul_with_overflow(i1 %c, i16 %a, i16 %b) { 388; CHECK-LABEL: define i16 @fold_select_smul_with_overflow( 389; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) { 390; CHECK-NEXT: [[RES:%.*]] = call { i16, i1 } @llvm.smul.with.overflow.i16(i16 [[B]], i16 [[A]]) 391; CHECK-NEXT: [[OBIT:%.*]] = extractvalue { i16, i1 } [[RES]], 1 392; CHECK-NEXT: br i1 [[OBIT]], label [[OVERFLOW:%.*]], label [[NORMAL:%.*]] 393; CHECK: overflow: 394; CHECK-NEXT: ret i16 0 395; CHECK: normal: 396; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i16, i1 } [[RES]], 0 397; CHECK-NEXT: ret i16 [[MUL]] 398; 399 %s0 = select i1 %c, i16 %a, i16 %b 400 %s1 = select i1 %c, i16 %b, i16 %a 401 %res = call {i16, i1} @llvm.smul.with.overflow.i16(i16 %s1, i16 %s0) 402 %obit = extractvalue {i16, i1} %res, 1 403 br i1 %obit, label %overflow, label %normal 404overflow: 405 ret i16 0 406normal: 407 %mul = extractvalue {i16, i1} %res, 0 408 ret i16 %mul 409} 410 411define i16 @fold_select_umul_with_overflow(i1 %c, i16 %a, i16 %b) { 412; CHECK-LABEL: define i16 @fold_select_umul_with_overflow( 413; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]]) { 414; CHECK-NEXT: [[RES:%.*]] = call { i16, i1 } @llvm.umul.with.overflow.i16(i16 [[B]], i16 [[A]]) 415; CHECK-NEXT: [[OBIT:%.*]] = extractvalue { i16, i1 } [[RES]], 1 416; CHECK-NEXT: br i1 [[OBIT]], label [[OVERFLOW:%.*]], label [[NORMAL:%.*]] 417; CHECK: overflow: 418; CHECK-NEXT: ret i16 0 419; CHECK: normal: 420; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i16, i1 } [[RES]], 0 421; CHECK-NEXT: ret i16 [[MUL]] 422; 423 %s0 = select i1 %c, i16 %a, i16 %b 424 %s1 = select i1 %c, i16 %b, i16 %a 425 %res = call {i16, i1} @llvm.umul.with.overflow.i16(i16 %s1, i16 %s0) 426 %obit = extractvalue {i16, i1} %res, 1 427 br i1 %obit, label %overflow, label %normal 428overflow: 429 ret i16 0 430normal: 431 %mul = extractvalue {i16, i1} %res, 0 432 ret i16 %mul 433} 434 435define i16 @fold_select_smul_fix(i1 %c, i16 %a, i16 %b, i32 %y) { 436; CHECK-LABEL: define i16 @fold_select_smul_fix( 437; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]], i32 [[Y:%.*]]) { 438; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[B]], i16 [[A]], i32 1) 439; CHECK-NEXT: ret i16 [[RET]] 440; 441 %s0 = select i1 %c, i16 %a, i16 %b 442 %s1 = select i1 %c, i16 %b, i16 %a 443 %ret = call i16 @llvm.smul.fix.i16(i16 %s1, i16 %s0, i32 1) 444 ret i16 %ret 445} 446 447define i16 @fold_select_umul_fix(i1 %c, i16 %a, i16 %b, i32 %y) { 448; CHECK-LABEL: define i16 @fold_select_umul_fix( 449; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]], i32 [[Y:%.*]]) { 450; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[B]], i16 [[A]], i32 1) 451; CHECK-NEXT: ret i16 [[RET]] 452; 453 %s0 = select i1 %c, i16 %a, i16 %b 454 %s1 = select i1 %c, i16 %b, i16 %a 455 %ret = call i16 @llvm.umul.fix.i16(i16 %s1, i16 %s0, i32 1) 456 ret i16 %ret 457} 458 459define i16 @fold_select_smul_fix_sat(i1 %c, i16 %a, i16 %b, i32 %y) { 460; CHECK-LABEL: define i16 @fold_select_smul_fix_sat( 461; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]], i32 [[Y:%.*]]) { 462; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.smul.fix.sat.i16(i16 [[B]], i16 [[A]], i32 1) 463; CHECK-NEXT: ret i16 [[RET]] 464; 465 %s0 = select i1 %c, i16 %a, i16 %b 466 %s1 = select i1 %c, i16 %b, i16 %a 467 %ret = call i16 @llvm.smul.fix.sat.i16(i16 %s1, i16 %s0, i32 1) 468 ret i16 %ret 469} 470 471define i16 @fold_select_umul_fix_sat(i1 %c, i16 %a, i16 %b, i32 %y) { 472; CHECK-LABEL: define i16 @fold_select_umul_fix_sat( 473; CHECK-SAME: i1 [[C:%.*]], i16 [[A:%.*]], i16 [[B:%.*]], i32 [[Y:%.*]]) { 474; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.umul.fix.sat.i16(i16 [[B]], i16 [[A]], i32 1) 475; CHECK-NEXT: ret i16 [[RET]] 476; 477 %s0 = select i1 %c, i16 %a, i16 %b 478 %s1 = select i1 %c, i16 %b, i16 %a 479 %ret = call i16 @llvm.umul.fix.sat.i16(i16 %s1, i16 %s0, i32 1) 480 ret i16 %ret 481} 482 483define float @fold_select_fma(i1 %c, float %a, float %b, float %y) { 484; CHECK-LABEL: define float @fold_select_fma( 485; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]], float [[Y:%.*]]) { 486; CHECK-NEXT: [[RET:%.*]] = call float @llvm.fma.f32(float [[B]], float [[A]], float [[Y]]) 487; CHECK-NEXT: ret float [[RET]] 488; 489 %s0 = select i1 %c, float %a, float %b 490 %s1 = select i1 %c, float %b, float %a 491 %ret = call float @llvm.fma.f32(float %s1, float %s0, float %y) 492 ret float %ret 493} 494 495define float @fold_select_fmuladd(i1 %c, float %a, float %b, float %y) { 496; CHECK-LABEL: define float @fold_select_fmuladd( 497; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]], float [[Y:%.*]]) { 498; CHECK-NEXT: [[RET:%.*]] = call float @llvm.fmuladd.f32(float [[B]], float [[A]], float [[Y]]) 499; CHECK-NEXT: ret float [[RET]] 500; 501 %s0 = select i1 %c, float %a, float %b 502 %s1 = select i1 %c, float %b, float %a 503 %ret = call float @llvm.fmuladd.f32(float %s1, float %s0, float %y) 504 ret float %ret 505} 506 507;negative tests: 508 509define i8 @fold_select_unmatch_mul_neg(i1 %c, i1 %c1, i8 %a, i8 %b) { 510; CHECK-LABEL: define i8 @fold_select_unmatch_mul_neg( 511; CHECK-SAME: i1 [[C:%.*]], i1 [[C1:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) { 512; CHECK-NEXT: [[S0:%.*]] = select i1 [[C]], i8 [[A]], i8 [[B]] 513; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1]], i8 [[B]], i8 [[A]] 514; CHECK-NEXT: [[RET:%.*]] = mul i8 [[S1]], [[S0]] 515; CHECK-NEXT: ret i8 [[RET]] 516; 517 %s0 = select i1 %c, i8 %a, i8 %b 518 %s1 = select i1 %c1, i8 %b, i8 %a 519 %ret = mul i8 %s1, %s0 520 ret i8 %ret 521} 522 523define i8 @fold_select_sub_neg(i1 %c, i8 %a, i8 %b) { 524; CHECK-LABEL: define i8 @fold_select_sub_neg( 525; CHECK-SAME: i1 [[C:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) { 526; CHECK-NEXT: [[S0:%.*]] = select i1 [[C]], i8 [[A]], i8 [[B]] 527; CHECK-NEXT: [[S1:%.*]] = select i1 [[C]], i8 [[B]], i8 [[A]] 528; CHECK-NEXT: [[RET:%.*]] = sub i8 [[S1]], [[S0]] 529; CHECK-NEXT: ret i8 [[RET]] 530; 531 %s0 = select i1 %c, i8 %a, i8 %b 532 %s1 = select i1 %c, i8 %b, i8 %a 533 %ret = sub i8 %s1, %s0 534 ret i8 %ret 535} 536 537define float @fold_select_fma_neg(i1 %c, i1 %c1, float %a, float %b, float %y) { 538; CHECK-LABEL: define float @fold_select_fma_neg( 539; CHECK-SAME: i1 [[C:%.*]], i1 [[C1:%.*]], float [[A:%.*]], float [[B:%.*]], float [[Y:%.*]]) { 540; CHECK-NEXT: [[S0:%.*]] = select i1 [[C]], float [[A]], float [[B]] 541; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1]], float [[B]], float [[A]] 542; CHECK-NEXT: [[RET:%.*]] = call float @llvm.fma.f32(float [[S1]], float [[S0]], float [[Y]]) 543; CHECK-NEXT: ret float [[RET]] 544; 545 %s0 = select i1 %c, float %a, float %b 546 %s1 = select i1 %c1, float %b, float %a 547 %ret = call float @llvm.fma.f32(float %s1, float %s0, float %y) 548 ret float %ret 549} 550 551define float @fold_select_fma_match_neg(i1 %c, float %a, float %b, float %y) { 552; CHECK-LABEL: define float @fold_select_fma_match_neg( 553; CHECK-SAME: i1 [[C:%.*]], float [[A:%.*]], float [[B:%.*]], float [[Y:%.*]]) { 554; CHECK-NEXT: [[S0:%.*]] = select i1 [[C]], float [[A]], float [[B]] 555; CHECK-NEXT: [[S1:%.*]] = select i1 [[C]], float [[B]], float [[A]] 556; CHECK-NEXT: [[RET:%.*]] = call float @llvm.fma.f32(float [[Y]], float [[S0]], float [[S1]]) 557; CHECK-NEXT: ret float [[RET]] 558; 559 %s0 = select i1 %c, float %a, float %b 560 %s1 = select i1 %c, float %b, float %a 561 %ret = call float @llvm.fma.f32(float %y, float %s0, float %s1) 562 ret float %ret 563} 564