[llvm-commits] Patch resubmit: ROTL/ROTR cleanups

Chris Lattner clattner at apple.com
Mon Apr 2 13:11:53 PDT 2007


On Mar 30, 2007, at 12:02 PM, Scott Michel wrote:
> Spotted what was probably a long-standing bug, since some of my  
> cleanups
> were simple substitutions.

Sorry for the delay.  In general, if you keep the changes as simple  
and disjoint as possible, I'm more likely to look at them soon :).   
Here you could split up the "allow custom legalize of rotates" part  
from the "introduce some temporary vars" part from "match ext rotate  
cases" part.

> -scooter
> Index: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
> ===================================================================
> --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp	(.../trunk)	(revision  
> 2119)
> +++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp	(.../branches/llvm- 
> spu)	(revision 2119)
> @@ -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;

Looks good.

>    case ISD::BSWAP:
> Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp
> ===================================================================
> --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp	(.../trunk)	(revision  
> 2119)
> +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp	(.../branches/llvm- 
> spu)	(revision 2119)
> @@ -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) {

Looks fine.

> @@ -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,  
> RHSShiftAmt).Val;
>      }
>    }

ok

>    // 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;
>      }
>    }

Ok

> +
> +  // 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 LExtOp0 = LHSShiftAmt.getOperand(0);
> +    SDOperand RExtOp0 = RHSShiftAmt.getOperand(0);
> +    if (RExtOp0.getOpcode() == ISD::SUB &&
> +        RExtOp0.getOperand(1) == LExtOp0) {
> +      // 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> 
> (RExtOp0.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;
> +	}

Okay, but needs an extra level of spacing for the indentation here (2  
spaces, not 1).

> +      }
> +    } else if (LExtOp0.getOpcode() == ISD::SUB &&
> +               RExtOp0 == LExtOp0.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> 
> (LExtOp0.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;
> +	}

Likewise.

> +      }
> +    }
> +  }

Otherwise, looks great!  Please commit,

-Chris



More information about the llvm-commits mailing list