Skip to content

Commit 7cc0a29

Browse files
committed
[Analysis] propagate poison through add/sub saturate intrinsics
A more general enhancement needs to add tests and make sure that intrinsics that return structs are correct. There are also target-specific intrinsics, and I'm not sure what behavior is expected for those.
1 parent 00218c1 commit 7cc0a29

File tree

2 files changed

+34
-24
lines changed

2 files changed

+34
-24
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2577,6 +2577,11 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
25772577
}
25782578
case Intrinsic::uadd_sat:
25792579
case Intrinsic::sadd_sat:
2580+
// This is the same as for binary ops - poison propagates.
2581+
// TODO: Poison handling should be consolidated.
2582+
if (isa<PoisonValue>(Operands[0]) || isa<PoisonValue>(Operands[1]))
2583+
return PoisonValue::get(Ty);
2584+
25802585
if (!C0 && !C1)
25812586
return UndefValue::get(Ty);
25822587
if (!C0 || !C1)
@@ -2587,6 +2592,11 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
25872592
return ConstantInt::get(Ty, C0->sadd_sat(*C1));
25882593
case Intrinsic::usub_sat:
25892594
case Intrinsic::ssub_sat:
2595+
// This is the same as for binary ops - poison propagates.
2596+
// TODO: Poison handling should be consolidated.
2597+
if (isa<PoisonValue>(Operands[0]) || isa<PoisonValue>(Operands[1]))
2598+
return PoisonValue::get(Ty);
2599+
25902600
if (!C0 && !C1)
25912601
return UndefValue::get(Ty);
25922602
if (!C0 || !C1)

