[llvm] [InstCombine] Guard noundef for transformation from xor to or disjoint (PR #96905)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 27 07:02:53 PDT 2024


https://github.com/vfdff updated https://github.com/llvm/llvm-project/pull/96905

>From 2be397a5da55987ea3179ca5cb9410192fa428a5 Mon Sep 17 00:00:00 2001
From: zhongyunde 00443407 <zhongyunde at huawei.com>
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 <zhongyunde at huawei.com>
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);



More information about the llvm-commits mailing list