diff options
Diffstat (limited to 'lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 127 |
1 files changed, 118 insertions, 9 deletions
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 5fe67b5d3b..f15c121668 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -130,6 +130,8 @@ namespace { bool CombineToPostIndexedLoadStore(SDNode *N); SDValue PromoteIntBinOp(SDValue Op); + SDValue PromoteExtend(SDValue Op); + bool PromoteLoad(SDValue Op); /// combine - call the node-specific routine that knows how to fold each /// particular type of node. If that doesn't do anything, try the @@ -167,6 +169,8 @@ namespace { SDValue visitSHL(SDNode *N); SDValue visitSRA(SDNode *N); SDValue visitSRL(SDNode *N); + SDValue visitROTL(SDNode *N); + SDValue visitROTR(SDNode *N); SDValue visitCTLZ(SDNode *N); SDValue visitCTTZ(SDNode *N); SDValue visitCTPOP(SDNode *N); @@ -633,25 +637,44 @@ bool DAGCombiner::SimplifyDemandedBits(SDValue Op, const APInt &Demanded) { return true; } +static SDValue SExtPromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG, + const TargetLowering &TLI); +static SDValue ZExtPromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG, + const TargetLowering &TLI); + static SDValue PromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG, const TargetLowering &TLI) { + DebugLoc dl = Op.getDebugLoc(); if (LoadSDNode *LD = dyn_cast<LoadSDNode>(Op)) { - return DAG.getExtLoad(ISD::EXTLOAD, Op.getDebugLoc(), PVT, + ISD::LoadExtType ExtType = + ISD::isNON_EXTLoad(LD) ? ISD::EXTLOAD : LD->getExtensionType(); + return DAG.getExtLoad(ExtType, dl, PVT, LD->getChain(), LD->getBasePtr(), LD->getSrcValue(), LD->getSrcValueOffset(), LD->getMemoryVT(), LD->isVolatile(), LD->isNonTemporal(), LD->getAlignment()); } - unsigned Opc = ISD::ANY_EXTEND; - if (Op.getOpcode() == ISD::Constant) + unsigned Opc = Op.getOpcode(); + if (Opc == ISD::AssertSext) + return DAG.getNode(ISD::AssertSext, dl, PVT, + SExtPromoteOperand(Op.getOperand(0), PVT, DAG, TLI), + Op.getOperand(1)); + else if (Opc == ISD::AssertZext) + return DAG.getNode(ISD::AssertZext, dl, PVT, + ZExtPromoteOperand(Op.getOperand(0), PVT, DAG, TLI), + Op.getOperand(1)); + + unsigned ExtOpc = ISD::ANY_EXTEND; + if (Opc == ISD::Constant) // Zero extend things like i1, sign extend everything else. It shouldn't // matter in theory which one we pick, but this tends to give better code? // See DAGTypeLegalizer::PromoteIntRes_Constant. - Opc = Op.getValueType().isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; - if (!TLI.isOperationLegal(Opc, PVT)) + ExtOpc = + Op.getValueType().isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + if (!TLI.isOperationLegal(ExtOpc, PVT)) return SDValue(); - return DAG.getNode(Opc, Op.getDebugLoc(), PVT, Op); + return DAG.getNode(ExtOpc, dl, PVT, Op); } static SDValue SExtPromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG, @@ -727,6 +750,80 @@ SDValue DAGCombiner::PromoteIntBinOp(SDValue Op) { return SDValue(); } +SDValue DAGCombiner::PromoteExtend(SDValue Op) { + if (!LegalOperations) + return SDValue(); + + EVT VT = Op.getValueType(); + if (VT.isVector() || !VT.isInteger()) + return SDValue(); + + // If operation type is 'undesirable', e.g. i16 on x86, consider + // promoting it. + unsigned Opc = Op.getOpcode(); + if (TLI.isTypeDesirableForOp(Opc, VT)) + return SDValue(); + + EVT PVT = VT; + // Consult target whether it is a good idea to promote this operation and + // what's the right type to promote it to. + if (TLI.IsDesirableToPromoteOp(Op, PVT)) { + assert(PVT != VT && "Don't know what type to promote to!"); + // fold (aext (aext x)) -> (aext x) + // fold (aext (zext x)) -> (zext x) + // fold (aext (sext x)) -> (sext x) + return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), VT, Op.getOperand(0)); + } + return SDValue(); +} + +bool DAGCombiner::PromoteLoad(SDValue Op) { + if (!LegalOperations) + return false; + + EVT VT = Op.getValueType(); + if (VT.isVector() || !VT.isInteger()) + return false; + + // If operation type is 'undesirable', e.g. i16 on x86, consider + // promoting it. + unsigned Opc = Op.getOpcode(); + if (TLI.isTypeDesirableForOp(Opc, VT)) + return false; + + EVT PVT = VT; + // Consult target whether it is a good idea to promote this operation and + // what's the right type to promote it to. + if (TLI.IsDesirableToPromoteOp(Op, PVT)) { + assert(PVT != VT && "Don't know what type to promote to!"); + + DebugLoc dl = Op.getDebugLoc(); + SDNode *N = Op.getNode(); + LoadSDNode *LD = cast<LoadSDNode>(N); + ISD::LoadExtType ExtType = + ISD::isNON_EXTLoad(LD) ? ISD::EXTLOAD : LD->getExtensionType(); + SDValue NewLD = DAG.getExtLoad(ExtType, dl, PVT, + LD->getChain(), LD->getBasePtr(), + LD->getSrcValue(), LD->getSrcValueOffset(), + LD->getMemoryVT(), LD->isVolatile(), + LD->isNonTemporal(), LD->getAlignment()); + SDValue Result = DAG.getNode(ISD::TRUNCATE, dl, VT, NewLD); + + DEBUG(dbgs() << "\nReplacing.x "; + N->dump(&DAG); + dbgs() << "\nWith: "; + Result.getNode()->dump(&DAG); + dbgs() << '\n'); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result, &DeadNodes); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), NewLD.getValue(1), &DeadNodes); + removeFromWorkList(N); + DAG.DeleteNode(N); + return true; + } + return false; +} + //===----------------------------------------------------------------------===// // Main DAG Combiner implementation @@ -856,6 +953,8 @@ SDValue DAGCombiner::visit(SDNode *N) { case ISD::SHL: return visitSHL(N); case ISD::SRA: return visitSRA(N); case ISD::SRL: return visitSRL(N); + case ISD::ROTL: return visitROTL(N); + case ISD::ROTR: return visitROTR(N); case ISD::CTLZ: return visitCTLZ(N); case ISD::CTTZ: return visitCTTZ(N); case ISD::CTPOP: return visitCTPOP(N); @@ -2975,6 +3074,14 @@ SDValue DAGCombiner::visitSRL(SDNode *N) { return PromoteIntBinOp(SDValue(N, 0)); } +SDValue DAGCombiner::visitROTL(SDNode *N) { + return PromoteIntBinOp(SDValue(N, 0)); +} + +SDValue DAGCombiner::visitROTR(SDNode *N) { + return PromoteIntBinOp(SDValue(N, 0)); +} + SDValue DAGCombiner::visitCTLZ(SDNode *N) { SDValue N0 = N->getOperand(0); EVT VT = N->getValueType(0); @@ -3369,7 +3476,7 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { DAG.SignBitIsZero(N0)) return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, N0); - return SDValue(); + return PromoteExtend(SDValue(N, 0)); } SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { @@ -3532,7 +3639,7 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { N0.getOperand(1))); } - return SDValue(); + return PromoteExtend(SDValue(N, 0)); } SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { @@ -3668,7 +3775,7 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { return SCC; } - return SDValue(); + return PromoteExtend(SDValue(N, 0)); } /// GetDemandedBits - See if the specified operand can be simplified with the @@ -5270,6 +5377,8 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) { if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N)) return SDValue(N, 0); + if (PromoteLoad(SDValue(N, 0))) + return SDValue(N, 0); return SDValue(); } |