[llvm] r358805 - [X86] Don't turn (and (shl X, C1), C2) into (shl (and X, (C1 >> C2), C2) if the original AND can represented by MOVZX.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 19 21:38:53 PDT 2019


Author: ctopper
Date: Fri Apr 19 21:38:53 2019
New Revision: 358805

URL: http://llvm.org/viewvc/llvm-project?rev=358805&view=rev
Log:
[X86] Don't turn (and (shl X, C1), C2) into (shl (and X, (C1 >> C2), C2) if the original AND can represented by MOVZX.

The MOVZX doesn't require an immediate to be encoded at all. Though it does use
a 2 byte opcode so its the same size as a 1 byte immediate. But it has a
separate source and dest register so can help avoid copies.

Modified:
    llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
    llvm/trunk/test/CodeGen/X86/narrow-shl-cst.ll

Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=358805&r1=358804&r2=358805&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Fri Apr 19 21:38:53 2019
@@ -3983,10 +3983,11 @@ void X86DAGToDAGISel::Select(SDNode *Nod
     if (!Cst)
       break;
 
+    int64_t Val = Cst->getSExtValue();
+
     // If we have an any_extend feeding the AND, look through it to see if there
     // is a shift behind it. But only if the AND doesn't use the extended bits.
     // FIXME: Generalize this to other ANY_EXTEND than i32 to i64?
-    int64_t Val = Cst->getSExtValue();
     bool FoundAnyExtend = false;
     if (Shift.getOpcode() == ISD::ANY_EXTEND && Shift.hasOneUse() &&
         Shift.getOperand(0).getSimpleValueType() == MVT::i32 &&
@@ -4041,26 +4042,44 @@ void X86DAGToDAGISel::Select(SDNode *Nod
     };
 
     int64_t ShiftedVal;
-    if (CanShrinkImmediate(ShiftedVal)) {
-      SDValue X = Shift.getOperand(0);
-      if (FoundAnyExtend) {
-        SDValue NewX = CurDAG->getNode(ISD::ANY_EXTEND, dl, NVT, X);
-        insertDAGNode(*CurDAG, SDValue(Node, 0), NewX);
-        X = NewX;
-      }
+    if (!CanShrinkImmediate(ShiftedVal))
+      break;
+
+    // Ok, we can reorder to get a smaller immediate.
+
+    // But, its possible the original immediate allowed an AND to become MOVZX.
+    // Doing this late due to avoid the MakedValueIsZero call as late as
+    // possible.
+    if (Opcode == ISD::AND) {
+      // Find the smallest zext this could possibly be.
+      unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
+      ZExtWidth = PowerOf2Ceil(std::max(ZExtWidth, 8U));
+
+      // Figure out which bits need to be zero to achieve that mask.
+      APInt NeededMask = APInt::getLowBitsSet(NVT.getSizeInBits(),
+                                              ZExtWidth);
+      NeededMask &= ~Cst->getAPIntValue();
+
+      if (CurDAG->MaskedValueIsZero(Node->getOperand(0), NeededMask))
+        break;
+    }
 
-      SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT);
-      insertDAGNode(*CurDAG, SDValue(Node, 0), NewCst);
-      SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst);
-      insertDAGNode(*CurDAG, SDValue(Node, 0), NewBinOp);
-      SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp,
-                                       Shift.getOperand(1));
-      ReplaceNode(Node, NewSHL.getNode());
-      SelectCode(NewSHL.getNode());
-      return;
+    SDValue X = Shift.getOperand(0);
+    if (FoundAnyExtend) {
+      SDValue NewX = CurDAG->getNode(ISD::ANY_EXTEND, dl, NVT, X);
+      insertDAGNode(*CurDAG, SDValue(Node, 0), NewX);
+      X = NewX;
     }
 
-    break;
+    SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT);
+    insertDAGNode(*CurDAG, SDValue(Node, 0), NewCst);
+    SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst);
+    insertDAGNode(*CurDAG, SDValue(Node, 0), NewBinOp);
+    SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp,
+                                     Shift.getOperand(1));
+    ReplaceNode(Node, NewSHL.getNode());
+    SelectCode(NewSHL.getNode());
+    return;
   }
   case X86ISD::SMUL:
     // i16/i32/i64 are handled with isel patterns.

Modified: llvm/trunk/test/CodeGen/X86/narrow-shl-cst.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/narrow-shl-cst.ll?rev=358805&r1=358804&r2=358805&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/narrow-shl-cst.ll (original)
+++ llvm/trunk/test/CodeGen/X86/narrow-shl-cst.ll Fri Apr 19 21:38:53 2019
@@ -138,9 +138,8 @@ define i64 @test11(i64 %x) nounwind {
 define i32 @test12(i32 %x, i32* %y) nounwind {
 ; CHECK-LABEL: test12:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl %edi, %eax
-; CHECK-NEXT:    andl $127, %eax
-; CHECK-NEXT:    addl %eax, %eax
+; CHECK-NEXT:    addl %edi, %edi
+; CHECK-NEXT:    movzbl %dil, %eax
 ; CHECK-NEXT:    movl %eax, (%rsi)
 ; CHECK-NEXT:    retq
   %and = shl i32 %x, 1
@@ -152,9 +151,8 @@ define i32 @test12(i32 %x, i32* %y) noun
 define i64 @test13(i64 %x, i64* %y) nounwind {
 ; CHECK-LABEL: test13:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movq %rdi, %rax
-; CHECK-NEXT:    andl $127, %eax
-; CHECK-NEXT:    addq %rax, %rax
+; CHECK-NEXT:    addl %edi, %edi
+; CHECK-NEXT:    movzbl %dil, %eax
 ; CHECK-NEXT:    movq %rax, (%rsi)
 ; CHECK-NEXT:    retq
   %and = shl i64 %x, 1




More information about the llvm-commits mailing list