Cleanups in ROTL/ROTR DAG combiner code

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Cleanups in ROTL/ROTR DAG combiner code

Scott Michel
The attached patch contains:

- Cleanups in the DAGCombiner.cpp ROTL/ROTR combine code, primarily
  helping me to fix 80col violations (benefiting the code as a whole).
 
- Detect sign/zext/any-extended versions of ROTL/ROTR patterns.

- Allow custom lowering for ROTL/ROTR (needed in the CellSPU's case
  for 8-bit rotates, when only 16-bit and 32-bit rotates are actually
  implemented in the instruction set.)


-scooter

Index: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (.../trunk) (revision 2118)
+++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (.../branches/llvm-spu) (revision 2118)
@@ -2683,10 +2683,24 @@
   case ISD::ROTR:
     Tmp1 = LegalizeOp(Node->getOperand(0));   // LHS
     Tmp2 = LegalizeOp(Node->getOperand(1));   // RHS
-    
-    assert(TLI.isOperationLegal(Node->getOpcode(), Node->getValueType(0)) &&
-           "Cannot handle this yet!");
     Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+    switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
+    default:
+      assert(0 && "ROTL/ROTR legalize operation not supported");
+      break;
+    case TargetLowering::Legal:
+      break;
+    case TargetLowering::Custom:
+      Tmp1 = TLI.LowerOperation(Result, DAG);
+      if (Tmp1.Val) Result = Tmp1;
+      break;
+    case TargetLowering::Promote:
+      assert(0 && "Do not know how to promote ROTL/ROTR");
+      break;
+    case TargetLowering::Expand:
+      assert(0 && "Do not know how to expand ROTL/ROTR");
+      break;
+    }
     break;
     
   case ISD::BSWAP:
Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/DAGCombiner.cpp (.../trunk) (revision 2118)
+++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp (.../branches/llvm-spu) (revision 2118)
@@ -1488,23 +1488,24 @@
   }
 
   unsigned OpSizeInBits = MVT::getSizeInBits(VT);
+  SDOperand LHSShiftArg = LHSShift.getOperand(0);
+  SDOperand LHSShiftAmt = LHSShift.getOperand(1);
+  SDOperand RHSShiftAmt = RHSShift.getOperand(1);
 
   // fold (or (shl x, C1), (srl x, C2)) -> (rotl x, C1)
   // fold (or (shl x, C1), (srl x, C2)) -> (rotr x, C2)
