[PATCH] D87465: [TargetLowering] Change SimplifyDemandedBits for XOR

Jay Foad via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 09:21:27 PDT 2020


foad created this revision.
foad added reviewers: RKSimon, craig.topper.
Herald added subscribers: llvm-commits, hiraditya.
Herald added a project: LLVM.
foad requested review of this revision.

Don't simplify XOR to AND whenever we can, because it's not clear
(to me) that it's simpler.

Instead simplify:

  (X | C) ^ C -> X & ~C
  (X & ~C) ^ C -> X | C

These are clearly better because they remove one operation.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87465

Files:
  llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
  llvm/test/CodeGen/X86/2012-08-07-CmpISelBug.ll


Index: llvm/test/CodeGen/X86/2012-08-07-CmpISelBug.ll
===================================================================
--- llvm/test/CodeGen/X86/2012-08-07-CmpISelBug.ll
+++ llvm/test/CodeGen/X86/2012-08-07-CmpISelBug.ll
@@ -10,11 +10,9 @@
 ; CHECK:       ## %bb.0: ## %bb
 ; CHECK-NEXT:    ## kill: def $edi killed $edi def $rdi
 ; CHECK-NEXT:    andl $32, %edi
-; CHECK-NEXT:    leal 13(%rdi), %eax
-; CHECK-NEXT:    xorb $-14, %al
-; CHECK-NEXT:    addb $82, %al
-; CHECK-NEXT:    movzbl %al, %eax
+; CHECK-NEXT:    leal 82(%rdi), %eax
 ; CHECK-NEXT:    testl %esi, %edi
+; CHECK-NEXT:    movzbl %al, %eax
 ; CHECK-NEXT:    movl $1, %ecx
 ; CHECK-NEXT:    cmovnel %eax, %ecx
 ; CHECK-NEXT:    xorb $81, %cl
Index: llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1349,29 +1349,38 @@
       return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::OR, dl, VT, Op0, Op1));
 
     ConstantSDNode* C = isConstOrConstSplat(Op1, DemandedElts);
-    if (C) {
-      // If one side is a constant, and all of the set bits in the constant are
-      // also known set on the other side, turn this into an AND, as we know
-      // the bits will be cleared.
-      //    e.g. (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2
-      // NB: it is okay if more bits are known than are requested
-      if (C->getAPIntValue() == Known2.One) {
-        SDValue ANDC =
-            TLO.DAG.getConstant(~C->getAPIntValue() & DemandedBits, dl, VT);
-        return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::AND, dl, VT, Op0, ANDC));
-      }
+    if (C && (Op0.getOpcode() == ISD::OR || Op0.getOpcode() == ISD::AND)) {
+      ConstantSDNode *C1 = isConstOrConstSplat(Op0.getOperand(1), DemandedElts);
+      if (C1) {
+        // (X | C) ^ C -> X & ~C
+        if (Op0.getOpcode() == ISD::OR &&
+            !((C->getAPIntValue() ^ C1->getAPIntValue()) & DemandedBits)) {
+          SDValue NOTC =
+              TLO.DAG.getConstant(~C->getAPIntValue() & DemandedBits, dl, VT);
+          return TLO.CombineTo(
+              Op, TLO.DAG.getNode(ISD::AND, dl, VT, Op0.getOperand(0), NOTC));
+        }
 
-      // If the RHS is a constant, see if we can change it. Don't alter a -1
-      // constant because that's a 'not' op, and that is better for combining
-      // and codegen.
-      if (!C->isAllOnesValue() &&
-          DemandedBits.isSubsetOf(C->getAPIntValue())) {
-        // We're flipping all demanded bits. Flip the undemanded bits too.
-        SDValue New = TLO.DAG.getNOT(dl, Op0, VT);
-        return TLO.CombineTo(Op, New);
+        // (X & ~C) ^ C -> X | C
+        // TODO do this for the non-constant case too? I.e. (X & Y) ^ Z -> X | Z
+        // when all demanded bits of Y and Z are known to be different
+        if (Op0.getOpcode() == ISD::OR &&
+            DemandedBits.isSubsetOf(C->getAPIntValue() ^ C1->getAPIntValue()))
+          return TLO.CombineTo(
+              Op, TLO.DAG.getNode(ISD::AND, dl, VT, Op0.getOperand(0), Op1));
       }
     }
 
+    // If the RHS is a constant, see if we can change it. Don't alter a -1
+    // constant because that's a 'not' op, and that is better for combining
+    // and codegen.
+    if (C && !C->isAllOnesValue() &&
+        DemandedBits.isSubsetOf(C->getAPIntValue())) {
+      // We're flipping all demanded bits. Flip the undemanded bits too.
+      SDValue New = TLO.DAG.getNOT(dl, Op0, VT);
+      return TLO.CombineTo(Op, New);
+    }
+
     // If we can't turn this into a 'not', try to shrink the constant.
     if (!C || !C->isAllOnesValue())
       if (ShrinkDemandedConstant(Op, DemandedBits, DemandedElts, TLO))


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87465.290999.patch
Type: text/x-patch
Size: 3759 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200910/e57aa28d/attachment.bin>


More information about the llvm-commits mailing list