forked from OSchip/llvm-project
[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
This commit is contained in:
parent
459134064d
commit
6456252dbf
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue