diff options
| author | Bjorn Pettersson <bjorn.a.pettersson@ericsson.com> | 2019-10-18 07:42:02 +0000 |
|---|---|---|
| committer | Bjorn Pettersson <bjorn.a.pettersson@ericsson.com> | 2019-10-18 07:42:02 +0000 |
| commit | 6456252dbf67f26f88873e92c0813ebf8a1f96a3 (patch) | |
| tree | 8eb340bc23a1f6478fa961c3c82e2f0b1bd5619f /llvm | |
| parent | 459134064daeef03a762979ab162587f94361cdc (diff) | |
| download | bcm5719-llvm-6456252dbf67f26f88873e92c0813ebf8a1f96a3.tar.gz bcm5719-llvm-6456252dbf67f26f88873e92c0813ebf8a1f96a3.zip | |
[InstCombine] Fix miscompile bug in canEvaluateShuffled
Summary:
Add restrictions in canEvaluateShuffled to prevent that we for example
transform
%0 = insertelement <2 x i16> undef, i16 %a, i32 0
%1 = srem <2 x i16> %0, <i16 2, i16 1>
%2 = shufflevector <2 x i16> %1, <2 x i16> undef, <2 x i32> <i32 undef, i32 0>
into
%1 = insertelement <2 x i16> undef, i16 %a, i32 1
%2 = srem <2 x i16> %1, <i16 undef, i16 2>
as having an undef denominator makes the srem undefined (for all
vector elements).
Fixes: https://bugs.llvm.org/show_bug.cgi?id=43689
Reviewers: spatel, lebedev.ri
Reviewed By: spatel, lebedev.ri
Subscribers: lebedev.ri, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D69038
llvm-svn: 375208
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp | 18 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/shufflevector-div-rem.ll | 31 |
2 files changed, 37 insertions, 12 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index b07aae466a3..13c38caa1e6 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -1061,17 +1061,23 @@ static bool canEvaluateShuffled(Value *V, ArrayRef<int> Mask, if (Depth == 0) return false; switch (I->getOpcode()) { + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::URem: + case Instruction::SRem: + // Propagating an undefined shuffle mask element to integer div/rem is not + // allowed because those opcodes can create immediate undefined behavior + // from an undefined element in an operand. + if (llvm::any_of(Mask, [](int M){ return M == -1; })) + return false; + LLVM_FALLTHROUGH; case Instruction::Add: case Instruction::FAdd: case Instruction::Sub: case Instruction::FSub: case Instruction::Mul: case Instruction::FMul: - case Instruction::UDiv: - case Instruction::SDiv: case Instruction::FDiv: - case Instruction::URem: - case Instruction::SRem: case Instruction::FRem: case Instruction::Shl: case Instruction::LShr: @@ -1092,9 +1098,7 @@ static bool canEvaluateShuffled(Value *V, ArrayRef<int> Mask, case Instruction::FPExt: case Instruction::GetElementPtr: { // Bail out if we would create longer vector ops. We could allow creating - // longer vector ops, but that may result in more expensive codegen. We - // would also need to limit the transform to avoid undefined behavior for - // integer div/rem. + // longer vector ops, but that may result in more expensive codegen. Type *ITy = I->getType(); if (ITy->isVectorTy() && Mask.size() > ITy->getVectorNumElements()) return false; diff --git a/llvm/test/Transforms/InstCombine/shufflevector-div-rem.ll b/llvm/test/Transforms/InstCombine/shufflevector-div-rem.ll index ee63a25653b..8364aab0aa2 100644 --- a/llvm/test/Transforms/InstCombine/shufflevector-div-rem.ll +++ b/llvm/test/Transforms/InstCombine/shufflevector-div-rem.ll @@ -8,7 +8,12 @@ ; extracting the second element in the vector). define i16 @test_srem_orig(i16 %a, i1 %cmp) { ; CHECK-LABEL: @test_srem_orig( -; CHECK-NEXT: ret i16 1 +; CHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x i16> undef, i16 [[A:%.*]], i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = srem <2 x i16> [[SPLATINSERT]], <i16 2, i16 1> +; CHECK-NEXT: [[SPLAT_OP:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> undef, <2 x i32> <i32 undef, i32 0> +; CHECK-NEXT: [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x i16> <i16 undef, i16 1>, <2 x i16> [[SPLAT_OP]] +; CHECK-NEXT: [[T3:%.*]] = extractelement <2 x i16> [[T2]], i32 1 +; CHECK-NEXT: ret i16 [[T3]] ; %splatinsert = insertelement <2 x i16> undef, i16 %a, i32 0 %splat = shufflevector <2 x i16> %splatinsert, <2 x i16> undef, <2 x i32> zeroinitializer @@ -24,7 +29,11 @@ define i16 @test_srem_orig(i16 %a, i1 %cmp) { ; "evaluateInDifferentElementOrder". define <2 x i16> @test_srem(i16 %a, i1 %cmp) { ; CHECK-LABEL: @test_srem( -; CHECK-NEXT: ret <2 x i16> <i16 77, i16 99> +; CHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x i16> undef, i16 [[A:%.*]], i32 0 +; CHECK-NEXT: [[T1:%.*]] = srem <2 x i16> [[SPLATINSERT]], <i16 2, i16 1> +; CHECK-NEXT: [[SPLAT_OP:%.*]] = shufflevector <2 x i16> [[T1]], <2 x i16> undef, <2 x i32> <i32 undef, i32 0> +; CHECK-NEXT: [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x i16> <i16 77, i16 99>, <2 x i16> [[SPLAT_OP]] +; CHECK-NEXT: ret <2 x i16> [[T2]] ; %splatinsert = insertelement <2 x i16> undef, i16 %a, i32 0 %t1 = srem <2 x i16> %splatinsert, <i16 2, i16 1> @@ -35,7 +44,11 @@ define <2 x i16> @test_srem(i16 %a, i1 %cmp) { define <2 x i16> @test_urem(i16 %a, i1 %cmp) { ; CHECK-LABEL: @test_urem( -; CHECK-NEXT: ret <2 x i16> <i16 77, i16 99> +; CHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x i16> undef, i16 [[A:%.*]], i32 0 +; CHECK-NEXT: [[T1:%.*]] = urem <2 x i16> [[SPLATINSERT]], <i16 3, i16 1> +; CHECK-NEXT: [[SPLAT_OP:%.*]] = shufflevector <2 x i16> [[T1]], <2 x i16> undef, <2 x i32> <i32 undef, i32 0> +; CHECK-NEXT: [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x i16> <i16 77, i16 99>, <2 x i16> [[SPLAT_OP]] +; CHECK-NEXT: ret <2 x i16> [[T2]] ; %splatinsert = insertelement <2 x i16> undef, i16 %a, i32 0 %t1 = urem <2 x i16> %splatinsert, <i16 3, i16 1> @@ -46,7 +59,11 @@ define <2 x i16> @test_urem(i16 %a, i1 %cmp) { define <2 x i16> @test_sdiv(i16 %a, i1 %cmp) { ; CHECK-LABEL: @test_sdiv( -; CHECK-NEXT: ret <2 x i16> <i16 77, i16 99> +; CHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x i16> undef, i16 [[A:%.*]], i32 0 +; CHECK-NEXT: [[T1:%.*]] = sdiv <2 x i16> [[SPLATINSERT]], <i16 2, i16 1> +; CHECK-NEXT: [[SPLAT_OP:%.*]] = shufflevector <2 x i16> [[T1]], <2 x i16> undef, <2 x i32> <i32 undef, i32 0> +; CHECK-NEXT: [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x i16> <i16 77, i16 99>, <2 x i16> [[SPLAT_OP]] +; CHECK-NEXT: ret <2 x i16> [[T2]] ; %splatinsert = insertelement <2 x i16> undef, i16 %a, i32 0 %t1 = sdiv <2 x i16> %splatinsert, <i16 2, i16 1> @@ -57,7 +74,11 @@ define <2 x i16> @test_sdiv(i16 %a, i1 %cmp) { define <2 x i16> @test_udiv(i16 %a, i1 %cmp) { ; CHECK-LABEL: @test_udiv( -; CHECK-NEXT: ret <2 x i16> <i16 77, i16 99> +; CHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x i16> undef, i16 [[A:%.*]], i32 0 +; CHECK-NEXT: [[T1:%.*]] = udiv <2 x i16> [[SPLATINSERT]], <i16 3, i16 1> +; CHECK-NEXT: [[SPLAT_OP:%.*]] = shufflevector <2 x i16> [[T1]], <2 x i16> undef, <2 x i32> <i32 undef, i32 0> +; CHECK-NEXT: [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x i16> <i16 77, i16 99>, <2 x i16> [[SPLAT_OP]] +; CHECK-NEXT: ret <2 x i16> [[T2]] ; %splatinsert = insertelement <2 x i16> undef, i16 %a, i32 0 %t1 = udiv <2 x i16> %splatinsert, <i16 3, i16 1> |

