1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instsimplify -S | FileCheck %s 3; RUN: opt < %s -passes=instsimplify -S | FileCheck %s 4 5declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b) 6declare {i8, i1} @llvm.sadd.with.overflow.i8(i8 %a, i8 %b) 7declare {i8, i1} @llvm.usub.with.overflow.i8(i8 %a, i8 %b) 8declare {i8, i1} @llvm.ssub.with.overflow.i8(i8 %a, i8 %b) 9declare {i8, i1} @llvm.umul.with.overflow.i8(i8 %a, i8 %b) 10declare {i8, i1} @llvm.smul.with.overflow.i8(i8 %a, i8 %b) 11 12define i1 @test_uadd1() { 13; CHECK-LABEL: @test_uadd1( 14; CHECK-NEXT: ret i1 true 15; 16 %x = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 254, i8 3) 17 %overflow = extractvalue {i8, i1} %x, 1 18 ret i1 %overflow 19} 20 21define i8 @test_uadd2() { 22; CHECK-LABEL: @test_uadd2( 23; CHECK-NEXT: ret i8 42 24; 25 %x = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 254, i8 44) 26 %result = extractvalue {i8, i1} %x, 0 27 ret i8 %result 28} 29 30define {i8, i1} @test_uadd3(i8 %v) { 31; CHECK-LABEL: @test_uadd3( 32; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } 33; 34 %result = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %v, i8 undef) 35 ret {i8, i1} %result 36} 37 38define {i8, i1} @test_uadd3_poison(i8 %v) { 39; CHECK-LABEL: @test_uadd3_poison( 40; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } 41; 42 %result = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %v, i8 poison) 43 ret {i8, i1} %result 44} 45 46define {i8, i1} @test_uadd4(i8 %v) { 47; CHECK-LABEL: @test_uadd4( 48; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } 49; 50 %result = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 undef, i8 %v) 51 ret {i8, i1} %result 52} 53 54define {i8, i1} @test_uadd4_poison(i8 %v) { 55; CHECK-LABEL: @test_uadd4_poison( 56; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } 57; 58 %result = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 poison, i8 %v) 59 ret {i8, i1} %result 60} 61 62define i1 @test_sadd1() { 63; CHECK-LABEL: @test_sadd1( 64; CHECK-NEXT: ret i1 true 65; 66 %x = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 126, i8 3) 67 %overflow = extractvalue {i8, i1} %x, 1 68 ret i1 %overflow 69} 70 71define i8 @test_sadd2() { 72; CHECK-LABEL: @test_sadd2( 73; CHECK-NEXT: ret i8 -86 74; 75 %x = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 126, i8 44) 76 %result = extractvalue {i8, i1} %x, 0 77 ret i8 %result 78} 79 80define {i8, i1} @test_sadd3(i8 %v) { 81; CHECK-LABEL: @test_sadd3( 82; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } 83; 84 %result = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 %v, i8 undef) 85 ret {i8, i1} %result 86} 87 88define {i8, i1} @test_sadd3_poison(i8 %v) { 89; CHECK-LABEL: @test_sadd3_poison( 90; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } 91; 92 %result = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 %v, i8 poison) 93 ret {i8, i1} %result 94} 95 96define {i8, i1} @test_sadd4(i8 %v) { 97; CHECK-LABEL: @test_sadd4( 98; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } 99; 100 %result = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 undef, i8 %v) 101 ret {i8, i1} %result 102} 103 104define {i8, i1} @test_sadd4_poison(i8 %v) { 105; CHECK-LABEL: @test_sadd4_poison( 106; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } 107; 108 %result = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 poison, i8 %v) 109 ret {i8, i1} %result 110} 111 112define {i8, i1} @test_usub1(i8 %V) { 113; CHECK-LABEL: @test_usub1( 114; CHECK-NEXT: ret { i8, i1 } zeroinitializer 115; 116 %x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 %V, i8 %V) 117 ret {i8, i1} %x 118} 119 120define {i8, i1} @test_usub2(i8 %V) { 121; CHECK-LABEL: @test_usub2( 122; CHECK-NEXT: ret { i8, i1 } zeroinitializer 123; 124 %x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 %V, i8 undef) 125 ret {i8, i1} %x 126} 127 128define {i8, i1} @test_usub2_poison(i8 %V) { 129; CHECK-LABEL: @test_usub2_poison( 130; CHECK-NEXT: ret { i8, i1 } zeroinitializer 131; 132 %x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 %V, i8 poison) 133 ret {i8, i1} %x 134} 135 136define {i8, i1} @test_usub3(i8 %V) { 137; CHECK-LABEL: @test_usub3( 138; CHECK-NEXT: ret { i8, i1 } zeroinitializer 139; 140 %x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 undef, i8 %V) 141 ret {i8, i1} %x 142} 143 144define {i8, i1} @test_usub3_poison(i8 %V) { 145; CHECK-LABEL: @test_usub3_poison( 146; CHECK-NEXT: ret { i8, i1 } zeroinitializer 147; 148 %x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 poison, i8 %V) 149 ret {i8, i1} %x 150} 151 152define {i8, i1} @test_ssub1(i8 %V) { 153; CHECK-LABEL: @test_ssub1( 154; CHECK-NEXT: ret { i8, i1 } zeroinitializer 155; 156 %x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 %V, i8 %V) 157 ret {i8, i1} %x 158} 159 160define {i8, i1} @test_ssub2(i8 %V) { 161; CHECK-LABEL: @test_ssub2( 162; CHECK-NEXT: ret { i8, i1 } zeroinitializer 163; 164 %x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 %V, i8 undef) 165 ret {i8, i1} %x 166} 167 168define {i8, i1} @test_ssub2_poison(i8 %V) { 169; CHECK-LABEL: @test_ssub2_poison( 170; CHECK-NEXT: ret { i8, i1 } zeroinitializer 171; 172 %x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 %V, i8 poison) 173 ret {i8, i1} %x 174} 175 176define {i8, i1} @test_ssub3(i8 %V) { 177; CHECK-LABEL: @test_ssub3( 178; CHECK-NEXT: ret { i8, i1 } zeroinitializer 179; 180 %x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 undef, i8 %V) 181 ret {i8, i1} %x 182} 183 184define {i8, i1} @test_ssub3_poison(i8 %V) { 185; CHECK-LABEL: @test_ssub3_poison( 186; CHECK-NEXT: ret { i8, i1 } zeroinitializer 187; 188 %x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 poison, i8 %V) 189 ret {i8, i1} %x 190} 191 192define {i8, i1} @test_umul1(i8 %V) { 193; CHECK-LABEL: @test_umul1( 194; CHECK-NEXT: ret { i8, i1 } zeroinitializer 195; 196 %x = call {i8, i1} @llvm.umul.with.overflow.i8(i8 %V, i8 0) 197 ret {i8, i1} %x 198} 199 200define {i8, i1} @test_umul2(i8 %V) { 201; CHECK-LABEL: @test_umul2( 202; CHECK-NEXT: ret { i8, i1 } zeroinitializer 203; 204 %x = call {i8, i1} @llvm.umul.with.overflow.i8(i8 %V, i8 undef) 205 ret {i8, i1} %x 206} 207 208define {i8, i1} @test_umul2_poison(i8 %V) { 209; CHECK-LABEL: @test_umul2_poison( 210; CHECK-NEXT: ret { i8, i1 } zeroinitializer 211; 212 %x = call {i8, i1} @llvm.umul.with.overflow.i8(i8 %V, i8 poison) 213 ret {i8, i1} %x 214} 215 216define {i8, i1} @test_umul3(i8 %V) { 217; CHECK-LABEL: @test_umul3( 218; CHECK-NEXT: ret { i8, i1 } zeroinitializer 219; 220 %x = call {i8, i1} @llvm.umul.with.overflow.i8(i8 0, i8 %V) 221 ret {i8, i1} %x 222} 223 224define {i8, i1} @test_umul4(i8 %V) { 225; CHECK-LABEL: @test_umul4( 226; CHECK-NEXT: ret { i8, i1 } zeroinitializer 227; 228 %x = call {i8, i1} @llvm.umul.with.overflow.i8(i8 undef, i8 %V) 229 ret {i8, i1} %x 230} 231 232define {i8, i1} @test_umul4_poison(i8 %V) { 233; CHECK-LABEL: @test_umul4_poison( 234; CHECK-NEXT: ret { i8, i1 } zeroinitializer 235; 236 %x = call {i8, i1} @llvm.umul.with.overflow.i8(i8 poison, i8 %V) 237 ret {i8, i1} %x 238} 239 240define {i8, i1} @test_smul1(i8 %V) { 241; CHECK-LABEL: @test_smul1( 242; CHECK-NEXT: ret { i8, i1 } zeroinitializer 243; 244 %x = call {i8, i1} @llvm.smul.with.overflow.i8(i8 %V, i8 0) 245 ret {i8, i1} %x 246} 247 248define {i8, i1} @test_smul2(i8 %V) { 249; CHECK-LABEL: @test_smul2( 250; CHECK-NEXT: ret { i8, i1 } zeroinitializer 251; 252 %x = call {i8, i1} @llvm.smul.with.overflow.i8(i8 %V, i8 undef) 253 ret {i8, i1} %x 254} 255 256define {i8, i1} @test_smul2_poison(i8 %V) { 257; CHECK-LABEL: @test_smul2_poison( 258; CHECK-NEXT: ret { i8, i1 } zeroinitializer 259; 260 %x = call {i8, i1} @llvm.smul.with.overflow.i8(i8 %V, i8 poison) 261 ret {i8, i1} %x 262} 263 264define {i8, i1} @test_smul3(i8 %V) { 265; CHECK-LABEL: @test_smul3( 266; CHECK-NEXT: ret { i8, i1 } zeroinitializer 267; 268 %x = call {i8, i1} @llvm.smul.with.overflow.i8(i8 0, i8 %V) 269 ret {i8, i1} %x 270} 271 272define {i8, i1} @test_smul4(i8 %V) { 273; CHECK-LABEL: @test_smul4( 274; CHECK-NEXT: ret { i8, i1 } zeroinitializer 275; 276 %x = call {i8, i1} @llvm.smul.with.overflow.i8(i8 undef, i8 %V) 277 ret {i8, i1} %x 278} 279 280define {i8, i1} @test_smul4_poison(i8 %V) { 281; CHECK-LABEL: @test_smul4_poison( 282; CHECK-NEXT: ret { i8, i1 } zeroinitializer 283; 284 %x = call {i8, i1} @llvm.smul.with.overflow.i8(i8 poison, i8 %V) 285 ret {i8, i1} %x 286} 287 288; Test a non-intrinsic that we know about as a library call. 289declare float @fabs(float %x) 290 291define float @test_fabs_libcall() { 292; CHECK-LABEL: @test_fabs_libcall( 293; CHECK-NEXT: [[X:%.*]] = call float @fabs(float -4.200000e+01) 294; CHECK-NEXT: ret float 4.200000e+01 295; 296 297 %x = call float @fabs(float -42.0) 298; This is still a real function call, so instsimplify won't nuke it -- other 299; passes have to do that. 300 301 ret float %x 302} 303 304 305declare float @llvm.fabs.f32(float) nounwind readnone 306declare float @llvm.floor.f32(float) nounwind readnone 307declare float @llvm.ceil.f32(float) nounwind readnone 308declare float @llvm.trunc.f32(float) nounwind readnone 309declare float @llvm.rint.f32(float) nounwind readnone 310declare float @llvm.nearbyint.f32(float) nounwind readnone 311declare float @llvm.canonicalize.f32(float) nounwind readnone 312 313; Test idempotent intrinsics 314define float @test_idempotence(float %a) { 315; CHECK-LABEL: @test_idempotence( 316; CHECK-NEXT: [[A0:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) 317; CHECK-NEXT: [[B0:%.*]] = call float @llvm.floor.f32(float [[A]]) 318; CHECK-NEXT: [[C0:%.*]] = call float @llvm.ceil.f32(float [[A]]) 319; CHECK-NEXT: [[D0:%.*]] = call float @llvm.trunc.f32(float [[A]]) 320; CHECK-NEXT: [[E0:%.*]] = call float @llvm.rint.f32(float [[A]]) 321; CHECK-NEXT: [[F0:%.*]] = call float @llvm.nearbyint.f32(float [[A]]) 322; CHECK-NEXT: [[G0:%.*]] = call float @llvm.canonicalize.f32(float [[A]]) 323; CHECK-NEXT: [[R0:%.*]] = fadd float [[A0]], [[B0]] 324; CHECK-NEXT: [[R1:%.*]] = fadd float [[R0]], [[C0]] 325; CHECK-NEXT: [[R2:%.*]] = fadd float [[R1]], [[D0]] 326; CHECK-NEXT: [[R3:%.*]] = fadd float [[R2]], [[E0]] 327; CHECK-NEXT: [[R4:%.*]] = fadd float [[R3]], [[F0]] 328; CHECK-NEXT: [[R5:%.*]] = fadd float [[R4]], [[G0]] 329; CHECK-NEXT: ret float [[R5]] 330; 331 332 %a0 = call float @llvm.fabs.f32(float %a) 333 %a1 = call float @llvm.fabs.f32(float %a0) 334 335 %b0 = call float @llvm.floor.f32(float %a) 336 %b1 = call float @llvm.floor.f32(float %b0) 337 338 %c0 = call float @llvm.ceil.f32(float %a) 339 %c1 = call float @llvm.ceil.f32(float %c0) 340 341 %d0 = call float @llvm.trunc.f32(float %a) 342 %d1 = call float @llvm.trunc.f32(float %d0) 343 344 %e0 = call float @llvm.rint.f32(float %a) 345 %e1 = call float @llvm.rint.f32(float %e0) 346 347 %f0 = call float @llvm.nearbyint.f32(float %a) 348 %f1 = call float @llvm.nearbyint.f32(float %f0) 349 350 %g0 = call float @llvm.canonicalize.f32(float %a) 351 %g1 = call float @llvm.canonicalize.f32(float %g0) 352 353 %r0 = fadd float %a1, %b1 354 %r1 = fadd float %r0, %c1 355 %r2 = fadd float %r1, %d1 356 %r3 = fadd float %r2, %e1 357 %r4 = fadd float %r3, %f1 358 %r5 = fadd float %r4, %g1 359 360 ret float %r5 361} 362 363define i8* @operator_new() { 364; CHECK-LABEL: @operator_new( 365; CHECK-NEXT: entry: 366; CHECK-NEXT: [[CALL:%.*]] = tail call noalias i8* @_Znwm(i64 8) 367; CHECK-NEXT: br i1 false, label [[CAST_END:%.*]], label [[CAST_NOTNULL:%.*]] 368; CHECK: cast.notnull: 369; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[CALL]], i64 4 370; CHECK-NEXT: br label [[CAST_END]] 371; CHECK: cast.end: 372; CHECK-NEXT: [[CAST_RESULT:%.*]] = phi i8* [ [[ADD_PTR]], [[CAST_NOTNULL]] ], [ null, [[ENTRY:%.*]] ] 373; CHECK-NEXT: ret i8* [[CAST_RESULT]] 374; 375entry: 376 %call = tail call noalias i8* @_Znwm(i64 8) 377 %cmp = icmp eq i8* %call, null 378 br i1 %cmp, label %cast.end, label %cast.notnull 379 380cast.notnull: ; preds = %entry 381 %add.ptr = getelementptr inbounds i8, i8* %call, i64 4 382 br label %cast.end 383 384cast.end: ; preds = %cast.notnull, %entry 385 %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ] 386 ret i8* %cast.result 387 388} 389 390declare nonnull noalias i8* @_Znwm(i64) 391 392%"struct.std::nothrow_t" = type { i8 } 393@_ZSt7nothrow = external global %"struct.std::nothrow_t" 394 395define i8* @operator_new_nothrow_t() { 396; CHECK-LABEL: @operator_new_nothrow_t( 397; CHECK-NEXT: entry: 398; CHECK-NEXT: [[CALL:%.*]] = tail call noalias i8* @_ZnamRKSt9nothrow_t(i64 8, %"struct.std::nothrow_t"* @_ZSt7nothrow) 399; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8* [[CALL]], null 400; CHECK-NEXT: br i1 [[CMP]], label [[CAST_END:%.*]], label [[CAST_NOTNULL:%.*]] 401; CHECK: cast.notnull: 402; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[CALL]], i64 4 403; CHECK-NEXT: br label [[CAST_END]] 404; CHECK: cast.end: 405; CHECK-NEXT: [[CAST_RESULT:%.*]] = phi i8* [ [[ADD_PTR]], [[CAST_NOTNULL]] ], [ null, [[ENTRY:%.*]] ] 406; CHECK-NEXT: ret i8* [[CAST_RESULT]] 407; 408entry: 409 %call = tail call noalias i8* @_ZnamRKSt9nothrow_t(i64 8, %"struct.std::nothrow_t"* @_ZSt7nothrow) 410 %cmp = icmp eq i8* %call, null 411 br i1 %cmp, label %cast.end, label %cast.notnull 412 413cast.notnull: ; preds = %entry 414 %add.ptr = getelementptr inbounds i8, i8* %call, i64 4 415 br label %cast.end 416 417cast.end: ; preds = %cast.notnull, %entry 418 %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ] 419 ret i8* %cast.result 420 421} 422 423declare i8* @_ZnamRKSt9nothrow_t(i64, %"struct.std::nothrow_t"*) nounwind 424 425define i8* @malloc_can_return_null() { 426; CHECK-LABEL: @malloc_can_return_null( 427; CHECK-NEXT: entry: 428; CHECK-NEXT: [[CALL:%.*]] = tail call noalias i8* @malloc(i64 8) 429; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8* [[CALL]], null 430; CHECK-NEXT: br i1 [[CMP]], label [[CAST_END:%.*]], label [[CAST_NOTNULL:%.*]] 431; CHECK: cast.notnull: 432; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[CALL]], i64 4 433; CHECK-NEXT: br label [[CAST_END]] 434; CHECK: cast.end: 435; CHECK-NEXT: [[CAST_RESULT:%.*]] = phi i8* [ [[ADD_PTR]], [[CAST_NOTNULL]] ], [ null, [[ENTRY:%.*]] ] 436; CHECK-NEXT: ret i8* [[CAST_RESULT]] 437; 438entry: 439 %call = tail call noalias i8* @malloc(i64 8) 440 %cmp = icmp eq i8* %call, null 441 br i1 %cmp, label %cast.end, label %cast.notnull 442 443cast.notnull: ; preds = %entry 444 %add.ptr = getelementptr inbounds i8, i8* %call, i64 4 445 br label %cast.end 446 447cast.end: ; preds = %cast.notnull, %entry 448 %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ] 449 ret i8* %cast.result 450 451} 452 453define i32 @call_null() { 454; CHECK-LABEL: @call_null( 455; CHECK-NEXT: entry: 456; CHECK-NEXT: [[CALL:%.*]] = call i32 null() 457; CHECK-NEXT: ret i32 poison 458; 459entry: 460 %call = call i32 null() 461 ret i32 %call 462} 463 464define i32 @call_undef() { 465; CHECK-LABEL: @call_undef( 466; CHECK-NEXT: entry: 467; CHECK-NEXT: [[CALL:%.*]] = call i32 undef() 468; CHECK-NEXT: ret i32 poison 469; 470entry: 471 %call = call i32 undef() 472 ret i32 %call 473} 474 475@GV = private constant [8 x i32] [i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49] 476 477define <8 x i32> @partial_masked_load() { 478; CHECK-LABEL: @partial_masked_load( 479; CHECK-NEXT: ret <8 x i32> <i32 undef, i32 undef, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47> 480; 481 %masked.load = call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* bitcast (i32* getelementptr ([8 x i32], [8 x i32]* @GV, i64 0, i64 -2) to <8 x i32>*), i32 4, <8 x i1> <i1 false, i1 false, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <8 x i32> undef) 482 ret <8 x i32> %masked.load 483} 484 485define <8 x i32> @masked_load_undef_mask(<8 x i32>* %V) { 486; CHECK-LABEL: @masked_load_undef_mask( 487; CHECK-NEXT: ret <8 x i32> <i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0> 488; 489 %masked.load = call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* %V, i32 4, <8 x i1> undef, <8 x i32> <i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0>) 490 ret <8 x i32> %masked.load 491} 492 493declare noalias i8* @malloc(i64) 494 495declare <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>*, i32, <8 x i1>, <8 x i32>) 496 497declare double @llvm.powi.f64.i16(double, i16) 498declare <2 x double> @llvm.powi.v2f64.i16(<2 x double>, i16) 499declare double @llvm.powi.f64.i32(double, i32) 500declare <2 x double> @llvm.powi.v2f64.i32(<2 x double>, i32) 501 502define double @constant_fold_powi() { 503; CHECK-LABEL: @constant_fold_powi( 504; CHECK-NEXT: ret double 9.000000e+00 505; 506 %t0 = call double @llvm.powi.f64.i32(double 3.00000e+00, i32 2) 507 ret double %t0 508} 509 510define double @constant_fold_powi_i16() { 511; CHECK-LABEL: @constant_fold_powi_i16( 512; CHECK-NEXT: ret double 9.000000e+00 513; 514 %t0 = call double @llvm.powi.f64.i16(double 3.00000e+00, i16 2) 515 ret double %t0 516} 517 518define <2 x double> @constant_fold_powi_vec() { 519; CHECK-LABEL: @constant_fold_powi_vec( 520; CHECK-NEXT: ret <2 x double> <double 9.000000e+00, double 2.500000e+01> 521; 522 %t0 = call <2 x double> @llvm.powi.v2f64.i32(<2 x double> <double 3.00000e+00, double 5.00000e+00>, i32 2) 523 ret <2 x double> %t0 524} 525 526define <2 x double> @constant_fold_powi_vec_i16() { 527; CHECK-LABEL: @constant_fold_powi_vec_i16( 528; CHECK-NEXT: ret <2 x double> <double 9.000000e+00, double 2.500000e+01> 529; 530 %t0 = call <2 x double> @llvm.powi.v2f64.i16(<2 x double> <double 3.00000e+00, double 5.00000e+00>, i16 2) 531 ret <2 x double> %t0 532} 533 534declare i8 @llvm.fshl.i8(i8, i8, i8) 535declare i9 @llvm.fshr.i9(i9, i9, i9) 536declare <2 x i7> @llvm.fshl.v2i7(<2 x i7>, <2 x i7>, <2 x i7>) 537declare <2 x i8> @llvm.fshr.v2i8(<2 x i8>, <2 x i8>, <2 x i8>) 538 539define i8 @fshl_no_shift(i8 %x, i8 %y) { 540; CHECK-LABEL: @fshl_no_shift( 541; CHECK-NEXT: ret i8 [[X:%.*]] 542; 543 %z = call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 0) 544 ret i8 %z 545} 546 547define i9 @fshr_no_shift(i9 %x, i9 %y) { 548; CHECK-LABEL: @fshr_no_shift( 549; CHECK-NEXT: ret i9 [[Y:%.*]] 550; 551 %z = call i9 @llvm.fshr.i9(i9 %x, i9 %y, i9 0) 552 ret i9 %z 553} 554 555define i8 @fshl_no_shift_modulo_bitwidth(i8 %x, i8 %y) { 556; CHECK-LABEL: @fshl_no_shift_modulo_bitwidth( 557; CHECK-NEXT: ret i8 [[X:%.*]] 558; 559 %z = call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 40) 560 ret i8 %z 561} 562 563define i9 @fshr_no_shift_modulo_bitwidth(i9 %x, i9 %y) { 564; CHECK-LABEL: @fshr_no_shift_modulo_bitwidth( 565; CHECK-NEXT: ret i9 [[Y:%.*]] 566; 567 %z = call i9 @llvm.fshr.i9(i9 %x, i9 %y, i9 189) 568 ret i9 %z 569} 570 571define <2 x i7> @fshl_no_shift_modulo_bitwidth_splat(<2 x i7> %x, <2 x i7> %y) { 572; CHECK-LABEL: @fshl_no_shift_modulo_bitwidth_splat( 573; CHECK-NEXT: ret <2 x i7> [[X:%.*]] 574; 575 %z = call <2 x i7> @llvm.fshl.v2i7(<2 x i7> %x, <2 x i7> %y, <2 x i7> <i7 21, i7 21>) 576 ret <2 x i7> %z 577} 578 579define <2 x i8> @fshr_no_shift_modulo_bitwidth_splat(<2 x i8> %x, <2 x i8> %y) { 580; CHECK-LABEL: @fshr_no_shift_modulo_bitwidth_splat( 581; CHECK-NEXT: ret <2 x i8> [[Y:%.*]] 582; 583 %z = call <2 x i8> @llvm.fshr.v2i8(<2 x i8> %x, <2 x i8> %y, <2 x i8> <i8 72, i8 72>) 584 ret <2 x i8> %z 585} 586 587; If y is poison, eliminating the guard is not safe. 588 589define i8 @fshl_zero_shift_guard(i8 %x, i8 %y, i8 %sh) { 590; CHECK-LABEL: @fshl_zero_shift_guard( 591; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[SH:%.*]], 0 592; CHECK-NEXT: [[F:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[SH]]) 593; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 [[X]], i8 [[F]] 594; CHECK-NEXT: ret i8 [[S]] 595; 596 %c = icmp eq i8 %sh, 0 597 %f = call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 %sh) 598 %s = select i1 %c, i8 %x, i8 %f 599 ret i8 %s 600} 601 602; If y is poison, eliminating the guard is not safe. 603 604define i8 @fshl_zero_shift_guard_swapped(i8 %x, i8 %y, i8 %sh) { 605; CHECK-LABEL: @fshl_zero_shift_guard_swapped( 606; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[SH:%.*]], 0 607; CHECK-NEXT: [[F:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[SH]]) 608; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 [[F]], i8 [[X]] 609; CHECK-NEXT: ret i8 [[S]] 610; 611 %c = icmp ne i8 %sh, 0 612 %f = call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 %sh) 613 %s = select i1 %c, i8 %f, i8 %x 614 ret i8 %s 615} 616 617; When the shift amount is 0, fshl returns its 1st parameter (x), so everything is deleted. 618 619define i8 @fshl_zero_shift_guard_inverted(i8 %x, i8 %y, i8 %sh) { 620; CHECK-LABEL: @fshl_zero_shift_guard_inverted( 621; CHECK-NEXT: ret i8 [[X:%.*]] 622; 623 %c = icmp eq i8 %sh, 0 624 %f = call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 %sh) 625 %s = select i1 %c, i8 %f, i8 %x 626 ret i8 %s 627} 628 629; When the shift amount is 0, fshl returns its 1st parameter (x), so everything is deleted. 630 631define i8 @fshl_zero_shift_guard_inverted_swapped(i8 %x, i8 %y, i8 %sh) { 632; CHECK-LABEL: @fshl_zero_shift_guard_inverted_swapped( 633; CHECK-NEXT: ret i8 [[X:%.*]] 634; 635 %c = icmp ne i8 %sh, 0 636 %f = call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 %sh) 637 %s = select i1 %c, i8 %x, i8 %f 638 ret i8 %s 639} 640 641; If x is poison, eliminating the guard is not safe. 642 643define i9 @fshr_zero_shift_guard(i9 %x, i9 %y, i9 %sh) { 644; CHECK-LABEL: @fshr_zero_shift_guard( 645; CHECK-NEXT: [[C:%.*]] = icmp eq i9 [[SH:%.*]], 0 646; CHECK-NEXT: [[F:%.*]] = call i9 @llvm.fshr.i9(i9 [[X:%.*]], i9 [[Y:%.*]], i9 [[SH]]) 647; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i9 [[Y]], i9 [[F]] 648; CHECK-NEXT: ret i9 [[S]] 649; 650 %c = icmp eq i9 %sh, 0 651 %f = call i9 @llvm.fshr.i9(i9 %x, i9 %y, i9 %sh) 652 %s = select i1 %c, i9 %y, i9 %f 653 ret i9 %s 654} 655 656; If x is poison, eliminating the guard is not safe. 657 658define i9 @fshr_zero_shift_guard_swapped(i9 %x, i9 %y, i9 %sh) { 659; CHECK-LABEL: @fshr_zero_shift_guard_swapped( 660; CHECK-NEXT: [[C:%.*]] = icmp ne i9 [[SH:%.*]], 0 661; CHECK-NEXT: [[F:%.*]] = call i9 @llvm.fshr.i9(i9 [[X:%.*]], i9 [[Y:%.*]], i9 [[SH]]) 662; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i9 [[F]], i9 [[Y]] 663; CHECK-NEXT: ret i9 [[S]] 664; 665 %c = icmp ne i9 %sh, 0 666 %f = call i9 @llvm.fshr.i9(i9 %x, i9 %y, i9 %sh) 667 %s = select i1 %c, i9 %f, i9 %y 668 ret i9 %s 669} 670 671; When the shift amount is 0, fshr returns its 2nd parameter (y), so everything is deleted. 672 673define i9 @fshr_zero_shift_guard_inverted(i9 %x, i9 %y, i9 %sh) { 674; CHECK-LABEL: @fshr_zero_shift_guard_inverted( 675; CHECK-NEXT: ret i9 [[Y:%.*]] 676; 677 %c = icmp eq i9 %sh, 0 678 %f = call i9 @llvm.fshr.i9(i9 %x, i9 %y, i9 %sh) 679 %s = select i1 %c, i9 %f, i9 %y 680 ret i9 %s 681} 682 683; When the shift amount is 0, fshr returns its 2nd parameter (y), so everything is deleted. 684 685define i9 @fshr_zero_shift_guard_inverted_swapped(i9 %x, i9 %y, i9 %sh) { 686; CHECK-LABEL: @fshr_zero_shift_guard_inverted_swapped( 687; CHECK-NEXT: ret i9 [[Y:%.*]] 688; 689 %c = icmp ne i9 %sh, 0 690 %f = call i9 @llvm.fshr.i9(i9 %x, i9 %y, i9 %sh) 691 %s = select i1 %c, i9 %y, i9 %f 692 ret i9 %s 693} 694 695; When the shift amount is 0, fshl returns its 1st parameter (x), so the guard is not needed. 696 697define i8 @rotl_zero_shift_guard(i8 %x, i8 %sh) { 698; CHECK-LABEL: @rotl_zero_shift_guard( 699; CHECK-NEXT: [[F:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[SH:%.*]]) 700; CHECK-NEXT: ret i8 [[F]] 701; 702 %c = icmp eq i8 %sh, 0 703 %f = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %sh) 704 %s = select i1 %c, i8 %x, i8 %f 705 ret i8 %s 706} 707 708; When the shift amount is 0, fshl returns its 1st parameter (x), so the guard is not needed. 709 710define i8 @rotl_zero_shift_guard_swapped(i8 %x, i8 %sh) { 711; CHECK-LABEL: @rotl_zero_shift_guard_swapped( 712; CHECK-NEXT: [[F:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[SH:%.*]]) 713; CHECK-NEXT: ret i8 [[F]] 714; 715 %c = icmp ne i8 %sh, 0 716 %f = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %sh) 717 %s = select i1 %c, i8 %f, i8 %x 718 ret i8 %s 719} 720 721; When the shift amount is 0, fshl returns its 1st parameter (x), so everything is deleted. 722 723define i8 @rotl_zero_shift_guard_inverted(i8 %x, i8 %sh) { 724; CHECK-LABEL: @rotl_zero_shift_guard_inverted( 725; CHECK-NEXT: ret i8 [[X:%.*]] 726; 727 %c = icmp eq i8 %sh, 0 728 %f = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %sh) 729 %s = select i1 %c, i8 %f, i8 %x 730 ret i8 %s 731} 732 733; When the shift amount is 0, fshl returns its 1st parameter (x), so everything is deleted. 734 735define i8 @rotl_zero_shift_guard_inverted_swapped(i8 %x, i8 %sh) { 736; CHECK-LABEL: @rotl_zero_shift_guard_inverted_swapped( 737; CHECK-NEXT: ret i8 [[X:%.*]] 738; 739 %c = icmp ne i8 %sh, 0 740 %f = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %sh) 741 %s = select i1 %c, i8 %x, i8 %f 742 ret i8 %s 743} 744 745; When the shift amount is 0, fshr returns its 2nd parameter (x), so the guard is not needed. 746 747define i9 @rotr_zero_shift_guard(i9 %x, i9 %sh) { 748; CHECK-LABEL: @rotr_zero_shift_guard( 749; CHECK-NEXT: [[F:%.*]] = call i9 @llvm.fshr.i9(i9 [[X:%.*]], i9 [[X]], i9 [[SH:%.*]]) 750; CHECK-NEXT: ret i9 [[F]] 751; 752 %c = icmp eq i9 %sh, 0 753 %f = call i9 @llvm.fshr.i9(i9 %x, i9 %x, i9 %sh) 754 %s = select i1 %c, i9 %x, i9 %f 755 ret i9 %s 756} 757 758; When the shift amount is 0, fshr returns its 2nd parameter (x), so the guard is not needed. 759 760define i9 @rotr_zero_shift_guard_swapped(i9 %x, i9 %sh) { 761; CHECK-LABEL: @rotr_zero_shift_guard_swapped( 762; CHECK-NEXT: [[F:%.*]] = call i9 @llvm.fshr.i9(i9 [[X:%.*]], i9 [[X]], i9 [[SH:%.*]]) 763; CHECK-NEXT: ret i9 [[F]] 764; 765 %c = icmp ne i9 %sh, 0 766 %f = call i9 @llvm.fshr.i9(i9 %x, i9 %x, i9 %sh) 767 %s = select i1 %c, i9 %f, i9 %x 768 ret i9 %s 769} 770 771; When the shift amount is 0, fshr returns its 2nd parameter (x), so everything is deleted. 772 773define i9 @rotr_zero_shift_guard_inverted(i9 %x, i9 %sh) { 774; CHECK-LABEL: @rotr_zero_shift_guard_inverted( 775; CHECK-NEXT: ret i9 [[X:%.*]] 776; 777 %c = icmp eq i9 %sh, 0 778 %f = call i9 @llvm.fshr.i9(i9 %x, i9 %x, i9 %sh) 779 %s = select i1 %c, i9 %f, i9 %x 780 ret i9 %s 781} 782 783; When the shift amount is 0, fshr returns its 2nd parameter (x), so everything is deleted. 784 785define i9 @rotr_zero_shift_guard_inverted_swapped(i9 %x, i9 %sh) { 786; CHECK-LABEL: @rotr_zero_shift_guard_inverted_swapped( 787; CHECK-NEXT: ret i9 [[X:%.*]] 788; 789 %c = icmp ne i9 %sh, 0 790 %f = call i9 @llvm.fshr.i9(i9 %x, i9 %x, i9 %sh) 791 %s = select i1 %c, i9 %x, i9 %f 792 ret i9 %s 793} 794 795; Negative test - make sure we're matching the correct parameter of fshl. 796 797define i8 @fshl_zero_shift_guard_wrong_select_op(i8 %x, i8 %y, i8 %sh) { 798; CHECK-LABEL: @fshl_zero_shift_guard_wrong_select_op( 799; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[SH:%.*]], 0 800; CHECK-NEXT: [[F:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[SH]]) 801; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 [[Y]], i8 [[F]] 802; CHECK-NEXT: ret i8 [[S]] 803; 804 %c = icmp eq i8 %sh, 0 805 %f = call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 %sh) 806 %s = select i1 %c, i8 %y, i8 %f 807 ret i8 %s 808} 809 810; Vector types work too. 811 812define <2 x i8> @rotr_zero_shift_guard_splat(<2 x i8> %x, <2 x i8> %sh) { 813; CHECK-LABEL: @rotr_zero_shift_guard_splat( 814; CHECK-NEXT: [[F:%.*]] = call <2 x i8> @llvm.fshr.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[X]], <2 x i8> [[SH:%.*]]) 815; CHECK-NEXT: ret <2 x i8> [[F]] 816; 817 %c = icmp eq <2 x i8> %sh, zeroinitializer 818 %f = call <2 x i8> @llvm.fshr.v2i8(<2 x i8> %x, <2 x i8> %x, <2 x i8> %sh) 819 %s = select <2 x i1> %c, <2 x i8> %x, <2 x i8> %f 820 ret <2 x i8> %s 821} 822 823; If first two operands of funnel shift are undef, the result is undef 824 825define i8 @fshl_ops_undef(i8 %shamt) { 826; CHECK-LABEL: @fshl_ops_undef( 827; CHECK-NEXT: ret i8 undef 828; 829 %r = call i8 @llvm.fshl.i8(i8 undef, i8 undef, i8 %shamt) 830 ret i8 %r 831} 832 833define i9 @fshr_ops_undef(i9 %shamt) { 834; CHECK-LABEL: @fshr_ops_undef( 835; CHECK-NEXT: ret i9 undef 836; 837 %r = call i9 @llvm.fshr.i9(i9 undef, i9 undef, i9 %shamt) 838 ret i9 %r 839} 840 841; If shift amount is undef, treat it as zero, returning operand 0 or 1 842 843define i8 @fshl_shift_undef(i8 %x, i8 %y) { 844; CHECK-LABEL: @fshl_shift_undef( 845; CHECK-NEXT: ret i8 [[X:%.*]] 846; 847 %r = call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 undef) 848 ret i8 %r 849} 850 851define i9 @fshr_shift_undef(i9 %x, i9 %y) { 852; CHECK-LABEL: @fshr_shift_undef( 853; CHECK-NEXT: ret i9 [[Y:%.*]] 854; 855 %r = call i9 @llvm.fshr.i9(i9 %x, i9 %y, i9 undef) 856 ret i9 %r 857} 858 859; If one of operands is poison, the result is poison 860; TODO: these should be poison 861define i8 @fshl_ops_poison(i8 %b, i8 %shamt) { 862; CHECK-LABEL: @fshl_ops_poison( 863; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.fshl.i8(i8 poison, i8 [[B:%.*]], i8 [[SHAMT:%.*]]) 864; CHECK-NEXT: ret i8 [[R]] 865; 866 %r = call i8 @llvm.fshl.i8(i8 poison, i8 %b, i8 %shamt) 867 ret i8 %r 868} 869 870define i8 @fshl_ops_poison2(i8 %shamt) { 871; CHECK-LABEL: @fshl_ops_poison2( 872; CHECK-NEXT: ret i8 undef 873; 874 %r = call i8 @llvm.fshl.i8(i8 poison, i8 undef, i8 %shamt) 875 ret i8 %r 876} 877 878define i8 @fshl_ops_poison3(i8 %a, i8 %shamt) { 879; CHECK-LABEL: @fshl_ops_poison3( 880; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[A:%.*]], i8 poison, i8 [[SHAMT:%.*]]) 881; CHECK-NEXT: ret i8 [[R]] 882; 883 %r = call i8 @llvm.fshl.i8(i8 %a, i8 poison, i8 %shamt) 884 ret i8 %r 885} 886 887define i8 @fshl_ops_poison4(i8 %shamt) { 888; CHECK-LABEL: @fshl_ops_poison4( 889; CHECK-NEXT: ret i8 undef 890; 891 %r = call i8 @llvm.fshl.i8(i8 undef, i8 poison, i8 %shamt) 892 ret i8 %r 893} 894 895define i8 @fshl_ops_poison5(i8 %a, i8 %b) { 896; CHECK-LABEL: @fshl_ops_poison5( 897; CHECK-NEXT: ret i8 [[A:%.*]] 898; 899 %r = call i8 @llvm.fshl.i8(i8 %a, i8 %b, i8 poison) 900 ret i8 %r 901} 902 903define i8 @fshl_ops_poison6() { 904; CHECK-LABEL: @fshl_ops_poison6( 905; CHECK-NEXT: ret i8 undef 906; 907 %r = call i8 @llvm.fshl.i8(i8 undef, i8 undef, i8 poison) 908 ret i8 %r 909} 910 911define i9 @fshr_ops_poison(i9 %b, i9 %shamt) { 912; CHECK-LABEL: @fshr_ops_poison( 913; CHECK-NEXT: [[R:%.*]] = call i9 @llvm.fshr.i9(i9 poison, i9 [[B:%.*]], i9 [[SHAMT:%.*]]) 914; CHECK-NEXT: ret i9 [[R]] 915; 916 %r = call i9 @llvm.fshr.i9(i9 poison, i9 %b, i9 %shamt) 917 ret i9 %r 918} 919 920define i9 @fshr_ops_poison2(i9 %shamt) { 921; CHECK-LABEL: @fshr_ops_poison2( 922; CHECK-NEXT: ret i9 undef 923; 924 %r = call i9 @llvm.fshr.i9(i9 poison, i9 undef, i9 %shamt) 925 ret i9 %r 926} 927 928define i9 @fshr_ops_poison3(i9 %a, i9 %shamt) { 929; CHECK-LABEL: @fshr_ops_poison3( 930; CHECK-NEXT: [[R:%.*]] = call i9 @llvm.fshr.i9(i9 [[A:%.*]], i9 poison, i9 [[SHAMT:%.*]]) 931; CHECK-NEXT: ret i9 [[R]] 932; 933 %r = call i9 @llvm.fshr.i9(i9 %a, i9 poison, i9 %shamt) 934 ret i9 %r 935} 936 937define i9 @fshr_ops_poison4(i9 %shamt) { 938; CHECK-LABEL: @fshr_ops_poison4( 939; CHECK-NEXT: ret i9 undef 940; 941 %r = call i9 @llvm.fshr.i9(i9 undef, i9 poison, i9 %shamt) 942 ret i9 %r 943} 944 945define i9 @fshr_ops_poison5(i9 %a, i9 %b) { 946; CHECK-LABEL: @fshr_ops_poison5( 947; CHECK-NEXT: ret i9 [[B:%.*]] 948; 949 %r = call i9 @llvm.fshr.i9(i9 %a, i9 %b, i9 poison) 950 ret i9 %r 951} 952 953define i9 @fshr_ops_poison6() { 954; CHECK-LABEL: @fshr_ops_poison6( 955; CHECK-NEXT: ret i9 undef 956; 957 %r = call i9 @llvm.fshr.i9(i9 undef, i9 undef, i9 poison) 958 ret i9 %r 959} 960 961declare double @llvm.fma.f64(double,double,double) 962declare double @llvm.fmuladd.f64(double,double,double) 963 964define double @fma_undef_op0(double %x, double %y) { 965; CHECK-LABEL: @fma_undef_op0( 966; CHECK-NEXT: ret double 0x7FF8000000000000 967; 968 %r = call double @llvm.fma.f64(double undef, double %x, double %y) 969 ret double %r 970} 971 972define double @fma_poison_op0(double %x, double %y) { 973; CHECK-LABEL: @fma_poison_op0( 974; CHECK-NEXT: ret double poison 975; 976 %r = call double @llvm.fma.f64(double poison, double %x, double %y) 977 ret double %r 978} 979 980define double @fma_undef_op1(double %x, double %y) { 981; CHECK-LABEL: @fma_undef_op1( 982; CHECK-NEXT: ret double 0x7FF8000000000000 983; 984 %r = call double @llvm.fma.f64(double %x, double undef, double %y) 985 ret double %r 986} 987 988define double @fma_poison_op1(double %x, double %y) { 989; CHECK-LABEL: @fma_poison_op1( 990; CHECK-NEXT: ret double poison 991; 992 %r = call double @llvm.fma.f64(double %x, double poison, double %y) 993 ret double %r 994} 995 996define double @fma_undef_op2(double %x, double %y) { 997; CHECK-LABEL: @fma_undef_op2( 998; CHECK-NEXT: ret double 0x7FF8000000000000 999; 1000 %r = call double @llvm.fma.f64(double %x, double %y, double undef) 1001 ret double %r 1002} 1003 1004define double @fma_poison_op2(double %x, double %y) { 1005; CHECK-LABEL: @fma_poison_op2( 1006; CHECK-NEXT: ret double poison 1007; 1008 %r = call double @llvm.fma.f64(double %x, double %y, double poison) 1009 ret double %r 1010} 1011 1012define double @fmuladd_undef_op0(double %x, double %y) { 1013; CHECK-LABEL: @fmuladd_undef_op0( 1014; CHECK-NEXT: ret double 0x7FF8000000000000 1015; 1016 %r = call double @llvm.fmuladd.f64(double undef, double %x, double %y) 1017 ret double %r 1018} 1019 1020define double @fmuladd_poison_op0(double %x, double %y) { 1021; CHECK-LABEL: @fmuladd_poison_op0( 1022; CHECK-NEXT: ret double poison 1023; 1024 %r = call double @llvm.fmuladd.f64(double poison, double %x, double %y) 1025 ret double %r 1026} 1027 1028define double @fmuladd_undef_op1(double %x, double %y) { 1029; CHECK-LABEL: @fmuladd_undef_op1( 1030; CHECK-NEXT: ret double 0x7FF8000000000000 1031; 1032 %r = call double @llvm.fmuladd.f64(double %x, double undef, double %y) 1033 ret double %r 1034} 1035 1036define double @fmuladd_poison_op1(double %x, double %y) { 1037; CHECK-LABEL: @fmuladd_poison_op1( 1038; CHECK-NEXT: ret double poison 1039; 1040 %r = call double @llvm.fmuladd.f64(double %x, double poison, double %y) 1041 ret double %r 1042} 1043 1044define double @fmuladd_undef_op2(double %x, double %y) { 1045; CHECK-LABEL: @fmuladd_undef_op2( 1046; CHECK-NEXT: ret double 0x7FF8000000000000 1047; 1048 %r = call double @llvm.fmuladd.f64(double %x, double %y, double undef) 1049 ret double %r 1050} 1051 1052define double @fmuladd_poison_op2(double %x, double %y) { 1053; CHECK-LABEL: @fmuladd_poison_op2( 1054; CHECK-NEXT: ret double poison 1055; 1056 %r = call double @llvm.fmuladd.f64(double %x, double %y, double poison) 1057 ret double %r 1058} 1059 1060define double @fma_nan_op0(double %x, double %y) { 1061; CHECK-LABEL: @fma_nan_op0( 1062; CHECK-NEXT: ret double 0x7FF8000000000000 1063; 1064 %r = call double @llvm.fma.f64(double 0x7ff8000000000000, double %x, double %y) 1065 ret double %r 1066} 1067 1068define double @fma_nan_op1(double %x, double %y) { 1069; CHECK-LABEL: @fma_nan_op1( 1070; CHECK-NEXT: ret double 0x7FF8000000000001 1071; 1072 %r = call double @llvm.fma.f64(double %x, double 0x7ff8000000000001, double %y) 1073 ret double %r 1074} 1075 1076define double @fma_nan_op2(double %x, double %y) { 1077; CHECK-LABEL: @fma_nan_op2( 1078; CHECK-NEXT: ret double 0x7FF8000000000002 1079; 1080 %r = call double @llvm.fma.f64(double %x, double %y, double 0x7ff8000000000002) 1081 ret double %r 1082} 1083 1084define double @fmuladd_nan_op0_op1(double %x) { 1085; CHECK-LABEL: @fmuladd_nan_op0_op1( 1086; CHECK-NEXT: ret double 0x7FF8000000001234 1087; 1088 %r = call double @llvm.fmuladd.f64(double 0x7ff8000000001234, double 0x7ff800000000dead, double %x) 1089 ret double %r 1090} 1091 1092define double @fmuladd_nan_op0_op2(double %x) { 1093; CHECK-LABEL: @fmuladd_nan_op0_op2( 1094; CHECK-NEXT: ret double 0x7FF8000000005678 1095; 1096 %r = call double @llvm.fmuladd.f64(double 0x7ff8000000005678, double %x, double 0x7ff800000000dead) 1097 ret double %r 1098} 1099 1100define double @fmuladd_nan_op1_op2(double %x) { 1101; CHECK-LABEL: @fmuladd_nan_op1_op2( 1102; CHECK-NEXT: ret double 0x7FF80000AAAAAAAA 1103; 1104 %r = call double @llvm.fmuladd.f64(double %x, double 0x7ff80000aaaaaaaa, double 0x7ff800000000dead) 1105 ret double %r 1106} 1107 1108define double @fma_nan_multiplicand_inf_zero(double %x) { 1109; CHECK-LABEL: @fma_nan_multiplicand_inf_zero( 1110; CHECK-NEXT: [[R:%.*]] = call double @llvm.fma.f64(double 0x7FF0000000000000, double 0.000000e+00, double [[X:%.*]]) 1111; CHECK-NEXT: ret double [[R]] 1112; 1113 %r = call double @llvm.fma.f64(double 0x7ff0000000000000, double 0.0, double %x) 1114 ret double %r 1115} 1116 1117define double @fma_nan_multiplicand_zero_inf(double %x) { 1118; CHECK-LABEL: @fma_nan_multiplicand_zero_inf( 1119; CHECK-NEXT: [[R:%.*]] = call double @llvm.fma.f64(double 0.000000e+00, double 0x7FF0000000000000, double [[X:%.*]]) 1120; CHECK-NEXT: ret double [[R]] 1121; 1122 %r = call double @llvm.fma.f64(double 0.0, double 0x7ff0000000000000, double %x) 1123 ret double %r 1124} 1125 1126define double @fma_nan_addend_inf_neginf(double %x, i32 %y) { 1127; CHECK-LABEL: @fma_nan_addend_inf_neginf( 1128; CHECK-NEXT: [[NOTNAN:%.*]] = uitofp i32 [[Y:%.*]] to double 1129; CHECK-NEXT: [[R:%.*]] = call double @llvm.fma.f64(double 0x7FF0000000000000, double [[NOTNAN]], double 0xFFF0000000000000) 1130; CHECK-NEXT: ret double [[R]] 1131; 1132 %notnan = uitofp i32 %y to double 1133 %r = call double @llvm.fma.f64(double 0x7ff0000000000000, double %notnan, double 0xfff0000000000000) 1134 ret double %r 1135} 1136 1137define double @fma_nan_addend_neginf_inf(double %x, i1 %y) { 1138; CHECK-LABEL: @fma_nan_addend_neginf_inf( 1139; CHECK-NEXT: [[NOTNAN:%.*]] = select i1 [[Y:%.*]], double 4.200000e+01, double -1.000000e-01 1140; CHECK-NEXT: [[R:%.*]] = call double @llvm.fma.f64(double [[NOTNAN]], double 0xFFF0000000000000, double 0x7FF0000000000000) 1141; CHECK-NEXT: ret double [[R]] 1142; 1143 %notnan = select i1 %y, double 42.0, double -0.1 1144 %r = call double @llvm.fma.f64(double %notnan, double 0xfff0000000000000, double 0x7ff0000000000000) 1145 ret double %r 1146} 1147 1148define double @fmuladd_nan_multiplicand_neginf_zero(double %x) { 1149; CHECK-LABEL: @fmuladd_nan_multiplicand_neginf_zero( 1150; CHECK-NEXT: [[R:%.*]] = call double @llvm.fmuladd.f64(double 0xFFF0000000000000, double 0.000000e+00, double [[X:%.*]]) 1151; CHECK-NEXT: ret double [[R]] 1152; 1153 %r = call double @llvm.fmuladd.f64(double 0xfff0000000000000, double 0.0, double %x) 1154 ret double %r 1155} 1156 1157define double @fmuladd_nan_multiplicand_negzero_inf(double %x) { 1158; CHECK-LABEL: @fmuladd_nan_multiplicand_negzero_inf( 1159; CHECK-NEXT: [[R:%.*]] = call double @llvm.fmuladd.f64(double -0.000000e+00, double 0x7FF0000000000000, double [[X:%.*]]) 1160; CHECK-NEXT: ret double [[R]] 1161; 1162 %r = call double @llvm.fmuladd.f64(double -0.0, double 0x7ff0000000000000, double %x) 1163 ret double %r 1164} 1165 1166define double @fmuladd_nan_addend_inf_neginf(double %x, i32 %y) { 1167; CHECK-LABEL: @fmuladd_nan_addend_inf_neginf( 1168; CHECK-NEXT: [[NOTNAN:%.*]] = sitofp i32 [[Y:%.*]] to double 1169; CHECK-NEXT: [[R:%.*]] = call double @llvm.fmuladd.f64(double 0x7FF0000000000000, double [[NOTNAN]], double 0xFFF0000000000000) 1170; CHECK-NEXT: ret double [[R]] 1171; 1172 %notnan = sitofp i32 %y to double 1173 %r = call double @llvm.fmuladd.f64(double 0x7ff0000000000000, double %notnan, double 0xfff0000000000000) 1174 ret double %r 1175} 1176 1177define double @fmuladd_nan_addend_neginf_inf(double %x, i1 %y) { 1178; CHECK-LABEL: @fmuladd_nan_addend_neginf_inf( 1179; CHECK-NEXT: [[NOTNAN:%.*]] = select i1 [[Y:%.*]], double 4.200000e+01, double -1.000000e-01 1180; CHECK-NEXT: [[R:%.*]] = call double @llvm.fmuladd.f64(double [[NOTNAN]], double 0xFFF0000000000000, double 0x7FF0000000000000) 1181; CHECK-NEXT: ret double [[R]] 1182; 1183 %notnan = select i1 %y, double 42.0, double -0.1 1184 %r = call double @llvm.fmuladd.f64(double %notnan, double 0xfff0000000000000, double 0x7ff0000000000000) 1185 ret double %r 1186} 1187 1188declare float @llvm.copysign.f32(float, float) 1189declare <2 x double> @llvm.copysign.v2f64(<2 x double>, <2 x double>) 1190 1191define float @copysign_same_operand(float %x) { 1192; CHECK-LABEL: @copysign_same_operand( 1193; CHECK-NEXT: ret float [[X:%.*]] 1194; 1195 %r = call float @llvm.copysign.f32(float %x, float %x) 1196 ret float %r 1197} 1198 1199define <2 x double> @copysign_same_operand_vec(<2 x double> %x) { 1200; CHECK-LABEL: @copysign_same_operand_vec( 1201; CHECK-NEXT: ret <2 x double> [[X:%.*]] 1202; 1203 %r = call <2 x double> @llvm.copysign.v2f64(<2 x double> %x, <2 x double> %x) 1204 ret <2 x double> %r 1205} 1206 1207define float @negated_sign_arg(float %x) { 1208; CHECK-LABEL: @negated_sign_arg( 1209; CHECK-NEXT: [[NEGX:%.*]] = fsub ninf float -0.000000e+00, [[X:%.*]] 1210; CHECK-NEXT: ret float [[NEGX]] 1211; 1212 %negx = fsub ninf float -0.0, %x 1213 %r = call arcp float @llvm.copysign.f32(float %x, float %negx) 1214 ret float %r 1215} 1216 1217define <2 x double> @negated_sign_arg_vec(<2 x double> %x) { 1218; CHECK-LABEL: @negated_sign_arg_vec( 1219; CHECK-NEXT: [[NEGX:%.*]] = fneg afn <2 x double> [[X:%.*]] 1220; CHECK-NEXT: ret <2 x double> [[NEGX]] 1221; 1222 %negx = fneg afn <2 x double> %x 1223 %r = call arcp <2 x double> @llvm.copysign.v2f64(<2 x double> %x, <2 x double> %negx) 1224 ret <2 x double> %r 1225} 1226 1227define float @negated_mag_arg(float %x) { 1228; CHECK-LABEL: @negated_mag_arg( 1229; CHECK-NEXT: ret float [[X:%.*]] 1230; 1231 %negx = fneg nnan float %x 1232 %r = call ninf float @llvm.copysign.f32(float %negx, float %x) 1233 ret float %r 1234} 1235 1236define <2 x double> @negated_mag_arg_vec(<2 x double> %x) { 1237; CHECK-LABEL: @negated_mag_arg_vec( 1238; CHECK-NEXT: ret <2 x double> [[X:%.*]] 1239; 1240 %negx = fneg afn <2 x double> %x 1241 %r = call arcp <2 x double> @llvm.copysign.v2f64(<2 x double> %negx, <2 x double> %x) 1242 ret <2 x double> %r 1243} 1244 1245; We handle the "returned" attribute only in InstCombine, because the fact 1246; that this simplification may replace one call with another may cause issues 1247; for call graph passes. 1248 1249declare i32 @passthru_i32(i32 returned) 1250declare i8* @passthru_p8(i8* returned) 1251 1252define i32 @returned_const_int_arg() { 1253; CHECK-LABEL: @returned_const_int_arg( 1254; CHECK-NEXT: [[X:%.*]] = call i32 @passthru_i32(i32 42) 1255; CHECK-NEXT: ret i32 [[X]] 1256; 1257 %x = call i32 @passthru_i32(i32 42) 1258 ret i32 %x 1259} 1260 1261define i8* @returned_const_ptr_arg() { 1262; CHECK-LABEL: @returned_const_ptr_arg( 1263; CHECK-NEXT: [[X:%.*]] = call i8* @passthru_p8(i8* null) 1264; CHECK-NEXT: ret i8* [[X]] 1265; 1266 %x = call i8* @passthru_p8(i8* null) 1267 ret i8* %x 1268} 1269 1270define i32 @returned_var_arg(i32 %arg) { 1271; CHECK-LABEL: @returned_var_arg( 1272; CHECK-NEXT: [[X:%.*]] = call i32 @passthru_i32(i32 [[ARG:%.*]]) 1273; CHECK-NEXT: ret i32 [[X]] 1274; 1275 %x = call i32 @passthru_i32(i32 %arg) 1276 ret i32 %x 1277} 1278 1279define i32 @returned_const_int_arg_musttail(i32 %arg) { 1280; CHECK-LABEL: @returned_const_int_arg_musttail( 1281; CHECK-NEXT: [[X:%.*]] = musttail call i32 @passthru_i32(i32 42) 1282; CHECK-NEXT: ret i32 [[X]] 1283; 1284 %x = musttail call i32 @passthru_i32(i32 42) 1285 ret i32 %x 1286} 1287 1288define i32 @returned_var_arg_musttail(i32 %arg) { 1289; CHECK-LABEL: @returned_var_arg_musttail( 1290; CHECK-NEXT: [[X:%.*]] = musttail call i32 @passthru_i32(i32 [[ARG:%.*]]) 1291; CHECK-NEXT: ret i32 [[X]] 1292; 1293 %x = musttail call i32 @passthru_i32(i32 %arg) 1294 ret i32 %x 1295} 1296 1297define i32 @call_undef_musttail() { 1298; CHECK-LABEL: @call_undef_musttail( 1299; CHECK-NEXT: [[X:%.*]] = musttail call i32 undef() 1300; CHECK-NEXT: ret i32 [[X]] 1301; 1302 %x = musttail call i32 undef() 1303 ret i32 %x 1304} 1305 1306; This is not the builtin fmax, so we don't know anything about its behavior. 1307 1308declare float @fmaxf(float, float) 1309 1310define float @nobuiltin_fmax() { 1311; CHECK-LABEL: @nobuiltin_fmax( 1312; CHECK-NEXT: [[M:%.*]] = call float @fmaxf(float 0.000000e+00, float 1.000000e+00) #[[ATTR3:[0-9]+]] 1313; CHECK-NEXT: [[R:%.*]] = call float @llvm.fabs.f32(float [[M]]) 1314; CHECK-NEXT: ret float [[R]] 1315; 1316 %m = call float @fmaxf(float 0.0, float 1.0) #0 1317 %r = call float @llvm.fabs.f32(float %m) 1318 ret float %r 1319} 1320 1321 1322declare i32 @llvm.ctpop.i32(i32) 1323declare <3 x i33> @llvm.ctpop.v3i33(<3 x i33>) 1324declare i1 @llvm.ctpop.i1(i1) 1325 1326define i32 @ctpop_lowbit(i32 %x) { 1327; CHECK-LABEL: @ctpop_lowbit( 1328; CHECK-NEXT: [[B:%.*]] = and i32 [[X:%.*]], 1 1329; CHECK-NEXT: ret i32 [[B]] 1330; 1331 %b = and i32 %x, 1 1332 %r = call i32 @llvm.ctpop.i32(i32 %b) 1333 ret i32 %r 1334} 1335 1336; Negative test - only low bit allowed 1337; This could be reduced by instcombine to and+shift. 1338 1339define i32 @ctpop_pow2(i32 %x) { 1340; CHECK-LABEL: @ctpop_pow2( 1341; CHECK-NEXT: [[B:%.*]] = and i32 [[X:%.*]], 4 1342; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.ctpop.i32(i32 [[B]]) 1343; CHECK-NEXT: ret i32 [[R]] 1344; 1345 %b = and i32 %x, 4 1346 %r = call i32 @llvm.ctpop.i32(i32 %b) 1347 ret i32 %r 1348} 1349 1350define <3 x i33> @ctpop_signbit(<3 x i33> %x) { 1351; CHECK-LABEL: @ctpop_signbit( 1352; CHECK-NEXT: [[B:%.*]] = lshr <3 x i33> [[X:%.*]], <i33 32, i33 32, i33 32> 1353; CHECK-NEXT: ret <3 x i33> [[B]] 1354; 1355 %b = lshr <3 x i33> %x, <i33 32, i33 32, i33 32> 1356 %r = tail call <3 x i33> @llvm.ctpop.v3i33(<3 x i33> %b) 1357 ret <3 x i33> %r 1358} 1359 1360; Negative test - only 1 bit allowed 1361 1362define <3 x i33> @ctpop_notsignbit(<3 x i33> %x) { 1363; CHECK-LABEL: @ctpop_notsignbit( 1364; CHECK-NEXT: [[B:%.*]] = lshr <3 x i33> [[X:%.*]], <i33 31, i33 31, i33 31> 1365; CHECK-NEXT: [[R:%.*]] = tail call <3 x i33> @llvm.ctpop.v3i33(<3 x i33> [[B]]) 1366; CHECK-NEXT: ret <3 x i33> [[R]] 1367; 1368 %b = lshr <3 x i33> %x, <i33 31, i33 31, i33 31> 1369 %r = tail call <3 x i33> @llvm.ctpop.v3i33(<3 x i33> %b) 1370 ret <3 x i33> %r 1371} 1372 1373define i1 @ctpop_bool(i1 %x) { 1374; CHECK-LABEL: @ctpop_bool( 1375; CHECK-NEXT: ret i1 [[X:%.*]] 1376; 1377 %r = tail call i1 @llvm.ctpop.i1(i1 %x) 1378 ret i1 %r 1379} 1380 1381declare i32 @llvm.cttz.i32(i32, i1) 1382declare <3 x i33> @llvm.cttz.v3i33(<3 x i33>, i1) 1383 1384define i32 @cttz_shl1(i32 %x) { 1385; CHECK-LABEL: @cttz_shl1( 1386; CHECK-NEXT: ret i32 [[X:%.*]] 1387; 1388 %s = shl i32 1, %x 1389 %r = call i32 @llvm.cttz.i32(i32 %s, i1 true) 1390 ret i32 %r 1391} 1392 1393define <3 x i33> @cttz_shl1_vec(<3 x i33> %x) { 1394; CHECK-LABEL: @cttz_shl1_vec( 1395; CHECK-NEXT: ret <3 x i33> [[X:%.*]] 1396; 1397 %s = shl <3 x i33> <i33 1, i33 1, i33 undef>, %x 1398 %r = call <3 x i33> @llvm.cttz.v3i33(<3 x i33> %s, i1 false) 1399 ret <3 x i33> %r 1400} 1401 1402; Negative test - this could be generalized in instcombine though. 1403 1404define i32 @cttz_shl_not_low_bit(i32 %x) { 1405; CHECK-LABEL: @cttz_shl_not_low_bit( 1406; CHECK-NEXT: [[S:%.*]] = shl i32 2, [[X:%.*]] 1407; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.cttz.i32(i32 [[S]], i1 true) 1408; CHECK-NEXT: ret i32 [[R]] 1409; 1410 %s = shl i32 2, %x 1411 %r = call i32 @llvm.cttz.i32(i32 %s, i1 true) 1412 ret i32 %r 1413} 1414 1415declare i32 @llvm.ctlz.i32(i32, i1) 1416declare <3 x i33> @llvm.ctlz.v3i33(<3 x i33>, i1) 1417 1418define i32 @ctlz_lshr_sign_bit(i32 %x) { 1419; CHECK-LABEL: @ctlz_lshr_sign_bit( 1420; CHECK-NEXT: ret i32 [[X:%.*]] 1421; 1422 %s = lshr i32 2147483648, %x 1423 %r = call i32 @llvm.ctlz.i32(i32 %s, i1 true) 1424 ret i32 %r 1425} 1426 1427define i32 @ctlz_lshr_negative(i32 %x) { 1428; CHECK-LABEL: @ctlz_lshr_negative( 1429; CHECK-NEXT: ret i32 [[X:%.*]] 1430; 1431 %s = lshr i32 -42, %x 1432 %r = call i32 @llvm.ctlz.i32(i32 %s, i1 true) 1433 ret i32 %r 1434} 1435 1436define <3 x i33> @ctlz_lshr_sign_bit_vec(<3 x i33> %x) { 1437; CHECK-LABEL: @ctlz_lshr_sign_bit_vec( 1438; CHECK-NEXT: ret <3 x i33> [[X:%.*]] 1439; 1440 %s = lshr <3 x i33> <i33 undef, i33 4294967296, i33 4294967296>, %x 1441 %r = call <3 x i33> @llvm.ctlz.v3i33(<3 x i33> %s, i1 false) 1442 ret <3 x i33> %r 1443} 1444 1445; Negative test - this could be generalized in instcombine though. 1446 1447define i32 @ctlz_lshr_not_negative(i32 %x) { 1448; CHECK-LABEL: @ctlz_lshr_not_negative( 1449; CHECK-NEXT: [[S:%.*]] = lshr i32 42, [[X:%.*]] 1450; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.ctlz.i32(i32 [[S]], i1 true) 1451; CHECK-NEXT: ret i32 [[R]] 1452; 1453 %s = lshr i32 42, %x 1454 %r = call i32 @llvm.ctlz.i32(i32 %s, i1 true) 1455 ret i32 %r 1456} 1457 1458define i32 @ctlz_ashr_sign_bit(i32 %x) { 1459; CHECK-LABEL: @ctlz_ashr_sign_bit( 1460; CHECK-NEXT: ret i32 0 1461; 1462 %s = ashr i32 2147483648, %x 1463 %r = call i32 @llvm.ctlz.i32(i32 %s, i1 false) 1464 ret i32 %r 1465} 1466 1467define i32 @ctlz_ashr_negative(i32 %x) { 1468; CHECK-LABEL: @ctlz_ashr_negative( 1469; CHECK-NEXT: ret i32 0 1470; 1471 %s = ashr i32 -42, %x 1472 %r = call i32 @llvm.ctlz.i32(i32 %s, i1 false) 1473 ret i32 %r 1474} 1475 1476define <3 x i33> @ctlz_ashr_sign_bit_vec(<3 x i33> %x) { 1477; CHECK-LABEL: @ctlz_ashr_sign_bit_vec( 1478; CHECK-NEXT: ret <3 x i33> zeroinitializer 1479; 1480 %s = ashr <3 x i33> <i33 4294967296, i33 undef, i33 4294967296>, %x 1481 %r = call <3 x i33> @llvm.ctlz.v3i33(<3 x i33> %s, i1 true) 1482 ret <3 x i33> %r 1483} 1484 1485attributes #0 = { nobuiltin readnone } 1486