From 2be397a5da55987ea3179ca5cb9410192fa428a5 Mon Sep 17 00:00:00 2001 From: zhongyunde 00443407 Date: Thu, 27 Jun 2024 08:11:28 -0400 Subject: [PATCH 1/2] [InstCombine] Guard noundef for transformation from xor to or disjoint Fix https://github.com/llvm/llvm-project/issues/96857 --- .../InstCombine/InstCombineAndOrXor.cpp | 8 +++-- llvm/test/Transforms/InstCombine/xor.ll | 32 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index d767fa3930e2f..a8547b40eb6b0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -4593,8 +4593,12 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); Value *M; if (match(&I, m_c_Xor(m_c_And(m_Not(m_Value(M)), m_Value()), - m_c_And(m_Deferred(M), m_Value())))) - return BinaryOperator::CreateDisjointOr(Op0, Op1); + m_c_And(m_Deferred(M), m_Value())))) { + if (isGuaranteedNotToBeUndefOrPoison(M)) + return BinaryOperator::CreateDisjointOr(Op0, Op1); + else + return BinaryOperator::CreateOr(Op0, Op1); + } if (Instruction *Xor = visitMaskedMerge(I, Builder)) return Xor; diff --git a/llvm/test/Transforms/InstCombine/xor.ll b/llvm/test/Transforms/InstCombine/xor.ll index 9a59db40ef8b1..2ff95821f4e00 100644 --- a/llvm/test/Transforms/InstCombine/xor.ll +++ b/llvm/test/Transforms/InstCombine/xor.ll @@ -1453,3 +1453,35 @@ define i32 @tryFactorization_xor_ashr_ashr(i32 %a) { %xor = xor i32 %not, %shr1 ret i32 %xor } + +; https://alive2.llvm.org/ce/z/SOxv-e +define i4 @PR96857_xor_with_noundef(i4 %val0, i4 %val1, i4 noundef %val2) { +; CHECK-LABEL: @PR96857_xor_with_noundef( +; CHECK-NEXT: [[VAL4:%.*]] = and i4 [[VAL2:%.*]], [[VAL0:%.*]] +; CHECK-NEXT: [[VAL5:%.*]] = xor i4 [[VAL2]], -1 +; CHECK-NEXT: [[VAL6:%.*]] = and i4 [[VAL5]], [[VAL1:%.*]] +; CHECK-NEXT: [[VAL7:%.*]] = or disjoint i4 [[VAL4]], [[VAL6]] +; CHECK-NEXT: ret i4 [[VAL7]] +; + %val4 = and i4 %val2, %val0 + %val5 = xor i4 %val2, -1 + %val6 = and i4 %val5, %val1 + %val7 = xor i4 %val4, %val6 + ret i4 %val7 +} + +; https://alive2.llvm.org/ce/z/whLTaJ +define i4 @PR96857_xor_without_noundef(i4 %val0, i4 %val1, i4 %val2) { +; CHECK-LABEL: @PR96857_xor_without_noundef( +; CHECK-NEXT: [[VAL4:%.*]] = and i4 [[VAL2:%.*]], [[VAL0:%.*]] +; CHECK-NEXT: [[VAL5:%.*]] = xor i4 [[VAL2]], -1 +; CHECK-NEXT: [[VAL6:%.*]] = and i4 [[VAL5]], [[VAL1:%.*]] +; CHECK-NEXT: [[VAL7:%.*]] = or i4 [[VAL4]], [[VAL6]] +; CHECK-NEXT: ret i4 [[VAL7]] +; + %val4 = and i4 %val2, %val0 + %val5 = xor i4 %val2, -1 + %val6 = and i4 %val5, %val1 + %val7 = xor i4 %val4, %val6 + ret i4 %val7 +} From 99be29427a10ce3c4c65c7b0ca9919d314f42492 Mon Sep 17 00:00:00 2001 From: Zhongyunde Date: Thu, 27 Jun 2024 22:02:33 +0800 Subject: [PATCH 2/2] It is safe with Poison --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index a8547b40eb6b0..1798017f1dfe6 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -4594,7 +4594,7 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) { Value *M; if (match(&I, m_c_Xor(m_c_And(m_Not(m_Value(M)), m_Value()), m_c_And(m_Deferred(M), m_Value())))) { - if (isGuaranteedNotToBeUndefOrPoison(M)) + if (isGuaranteedNotToBeUndef(M)) return BinaryOperator::CreateDisjointOr(Op0, Op1); else return BinaryOperator::CreateOr(Op0, Op1);