From d97591a9615512120b5ce9a8071b97a36ad7c76a Mon Sep 17 00:00:00 2001 From: Andrew Lenharth Date: Thu, 20 Oct 2005 00:29:02 +0000 Subject: [PATCH] forgot this one git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23833 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Alpha/AlphaISelDAGToDAG.cpp | 265 +++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 lib/Target/Alpha/AlphaISelDAGToDAG.cpp diff --git a/lib/Target/Alpha/AlphaISelDAGToDAG.cpp b/lib/Target/Alpha/AlphaISelDAGToDAG.cpp new file mode 100644 index 00000000000..73fd4fcebb3 --- /dev/null +++ b/lib/Target/Alpha/AlphaISelDAGToDAG.cpp @@ -0,0 +1,265 @@ +//===-- AlphaISelDAGToDAG.cpp - Alpha pattern matching inst selector ------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Andrew Lenharth and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a pattern matching instruction selector for Alpha, +// converting from a legalized dag to a Alpha dag. +// +//===----------------------------------------------------------------------===// + +#include "Alpha.h" +#include "AlphaTargetMachine.h" +#include "AlphaISelLowering.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/SSARegMap.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Constants.h" +#include "llvm/GlobalValue.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" +using namespace llvm; + +namespace { + + //===--------------------------------------------------------------------===// + /// AlphaDAGToDAGISel - Alpha specific code to select Alpha machine + /// instructions for SelectionDAG operations. + /// + class AlphaDAGToDAGISel : public SelectionDAGISel { + AlphaTargetLowering AlphaLowering; + + public: + AlphaDAGToDAGISel(TargetMachine &TM) + : SelectionDAGISel(AlphaLowering), AlphaLowering(TM) {} + + /// getI64Imm - Return a target constant with the specified value, of type + /// i64. + inline SDOperand getI64Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i64); + } + + virtual bool runOnFunction(Function &Fn) { + return SelectionDAGISel::runOnFunction(Fn); + } + + // Select - Convert the specified operand from a target-independent to a + // target-specific node if it hasn't already been changed. + SDOperand Select(SDOperand Op); + + /// InstructionSelectBasicBlock - This callback is invoked by + /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. + virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); + + virtual const char *getPassName() const { + return "Alpha DAG->DAG Pattern Instruction Selection"; + } + +// Include the pieces autogenerated from the target description. +#include "AlphaGenDAGISel.inc" + +private: + }; +} + +/// InstructionSelectBasicBlock - This callback is invoked by +/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. +void AlphaDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { + DEBUG(BB->dump()); + + // The selection process is inherently a bottom-up recursive process (users + // select their uses before themselves). Given infinite stack space, we + // could just start selecting on the root and traverse the whole graph. In + // practice however, this causes us to run out of stack space on large basic + // blocks. To avoid this problem, select the entry node, then all its uses, + // iteratively instead of recursively. + std::vector Worklist; + Worklist.push_back(DAG.getEntryNode()); + + // Note that we can do this in the Alpha target (scanning forward across token + // chain edges) because no nodes ever get folded across these edges. On a + // target like X86 which supports load/modify/store operations, this would + // have to be more careful. + while (!Worklist.empty()) { + SDOperand Node = Worklist.back(); + Worklist.pop_back(); + + // Chose from the least deep of the top two nodes. + if (!Worklist.empty() && + Worklist.back().Val->getNodeDepth() < Node.Val->getNodeDepth()) + std::swap(Worklist.back(), Node); + + if ((Node.Val->getOpcode() >= ISD::BUILTIN_OP_END && + Node.Val->getOpcode() < AlphaISD::FIRST_NUMBER) || + CodeGenMap.count(Node)) continue; + + for (SDNode::use_iterator UI = Node.Val->use_begin(), + E = Node.Val->use_end(); UI != E; ++UI) { + // Scan the values. If this use has a value that is a token chain, add it + // to the worklist. + SDNode *User = *UI; + for (unsigned i = 0, e = User->getNumValues(); i != e; ++i) + if (User->getValueType(i) == MVT::Other) { + Worklist.push_back(SDOperand(User, i)); + break; + } + } + + // Finally, legalize this node. + Select(Node); + } + + // Select target instructions for the DAG. + DAG.setRoot(Select(DAG.getRoot())); + CodeGenMap.clear(); + DAG.RemoveDeadNodes(); + + // Emit machine code to BB. + ScheduleAndEmitDAG(DAG); +} + +// Select - Convert the specified operand from a target-independent to a +// target-specific node if it hasn't already been changed. +SDOperand AlphaDAGToDAGISel::Select(SDOperand Op) { + SDNode *N = Op.Val; + if (N->getOpcode() >= ISD::BUILTIN_OP_END && + N->getOpcode() < AlphaISD::FIRST_NUMBER) + return Op; // Already selected. + + // If this has already been converted, use it. + std::map::iterator CGMI = CodeGenMap.find(Op); + if (CGMI != CodeGenMap.end()) return CGMI->second; + + switch (N->getOpcode()) { + default: break; + case ISD::DYNAMIC_STACKALLOC: + case ISD::ADD_PARTS: + case ISD::SUB_PARTS: + case ISD::SETCC: + case ISD::CALL: + case ISD::TAILCALL: + assert(0 && "You want these too?"); + + case ISD::TokenFactor: { + SDOperand New; + if (N->getNumOperands() == 2) { + SDOperand Op0 = Select(N->getOperand(0)); + SDOperand Op1 = Select(N->getOperand(1)); + New = CurDAG->getNode(ISD::TokenFactor, MVT::Other, Op0, Op1); + } else { + std::vector Ops; + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + Ops.push_back(Select(N->getOperand(i))); + New = CurDAG->getNode(ISD::TokenFactor, MVT::Other, Ops); + } + + CodeGenMap[Op] = New; + return New; + } + case ISD::CopyFromReg: { + SDOperand Chain = Select(N->getOperand(0)); + if (Chain == N->getOperand(0)) return Op; // No change + SDOperand New = CurDAG->getCopyFromReg(Chain, + cast(N->getOperand(1))->getReg(), N->getValueType(0)); + return New.getValue(Op.ResNo); + } + case ISD::CopyToReg: { + SDOperand Chain = Select(N->getOperand(0)); + SDOperand Reg = N->getOperand(1); + SDOperand Val = Select(N->getOperand(2)); + SDOperand New = CurDAG->getNode(ISD::CopyToReg, MVT::Other, + Chain, Reg, Val); + CodeGenMap[Op] = New; + return New; + } + case ISD::UNDEF: + if (N->getValueType(0) == MVT::i64) + CurDAG->SelectNodeTo(N, Alpha::IDEF, MVT::i64); +// else if (N->getValueType(0) == MVT::f32) +// CurDAG->SelectNodeTo(N, PPC::IMPLICIT_DEF_F4, MVT::f32); +// else +// CurDAG->SelectNodeTo(N, PPC::IMPLICIT_DEF_F8, MVT::f64); + return SDOperand(N, 0); + case ISD::FrameIndex: { +// int FI = cast(N)->getIndex(); +// CurDAG->SelectNodeTo(N, Alpha::LDA, MVT::i64, +// CurDAG->getTargetFrameIndex(FI, MVT::i32), +// getI32Imm(0)); +// return SDOperand(N, 0); + assert(0 && "Frame?, you are suppose to look through the window, not at the frame!"); + } + case ISD::ConstantPool: { +// Constant *C = cast(N)->get(); +// SDOperand Tmp, CPI = CurDAG->getTargetConstantPool(C, MVT::i32); +// if (PICEnabled) +// Tmp = CurDAG->getTargetNode(PPC::ADDIS, MVT::i32, getGlobalBaseReg(),CPI); +// else +// Tmp = CurDAG->getTargetNode(PPC::LIS, MVT::i32, CPI); +// CurDAG->SelectNodeTo(N, PPC::LA, MVT::i32, Tmp, CPI); +// return SDOperand(N, 0); + assert(0 && "Constants are overrated"); + } + case ISD::GlobalAddress: { +// GlobalValue *GV = cast(N)->getGlobal(); +// SDOperand Tmp; +// SDOperand GA = CurDAG->getTargetGlobalAddress(GV, MVT::i32); +// if (PICEnabled) +// Tmp = CurDAG->getTargetNode(PPC::ADDIS, MVT::i32, getGlobalBaseReg(), GA); +// else +// Tmp = CurDAG->getTargetNode(PPC::LIS, MVT::i32, GA); + +// if (GV->hasWeakLinkage() || GV->isExternal()) +// CurDAG->SelectNodeTo(N, PPC::LWZ, MVT::i32, GA, Tmp); +// else +// CurDAG->SelectNodeTo(N, PPC::LA, MVT::i32, Tmp, GA); +// return SDOperand(N, 0); + assert(0 && "GlobalAddresses are for wimps"); + } + + case ISD::CALLSEQ_START: + case ISD::CALLSEQ_END: { + unsigned Amt = cast(N->getOperand(1))->getValue(); + unsigned Opc = N->getOpcode() == ISD::CALLSEQ_START ? + Alpha::ADJUSTSTACKDOWN : Alpha::ADJUSTSTACKUP; + CurDAG->SelectNodeTo(N, Opc, MVT::Other, + getI64Imm(Amt), Select(N->getOperand(0))); + return SDOperand(N, 0); + } + case ISD::RET: { + SDOperand Chain = Select(N->getOperand(0)); // Token chain. + + if (N->getNumOperands() == 2) { + SDOperand Val = Select(N->getOperand(1)); + if (N->getOperand(1).getValueType() == MVT::i64) { + Chain = CurDAG->getCopyToReg(Chain, Alpha::R0, Val); + } + } + //BuildMI(BB, Alpha::RET, 2, Alpha::R31).addReg(Alpha::R26).addImm(1); + + // FIXME: add restoring of the RA to R26 to the chain + // Finally, select this to a ret instruction. + CurDAG->SelectNodeTo(N, Alpha::RETDAG, MVT::Other, Chain); + return SDOperand(N, 0); + } + + + + } + + return SelectCode(Op); +} + +/// createAlphaISelDag - This pass converts a legalized DAG into a +/// Alpha-specific DAG, ready for instruction scheduling. +/// +FunctionPass *llvm::createAlphaISelDag(TargetMachine &TM) { + return new AlphaDAGToDAGISel(TM); +} -- 2.34.1