[llvm] [InstCombine] Fold xored one-complemented operand comparisons (PR #69882)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 24 20:00:19 PDT 2023


================
@@ -7117,38 +7117,53 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
     return Res;
 
   {
-    Value *A, *B;
-    // Transform (A & ~B) == 0 --> (A & B) != 0
-    // and       (A & ~B) != 0 --> (A & B) == 0
-    // if A is a power of 2.
-    if (match(Op0, m_And(m_Value(A), m_Not(m_Value(B)))) &&
-        match(Op1, m_Zero()) &&
-        isKnownToBeAPowerOfTwo(A, false, 0, &I) && I.isEquality())
-      return new ICmpInst(I.getInversePredicate(), Builder.CreateAnd(A, B),
+    Value *X, *Y, *Z;
+    // Transform (X & ~Y) == 0 --> (X & Y) != 0
+    // and       (X & ~Y) != 0 --> (X & Y) == 0
+    // if X is a power of 2.
+    if (match(Op0, m_And(m_Value(X), m_Not(m_Value(Y)))) &&
+        match(Op1, m_Zero()) && isKnownToBeAPowerOfTwo(X, false, 0, &I) &&
+        I.isEquality())
+      return new ICmpInst(I.getInversePredicate(), Builder.CreateAnd(X, Y),
                           Op1);
 
+    // Transform (~X ^ Y) s< ~Z  --> (X ^ Y) s> Z,
+    //           (~X ^ Y) s> ~Z  --> (X ^ Y) s< Z,
+    //           (~X ^ Y) s<= ~Z --> (X ^ Y) s>= Z,
+    //           (~X ^ Y) s>= ~Z --> (X ^ Y) s<= Z,
+    //           (~X ^ Y) u< ~Z  --> (X ^ Y) u< Z,
+    //           (~X ^ Y) u> ~Z  --> (X ^ Y) u< Z,
+    //           (~X ^ Y) u<= ~Z --> (X ^ Y) u>= Z,
+    //           (~X ^ Y) u>= ~Z --> (X ^ Y) <= Z,
+    //           (~X ^ Y) == ~Z  --> (X ^ Y) != Z,
+    // and       (~X ^ Y) != ~Z  --> (X ^ Y) == Z,
+    if (match(&I, m_c_ICmp(Pred, m_c_Xor(m_Not(m_Value(X)), m_Value(Y)),
+                           m_Not(m_Value(Z)))))
----------------
dtcxzyw wrote:

```suggestion
    if (match(&I, m_c_ICmp(Pred, m_c_Xor(m_Not(m_Value(X)), m_Value(Y)),
                           m_Not(m_Value(Z)))) && (I.getOperand(0)->hasOneUse() || I.getOperand(1)->hasOneUse()))
```
Please add a test that both operands are multi-use.
```
; Negative tests
define i1 @test_xor1_nofold_multi_use(i8 %x, i8 %y, i8 %z) {
  %xor = xor i8 %x, -1
  call void @use.i8(i8 %xor)
  %xor2 = xor i8 %xor, %y
  %nz = xor i8 %z, -1
  call void @use.i8(i8 %nz)
  %r = icmp slt i8 %xor2, %nz
  ret i1 %r
}
```


https://github.com/llvm/llvm-project/pull/69882


More information about the llvm-commits mailing list