From 7cc0a29b3ffa2d89b4d1c2f8f52b8c393b0d41da Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Tue, 15 Feb 2022 10:17:45 -0500 Subject: [PATCH] [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. --- llvm/lib/Analysis/ConstantFolding.cpp | 10 +++++ .../InstSimplify/ConstProp/saturating-add-sub.ll | 48 +++++++++++----------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index b5169e5..fff46bf 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -2577,6 +2577,11 @@ static Constant *ConstantFoldScalarCall2(StringRef Name, } case Intrinsic::uadd_sat: case Intrinsic::sadd_sat: + // This is the same as for binary ops - poison propagates. + // TODO: Poison handling should be consolidated. + if (isa(Operands[0]) || isa(Operands[1])) + return PoisonValue::get(Ty); + if (!C0 && !C1) return UndefValue::get(Ty); if (!C0 || !C1) @@ -2587,6 +2592,11 @@ static Constant *ConstantFoldScalarCall2(StringRef Name, return ConstantInt::get(Ty, C0->sadd_sat(*C1)); case Intrinsic::usub_sat: case Intrinsic::ssub_sat: + // This is the same as for binary ops - poison propagates. + // TODO: Poison handling should be consolidated. + if (isa(Operands[0]) || isa(Operands[1])) + return PoisonValue::get(Ty); + if (!C0 && !C1) return UndefValue::get(Ty); if (!C0 || !C1) diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/saturating-add-sub.ll b/llvm/test/Transforms/InstSimplify/ConstProp/saturating-add-sub.ll index a6e6373..deeb238 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/saturating-add-sub.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/saturating-add-sub.ll @@ -369,7 +369,7 @@ define <2 x i8> @test_ssub_vector_op1_undef_mix2() { define i8 @test_uadd_scalar_both_poison() { ; CHECK-LABEL: @test_uadd_scalar_both_poison( -; CHECK-NEXT: ret i8 undef +; CHECK-NEXT: ret i8 poison ; %x = call i8 @llvm.uadd.sat.i8(i8 poison, i8 poison) ret i8 %x @@ -377,7 +377,7 @@ define i8 @test_uadd_scalar_both_poison() { define i8 @test_sadd_scalar_both_poison() { ; CHECK-LABEL: @test_sadd_scalar_both_poison( -; CHECK-NEXT: ret i8 undef +; CHECK-NEXT: ret i8 poison ; %x = call i8 @llvm.sadd.sat.i8(i8 poison, i8 poison) ret i8 %x @@ -385,7 +385,7 @@ define i8 @test_sadd_scalar_both_poison() { define i8 @test_usub_scalar_both_poison() { ; CHECK-LABEL: @test_usub_scalar_both_poison( -; CHECK-NEXT: ret i8 undef +; CHECK-NEXT: ret i8 poison ; %x = call i8 @llvm.usub.sat.i8(i8 poison, i8 poison) ret i8 %x @@ -393,7 +393,7 @@ define i8 @test_usub_scalar_both_poison() { define i8 @test_ssub_scalar_both_poison() { ; CHECK-LABEL: @test_ssub_scalar_both_poison( -; CHECK-NEXT: ret i8 undef +; CHECK-NEXT: ret i8 poison ; %x = call i8 @llvm.ssub.sat.i8(i8 poison, i8 poison) ret i8 %x @@ -401,7 +401,7 @@ define i8 @test_ssub_scalar_both_poison() { define i8 @test_uadd_scalar_op2_poison() { ; CHECK-LABEL: @test_uadd_scalar_op2_poison( -; CHECK-NEXT: ret i8 -1 +; CHECK-NEXT: ret i8 poison ; %x = call i8 @llvm.uadd.sat.i8(i8 10, i8 poison) ret i8 %x @@ -409,7 +409,7 @@ define i8 @test_uadd_scalar_op2_poison() { define i8 @test_sadd_scalar_op1_poison() { ; CHECK-LABEL: @test_sadd_scalar_op1_poison( -; CHECK-NEXT: ret i8 -1 +; CHECK-NEXT: ret i8 poison ; %x = call i8 @llvm.sadd.sat.i8(i8 poison, i8 10) ret i8 %x @@ -417,7 +417,7 @@ define i8 @test_sadd_scalar_op1_poison() { define i8 @test_usub_scalar_op2_poison() { ; CHECK-LABEL: @test_usub_scalar_op2_poison( -; CHECK-NEXT: ret i8 0 +; CHECK-NEXT: ret i8 poison ; %x = call i8 @llvm.usub.sat.i8(i8 10, i8 poison) ret i8 %x @@ -425,7 +425,7 @@ define i8 @test_usub_scalar_op2_poison() { define i8 @test_usub_scalar_op1_poison() { ; CHECK-LABEL: @test_usub_scalar_op1_poison( -; CHECK-NEXT: ret i8 0 +; CHECK-NEXT: ret i8 poison ; %x = call i8 @llvm.usub.sat.i8(i8 poison, i8 10) ret i8 %x @@ -433,7 +433,7 @@ define i8 @test_usub_scalar_op1_poison() { define <2 x i8> @test_uadd_vector_both_poison_splat() { ; CHECK-LABEL: @test_uadd_vector_both_poison_splat( -; CHECK-NEXT: ret <2 x i8> undef +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> poison, <2 x i8> poison) ret <2 x i8> %x @@ -441,7 +441,7 @@ define <2 x i8> @test_uadd_vector_both_poison_splat() { define <2 x i8> @test_sadd_vector_both_poison_splat() { ; CHECK-LABEL: @test_sadd_vector_both_poison_splat( -; CHECK-NEXT: ret <2 x i8> undef +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> poison, <2 x i8> poison) ret <2 x i8> %x @@ -449,7 +449,7 @@ define <2 x i8> @test_sadd_vector_both_poison_splat() { define <2 x i8> @test_usub_vector_both_poison_splat() { ; CHECK-LABEL: @test_usub_vector_both_poison_splat( -; CHECK-NEXT: ret <2 x i8> undef +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> poison, <2 x i8> poison) ret <2 x i8> %x @@ -457,7 +457,7 @@ define <2 x i8> @test_usub_vector_both_poison_splat() { define <2 x i8> @test_ssub_vector_both_poison_splat() { ; CHECK-LABEL: @test_ssub_vector_both_poison_splat( -; CHECK-NEXT: ret <2 x i8> undef +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> poison, <2 x i8> poison) ret <2 x i8> %x @@ -465,7 +465,7 @@ define <2 x i8> @test_ssub_vector_both_poison_splat() { define <2 x i8> @test_uadd_vector_op2_poison_splat() { ; CHECK-LABEL: @test_uadd_vector_op2_poison_splat( -; CHECK-NEXT: ret <2 x i8> +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> , <2 x i8> poison) ret <2 x i8> %x @@ -473,7 +473,7 @@ define <2 x i8> @test_uadd_vector_op2_poison_splat() { define <2 x i8> @test_sadd_vector_op1_poison_splat() { ; CHECK-LABEL: @test_sadd_vector_op1_poison_splat( -; CHECK-NEXT: ret <2 x i8> +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> poison, <2 x i8> ) ret <2 x i8> %x @@ -481,7 +481,7 @@ define <2 x i8> @test_sadd_vector_op1_poison_splat() { define <2 x i8> @test_usub_vector_op2_poison_splat() { ; CHECK-LABEL: @test_usub_vector_op2_poison_splat( -; CHECK-NEXT: ret <2 x i8> zeroinitializer +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> , <2 x i8> poison) ret <2 x i8> %x @@ -489,7 +489,7 @@ define <2 x i8> @test_usub_vector_op2_poison_splat() { define <2 x i8> @test_ssub_vector_op1_poison_splat() { ; CHECK-LABEL: @test_ssub_vector_op1_poison_splat( -; CHECK-NEXT: ret <2 x i8> zeroinitializer +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> poison, <2 x i8> ) ret <2 x i8> %x @@ -497,7 +497,7 @@ define <2 x i8> @test_ssub_vector_op1_poison_splat() { define <2 x i8> @test_uadd_vector_op2_poison_mix1() { ; CHECK-LABEL: @test_uadd_vector_op2_poison_mix1( -; CHECK-NEXT: ret <2 x i8> +; CHECK-NEXT: ret <2 x i8> ; %x = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> , <2 x i8> ) ret <2 x i8> %x @@ -505,7 +505,7 @@ define <2 x i8> @test_uadd_vector_op2_poison_mix1() { define <2 x i8> @test_uadd_vector_op2_poison_mix2() { ; CHECK-LABEL: @test_uadd_vector_op2_poison_mix2( -; CHECK-NEXT: ret <2 x i8> +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> , <2 x i8> ) ret <2 x i8> %x @@ -513,7 +513,7 @@ define <2 x i8> @test_uadd_vector_op2_poison_mix2() { define <2 x i8> @test_sadd_vector_op1_poison_mix1() { ; CHECK-LABEL: @test_sadd_vector_op1_poison_mix1( -; CHECK-NEXT: ret <2 x i8> +; CHECK-NEXT: ret <2 x i8> ; %x = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> , <2 x i8> ) ret <2 x i8> %x @@ -521,7 +521,7 @@ define <2 x i8> @test_sadd_vector_op1_poison_mix1() { define <2 x i8> @test_sadd_vector_op1_poison_mix2() { ; CHECK-LABEL: @test_sadd_vector_op1_poison_mix2( -; CHECK-NEXT: ret <2 x i8> +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> , <2 x i8> ) ret <2 x i8> %x @@ -529,7 +529,7 @@ define <2 x i8> @test_sadd_vector_op1_poison_mix2() { define <2 x i8> @test_usub_vector_op2_poison_mix1() { ; CHECK-LABEL: @test_usub_vector_op2_poison_mix1( -; CHECK-NEXT: ret <2 x i8> +; CHECK-NEXT: ret <2 x i8> ; %x = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> , <2 x i8> ) ret <2 x i8> %x @@ -537,7 +537,7 @@ define <2 x i8> @test_usub_vector_op2_poison_mix1() { define <2 x i8> @test_usub_vector_op2_poison_mix2() { ; CHECK-LABEL: @test_usub_vector_op2_poison_mix2( -; CHECK-NEXT: ret <2 x i8> zeroinitializer +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> , <2 x i8> ) ret <2 x i8> %x @@ -545,7 +545,7 @@ define <2 x i8> @test_usub_vector_op2_poison_mix2() { define <2 x i8> @test_ssub_vector_op1_poison_mix1() { ; CHECK-LABEL: @test_ssub_vector_op1_poison_mix1( -; CHECK-NEXT: ret <2 x i8> +; CHECK-NEXT: ret <2 x i8> ; %x = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> , <2 x i8> ) ret <2 x i8> %x @@ -553,7 +553,7 @@ define <2 x i8> @test_ssub_vector_op1_poison_mix1() { define <2 x i8> @test_ssub_vector_op1_poison_mix2() { ; CHECK-LABEL: @test_ssub_vector_op1_poison_mix2( -; CHECK-NEXT: ret <2 x i8> zeroinitializer +; CHECK-NEXT: ret <2 x i8> poison ; %x = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> , <2 x i8> ) ret <2 x i8> %x -- 2.7.4