From 72b16d820cf49026a00c732abcbc039b5fb8673f Mon Sep 17 00:00:00 2001 From: Andrew Lenharth Date: Fri, 17 Jun 2005 16:52:12 +0000 Subject: [PATCH] A start at a Sparc V8 Pattern ISel. Anyone want to implement the calling convention? ;) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22247 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/SparcV8ISelPattern.cpp | 479 ++++++++++++++++++++++ lib/Target/SparcV8/SparcV8ISelPattern.cpp | 479 ++++++++++++++++++++++ 2 files changed, 958 insertions(+) create mode 100644 lib/Target/Sparc/SparcV8ISelPattern.cpp create mode 100644 lib/Target/SparcV8/SparcV8ISelPattern.cpp diff --git a/lib/Target/Sparc/SparcV8ISelPattern.cpp b/lib/Target/Sparc/SparcV8ISelPattern.cpp new file mode 100644 index 00000000000..98d4f930494 --- /dev/null +++ b/lib/Target/Sparc/SparcV8ISelPattern.cpp @@ -0,0 +1,479 @@ +#if 0 +//===- SparcV8ISelPattern.cpp - A pattern matching isel for SparcV8 -------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group 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 SparcV8. +// +//===----------------------------------------------------------------------===// + +//Please note that this file is a work in progress, and not a high +//priority for anyone. + +#include "SparcV8.h" +#include "SparcV8RegisterInfo.h" +#include "llvm/Constants.h" // FIXME: REMOVE +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/SSARegMap.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/CommandLine.h" +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// V8TargetLowering - SparcV8 Implementation of the TargetLowering interface +namespace { + class V8TargetLowering : public TargetLowering { + int VarArgsFrameIndex; // FrameIndex for start of varargs area. + public: + V8TargetLowering(TargetMachine &TM) : TargetLowering(TM) { + // Set up the TargetLowering object. + //I am having problems with shr n ubyte 1 + setShiftAmountType(MVT::i32); + setSetCCResultType(MVT::i32); + setSetCCResultContents(ZeroOrOneSetCCResult); + + //FIXME: get these right + addRegisterClass(MVT::i64, V8::GPRCRegisterClass); + addRegisterClass(MVT::f64, V8::FPRCRegisterClass); + addRegisterClass(MVT::f32, V8::FPRCRegisterClass); + + setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); + setOperationAction(ISD::EXTLOAD, MVT::i1, Promote); + setOperationAction(ISD::EXTLOAD, MVT::f32, Promote); + + setOperationAction(ISD::ZEXTLOAD, MVT::i1, Expand); + setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand); + + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Expand); + + setOperationAction(ISD::UREM, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i32, Expand); + + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + setOperationAction(ISD::CTTZ, MVT::i32, Expand); + setOperationAction(ISD::CTLZ, MVT::i32, Expand); + + setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); + setOperationAction(ISD::MEMSET, MVT::Other, Expand); + setOperationAction(ISD::MEMCPY, MVT::Other, Expand); + + // We don't support sin/cos/sqrt + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FSQRT, MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + setOperationAction(ISD::FSQRT, MVT::f32, Expand); + + computeRegisterProperties(); + + addLegalFPImmediate(+0.0); //F31 + addLegalFPImmediate(-0.0); //-F31 + } + + /// LowerArguments - This hook must be implemented to indicate how we should + /// lower the arguments for the specified function, into the specified DAG. + virtual std::vector + LowerArguments(Function &F, SelectionDAG &DAG); + + /// LowerCallTo - This hook lowers an abstract call to a function into an + /// actual call. + virtual std::pair + LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC, + bool isTailCall, SDOperand Callee, ArgListTy &Args, + SelectionDAG &DAG); + }; +} + +/// AddLiveIn - This helper function adds the specified physical register to the +/// MachineFunction as a live in value. It also creates a corresponding virtual +/// register for it. +static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg, + TargetRegisterClass *RC) { + assert(RC->contains(PReg) && "Not the correct regclass!"); + unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC); + MF.addLiveIn(PReg, VReg); + return VReg; +} + +std::vector +V8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) +{ + //FIXME + std::vector ArgValues; + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo*MFI = MF.getFrameInfo(); + + MachineBasicBlock& BB = MF.front(); + + //return the arguments + return ArgValues; +} + +std::pair +V8TargetLowering::LowerCallTo(SDOperand Chain, + const Type *RetTy, bool isVarArg, + unsigned CallingConv, bool isTailCall, + SDOperand Callee, ArgListTy &Args, + SelectionDAG &DAG) { + //FIXME + return std::make_pair(Chain, Chain); +} + +namespace { + +//===--------------------------------------------------------------------===// +/// ISel - V8 specific code to select V8 machine instructions for +/// SelectionDAG operations. +//===--------------------------------------------------------------------===// +class ISel : public SelectionDAGISel { + + /// V8Lowering - This object fully describes how to lower LLVM code to an + /// V8-specific SelectionDAG. + V8TargetLowering V8Lowering; + + SelectionDAG *ISelDAG; // Hack to support us having a dag->dag transform + // for sdiv and udiv until it is put into the future + // dag combiner. + + /// ExprMap - As shared expressions are codegen'd, we keep track of which + /// vreg the value is produced in, so we only emit one copy of each compiled + /// tree. + static const unsigned notIn = (unsigned)(-1); + std::map ExprMap; + +public: + ISel(TargetMachine &TM) : SelectionDAGISel(V8Lowering), V8Lowering(TM) + {} + + /// InstructionSelectBasicBlock - This callback is invoked by + /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. + virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) { + DEBUG(BB->dump()); + + // Codegen the basic block. + ISelDAG = &DAG; + max_depth = DAG.getRoot().getNodeDepth(); + Select(DAG.getRoot()); + + // Clear state used for selection. + ExprMap.clear(); + } + + virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF); + + unsigned SelectExpr(SDOperand N); + void Select(SDOperand N); + +}; +} + +void ISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) { + // If this function has live-in values, emit the copies from pregs to vregs at + // the top of the function, before anything else. + MachineBasicBlock *BB = MF.begin(); + if (MF.livein_begin() != MF.livein_end()) { + SSARegMap *RegMap = MF.getSSARegMap(); + for (MachineFunction::livein_iterator LI = MF.livein_begin(), + E = MF.livein_end(); LI != E; ++LI) { + const TargetRegisterClass *RC = RegMap->getRegClass(LI->second); + if (RC == V8::GPRCRegisterClass) { + BuildMI(BB, V8::ORrr, 2, LI->second).addReg(LI->first).addReg(V8::G0); + } else if (RC == V8::FPRCRegisterClass) { + BuildMI(BB, V8::FMOVSrr, 2, LI->second).addReg(LI->first); + } else { + assert(0 && "Unknown regclass!"); + } + } + } +} + +//These describe LDAx +static const int IMM_LOW = -32768; +static const int IMM_HIGH = 32767; +static const int IMM_MULT = 65536; + +static long getUpper16(long l) +{ + long y = l / IMM_MULT; + if (l % IMM_MULT > IMM_HIGH) + ++y; + return y; +} + +static long getLower16(long l) +{ + long h = getUpper16(l); + return l - h * IMM_MULT; +} + +unsigned ISel::SelectExpr(SDOperand N) { + unsigned Result; + unsigned Tmp1, Tmp2 = 0, Tmp3; + unsigned Opc = 0; + unsigned opcode = N.getOpcode(); + + SDNode *Node = N.Val; + MVT::ValueType DestType = N.getValueType(); + + unsigned &Reg = ExprMap[N]; + if (Reg) return Reg; + + if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::TAILCALL) + Reg = Result = (N.getValueType() != MVT::Other) ? + MakeReg(N.getValueType()) : notIn; + else { + // If this is a call instruction, make sure to prepare ALL of the result + // values as well as the chain. + if (Node->getNumValues() == 1) + Reg = Result = notIn; // Void call, just a chain. + else { + Result = MakeReg(Node->getValueType(0)); + ExprMap[N.getValue(0)] = Result; + for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i) + ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); + ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn; + } + } + + switch (opcode) { + default: + Node->dump(); + assert(0 && "Node not handled!\n"); + + case ISD::EXTLOAD: + case ISD::ZEXTLOAD: + case ISD::SEXTLOAD: + case ISD::LOAD: + { + // Make sure we generate both values. + if (Result != notIn) + ExprMap[N.getValue(1)] = notIn; // Generate the token + else + Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); + + SDOperand Chain = N.getOperand(0); + SDOperand Address = N.getOperand(1); + Select(Chain); + unsigned Adr = SelectExpr(Address); + switch(cast(Node)->getExtraValueType()) { + case MVT::i32: Opc = V8::LD; + case MVT::i16: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUH : V8::LDSH; break; + case MVT::i8: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUB : V8::LDSB; break; + case MVT::f64: Opc = V8::LDFSRrr; + case MVT::f32: Opc = V8::LDDFrr; + default: + Node->dump(); + assert(0 && "Bad type!"); + break; + } + BuildMI(BB, Opc, 1, Result).addReg(Adr); + return Result; + } + + case ISD::TAILCALL: + case ISD::CALL: + { + //FIXME: + abort(); + return Result; + } + + case ISD::CopyFromReg: + { + // Make sure we generate both values. + if (Result != notIn) + ExprMap[N.getValue(1)] = notIn; // Generate the token + else + Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); + + SDOperand Chain = N.getOperand(0); + Select(Chain); + unsigned r = dyn_cast(Node)->getReg(); + + BuildMI(BB, V8::ORrr, 2, Result).addReg(r).addReg(V8::G0); + return Result; + } + + //Most of the plain arithmetic and logic share the same form, and the same + //constant immediate test + case ISD::XOR: + case ISD::AND: + case ISD::OR: + case ISD::SHL: + case ISD::SRL: + case ISD::SRA: + case ISD::ADD: + case ISD::SUB: + case ISD::SDIV: + case ISD::UDIV: + case ISD::SMUL: + case ISD::UMUL: + switch(opcode) { + case ISD::XOR: Opc = V8::XORrr; break; + case ISD::AND: Opc = V8::ANDrr; break; + case ISD::OR: Opc = V8::ORrr; break; + case ISD::SHL: Opc = V8::SLLrr; break; + case ISD::SRL: Opc = V8::SRLrr; break; + case ISD::SRA: Opc = V8::SRArr; break; + case ISD::ADD: Opc = V8::ADDrr; break; + case ISD::SUB: Opc = V8::SUBrr; break; + case ISD::SDIV: Opc = V8::SDIVrr; break; + case ISD::UDIV: Opc = V8::UDIVrr; break; + case ISD::SMUL: Opc = V8::SMULrr; break; + case ISD::UMUL: Opc = V8::UMULrr; break; + } + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + } + return 0; +} + +void ISel::Select(SDOperand N) { + unsigned Tmp1, Tmp2, Opc; + unsigned opcode = N.getOpcode(); + + if (!ExprMap.insert(std::make_pair(N, notIn)).second) + return; // Already selected. + + SDNode *Node = N.Val; + + switch (opcode) { + + default: + Node->dump(); std::cerr << "\n"; + assert(0 && "Node not handled yet!"); + + case ISD::BRCOND: { + //FIXME + abort(); + return; + } + + case ISD::BR: { + MachineBasicBlock *Dest = + cast(N.getOperand(1))->getBasicBlock(); + + Select(N.getOperand(0)); + BuildMI(BB, V8::BA, 1).addMBB(Dest); + return; + } + + case ISD::ImplicitDef: + Select(N.getOperand(0)); + BuildMI(BB, V8::IMPLICIT_DEF, 0, cast(N)->getReg()); + return; + + case ISD::EntryToken: return; // Noop + + case ISD::TokenFactor: + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) + Select(Node->getOperand(i)); + return; + + case ISD::CopyToReg: + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(1)); + Tmp2 = cast(N)->getReg(); + + if (Tmp1 != Tmp2) { + if (N.getOperand(1).getValueType() == MVT::f64 || + N.getOperand(1).getValueType() == MVT::f32) + BuildMI(BB, V8::FMOVS, 2, Tmp2).addReg(Tmp1); + else + BuildMI(BB, V8::ORrr, 2, Tmp2).addReg(Tmp1).addReg(V8::G0); + } + return; + + case ISD::RET: + //FIXME: + abort(); + return; + + case ISD::TRUNCSTORE: + case ISD::STORE: + { + SDOperand Chain = N.getOperand(0); + SDOperand Value = N.getOperand(1); + SDOperand Address = N.getOperand(2); + Select(Chain); + + Tmp1 = SelectExpr(Value); + Tmp2 = SelectExpr(Address); + + unsigned VT = opcode == ISD::STORE ? + Value.getValueType() : cast(Node)->getExtraValueType(); + switch(VT) { + default: assert(0 && "unknown Type in store"); + case MVT::f64: Opc = V8::STDFrr; break; + case MVT::f32: Opc = V8::STFrr; break; + case MVT::i1: //FIXME: DAG does not promote this load + case MVT::i8: Opc = V8::STBrr; break; + case MVT::i16: Opc = V8::STHrr; break; + case MVT::i32: Opc = V8::STLrr; break; + case MVT::i64: Opc = V8::STDrr; break; + } + + BuildMI(BB,Opc,2).addReg(Tmp1).addReg(Tmp2); + return; + } + + case ISD::EXTLOAD: + case ISD::SEXTLOAD: + case ISD::ZEXTLOAD: + case ISD::LOAD: + case ISD::CopyFromReg: + case ISD::TAILCALL: + case ISD::CALL: + case ISD::DYNAMIC_STACKALLOC: + ExprMap.erase(N); + SelectExpr(N); + return; + + case ISD::CALLSEQ_START: + case ISD::CALLSEQ_END: + Select(N.getOperand(0)); + Tmp1 = cast(N.getOperand(1))->getValue(); + + Opc = N.getOpcode() == ISD::CALLSEQ_START ? V8::ADJUSTCALLSTACKDOWN : + V8::ADJUSTCALLSTACKUP; + BuildMI(BB, Opc, 1).addImm(Tmp1); + return; + } + assert(0 && "Should not be reached!"); +} + + +/// createV8PatternInstructionSelector - This pass converts an LLVM function +/// into a machine code representation using pattern matching and a machine +/// description file. +/// +FunctionPass *llvm::createV8PatternInstructionSelector(TargetMachine &TM) { + return new ISel(TM); +} + +#endif diff --git a/lib/Target/SparcV8/SparcV8ISelPattern.cpp b/lib/Target/SparcV8/SparcV8ISelPattern.cpp new file mode 100644 index 00000000000..98d4f930494 --- /dev/null +++ b/lib/Target/SparcV8/SparcV8ISelPattern.cpp @@ -0,0 +1,479 @@ +#if 0 +//===- SparcV8ISelPattern.cpp - A pattern matching isel for SparcV8 -------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group 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 SparcV8. +// +//===----------------------------------------------------------------------===// + +//Please note that this file is a work in progress, and not a high +//priority for anyone. + +#include "SparcV8.h" +#include "SparcV8RegisterInfo.h" +#include "llvm/Constants.h" // FIXME: REMOVE +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/SSARegMap.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/CommandLine.h" +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// V8TargetLowering - SparcV8 Implementation of the TargetLowering interface +namespace { + class V8TargetLowering : public TargetLowering { + int VarArgsFrameIndex; // FrameIndex for start of varargs area. + public: + V8TargetLowering(TargetMachine &TM) : TargetLowering(TM) { + // Set up the TargetLowering object. + //I am having problems with shr n ubyte 1 + setShiftAmountType(MVT::i32); + setSetCCResultType(MVT::i32); + setSetCCResultContents(ZeroOrOneSetCCResult); + + //FIXME: get these right + addRegisterClass(MVT::i64, V8::GPRCRegisterClass); + addRegisterClass(MVT::f64, V8::FPRCRegisterClass); + addRegisterClass(MVT::f32, V8::FPRCRegisterClass); + + setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); + setOperationAction(ISD::EXTLOAD, MVT::i1, Promote); + setOperationAction(ISD::EXTLOAD, MVT::f32, Promote); + + setOperationAction(ISD::ZEXTLOAD, MVT::i1, Expand); + setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand); + + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Expand); + + setOperationAction(ISD::UREM, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i32, Expand); + + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + setOperationAction(ISD::CTTZ, MVT::i32, Expand); + setOperationAction(ISD::CTLZ, MVT::i32, Expand); + + setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); + setOperationAction(ISD::MEMSET, MVT::Other, Expand); + setOperationAction(ISD::MEMCPY, MVT::Other, Expand); + + // We don't support sin/cos/sqrt + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FSQRT, MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + setOperationAction(ISD::FSQRT, MVT::f32, Expand); + + computeRegisterProperties(); + + addLegalFPImmediate(+0.0); //F31 + addLegalFPImmediate(-0.0); //-F31 + } + + /// LowerArguments - This hook must be implemented to indicate how we should + /// lower the arguments for the specified function, into the specified DAG. + virtual std::vector + LowerArguments(Function &F, SelectionDAG &DAG); + + /// LowerCallTo - This hook lowers an abstract call to a function into an + /// actual call. + virtual std::pair + LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC, + bool isTailCall, SDOperand Callee, ArgListTy &Args, + SelectionDAG &DAG); + }; +} + +/// AddLiveIn - This helper function adds the specified physical register to the +/// MachineFunction as a live in value. It also creates a corresponding virtual +/// register for it. +static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg, + TargetRegisterClass *RC) { + assert(RC->contains(PReg) && "Not the correct regclass!"); + unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC); + MF.addLiveIn(PReg, VReg); + return VReg; +} + +std::vector +V8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) +{ + //FIXME + std::vector ArgValues; + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo*MFI = MF.getFrameInfo(); + + MachineBasicBlock& BB = MF.front(); + + //return the arguments + return ArgValues; +} + +std::pair +V8TargetLowering::LowerCallTo(SDOperand Chain, + const Type *RetTy, bool isVarArg, + unsigned CallingConv, bool isTailCall, + SDOperand Callee, ArgListTy &Args, + SelectionDAG &DAG) { + //FIXME + return std::make_pair(Chain, Chain); +} + +namespace { + +//===--------------------------------------------------------------------===// +/// ISel - V8 specific code to select V8 machine instructions for +/// SelectionDAG operations. +//===--------------------------------------------------------------------===// +class ISel : public SelectionDAGISel { + + /// V8Lowering - This object fully describes how to lower LLVM code to an + /// V8-specific SelectionDAG. + V8TargetLowering V8Lowering; + + SelectionDAG *ISelDAG; // Hack to support us having a dag->dag transform + // for sdiv and udiv until it is put into the future + // dag combiner. + + /// ExprMap - As shared expressions are codegen'd, we keep track of which + /// vreg the value is produced in, so we only emit one copy of each compiled + /// tree. + static const unsigned notIn = (unsigned)(-1); + std::map ExprMap; + +public: + ISel(TargetMachine &TM) : SelectionDAGISel(V8Lowering), V8Lowering(TM) + {} + + /// InstructionSelectBasicBlock - This callback is invoked by + /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. + virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) { + DEBUG(BB->dump()); + + // Codegen the basic block. + ISelDAG = &DAG; + max_depth = DAG.getRoot().getNodeDepth(); + Select(DAG.getRoot()); + + // Clear state used for selection. + ExprMap.clear(); + } + + virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF); + + unsigned SelectExpr(SDOperand N); + void Select(SDOperand N); + +}; +} + +void ISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) { + // If this function has live-in values, emit the copies from pregs to vregs at + // the top of the function, before anything else. + MachineBasicBlock *BB = MF.begin(); + if (MF.livein_begin() != MF.livein_end()) { + SSARegMap *RegMap = MF.getSSARegMap(); + for (MachineFunction::livein_iterator LI = MF.livein_begin(), + E = MF.livein_end(); LI != E; ++LI) { + const TargetRegisterClass *RC = RegMap->getRegClass(LI->second); + if (RC == V8::GPRCRegisterClass) { + BuildMI(BB, V8::ORrr, 2, LI->second).addReg(LI->first).addReg(V8::G0); + } else if (RC == V8::FPRCRegisterClass) { + BuildMI(BB, V8::FMOVSrr, 2, LI->second).addReg(LI->first); + } else { + assert(0 && "Unknown regclass!"); + } + } + } +} + +//These describe LDAx +static const int IMM_LOW = -32768; +static const int IMM_HIGH = 32767; +static const int IMM_MULT = 65536; + +static long getUpper16(long l) +{ + long y = l / IMM_MULT; + if (l % IMM_MULT > IMM_HIGH) + ++y; + return y; +} + +static long getLower16(long l) +{ + long h = getUpper16(l); + return l - h * IMM_MULT; +} + +unsigned ISel::SelectExpr(SDOperand N) { + unsigned Result; + unsigned Tmp1, Tmp2 = 0, Tmp3; + unsigned Opc = 0; + unsigned opcode = N.getOpcode(); + + SDNode *Node = N.Val; + MVT::ValueType DestType = N.getValueType(); + + unsigned &Reg = ExprMap[N]; + if (Reg) return Reg; + + if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::TAILCALL) + Reg = Result = (N.getValueType() != MVT::Other) ? + MakeReg(N.getValueType()) : notIn; + else { + // If this is a call instruction, make sure to prepare ALL of the result + // values as well as the chain. + if (Node->getNumValues() == 1) + Reg = Result = notIn; // Void call, just a chain. + else { + Result = MakeReg(Node->getValueType(0)); + ExprMap[N.getValue(0)] = Result; + for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i) + ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); + ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn; + } + } + + switch (opcode) { + default: + Node->dump(); + assert(0 && "Node not handled!\n"); + + case ISD::EXTLOAD: + case ISD::ZEXTLOAD: + case ISD::SEXTLOAD: + case ISD::LOAD: + { + // Make sure we generate both values. + if (Result != notIn) + ExprMap[N.getValue(1)] = notIn; // Generate the token + else + Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); + + SDOperand Chain = N.getOperand(0); + SDOperand Address = N.getOperand(1); + Select(Chain); + unsigned Adr = SelectExpr(Address); + switch(cast(Node)->getExtraValueType()) { + case MVT::i32: Opc = V8::LD; + case MVT::i16: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUH : V8::LDSH; break; + case MVT::i8: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUB : V8::LDSB; break; + case MVT::f64: Opc = V8::LDFSRrr; + case MVT::f32: Opc = V8::LDDFrr; + default: + Node->dump(); + assert(0 && "Bad type!"); + break; + } + BuildMI(BB, Opc, 1, Result).addReg(Adr); + return Result; + } + + case ISD::TAILCALL: + case ISD::CALL: + { + //FIXME: + abort(); + return Result; + } + + case ISD::CopyFromReg: + { + // Make sure we generate both values. + if (Result != notIn) + ExprMap[N.getValue(1)] = notIn; // Generate the token + else + Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); + + SDOperand Chain = N.getOperand(0); + Select(Chain); + unsigned r = dyn_cast(Node)->getReg(); + + BuildMI(BB, V8::ORrr, 2, Result).addReg(r).addReg(V8::G0); + return Result; + } + + //Most of the plain arithmetic and logic share the same form, and the same + //constant immediate test + case ISD::XOR: + case ISD::AND: + case ISD::OR: + case ISD::SHL: + case ISD::SRL: + case ISD::SRA: + case ISD::ADD: + case ISD::SUB: + case ISD::SDIV: + case ISD::UDIV: + case ISD::SMUL: + case ISD::UMUL: + switch(opcode) { + case ISD::XOR: Opc = V8::XORrr; break; + case ISD::AND: Opc = V8::ANDrr; break; + case ISD::OR: Opc = V8::ORrr; break; + case ISD::SHL: Opc = V8::SLLrr; break; + case ISD::SRL: Opc = V8::SRLrr; break; + case ISD::SRA: Opc = V8::SRArr; break; + case ISD::ADD: Opc = V8::ADDrr; break; + case ISD::SUB: Opc = V8::SUBrr; break; + case ISD::SDIV: Opc = V8::SDIVrr; break; + case ISD::UDIV: Opc = V8::UDIVrr; break; + case ISD::SMUL: Opc = V8::SMULrr; break; + case ISD::UMUL: Opc = V8::UMULrr; break; + } + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + } + return 0; +} + +void ISel::Select(SDOperand N) { + unsigned Tmp1, Tmp2, Opc; + unsigned opcode = N.getOpcode(); + + if (!ExprMap.insert(std::make_pair(N, notIn)).second) + return; // Already selected. + + SDNode *Node = N.Val; + + switch (opcode) { + + default: + Node->dump(); std::cerr << "\n"; + assert(0 && "Node not handled yet!"); + + case ISD::BRCOND: { + //FIXME + abort(); + return; + } + + case ISD::BR: { + MachineBasicBlock *Dest = + cast(N.getOperand(1))->getBasicBlock(); + + Select(N.getOperand(0)); + BuildMI(BB, V8::BA, 1).addMBB(Dest); + return; + } + + case ISD::ImplicitDef: + Select(N.getOperand(0)); + BuildMI(BB, V8::IMPLICIT_DEF, 0, cast(N)->getReg()); + return; + + case ISD::EntryToken: return; // Noop + + case ISD::TokenFactor: + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) + Select(Node->getOperand(i)); + return; + + case ISD::CopyToReg: + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(1)); + Tmp2 = cast(N)->getReg(); + + if (Tmp1 != Tmp2) { + if (N.getOperand(1).getValueType() == MVT::f64 || + N.getOperand(1).getValueType() == MVT::f32) + BuildMI(BB, V8::FMOVS, 2, Tmp2).addReg(Tmp1); + else + BuildMI(BB, V8::ORrr, 2, Tmp2).addReg(Tmp1).addReg(V8::G0); + } + return; + + case ISD::RET: + //FIXME: + abort(); + return; + + case ISD::TRUNCSTORE: + case ISD::STORE: + { + SDOperand Chain = N.getOperand(0); + SDOperand Value = N.getOperand(1); + SDOperand Address = N.getOperand(2); + Select(Chain); + + Tmp1 = SelectExpr(Value); + Tmp2 = SelectExpr(Address); + + unsigned VT = opcode == ISD::STORE ? + Value.getValueType() : cast(Node)->getExtraValueType(); + switch(VT) { + default: assert(0 && "unknown Type in store"); + case MVT::f64: Opc = V8::STDFrr; break; + case MVT::f32: Opc = V8::STFrr; break; + case MVT::i1: //FIXME: DAG does not promote this load + case MVT::i8: Opc = V8::STBrr; break; + case MVT::i16: Opc = V8::STHrr; break; + case MVT::i32: Opc = V8::STLrr; break; + case MVT::i64: Opc = V8::STDrr; break; + } + + BuildMI(BB,Opc,2).addReg(Tmp1).addReg(Tmp2); + return; + } + + case ISD::EXTLOAD: + case ISD::SEXTLOAD: + case ISD::ZEXTLOAD: + case ISD::LOAD: + case ISD::CopyFromReg: + case ISD::TAILCALL: + case ISD::CALL: + case ISD::DYNAMIC_STACKALLOC: + ExprMap.erase(N); + SelectExpr(N); + return; + + case ISD::CALLSEQ_START: + case ISD::CALLSEQ_END: + Select(N.getOperand(0)); + Tmp1 = cast(N.getOperand(1))->getValue(); + + Opc = N.getOpcode() == ISD::CALLSEQ_START ? V8::ADJUSTCALLSTACKDOWN : + V8::ADJUSTCALLSTACKUP; + BuildMI(BB, Opc, 1).addImm(Tmp1); + return; + } + assert(0 && "Should not be reached!"); +} + + +/// createV8PatternInstructionSelector - This pass converts an LLVM function +/// into a machine code representation using pattern matching and a machine +/// description file. +/// +FunctionPass *llvm::createV8PatternInstructionSelector(TargetMachine &TM) { + return new ISel(TM); +} + +#endif -- 2.34.1