llvm/test/Transforms/InstSimplify/ConstProp/saturating-add-sub.ll

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -369,191 +369,191 @@ define <2 x i8> @test_ssub_vector_op1_undef_mix2() {
369369

370370
define i8 @test_uadd_scalar_both_poison() {
371371
; CHECK-LABEL: @test_uadd_scalar_both_poison(
372-
; CHECK-NEXT: ret i8 undef
372+
; CHECK-NEXT: ret i8 poison
373373
;
374374
%x = call i8 @llvm.uadd.sat.i8(i8 poison, i8 poison)
375375
ret i8 %x
376376
}
377377

378378
define i8 @test_sadd_scalar_both_poison() {
379379
; CHECK-LABEL: @test_sadd_scalar_both_poison(
380-
; CHECK-NEXT: ret i8 undef
380+
; CHECK-NEXT: ret i8 poison
381381
;
382382
%x = call i8 @llvm.sadd.sat.i8(i8 poison, i8 poison)
383383
ret i8 %x
384384
}
385385

386386
define i8 @test_usub_scalar_both_poison() {
387387
; CHECK-LABEL: @test_usub_scalar_both_poison(
388-
; CHECK-NEXT: ret i8 undef
388+
; CHECK-NEXT: ret i8 poison
389389
;
390390
%x = call i8 @llvm.usub.sat.i8(i8 poison, i8 poison)
391391
ret i8 %x
392392
}
393393

394394
define i8 @test_ssub_scalar_both_poison() {
395395
; CHECK-LABEL: @test_ssub_scalar_both_poison(
396-
; CHECK-NEXT: ret i8 undef
396+
; CHECK-NEXT: ret i8 poison
397397
;
398398
%x = call i8 @llvm.ssub.sat.i8(i8 poison, i8 poison)
399399
ret i8 %x
400400
}
401401

402402
define i8 @test_uadd_scalar_op2_poison() {
403403
; CHECK-LABEL: @test_uadd_scalar_op2_poison(
404-
; CHECK-NEXT: ret i8 -1
404+
; CHECK-NEXT: ret i8 poison
405405
;
406406
%x = call i8 @llvm.uadd.sat.i8(i8 10, i8 poison)
407407
ret i8 %x
408408
}
409409

410410
define i8 @test_sadd_scalar_op1_poison() {
411411
; CHECK-LABEL: @test_sadd_scalar_op1_poison(
412-
; CHECK-NEXT: ret i8 -1
412+
; CHECK-NEXT: ret i8 poison
413413
;
414414
%x = call i8 @llvm.sadd.sat.i8(i8 poison, i8 10)
415415
ret i8 %x
416416
}
417417

418418
define i8 @test_usub_scalar_op2_poison() {
419419
; CHECK-LABEL: @test_usub_scalar_op2_poison(
420-
; CHECK-NEXT: ret i8 0
420+
; CHECK-NEXT: ret i8 poison
421421
;
422422
%x = call i8 @llvm.usub.sat.i8(i8 10, i8 poison)
423423
ret i8 %x
424424
}
425425

426426
define i8 @test_usub_scalar_op1_poison() {
427427
; CHECK-LABEL: @test_usub_scalar_op1_poison(
428-
; CHECK-NEXT: ret i8 0
428+
; CHECK-NEXT: ret i8 poison
429429
;
430430
%x = call i8 @llvm.usub.sat.i8(i8 poison, i8 10)
431431
ret i8 %x
432432
}
433433

434434
define <2 x i8> @test_uadd_vector_both_poison_splat() {
435435
; CHECK-LABEL: @test_uadd_vector_both_poison_splat(
436-
; CHECK-NEXT: ret <2 x i8> undef
436+
; CHECK-NEXT: ret <2 x i8> poison
437437
;
438438
%x = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> poison, <2 x i8> poison)
439439
ret <2 x i8> %x
440440
}
441441

442442
define <2 x i8> @test_sadd_vector_both_poison_splat() {
443443
; CHECK-LABEL: @test_sadd_vector_both_poison_splat(
444-
; CHECK-NEXT: ret <2 x i8> undef
444+
; CHECK-NEXT: ret <2 x i8> poison
445445
;
446446
%x = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> poison, <2 x i8> poison)
447447
ret <2 x i8> %x
448448
}
449449

450450
define <2 x i8> @test_usub_vector_both_poison_splat() {
451451
; CHECK-LABEL: @test_usub_vector_both_poison_splat(
452-
; CHECK-NEXT: ret <2 x i8> undef
452+
; CHECK-NEXT: ret <2 x i8> poison
453453
;
454454
%x = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> poison, <2 x i8> poison)
455455
ret <2 x i8> %x
456456
}
457457

458458
define <2 x i8> @test_ssub_vector_both_poison_splat() {
459459
; CHECK-LABEL: @test_ssub_vector_both_poison_splat(
460-
; CHECK-NEXT: ret <2 x i8> undef
460+
; CHECK-NEXT: ret <2 x i8> poison
461461
;
462462
%x = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> poison, <2 x i8> poison)
463463
ret <2 x i8> %x
464464
}
465465

466466
define <2 x i8> @test_uadd_vector_op2_poison_splat() {
467467
; CHECK-LABEL: @test_uadd_vector_op2_poison_splat(
468-
; CHECK-NEXT: ret <2 x i8> <i8 -1, i8 -1>
468+
; CHECK-NEXT: ret <2 x i8> poison
469469
;
470470
%x = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> <i8 10, i8 20>, <2 x i8> poison)
471471
ret <2 x i8> %x
472472
}
473473

474474
define <2 x i8> @test_sadd_vector_op1_poison_splat() {
475475
; CHECK-LABEL: @test_sadd_vector_op1_poison_splat(
476-
; CHECK-NEXT: ret <2 x i8> <i8 -1, i8 -1>
476+
; CHECK-NEXT: ret <2 x i8> poison
477477
;
478478
%x = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> poison, <2 x i8> <i8 10, i8 20>)
479479
ret <2 x i8> %x
480480
}
481481

482482
define <2 x i8> @test_usub_vector_op2_poison_splat() {
483483
; CHECK-LABEL: @test_usub_vector_op2_poison_splat(
484-
; CHECK-NEXT: ret <2 x i8> zeroinitializer
484+
; CHECK-NEXT: ret <2 x i8> poison
485485
;
486486
%x = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> <i8 10, i8 20>, <2 x i8> poison)
487487
ret <2 x i8> %x
488488
}
489489

490490
define <2 x i8> @test_ssub_vector_op1_poison_splat() {
491491
; CHECK-LABEL: @test_ssub_vector_op1_poison_splat(
492-
; CHECK-NEXT: ret <2 x i8> zeroinitializer
492+
; CHECK-NEXT: ret <2 x i8> poison
493493
;
494494
%x = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> poison, <2 x i8> <i8 10, i8 20>)
495495
ret <2 x i8> %x
496496
}
497497

498498
define <2 x i8> @test_uadd_vector_op2_poison_mix1() {
499499
; CHECK-LABEL: @test_uadd_vector_op2_poison_mix1(
500-
; CHECK-NEXT: ret <2 x i8> <i8 30, i8 undef>
500+
; CHECK-NEXT: ret <2 x i8> <i8 30, i8 poison>
501501
;
502502
%x = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> <i8 10, i8 poison>, <2 x i8> <i8 20, i8 poison>)
503503
ret <2 x i8> %x
504504
}
505505

506506
define <2 x i8> @test_uadd_vector_op2_poison_mix2() {
507507
; CHECK-LABEL: @test_uadd_vector_op2_poison_mix2(
508-
; CHECK-NEXT: ret <2 x i8> <i8 -1, i8 -1>
508+
; CHECK-NEXT: ret <2 x i8> poison
509509
;
510510
%x = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> <i8 10, i8 poison>, <2 x i8> <i8 poison, i8 20>)
511511
ret <2 x i8> %x
512512
}
513513

514514
define <2 x i8> @test_sadd_vector_op1_poison_mix1() {
515515
; CHECK-LABEL: @test_sadd_vector_op1_poison_mix1(
516-
; CHECK-NEXT: ret <2 x i8> <i8 undef, i8 30>
516+
; CHECK-NEXT: ret <2 x i8> <i8 poison, i8 30>
517517
;
518518
%x = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> <i8 poison, i8 10>, <2 x i8> <i8 poison, i8 20>)
519519
ret <2 x i8> %x
520520
}
521521

522522
define <2 x i8> @test_sadd_vector_op1_poison_mix2() {
523523
; CHECK-LABEL: @test_sadd_vector_op1_poison_mix2(
524-
; CHECK-NEXT: ret <2 x i8> <i8 -1, i8 -1>
524+
; CHECK-NEXT: ret <2 x i8> poison
525525
;
526526
%x = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> <i8 poison, i8 10>, <2 x i8> <i8 20, i8 poison>)
527527
ret <2 x i8> %x
528528
}
529529

530530
define <2 x i8> @test_usub_vector_op2_poison_mix1() {
531531
; CHECK-LABEL: @test_usub_vector_op2_poison_mix1(
532-
; CHECK-NEXT: ret <2 x i8> <i8 0, i8 undef>
532+
; CHECK-NEXT: ret <2 x i8> <i8 0, i8 poison>
533533
;
534534
%x = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> <i8 10, i8 poison>, <2 x i8> <i8 20, i8 poison>)
535535
ret <2 x i8> %x
536536
}
537537

538538
define <2 x i8> @test_usub_vector_op2_poison_mix2() {
539539
; CHECK-LABEL: @test_usub_vector_op2_poison_mix2(
540-
; CHECK-NEXT: ret <2 x i8> zeroinitializer
540+
; CHECK-NEXT: ret <2 x i8> poison
541541
;
542542
%x = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> <i8 10, i8 poison>, <2 x i8> <i8 poison, i8 20>)
543543
ret <2 x i8> %x
544544
}
545545

546546
define <2 x i8> @test_ssub_vector_op1_poison_mix1() {
547547
; CHECK-LABEL: @test_ssub_vector_op1_poison_mix1(
548-
; CHECK-NEXT: ret <2 x i8> <i8 undef, i8 -10>
548+
; CHECK-NEXT: ret <2 x i8> <i8 poison, i8 -10>
549549
;
550550
%x = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> <i8 poison, i8 10>, <2 x i8> <i8 poison, i8 20>)
551551
ret <2 x i8> %x
552552
}
553553

554554
define <2 x i8> @test_ssub_vector_op1_poison_mix2() {
555555
; CHECK-LABEL: @test_ssub_vector_op1_poison_mix2(
556-
; CHECK-NEXT: ret <2 x i8> zeroinitializer
556+
; CHECK-NEXT: ret <2 x i8> poison
557557
;
558558
%x = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> <i8 poison, i8 10>, <2 x i8> <i8 20, i8 poison>)
559559
ret <2 x i8> %x

0 commit comments

Comments
 (0)