[llvm-commits] CVS: llvm/lib/Target/SparcV8/SparcV8ISelPattern.cpp
Andrew Lenharth
alenhar2 at cs.uiuc.edu
Fri Jun 17 09:52:23 PDT 2005
Changes in directory llvm/lib/Target/SparcV8:
SparcV8ISelPattern.cpp added (r1.1)
---
Log message:
A start at a Sparc V8 Pattern ISel. Anyone want to implement the calling
convention? ;)
---
Diffs of the changes: (+479 -0)
SparcV8ISelPattern.cpp | 479 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 479 insertions(+)
Index: llvm/lib/Target/SparcV8/SparcV8ISelPattern.cpp
diff -c /dev/null llvm/lib/Target/SparcV8/SparcV8ISelPattern.cpp:1.1
*** /dev/null Fri Jun 17 11:52:22 2005
--- llvm/lib/Target/SparcV8/SparcV8ISelPattern.cpp Fri Jun 17 11:52:12 2005
***************
*** 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 <set>
+ #include <algorithm>
+ 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<SDOperand>
+ LowerArguments(Function &F, SelectionDAG &DAG);
+
+ /// LowerCallTo - This hook lowers an abstract call to a function into an
+ /// actual call.
+ virtual std::pair<SDOperand, SDOperand>
+ 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<SDOperand>
+ V8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
+ {
+ //FIXME
+ std::vector<SDOperand> ArgValues;
+
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo*MFI = MF.getFrameInfo();
+
+ MachineBasicBlock& BB = MF.front();
+
+ //return the arguments
+ return ArgValues;
+ }
+
+ std::pair<SDOperand, SDOperand>
+ 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<SDOperand, unsigned> 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<MVTSDNode>(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<RegSDNode>(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<BasicBlockSDNode>(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<RegSDNode>(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<RegSDNode>(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<MVTSDNode>(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<ConstantSDNode>(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
More information about the llvm-commits
mailing list