[llvm] add check inversion for x and xor x, -1 (PR #96425)

Zain Jaffal via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 23 03:10:10 PDT 2024


https://github.com/zjaffal created https://github.com/llvm/llvm-project/pull/96425

following https://github.com/llvm/llvm-project/pull/94915#discussion_r1649463570 we can move the check from there inside `isKnownInversion` and use the code for `foldOrOfInversions` to do the simplification

>From 6ff3af12740181a4b6b3f34658dab79ceba64db1 Mon Sep 17 00:00:00 2001
From: Zain Jaffal <zain at jjaffal.com>
Date: Sun, 23 Jun 2024 11:03:35 +0100
Subject: [PATCH] add check inversion for x and xor x, -1

---
 llvm/lib/Analysis/ValueTracking.cpp           |  5 +++++
 .../InstCombine/InstCombineAndOrXor.cpp       | 22 ++++++-------------
 .../test/Transforms/InstCombine/and-or-not.ll |  4 ++--
 3 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 0df061923f625..603ba5dbfa8ad 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8180,6 +8180,11 @@ bool llvm::isKnownNegation(const Value *X, const Value *Y, bool NeedNSW,
 }
 
 bool llvm::isKnownInversion(const Value *X, const Value *Y) {
+
+  // Handle X = xor Y, -1 or Y = xor X, -1
+  if (match(X, m_Not(m_Specific(Y))) || match(Y, m_Not(m_Specific(X))))
+    return true;
+
   // Handle X = icmp pred A, B, Y = icmp pred A, C.
   Value *A, *B, *C;
   ICmpInst::Predicate Pred1, Pred2;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 19a12343748df..41f32fe4e8335 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1840,14 +1840,6 @@ static Instruction *foldOrToXor(BinaryOperator &I,
         match(Op1, m_Not(m_c_Or(m_Specific(A), m_Specific(B)))))
       return BinaryOperator::CreateNot(Builder.CreateAnd(A, B));
 
-  // (A & ~B) | (~A & B) --> A ^ B
-  // (A & ~B) | (B & ~A) --> A ^ B
-  // (~B & A) | (~A & B) --> A ^ B
-  // (~B & A) | (B & ~A) --> A ^ B
-  if (match(Op0, m_c_And(m_Value(A), m_Not(m_Value(B)))) &&
-      match(Op1, m_c_And(m_Not(m_Specific(A)), m_Specific(B))))
-    return BinaryOperator::CreateXor(A, B);
-
   return nullptr;
 }
 
@@ -3426,16 +3418,16 @@ static Value *foldOrOfInversions(BinaryOperator &I,
   assert(I.getOpcode() == Instruction::Or &&
          "Simplification only supports or at the moment.");
 
-  Value *Cmp1, *Cmp2, *Cmp3, *Cmp4;
-  if (!match(I.getOperand(0), m_And(m_Value(Cmp1), m_Value(Cmp2))) ||
-      !match(I.getOperand(1), m_And(m_Value(Cmp3), m_Value(Cmp4))))
+  Value *A, *B, *C, *D;
+  if (!match(I.getOperand(0), m_And(m_Value(A), m_Value(B))) ||
+      !match(I.getOperand(1), m_And(m_Value(C), m_Value(D))))
     return nullptr;
 
   // Check if any two pairs of the and operations are inversions of each other.
-  if (isKnownInversion(Cmp1, Cmp3) && isKnownInversion(Cmp2, Cmp4))
-    return Builder.CreateXor(Cmp1, Cmp4);
-  if (isKnownInversion(Cmp1, Cmp4) && isKnownInversion(Cmp2, Cmp3))
-    return Builder.CreateXor(Cmp1, Cmp3);
+  if (isKnownInversion(A, C) && isKnownInversion(B, D))
+    return Builder.CreateXor(A, D);
+  if (isKnownInversion(A, D) && isKnownInversion(B, C))
+    return Builder.CreateXor(A, C);
 
   return nullptr;
 }
diff --git a/llvm/test/Transforms/InstCombine/and-or-not.ll b/llvm/test/Transforms/InstCombine/and-or-not.ll
index 2e351c30ea1f7..ba5a8c7a78439 100644
--- a/llvm/test/Transforms/InstCombine/and-or-not.ll
+++ b/llvm/test/Transforms/InstCombine/and-or-not.ll
@@ -200,7 +200,7 @@ define i32 @or_to_xor3(float %fa, float %fb) {
 ; CHECK-LABEL: @or_to_xor3(
 ; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
 ; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
-; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[B]], [[A]]
+; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i32 [[OR]]
 ;
   %a = fptosi float %fa to i32
@@ -219,7 +219,7 @@ define i32 @or_to_xor4(float %fa, float %fb) {
 ; CHECK-LABEL: @or_to_xor4(
 ; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
 ; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
-; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[B]], [[A]]
+; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i32 [[OR]]
 ;
   %a = fptosi float %fa to i32



More information about the llvm-commits mailing list