From fde8eb00e1466cecd0fc6697f8c2ab837c5b7cf3 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sun, 17 May 2020 21:58:55 +0300 Subject: [PATCH] [InstCombine] visitMaskedMerge(): when unfolding, sanitize undef constants (PR45955) We can't leave undef vector element constants as-is, it is a miscompile, so we need to sanitize them. We have two vectors (C and ~C): * We can't replace undef with 0 in both of them * We can't replace undef with 0 in only one of them * We could replace undef with -1 in both of them * We could replace undef with -1 in only one(!) of them * We could replace undef with -1 in one and 0 in another one of them. Therefore, it seems best to go with the last option, since otherwise we'd loose knowledge that C and ~C have no common bits set, which seems more important than preserving partial undef knowledge. Fixes https://bugs.llvm.org/show_bug.cgi?id=45955 --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 3 +++ .../InstCombine/unfold-masked-merge-with-const-mask-vector.ll | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 9bbedb292fb..35dcb739364 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -3049,6 +3049,9 @@ static Instruction *visitMaskedMerge(BinaryOperator &I, Constant *C; if (D->hasOneUse() && match(M, m_Constant(C))) { + // Propagating undef is unsafe. Clamp undef elements to -1. + Type *EltTy = C->getType()->getScalarType(); + C = Constant::replaceUndefsWith(C, ConstantInt::getAllOnesValue(EltTy)); // Unfold. Value *LHS = Builder.CreateAnd(X, C); Value *NotC = Builder.CreateNot(C); diff --git a/llvm/test/Transforms/InstCombine/unfold-masked-merge-with-const-mask-vector.ll b/llvm/test/Transforms/InstCombine/unfold-masked-merge-with-const-mask-vector.ll index f87b52b9743..4f92514afc8 100644 --- a/llvm/test/Transforms/InstCombine/unfold-masked-merge-with-const-mask-vector.ll +++ b/llvm/test/Transforms/InstCombine/unfold-masked-merge-with-const-mask-vector.ll @@ -21,8 +21,8 @@ define <2 x i4> @splat (<2 x i4> %x, <2 x i4> %y) { define <3 x i4> @splat_undef (<3 x i4> %x, <3 x i4> %y) { ; CHECK-LABEL: @splat_undef( -; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[X:%.*]], -; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i4> [[Y:%.*]], +; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i4> [[Y:%.*]], ; CHECK-NEXT: [[R:%.*]] = or <3 x i4> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <3 x i4> [[R]] ; @@ -85,8 +85,8 @@ define <2 x i4> @in_constant_varx_14_nonsplat(<2 x i4> %x, <2 x i4> %mask) { define <3 x i4> @in_constant_varx_14_undef(<3 x i4> %x, <3 x i4> %mask) { ; CHECK-LABEL: @in_constant_varx_14_undef( -; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[X:%.*]], -; CHECK-NEXT: [[R:%.*]] = or <3 x i4> [[TMP1]], +; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = or <3 x i4> [[TMP1]], ; CHECK-NEXT: ret <3 x i4> [[R]] ; %n0 = xor <3 x i4> %x, ; %x @@ -133,7 +133,7 @@ define <2 x i4> @in_constant_14_vary_nonsplat(<2 x i4> %y, <2 x i4> %mask) { define <3 x i4> @in_constant_14_vary_undef(<3 x i4> %y, <3 x i4> %mask) { ; CHECK-LABEL: @in_constant_14_vary_undef( -; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[Y:%.*]], +; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[Y:%.*]], ; CHECK-NEXT: [[R:%.*]] = or <3 x i4> [[TMP1]], ; CHECK-NEXT: ret <3 x i4> [[R]] ; -- 2.11.0