DAG combiner fix for rotates. Previously the outer-most condition checks

for ROTL availability. This prevents it from forming ROTR for targets that
has ROTR only.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29997 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2006-08-31 07:41:12 +00:00
parent 2ebfa0c618
commit dfcfacb0cb

View File

@ -1160,35 +1160,52 @@ SDOperand DAGCombiner::visitOR(SDNode *N) {
// check for rotl, rotr // check for rotl, rotr
if (N0.getOpcode() == ISD::SHL && N1.getOpcode() == ISD::SRL && if (N0.getOpcode() == ISD::SHL && N1.getOpcode() == ISD::SRL &&
N0.getOperand(0) == N1.getOperand(0) && N0.getOperand(0) == N1.getOperand(0) &&
TLI.isOperationLegal(ISD::ROTL, VT) && TLI.isTypeLegal(VT)) { TLI.isTypeLegal(VT)) {
// fold (or (shl x, C1), (srl x, C2)) -> (rotl x, C1) bool HasROTL = TLI.isOperationLegal(ISD::ROTL, VT);
if (N0.getOperand(1).getOpcode() == ISD::Constant && bool HasROTR = TLI.isOperationLegal(ISD::ROTR, VT);
N1.getOperand(1).getOpcode() == ISD::Constant) { if (HasROTL || HasROTR) {
uint64_t c1val = cast<ConstantSDNode>(N0.getOperand(1))->getValue(); // fold (or (shl x, C1), (srl x, C2)) -> (rotl x, C1)
uint64_t c2val = cast<ConstantSDNode>(N1.getOperand(1))->getValue(); // fold (or (shl x, C1), (srl x, C2)) -> (rotr x, C2)
if ((c1val + c2val) == OpSizeInBits) if (N0.getOperand(1).getOpcode() == ISD::Constant &&
return DAG.getNode(ISD::ROTL, VT, N0.getOperand(0), N0.getOperand(1)); N1.getOperand(1).getOpcode() == ISD::Constant) {
} uint64_t c1val = cast<ConstantSDNode>(N0.getOperand(1))->getValue();
// fold (or (shl x, y), (srl x, (sub 32, y))) -> (rotl x, y) uint64_t c2val = cast<ConstantSDNode>(N1.getOperand(1))->getValue();
if (N1.getOperand(1).getOpcode() == ISD::SUB && if ((c1val + c2val) == OpSizeInBits)
N0.getOperand(1) == N1.getOperand(1).getOperand(1)) if (HasROTL)
if (ConstantSDNode *SUBC =
dyn_cast<ConstantSDNode>(N1.getOperand(1).getOperand(0)))
if (SUBC->getValue() == OpSizeInBits)
return DAG.getNode(ISD::ROTL, VT, N0.getOperand(0), N0.getOperand(1));
// fold (or (shl x, (sub 32, y)), (srl x, r)) -> (rotr x, y)
if (N0.getOperand(1).getOpcode() == ISD::SUB &&
N1.getOperand(1) == N0.getOperand(1).getOperand(1))
if (ConstantSDNode *SUBC =
dyn_cast<ConstantSDNode>(N0.getOperand(1).getOperand(0)))
if (SUBC->getValue() == OpSizeInBits) {
if (TLI.isOperationLegal(ISD::ROTR, VT) && TLI.isTypeLegal(VT))
return DAG.getNode(ISD::ROTR, VT, N0.getOperand(0),
N1.getOperand(1));
else
return DAG.getNode(ISD::ROTL, VT, N0.getOperand(0), return DAG.getNode(ISD::ROTL, VT, N0.getOperand(0),
N0.getOperand(1)); N0.getOperand(1));
} else
return DAG.getNode(ISD::ROTR, VT, N0.getOperand(0),
N1.getOperand(1));
}
// 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 (N1.getOperand(1).getOpcode() == ISD::SUB &&
N0.getOperand(1) == N1.getOperand(1).getOperand(1))
if (ConstantSDNode *SUBC =
dyn_cast<ConstantSDNode>(N1.getOperand(1).getOperand(0)))
if (SUBC->getValue() == OpSizeInBits)
if (HasROTL)
return DAG.getNode(ISD::ROTL, VT, N0.getOperand(0),
N0.getOperand(1));
else
return DAG.getNode(ISD::ROTR, VT, N0.getOperand(0),
N1.getOperand(1));
// 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 (N0.getOperand(1).getOpcode() == ISD::SUB &&
N1.getOperand(1) == N0.getOperand(1).getOperand(1))
if (ConstantSDNode *SUBC =
dyn_cast<ConstantSDNode>(N0.getOperand(1).getOperand(0)))
if (SUBC->getValue() == OpSizeInBits)
if (HasROTR)
return DAG.getNode(ISD::ROTR, VT, N0.getOperand(0),
N1.getOperand(1));
else
return DAG.getNode(ISD::ROTL, VT, N0.getOperand(0),
N0.getOperand(1));
}
} }
return SDOperand(); return SDOperand();
} }