From 45b8caf1c5a1fd8337038d64c6da8fba2d299fdf Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 15 Jan 2005 07:15:18 +0000 Subject: [PATCH] Add support for legalizing FP_ROUND_INREG, SIGN_EXTEND_INREG, and ZERO_EXTEND_INREG for targets that don't support them. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19573 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 79 +++++++++++++++++------- 1 file changed, 58 insertions(+), 21 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 9312a5c87d7..28a9471cd06 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -14,6 +14,7 @@ #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetOptions.h" @@ -21,20 +22,6 @@ #include using namespace llvm; -static const Type *getTypeFor(MVT::ValueType VT) { - switch (VT) { - default: assert(0 && "Unknown MVT!"); - case MVT::i1: return Type::BoolTy; - case MVT::i8: return Type::UByteTy; - case MVT::i16: return Type::UShortTy; - case MVT::i32: return Type::UIntTy; - case MVT::i64: return Type::ULongTy; - case MVT::f32: return Type::FloatTy; - case MVT::f64: return Type::DoubleTy; - } -} - - //===----------------------------------------------------------------------===// /// SelectionDAGLegalize - This takes an arbitrary SelectionDAG as input and /// hacks on it until the target machine can handle it. This involves @@ -574,7 +561,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { Tmp2 = LegalizeOp(Node->getOperand(1)); if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1) || Tmp3 != Node->getOperand(2)) - Result = DAG.getNode(ISD::TRUNCSTORE, MVT::Other, Tmp1, Tmp3, Tmp2, + Result = DAG.getNode(ISD::TRUNCSTORE, MVT::Other, Tmp1, Tmp2, Tmp3, cast(Node)->getExtraValueType()); break; case Promote: @@ -774,13 +761,63 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { break; case ISD::FP_ROUND_INREG: case ISD::SIGN_EXTEND_INREG: - case ISD::ZERO_EXTEND_INREG: + case ISD::ZERO_EXTEND_INREG: { Tmp1 = LegalizeOp(Node->getOperand(0)); - if (Tmp1 != Node->getOperand(0)) - Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), Tmp1, - cast(Node)->getExtraValueType()); + MVT::ValueType ExtraVT = cast(Node)->getExtraValueType(); + + // If this operation is not supported, convert it to a shl/shr or load/store + // pair. + if (!TLI.isOperationSupported(Node->getOpcode(), ExtraVT)) { + // If this is an integer extend and shifts are supported, do that. + if (Node->getOpcode() == ISD::ZERO_EXTEND_INREG) { + // NOTE: we could fall back on load/store here too for targets without + // AND. However, it is doubtful that any exist. + // AND out the appropriate bits. + SDOperand Mask = + DAG.getConstant((1ULL << MVT::getSizeInBits(ExtraVT))-1, + Node->getValueType(0)); + Result = DAG.getNode(ISD::AND, Node->getValueType(0), + Node->getOperand(0), Mask); + } else if (Node->getOpcode() == ISD::SIGN_EXTEND_INREG) { + // NOTE: we could fall back on load/store here too for targets without + // SAR. However, it is doubtful that any exist. + unsigned BitsDiff = MVT::getSizeInBits(Node->getValueType(0)) - + MVT::getSizeInBits(ExtraVT); + SDOperand ShiftCst = DAG.getConstant(BitsDiff, MVT::i8); + Result = DAG.getNode(ISD::SHL, Node->getValueType(0), + Node->getOperand(0), ShiftCst); + Result = DAG.getNode(ISD::SRA, Node->getValueType(0), + Result, ShiftCst); + } else if (Node->getOpcode() == ISD::FP_ROUND_INREG) { + // The only way we can lower this is to turn it into a STORETRUNC, + // EXTLOAD pair, targetting a temporary location (a stack slot). + + // NOTE: there is a choice here between constantly creating new stack + // slots and always reusing the same one. We currently always create + // new ones, as reuse may inhibit scheduling. + const Type *Ty = MVT::getTypeForValueType(ExtraVT); + unsigned TySize = (unsigned)TLI.getTargetData().getTypeSize(Ty); + unsigned Align = TLI.getTargetData().getTypeAlignment(Ty); + MachineFunction &MF = DAG.getMachineFunction(); + int SSFI = + MF.getFrameInfo()->CreateStackObject((unsigned)TySize, Align); + SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy()); + Result = DAG.getNode(ISD::TRUNCSTORE, MVT::Other, DAG.getEntryNode(), + Node->getOperand(0), StackSlot, ExtraVT); + Result = DAG.getNode(ISD::EXTLOAD, Node->getValueType(0), + Result, StackSlot, ExtraVT); + } else { + assert(0 && "Unknown op"); + } + Result = LegalizeOp(Result); + } else { + if (Tmp1 != Node->getOperand(0)) + Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), Tmp1, + ExtraVT); + } break; } + } if (!Op.Val->hasOneUse()) AddLegalizedOperand(Op, Result); @@ -1057,14 +1094,14 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){ TargetLowering::ArgListTy Args; for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) Args.push_back(std::make_pair(Node->getOperand(i), - getTypeFor(Node->getOperand(i).getValueType()))); + MVT::getTypeForValueType(Node->getOperand(i).getValueType()))); SDOperand Callee = DAG.getExternalSymbol(LibCallName, TLI.getPointerTy()); // We don't care about token chains for libcalls. We just use the entry // node as our input and ignore the output chain. This allows us to place // calls wherever we need them to satisfy data dependences. SDOperand Result = TLI.LowerCallTo(DAG.getEntryNode(), - getTypeFor(Op.getValueType()), Callee, + MVT::getTypeForValueType(Op.getValueType()), Callee, Args, DAG).first; ExpandOp(Result, Lo, Hi); } -- 2.34.1