-  if (LHSShift.getOperand(1).getOpcode() == ISD::Constant &&
-      RHSShift.getOperand(1).getOpcode() == ISD::Constant) {
-    uint64_t LShVal = cast<ConstantSDNode>(LHSShift.getOperand(1))->getValue();
-    uint64_t RShVal = cast<ConstantSDNode>(RHSShift.getOperand(1))->getValue();
+  if (LHSShiftAmt.getOpcode() == ISD::Constant &&
+      RHSShiftAmt.getOpcode() == ISD::Constant) {
+    uint64_t LShVal = cast<ConstantSDNode>(LHSShiftAmt)->getValue();
+    uint64_t RShVal = cast<ConstantSDNode>(RHSShiftAmt)->getValue();
     if ((LShVal + RShVal) != OpSizeInBits)
       return 0;
 
     SDOperand Rot;
     if (HasROTL)
-      Rot = DAG.getNode(ISD::ROTL, VT, LHSShift.getOperand(0),
-                        LHSShift.getOperand(1));
+      Rot = DAG.getNode(ISD::ROTL, VT, LHSShiftArg, LHSShiftAmt);
     else
-      Rot = DAG.getNode(ISD::ROTR, VT, LHSShift.getOperand(0),
-                        RHSShift.getOperand(1));
+      Rot = DAG.getNode(ISD::ROTR, VT, LHSShiftArg, RHSShiftAmt);
     
     // If there is an AND of either shifted operand, apply it to the result.
     if (LHSMask.Val || RHSMask.Val) {
@@ -1532,35 +1533,71 @@
   
   // fold (or (shl x, y), (srl x, (sub 32, y))) -> (rotl x, y)
   // fold (or (shl x, y), (srl x, (sub 32, y))) -> (rotr x, (sub 32, y))
-  if (RHSShift.getOperand(1).getOpcode() == ISD::SUB &&
-      LHSShift.getOperand(1) == RHSShift.getOperand(1).getOperand(1)) {
+  if (RHSShiftAmt.getOpcode() == ISD::SUB &&
+      LHSShiftAmt == RHSShiftAmt.getOperand(1)) {
     if (ConstantSDNode *SUBC =
-          dyn_cast<ConstantSDNode>(RHSShift.getOperand(1).getOperand(0))) {
+          dyn_cast<ConstantSDNode>(RHSShiftAmt.getOperand(0))) {
       if (SUBC->getValue() == OpSizeInBits)
         if (HasROTL)
-          return DAG.getNode(ISD::ROTL, VT, LHSShift.getOperand(0),
-                             LHSShift.getOperand(1)).Val;
+          return DAG.getNode(ISD::ROTL, VT, LHSShiftArg, LHSShiftAmt).Val;
         else
-          return DAG.getNode(ISD::ROTR, VT, LHSShift.getOperand(0),
-                             LHSShift.getOperand(1)).Val;
+          return DAG.getNode(ISD::ROTR, VT, LHSShiftArg, LHSShiftAmt).Val;
     }
   }
   
   // fold (or (shl x, (sub 32, y)), (srl x, r)) -> (rotr x, y)
   // fold (or (shl x, (sub 32, y)), (srl x, r)) -> (rotl x, (sub 32, y))
-  if (LHSShift.getOperand(1).getOpcode() == ISD::SUB &&
-      RHSShift.getOperand(1) == LHSShift.getOperand(1).getOperand(1)) {
+  if (LHSShiftAmt.getOpcode() == ISD::SUB &&
+      RHSShiftAmt == LHSShiftAmt.getOperand(1)) {
     if (ConstantSDNode *SUBC =
-          dyn_cast<ConstantSDNode>(LHSShift.getOperand(1).getOperand(0))) {
+          dyn_cast<ConstantSDNode>(LHSShiftAmt.getOperand(0))) {
       if (SUBC->getValue() == OpSizeInBits)
         if (HasROTL)
-          return DAG.getNode(ISD::ROTL, VT, LHSShift.getOperand(0),
-                             LHSShift.getOperand(1)).Val;
+          return DAG.getNode(ISD::ROTL, VT, LHSShiftArg, LHSShiftAmt).Val;
         else
-          return DAG.getNode(ISD::ROTR, VT, LHSShift.getOperand(0),
-                             RHSShift.getOperand(1)).Val;
+          return DAG.getNode(ISD::ROTR, VT, LHSShiftArg, RHSShiftAmt).Val;
     }
   }
+
+  // Look for sign/zext/any-extended cases:
+  if ((LHSShiftAmt.getOpcode() == ISD::SIGN_EXTEND
+       || LHSShiftAmt.getOpcode() == ISD::ZERO_EXTEND
+       || LHSShiftAmt.getOpcode() == ISD::ANY_EXTEND) &&
+      (RHSShiftAmt.getOpcode() == ISD::SIGN_EXTEND
+       || RHSShiftAmt.getOpcode() == ISD::ZERO_EXTEND
+       || RHSShiftAmt.getOpcode() == ISD::ANY_EXTEND)) {
+    SDOperand LHSOp0 = LHSShiftAmt.getOperand(0);
+    SDOperand RHSOp0 = RHSShiftAmt.getOperand(0);
+    if (RHSOp0.getOpcode() == ISD::SUB &&
+        RHSOp0.getOperand(1) == LHSOp0) {
+      // fold (or (shl x, (*ext y)), (srl x, (*ext (sub 32, y)))) ->
+      //   (rotr x, y)
+      // fold (or (shl x, (*ext y)), (srl x, (*ext (sub 32, y)))) ->
+      //   (rotl x, (sub 32, y))
+      if (ConstantSDNode *SUBC = cast<ConstantSDNode>(RHSOp0.getOperand(0))) {
+ if (SUBC->getValue() == OpSizeInBits) {
+  if (HasROTL)
+    return DAG.getNode(ISD::ROTL, VT, LHSShiftArg, LHSShiftAmt).Val;
+  else
+    return DAG.getNode(ISD::ROTR, VT, LHSShiftArg, RHSShiftAmt).Val;
+ }
+      }
+    } else if (LHSOp0.getOpcode() == ISD::SUB &&
+               RHSOp0 == LHSOp0.getOperand(1)) {
+      // fold (or (shl x, (*ext (sub 32, y))), (srl x, (*ext r))) ->
+      //   (rotl x, y)
+      // fold (or (shl x, (*ext (sub 32, y))), (srl x, (*ext r))) ->
+      //   (rotr x, (sub 32, y))
+      if (ConstantSDNode *SUBC = cast<ConstantSDNode>(LHSOp0.getOperand(0))) {
+ if (SUBC->getValue() == OpSizeInBits) {
+  if (HasROTL)
+    return DAG.getNode(ISD::ROTL, VT, LHSShiftArg, RHSShiftAmt).Val;
+  else
+    return DAG.getNode(ISD::ROTL, VT, LHSShiftArg, LHSShiftAmt).Val;
+ }
+      }
+    }
+  }
   
   return 0;
 }

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Cleanups in ROTL/ROTR DAG combiner code

Scott Michel
Not functioning well this morning... will resubmit to llvm-commits list.
This message wasn't meant for llvmdev.

Appoligies and virtual beers all around!


-scooter
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev