From: Nate Begeman Date: Wed, 6 Apr 2005 21:13:14 +0000 (+0000) Subject: Teach ExpandShift how to handle shifts by a constant. This allows targets X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=f1fe32e337cf825a27a57bb3e9fb847bc91a26ce;p=oota-llvm.git Teach ExpandShift how to handle shifts by a constant. This allows targets like PowerPC to codegen long shifts in many fewer instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21122 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index c696c18ed43..9441078d103 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1412,13 +1412,73 @@ void SelectionDAGLegalize::ExpandShiftParts(unsigned NodeOp, /// low-parts expanded into Lo and Hi. bool SelectionDAGLegalize::ExpandShift(unsigned Opc, SDOperand Op,SDOperand Amt, SDOperand &Lo, SDOperand &Hi) { - // FIXME: This code is buggy, disable it for now. Note that we should at - // least handle the case when Amt is an immediate here. - return false; - assert((Opc == ISD::SHL || Opc == ISD::SRA || Opc == ISD::SRL) && "This is not a shift!"); + MVT::ValueType NVT = TLI.getTypeToTransformTo(Op.getValueType()); + SDOperand ShAmt = LegalizeOp(Amt); + MVT::ValueType ShTy = ShAmt.getValueType(); + unsigned VTBits = MVT::getSizeInBits(Op.getValueType()); + unsigned NVTBits = MVT::getSizeInBits(NVT); + + // Handle the case when Amt is an immediate. Other cases are currently broken + // and are disabled. + if (ConstantSDNode *CN = dyn_cast(Amt.Val)) { + unsigned Cst = CN->getValue(); + // Expand the incoming operand to be shifted, so that we have its parts + SDOperand InL, InH; + ExpandOp(Op, InL, InH); + switch(Opc) { + case ISD::SHL: + if (Cst > VTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = DAG.getConstant(0, NVT); + } else if (Cst > NVTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Cst-NVTBits,ShTy)); + } else { + Lo = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Cst, ShTy)); + Hi = DAG.getNode(ISD::OR, NVT, + DAG.getNode(ISD::SHL, NVT, InH, DAG.getConstant(Cst, ShTy)), + DAG.getNode(ISD::SRL, NVT, InL, DAG.getConstant(NVTBits-Cst, ShTy))); + } + return true; + case ISD::SRL: + if (Cst > VTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = DAG.getConstant(0, NVT); + } else if (Cst > NVTBits) { + Lo = DAG.getNode(ISD::SRL, NVT, InH, DAG.getConstant(Cst-NVTBits,ShTy)); + Hi = DAG.getConstant(0, NVT); + } else { + Lo = DAG.getNode(ISD::OR, NVT, + DAG.getNode(ISD::SRL, NVT, InL, DAG.getConstant(Cst, ShTy)), + DAG.getNode(ISD::SHL, NVT, InH, DAG.getConstant(NVTBits-Cst, ShTy))); + Hi = DAG.getNode(ISD::SRL, NVT, InH, DAG.getConstant(Cst, ShTy)); + } + return true; + case ISD::SRA: + if (Cst > VTBits) { + Hi = Lo = DAG.getNode(ISD::SRA, NVT, InH, + DAG.getConstant(NVTBits-1, ShTy)); + } else if (Cst > NVTBits) { + Lo = DAG.getNode(ISD::SRA, NVT, InH, + DAG.getConstant(Cst-NVTBits, ShTy)); + Hi = DAG.getNode(ISD::SRA, NVT, InH, + DAG.getConstant(NVTBits-1, ShTy)); + } else { + Lo = DAG.getNode(ISD::OR, NVT, + DAG.getNode(ISD::SRL, NVT, InL, DAG.getConstant(Cst, ShTy)), + DAG.getNode(ISD::SHL, NVT, InH, DAG.getConstant(NVTBits-Cst, ShTy))); + Hi = DAG.getNode(ISD::SRA, NVT, InH, DAG.getConstant(Cst, ShTy)); + } + return true; + } + } + // FIXME: The following code for expanding shifts using ISD::SELECT is buggy, + // so disable it for now. Currently targets are handling this via SHL_PARTS + // and friends. + return false; // If we have an efficient select operation (or if the selects will all fold // away), lower to some complex code, otherwise just emit the libcall. @@ -1428,10 +1488,6 @@ bool SelectionDAGLegalize::ExpandShift(unsigned Opc, SDOperand Op,SDOperand Amt, SDOperand InL, InH; ExpandOp(Op, InL, InH); - SDOperand ShAmt = LegalizeOp(Amt); - MVT::ValueType ShTy = ShAmt.getValueType(); - - unsigned NVTBits = MVT::getSizeInBits(NVT); SDOperand NAmt = DAG.getNode(ISD::SUB, ShTy, // NAmt = 32-ShAmt DAG.getConstant(NVTBits, ShTy), ShAmt);