diff options
author | Kai Nacke <kai.nacke@redstar.de> | 2013-09-19 22:36:39 +0000 |
---|---|---|
committer | Kai Nacke <kai.nacke@redstar.de> | 2013-09-19 22:36:39 +0000 |
commit | 4eaf6444fa885dce03af1092d7b797ad918e997d (patch) | |
tree | b56589a403378d867b474ded245286ac52ad8b22 /llvm/lib/CodeGen/SelectionDAG | |
parent | 91a95a590a566ecf2906744b6d612a27e33be08d (diff) | |
download | bcm5719-llvm-4eaf6444fa885dce03af1092d7b797ad918e997d.tar.gz bcm5719-llvm-4eaf6444fa885dce03af1092d7b797ad918e997d.zip |
PR16726: extend rol/ror matching
C-like languages promote types like unsigned short to unsigned int before
performing an arithmetic operation. Currently the rotate matcher in the
DAGCombiner does not consider this situation.
This commit extends the DAGCombiner in the way that the pattern
(or (shl ([az]ext x), (*ext y)), (srl ([az]ext x), (*ext (sub 32, y))))
is folded into
([az]ext (rotl x, y))
The matching is restricted to aext and zext because in this cases the upper
bits are either undefined or known. Test case is included.
This fixes PR16726.
llvm-svn: 191045
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 0eecd39d247..b18c69b52a7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3341,6 +3341,7 @@ SDNode *DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, SDLoc DL) { unsigned OpSizeInBits = VT.getSizeInBits(); SDValue LHSShiftArg = LHSShift.getOperand(0); SDValue LHSShiftAmt = LHSShift.getOperand(1); + SDValue RHSShiftArg = RHSShift.getOperand(0); SDValue RHSShiftAmt = RHSShift.getOperand(1); // fold (or (shl x, C1), (srl x, C2)) -> (rotl x, C1) @@ -3424,6 +3425,23 @@ SDNode *DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, SDLoc DL) { return DAG.getNode(HasROTL ? ISD::ROTL : ISD::ROTR, DL, VT, LHSShiftArg, HasROTL ? LHSShiftAmt : RHSShiftAmt).getNode(); + else if (LHSShiftArg.getOpcode() == ISD::ZERO_EXTEND || + LHSShiftArg.getOpcode() == ISD::ANY_EXTEND) { + // fold (or (shl (*ext x), (*ext y)), + // (srl (*ext x), (*ext (sub 32, y)))) -> + // (*ext (rotl x, y)) + // fold (or (shl (*ext x), (*ext y)), + // (srl (*ext x), (*ext (sub 32, y)))) -> + // (*ext (rotr x, (sub 32, y))) + SDValue LArgExtOp0 = LHSShiftArg.getOperand(0); + EVT LArgVT = LArgExtOp0.getValueType(); + if (LArgVT.getSizeInBits() == SUBC->getAPIntValue()) { + SDValue V = DAG.getNode(HasROTL ? ISD::ROTL : ISD::ROTR, DL, LArgVT, + LArgExtOp0, + HasROTL ? LHSShiftAmt : RHSShiftAmt); + return DAG.getNode(LHSShiftArg.getOpcode(), DL, VT, V).getNode(); + } + } } else if (LExtOp0.getOpcode() == ISD::SUB && RExtOp0 == LExtOp0.getOperand(1)) { // fold (or (shl x, (*ext (sub 32, y))), (srl x, (*ext y))) -> @@ -3436,6 +3454,23 @@ SDNode *DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, SDLoc DL) { return DAG.getNode(HasROTR ? ISD::ROTR : ISD::ROTL, DL, VT, LHSShiftArg, HasROTR ? RHSShiftAmt : LHSShiftAmt).getNode(); + else if (RHSShiftArg.getOpcode() == ISD::ZERO_EXTEND || + RHSShiftArg.getOpcode() == ISD::ANY_EXTEND) { + // fold (or (shl (*ext x), (*ext (sub 32, y))), + // (srl (*ext x), (*ext y))) -> + // (*ext (rotl x, y)) + // fold (or (shl (*ext x), (*ext (sub 32, y))), + // (srl (*ext x), (*ext y))) -> + // (*ext (rotr x, (sub 32, y))) + SDValue RArgExtOp0 = RHSShiftArg.getOperand(0); + EVT RArgVT = RArgExtOp0.getValueType(); + if (RArgVT.getSizeInBits() == SUBC->getAPIntValue()) { + SDValue V = DAG.getNode(HasROTR ? ISD::ROTR : ISD::ROTL, DL, RArgVT, + RArgExtOp0, + HasROTR ? RHSShiftAmt : LHSShiftAmt); + return DAG.getNode(RHSShiftArg.getOpcode(), DL, VT, V).getNode(); + } + } } } |