[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