[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelPattern.cpp

Chris Lattner lattner at cs.uiuc.edu
Tue Jan 18 22:18:58 PST 2005



Changes in directory llvm/lib/Target/X86:

X86ISelPattern.cpp updated: 1.77 -> 1.78
---
Log message:

Codegen long >> 2 to this:

foo:
        mov %EAX, DWORD PTR [%ESP + 4]
        mov %EDX, DWORD PTR [%ESP + 8]
        shrd %EAX, %EDX, 2
        sar %EDX, 2
        ret

instead of this:

test1:
        mov %ECX, DWORD PTR [%ESP + 4]
        shr %ECX, 2
        mov %EDX, DWORD PTR [%ESP + 8]
        mov %EAX, %EDX
        shl %EAX, 30
        or %EAX, %ECX
        sar %EDX, 2
        ret

and long << 2 to this:

foo:
        mov %EAX, DWORD PTR [%ESP + 4]
        mov %ECX, DWORD PTR [%ESP + 8]
***     mov %EDX, %EAX
        shrd %EDX, %ECX, 30
        shl %EAX, 2
        ret

instead of this:

foo:
        mov %EAX, DWORD PTR [%ESP + 4]
        mov %ECX, %EAX
        shr %ECX, 30
        mov %EDX, DWORD PTR [%ESP + 8]
        shl %EDX, 2
        or %EDX, %ECX
        shl %EAX, 2
        ret

The extra copy (marked ***) can be eliminated when I teach the code generator
that shrd32rri8 is really commutative.



---
Diffs of the changes:  (+85 -1)

Index: llvm/lib/Target/X86/X86ISelPattern.cpp
diff -u llvm/lib/Target/X86/X86ISelPattern.cpp:1.77 llvm/lib/Target/X86/X86ISelPattern.cpp:1.78
--- llvm/lib/Target/X86/X86ISelPattern.cpp:1.77	Tue Jan 18 21:36:30 2005
+++ llvm/lib/Target/X86/X86ISelPattern.cpp	Wed Jan 19 00:18:43 2005
@@ -370,6 +370,7 @@
     void EmitFoldedLoad(SDOperand Op, X86AddressMode &AM);
     bool TryToFoldLoadOpStore(SDNode *Node);
 
+    bool EmitDoubleShift(SDOperand Op1, SDOperand Op2, unsigned DestReg);
     void EmitCMP(SDOperand LHS, SDOperand RHS, bool isOnlyUse);
     bool EmitBranchCC(MachineBasicBlock *Dest, SDOperand Chain, SDOperand Cond);
     void EmitSelectCC(SDOperand Cond, MVT::ValueType SVT,
@@ -1141,6 +1142,84 @@
     assert(0 && "Load emitted more than once!");
 }
 
+// EmitDoubleShift - Pattern match the expression (Op1|Op2), where we know that
+// op1 and op2 are i32 values with one use each (the or).  If we can form a SHLD
+// or SHRD, emit the instruction (generating the value into DestReg) and return
+// true.
+bool ISel::EmitDoubleShift(SDOperand Op1, SDOperand Op2, unsigned DestReg) {
+  if (Op1.getOpcode() == ISD::SHL && Op2.getOpcode() == ISD::SRL) {
+    // good!
+  } else if (Op2.getOpcode() == ISD::SHL && Op1.getOpcode() == ISD::SRL) {
+    std::swap(Op1, Op2);  // Op1 is the SHL now.
+  } else {
+    return false;  // No match
+  }
+
+  SDOperand ShlVal = Op1.getOperand(0);
+  SDOperand ShlAmt = Op1.getOperand(1);
+  SDOperand ShrVal = Op2.getOperand(0);
+  SDOperand ShrAmt = Op2.getOperand(1);
+
+  // Find out if ShrAmt = 32-ShlAmt  or  ShlAmt = 32-ShrAmt.
+  if (ShlAmt.getOpcode() == ISD::SUB && ShlAmt.getOperand(1) == ShrAmt)
+    if (ConstantSDNode *SubCST = dyn_cast<ConstantSDNode>(ShlAmt.getOperand(0)))
+      if (SubCST->getValue() == 32) {
+        // (A >> ShrAmt) | (B << (32-ShrAmt)) ==> SHRD A, B, ShrAmt
+        unsigned AReg, BReg;
+        if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) {
+          AReg = SelectExpr(ShrVal);
+          BReg = SelectExpr(ShlVal);
+        } else {
+          BReg = SelectExpr(ShlVal);
+          AReg = SelectExpr(ShrVal);
+        }
+        unsigned ShAmt = SelectExpr(ShrAmt);
+        BuildMI(BB, X86::MOV8rr, 1, X86::CL).addReg(ShAmt);
+        BuildMI(BB, X86::SHRD32rrCL,2,DestReg).addReg(AReg).addReg(BReg);
+        return true;
+      }
+
+  if (ShrAmt.getOpcode() == ISD::SUB && ShrAmt.getOperand(1) == ShlAmt)
+    if (ConstantSDNode *SubCST = dyn_cast<ConstantSDNode>(ShrAmt.getOperand(0)))
+      if (SubCST->getValue() == 32) {
+        // (A << ShlAmt) | (B >> (32-ShlAmt)) ==> SHLD A, B, ShrAmt
+        unsigned AReg, BReg;
+        if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) {
+          AReg = SelectExpr(ShrVal);
+          BReg = SelectExpr(ShlVal);
+        } else {
+          BReg = SelectExpr(ShlVal);
+          AReg = SelectExpr(ShrVal);
+        }
+        unsigned ShAmt = SelectExpr(ShlAmt);
+        BuildMI(BB, X86::MOV8rr, 1, X86::CL).addReg(ShAmt);
+        BuildMI(BB, X86::SHLD32rrCL,2,DestReg).addReg(AReg).addReg(BReg);
+        return true;
+      }
+
+  if (ConstantSDNode *ShrCst = dyn_cast<ConstantSDNode>(ShrAmt))
+    if (ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(ShlAmt))
+      if (ShrCst->getValue() < 32 && ShlCst->getValue() < 32) {
+        if (ShrCst->getValue() == 32-ShlCst->getValue()) {
+          // (A >> 5) | (B << 27) --> SHRD A, B, 5
+          unsigned AReg, BReg;
+          if (getRegPressure(ShlVal) > getRegPressure(ShrVal)) {
+            AReg = SelectExpr(ShrVal);
+            BReg = SelectExpr(ShlVal);
+          } else {
+            BReg = SelectExpr(ShlVal);
+            AReg = SelectExpr(ShrVal);
+          }
+          BuildMI(BB, X86::SHRD32rri8, 3, DestReg).addReg(AReg).addReg(BReg)
+            .addImm(ShrCst->getValue());
+          return true;
+        }
+      }
+
+
+  return false;
+}
+
 unsigned ISel::SelectExpr(SDOperand N) {
   unsigned Result;
   unsigned Tmp1, Tmp2, Tmp3;
@@ -1658,7 +1737,12 @@
     Op0 = Node->getOperand(0);
     Op1 = Node->getOperand(1);
 
-    if (Node->getOpcode() == ISD::SUB && MVT::isInteger(N.getValueType()))
+    if (Node->getOpcode() == ISD::OR && N.getValueType() == MVT::i32 &&
+        Op0.hasOneUse() && Op1.hasOneUse())          // Match SHLD and SHRD.
+      if (EmitDoubleShift(Op0, Op1, Result))
+        return Result;
+
+    if (Node->getOpcode() == ISD::SUB)
       if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(0)))
         if (CN->isNullValue()) {   // 0 - N -> neg N
           switch (N.getValueType()) {






More information about the llvm-commits mailing list