Let me introduce you to the early stages of the llvm backend for the alpha processor


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19764 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/Alpha/AlphaISelPattern.cpp b/lib/Target/Alpha/AlphaISelPattern.cpp
new file mode 100644
index 0000000..4431d8f
--- /dev/null
+++ b/lib/Target/Alpha/AlphaISelPattern.cpp
@@ -0,0 +1,797 @@
+//===-- AlphaISelPattern.cpp - A pattern matching inst selector for Alpha -----===//
+// 
+//                     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 Alpha.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Alpha.h"
+//#include "X86InstrBuilder.h"
+#include "AlphaRegisterInfo.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 <set>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+//  AlphaTargetLowering - Alpha Implementation of the TargetLowering interface
+namespace {
+  class AlphaTargetLowering : public TargetLowering {
+    int VarArgsFrameIndex;            // FrameIndex for start of varargs area.
+    unsigned GP; //GOT vreg
+  public:
+    AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) {
+      // Set up the TargetLowering object.
+      addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
+      addRegisterClass(MVT::f64, Alpha::FPRCRegisterClass);
+
+      setOperationAction(ISD::EXTLOAD          , MVT::i1   , Expand);
+      setOperationAction(ISD::EXTLOAD          , MVT::i8   , Expand);
+      setOperationAction(ISD::EXTLOAD          , MVT::i16  , Expand);
+      setOperationAction(ISD::ZEXTLOAD         , MVT::i1   , Expand);
+      setOperationAction(ISD::ZEXTLOAD         , MVT::i8   , Expand);
+      setOperationAction(ISD::ZEXTLOAD         , MVT::i16  , Expand);
+      setOperationAction(ISD::ZEXTLOAD         , MVT::i32  , Expand);
+      setOperationAction(ISD::SEXTLOAD         , MVT::i1   , Expand);
+      setOperationAction(ISD::SEXTLOAD         , MVT::i8   , Expand);
+      setOperationAction(ISD::SEXTLOAD         , MVT::i16  , Expand);
+
+      computeRegisterProperties();
+      
+      //      setOperationUnsupported(ISD::MUL, MVT::i8);
+      //      setOperationUnsupported(ISD::SELECT, MVT::i1);
+      //      setOperationUnsupported(ISD::SELECT, MVT::i8);
+      
+      //      addLegalFPImmediate(+0.0); // FLD0
+      //      addLegalFPImmediate(+1.0); // FLD1
+      //      addLegalFPImmediate(-0.0); // FLD0/FCHS
+      //      addLegalFPImmediate(-1.0); // FLD1/FCHS
+    }
+
+    /// 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, SDOperand Callee,
+                ArgListTy &Args, SelectionDAG &DAG);
+
+    virtual std::pair<SDOperand, SDOperand>
+    LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
+
+    virtual std::pair<SDOperand,SDOperand>
+    LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
+                   const Type *ArgTy, SelectionDAG &DAG);
+
+    virtual std::pair<SDOperand, SDOperand>
+    LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
+                            SelectionDAG &DAG);
+
+    void restoreGP(MachineBasicBlock* BB)
+    {
+      BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP);
+    }
+  };
+}
+
+//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21
+
+//For now, just use variable size stack frame format
+
+//In a standard call, the first six items are passed in registers $16
+//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
+//of argument-to-register correspondence.) The remaining items are
+//collected in a memory argument list that is a naturally aligned
+//array of quadwords. In a standard call, this list, if present, must
+//be passed at 0(SP).
+//7 ... n  	  	  	0(SP) ... (n-7)*8(SP)
+
+std::vector<SDOperand>
+AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) 
+{
+  std::vector<SDOperand> ArgValues;
+  
+  // //#define FP    $15
+  // //#define RA    $26
+  // //#define PV    $27
+  // //#define GP    $29
+  // //#define SP    $30
+  
+  //  assert(0 && "TODO");
+  MachineFunction &MF = DAG.getMachineFunction();
+  MachineFrameInfo *MFI = MF.getFrameInfo();
+
+  GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
+  MachineBasicBlock& BB = MF.front();
+
+  //Handle the return address
+  //BuildMI(&BB, Alpha::IDEF, 0, Alpha::R26);
+
+  unsigned args[] = {Alpha::R16, Alpha::R17, Alpha::R18, 
+		     Alpha::R19, Alpha::R20, Alpha::R21};
+  std::vector<unsigned> argVreg;
+
+  int count = 0;
+  for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I)
+    {
+      ++count;
+      assert(count <= 6 && "More than 6 args not supported");
+      assert(getValueType(I->getType()) != MVT::f64 && "No floats yet");
+      BuildMI(&BB, Alpha::IDEF, 0, args[count - 1]);
+      argVreg.push_back(MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64)));
+    }
+
+  BuildMI(&BB, Alpha::IDEF, 0, Alpha::R29);
+  BuildMI(&BB, Alpha::BIS, 2, GP).addReg(Alpha::R29).addReg(Alpha::R29);
+  count = 0;
+  for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I)
+    {
+      BuildMI(&BB, Alpha::BIS, 2, argVreg[count]).addReg(args[count]).addReg(args[count]);
+      
+      SDOperand argt, newroot;
+      switch (getValueType(I->getType()))
+	{
+	case MVT::i64:
+	  argt = newroot = DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot());
+	  break;
+	case MVT::i32:
+	  argt = newroot = DAG.getCopyFromReg(argVreg[count], MVT::i32, DAG.getRoot());
+	  break;
+	default:
+	  newroot = DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot());
+	  argt =  DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot);
+	}
+      DAG.setRoot(newroot.getValue(1));
+      ArgValues.push_back(argt);
+      ++count;
+    }
+  return ArgValues;
+}
+
+std::pair<SDOperand, SDOperand>
+AlphaTargetLowering::LowerCallTo(SDOperand Chain,
+				 const Type *RetTy, SDOperand Callee,
+				 ArgListTy &Args, SelectionDAG &DAG) {
+  int NumBytes = 0;
+  Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
+		      DAG.getConstant(NumBytes, getPointerTy()));
+  std::vector<SDOperand> args_to_use;
+  for (unsigned i = 0, e = Args.size(); i != e; ++i)
+    {
+      switch (getValueType(Args[i].second)) {
+      default: assert(0 && "Unexpected ValueType for argument!");
+      case MVT::i1:
+      case MVT::i8:
+      case MVT::i16:
+      case MVT::i32:
+	// Promote the integer to 64 bits.  If the input type is signed use a
+	// sign extend, otherwise use a zero extend.
+	if (Args[i].second->isSigned())
+	  Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
+	else
+	  Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
+	break;
+      case MVT::i64:
+	break;
+      }
+      args_to_use.push_back(Args[i].first);
+    }
+
+  std::vector<MVT::ValueType> RetVals;
+  MVT::ValueType RetTyVT = getValueType(RetTy);
+  if (RetTyVT != MVT::isVoid)
+    RetVals.push_back(RetTyVT);
+  RetVals.push_back(MVT::Other);
+
+  SDOperand TheCall = SDOperand(DAG.getCall(RetVals, Chain, Callee, args_to_use), 0);
+  Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
+  Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
+                      DAG.getConstant(NumBytes, getPointerTy()));
+   return std::make_pair(TheCall, Chain);
+}
+
+std::pair<SDOperand, SDOperand>
+AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
+  //vastart just returns the address of the VarArgsFrameIndex slot.
+  return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
+}
+
+std::pair<SDOperand,SDOperand> AlphaTargetLowering::
+LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
+                const Type *ArgTy, SelectionDAG &DAG) {
+  abort();
+}
+               
+
+std::pair<SDOperand, SDOperand> AlphaTargetLowering::
+LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
+                        SelectionDAG &DAG) {
+  abort();
+}
+
+
+
+
+
+namespace {
+
+  //===--------------------------------------------------------------------===//
+  /// ISel - Alpha specific code to select Alpha machine instructions for
+  /// SelectionDAG operations.
+  ///
+  class ISel : public SelectionDAGISel {
+
+    /// AlphaLowering - This object fully describes how to lower LLVM code to an
+    /// Alpha-specific SelectionDAG.
+    AlphaTargetLowering AlphaLowering;
+
+
+    /// 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.
+    std::map<SDOperand, unsigned> ExprMap;
+    std::set<SDOperand> LoweredTokens;
+
+  public:
+    ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM) {
+    }
+
+    /// InstructionSelectBasicBlock - This callback is invoked by
+    /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
+    virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
+      // Codegen the basic block.
+      Select(DAG.getRoot());
+
+      // Clear state used for selection.
+      ExprMap.clear();
+      LoweredTokens.clear();
+    }
+
+    unsigned SelectExpr(SDOperand N);
+    void Select(SDOperand N);
+  };
+}
+
+unsigned ISel::SelectExpr(SDOperand N) {
+  unsigned Result;
+  unsigned Tmp1, Tmp2, Tmp3;
+  unsigned Opc = 0;
+
+  SDNode *Node = N.Val;
+
+  unsigned &Reg = ExprMap[N];
+  if (Reg) return Reg;
+
+  if (N.getOpcode() != ISD::CALL)
+    Reg = Result = (N.getValueType() != MVT::Other) ?
+      MakeReg(N.getValueType()) : 1;
+  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 = 1;  // 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)] = 1;
+    }
+  }
+
+  switch (N.getOpcode()) {
+  default:
+    Node->dump();
+    assert(0 && "Node not handled!\n");
+ 
+  case ISD::FrameIndex:
+    Tmp1 = cast<FrameIndexSDNode>(N)->getIndex();
+    BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp1 * 8).addReg(Alpha::R30);
+    return Result;
+  
+  case ISD::EXTLOAD:
+  case ISD::SEXTLOAD:
+    // Make sure we generate both values.
+    if (Result != 1)
+      ExprMap[N.getValue(1)] = 1;   // Generate the token
+    else
+      Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
+    
+    Select(Node->getOperand(0)); // chain
+    Tmp1 = SelectExpr(Node->getOperand(1));
+    switch(Node->getValueType(0)) {
+    default: assert(0 && "Unknown type to sign extend to.");
+    case MVT::i64:
+      switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
+      default:
+        assert(0 && "Bad sign extend!");
+      case MVT::i32:
+	BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1);
+        break;
+      case MVT::i16:
+	BuildMI(BB, Alpha::LDW, 2, Result).addImm(0).addReg(Tmp1);
+        break;
+      case MVT::i8:
+	BuildMI(BB, Alpha::LDB, 2, Result).addImm(0).addReg(Tmp1);
+        break;
+      }
+      break;
+    }
+    return Result;
+
+  case ISD::GlobalAddress:
+    AlphaLowering.restoreGP(BB);
+    BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
+      .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
+    return Result;
+
+  case ISD::CALL:
+    {
+      Select(N.getOperand(0));
+
+      // The chain for this call is now lowered.
+      ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), 1));
+      
+      //grab the arguments
+      std::vector<unsigned> argvregs;
+      assert(Node->getNumOperands() < 8 && "Only 6 args supported");
+      for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
+      {
+	argvregs.push_back(SelectExpr(N.getOperand(i)));
+      }
+      for(int i = 0, e = argvregs.size(); i < e; ++i)
+      {
+	unsigned args[] = {Alpha::R16, Alpha::R17, Alpha::R18, 
+			   Alpha::R19, Alpha::R20, Alpha::R21};
+	
+	BuildMI(BB, Alpha::BIS, 2, args[i]).addReg(argvregs[i]).addReg(argvregs[i]);
+      }
+
+    //build the right kind of call
+    if (GlobalAddressSDNode *GASD =
+               dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) 
+      {
+	Select(N.getOperand(0));
+	AlphaLowering.restoreGP(BB);
+	BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
+      }
+    else if (ExternalSymbolSDNode *ESSDN =
+	     dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) 
+      {
+	Select(N.getOperand(0));
+	AlphaLowering.restoreGP(BB);
+	BuildMI(BB, Alpha::CALL, 0).addExternalSymbol(ESSDN->getSymbol(), true);
+      } 
+    else {
+      Select(N.getOperand(0));
+      Tmp1 = SelectExpr(N.getOperand(1));
+      BuildMI(BB, Alpha::CALL, 1).addReg(Tmp1);
+      AlphaLowering.restoreGP(BB);
+    }
+
+    //push the result into a virtual register
+    //    if (Result != 1)
+    //      BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
+
+    switch (Node->getValueType(0)) {
+    default: assert(0 && "Unknown value type for call result!");
+    case MVT::Other: return 1;
+    case MVT::i1:
+    case MVT::i8:
+    case MVT::i16:
+    case MVT::i32:
+    case MVT::i64:
+      BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
+    break;
+    }
+    return Result+N.ResNo;
+    }    
+  
+  case ISD::SIGN_EXTEND:
+    {
+      std::cerr << "DestT: " << N.getValueType() << "\n";
+      std::cerr << "SrcT: " << N.getOperand(0).getValueType() << "\n";
+      assert(0 && "Sign Extend not there yet");
+      return Result;
+    }
+  case ISD::SIGN_EXTEND_INREG:
+    {
+      Tmp1 = SelectExpr(N.getOperand(0));
+      MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
+      std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
+      switch(MVN->getExtraValueType())
+	{
+	default:
+	  assert(0 && "Sign Extend InReg not there yet");
+	  break;
+	case MVT::i32:
+	  {
+	    Tmp2 = MakeReg(MVT::i64);
+	    unsigned Tmp3 = MakeReg(MVT::i64);
+	    BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(16);
+	    BuildMI(BB, Alpha::SL, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
+	    BuildMI(BB, Alpha::SRA, 2, Result).addReg(Tmp3).addReg(Tmp2);
+	    break;
+	  }
+	case MVT::i16:
+	  BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
+	  break;
+	case MVT::i8:
+	  BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
+	  break;
+	}
+      return Result;
+    }
+  case ISD::ZERO_EXTEND_INREG:
+    {
+      Tmp1 = SelectExpr(N.getOperand(0));
+      MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
+      std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
+      switch(MVN->getExtraValueType())
+	{
+	default:
+	  assert(0 && "Zero Extend InReg not there yet");
+	  break;
+	case MVT::i32:
+	  {
+	    Tmp2 = MakeReg(MVT::i64);
+	    BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(0xf0);
+	    BuildMI(BB, Alpha::ZAP, 2, Result).addReg(Tmp1).addReg(Tmp2);
+	    break;
+	  }
+	case MVT::i16:
+	    Tmp2 = MakeReg(MVT::i64);
+	    BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(0xfc);
+	    BuildMI(BB, Alpha::ZAP, 2, Result).addReg(Tmp1).addReg(Tmp2);
+	    break;
+	case MVT::i8:
+	    Tmp2 = MakeReg(MVT::i64);
+	    BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(0xfe);
+	    BuildMI(BB, Alpha::ZAP, 2, Result).addReg(Tmp1).addReg(Tmp2);
+	    break;
+	}
+      return Result;
+    }
+    
+  case ISD::SETCC:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
+      if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
+	switch (SetCC->getCondition()) {
+	default: assert(0 && "Unknown integer comparison!");
+	case ISD::SETEQ:
+	  BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
+	  break;
+	case ISD::SETGT:
+	  BuildMI(BB, Alpha::CMPLT, 2, Result).addReg(Tmp2).addReg(Tmp1);
+	  break;
+	case ISD::SETGE:
+	  BuildMI(BB, Alpha::CMPLE, 2, Result).addReg(Tmp2).addReg(Tmp1);
+	  break;
+	case ISD::SETLT:
+	  BuildMI(BB, Alpha::CMPLT, 2, Result).addReg(Tmp1).addReg(Tmp2);
+	  break;
+	case ISD::SETLE:
+	  BuildMI(BB, Alpha::CMPLE, 2, Result).addReg(Tmp1).addReg(Tmp2);
+	  break;
+	case ISD::SETNE:
+	  {
+	    unsigned Tmp3 = MakeReg(MVT::i64);
+	    BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
+	    BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp3).addReg(Alpha::R31);
+	    break;
+	  }
+	case ISD::SETULT:
+	  BuildMI(BB, Alpha::CMPULT, 2, Result).addReg(Tmp1).addReg(Tmp2);
+	  break;
+	case ISD::SETUGT:
+	  BuildMI(BB, Alpha::CMPULT, 2, Result).addReg(Tmp2).addReg(Tmp1);
+	  break;
+	case ISD::SETULE:
+	  BuildMI(BB, Alpha::CMPULE, 2, Result).addReg(Tmp1).addReg(Tmp2);
+	  break;
+	case ISD::SETUGE:
+	  BuildMI(BB, Alpha::CMPULE, 2, Result).addReg(Tmp2).addReg(Tmp1);
+	  break;
+	}
+      }
+      else
+	assert(0 && "only integer");
+    }
+    else
+      assert(0 && "Not a setcc in setcc");
+
+    return Result;
+
+  case ISD::CopyFromReg:
+    {
+      if (Result == 1)
+	Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
+      
+      SDOperand Chain   = N.getOperand(0);
+
+      Select(Chain);
+      unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
+      //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
+      BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
+      return Result;
+    }
+
+  case ISD::ADD:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Alpha::ADDQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+  case ISD::SUB:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+
+  case ISD::AND:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Alpha::AND, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+  case ISD::OR:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Alpha::BIS, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+  case ISD::XOR:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Alpha::XOR, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+
+  case ISD::MUL:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Alpha::MULQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+  case ISD::UREM:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+        BuildMI(BB, Alpha::REMQU, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+
+  case ISD::SELECT:
+    {
+      Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
+      Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
+      Tmp1 = SelectExpr(N.getOperand(0)); //Cond
+      // Get the condition into the zero flag.
+      unsigned dummy = MakeReg(MVT::i64);
+      BuildMI(BB, Alpha::BIS, 2, dummy).addReg(Tmp3).addReg(Tmp3);
+      BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
+      return Result;
+    }
+
+  case ISD::SHL:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Alpha::SL, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+  case ISD::SRL:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Alpha::SRL, 1, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+  case ISD::SRA:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Alpha::SRA, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+
+  case ISD::Constant:
+    {
+      long val = cast<ConstantSDNode>(N)->getValue();
+      BuildMI(BB, Alpha::LOAD_IMM, 1, Result).addImm(val);
+      return Result;
+    }
+
+
+
+  case ISD::LOAD: 
+    {
+      // Make sure we generate both values.
+      if (Result != 1)
+	ExprMap[N.getValue(1)] = 1;   // Generate the token
+      else
+	Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
+      
+      SDOperand Chain   = N.getOperand(0);
+      SDOperand Address = N.getOperand(1);
+
+      if (Address.getOpcode() == ISD::GlobalAddress)
+	{
+	  Select(Chain);
+	  AlphaLowering.restoreGP(BB);
+	  BuildMI(BB, Alpha::LOAD, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
+	}
+      else
+	{
+	  Select(Chain);
+	  Tmp2 = SelectExpr(Address);
+	  BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp2);
+	}
+      return Result;
+    }
+  }
+
+  return 0;
+}
+
+void ISel::Select(SDOperand N) {
+  unsigned Tmp1, Tmp2, Opc;
+
+  // FIXME: Disable for our current expansion model!
+  if (/*!N->hasOneUse() &&*/ !LoweredTokens.insert(N).second)
+    return;  // Already selected.
+
+  SDNode *Node = N.Val;
+
+  switch (N.getOpcode()) {
+
+  default:
+    Node->dump(); std::cerr << "\n";
+    assert(0 && "Node not handled yet!");
+
+  case ISD::BRCOND: {
+    MachineBasicBlock *Dest =
+      cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
+
+    Select(N.getOperand(0));
+    Tmp1 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
+    return;
+  }
+
+  case ISD::BR: {
+    MachineBasicBlock *Dest =
+      cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
+
+    Select(N.getOperand(0));
+    BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
+    return;
+  }
+
+  case ISD::ImplicitDef:
+    Select(N.getOperand(0));
+    BuildMI(BB, Alpha::IDEF, 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));
+    
+    //N.Val->dump(); std::cerr << "\n";
+    //assert(0 && "Node not handled yet!");
+    
+    return;
+
+  case ISD::CopyToReg:
+    Select(N.getOperand(0));
+    Tmp1 = SelectExpr(N.getOperand(1));
+    Tmp2 = cast<RegSDNode>(N)->getReg();
+    
+    if (Tmp1 != Tmp2) {
+      BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
+    }
+    return;
+
+   case ISD::RET:
+     switch (N.getNumOperands()) {
+     default:
+       std::cerr << N.getNumOperands() << "\n";
+       for (unsigned i = 0; i < N.getNumOperands(); ++i)
+	 std::cerr << N.getOperand(i).getValueType() << "\n";
+       assert(0 && "Unknown return instruction!");
+     case 2:
+       Select(N.getOperand(0));
+       Tmp1 = SelectExpr(N.getOperand(1));
+       switch (N.getOperand(1).getValueType()) {
+       default: assert(0 && "All other types should have been promoted!!");
+       case MVT::i64:
+	 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
+	 break;
+       }
+       break;
+     case 1:
+       Select(N.getOperand(0));
+       break;
+     }
+     //Tmp2 = AlphaLowering.getRetAddr();
+     //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
+     BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
+     return;
+
+  case ISD::STORE: 
+    Select(N.getOperand(0));
+    Tmp1 = SelectExpr(N.getOperand(1)); //value
+    if (N.getOperand(2).getOpcode() == ISD::GlobalAddress)
+      {
+	AlphaLowering.restoreGP(BB);
+	BuildMI(BB, Alpha::STORE, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(N.getOperand(2))->getGlobal());
+      }
+    else
+      {
+	Tmp2 = SelectExpr(N.getOperand(2)); //address
+	BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addImm(0).addReg(Tmp2);
+      }
+    return;
+
+  case ISD::EXTLOAD:
+  case ISD::SEXTLOAD:
+  case ISD::ZEXTLOAD:
+  case ISD::LOAD:
+  case ISD::CopyFromReg:
+  case ISD::CALL:
+//   case ISD::DYNAMIC_STACKALLOC:
+    SelectExpr(N);
+    return;
+
+
+  case ISD::TRUNCSTORE: {  // truncstore chain, val, ptr :storety
+    MVT::ValueType StoredTy = cast<MVTSDNode>(Node)->getExtraValueType();
+    assert(StoredTy != MVT::i64 && "Unsupported TRUNCSTORE for this target!");
+
+    Select(N.getOperand(0));
+    Tmp1 = SelectExpr(N.getOperand(1));
+    Tmp2 = SelectExpr(N.getOperand(2));
+
+    switch (StoredTy) {
+    default: assert(0 && "Unhandled Type"); break;
+    case MVT::i8: Opc = Alpha::STB; break;
+    case MVT::i16: Opc = Alpha::STW; break;
+    case MVT::i32: Opc = Alpha::STL; break;
+    }
+
+    BuildMI(BB, Opc, 2).addReg(Tmp1).addImm(0).addReg(Tmp2);
+    return;
+  }
+
+  case ISD::ADJCALLSTACKDOWN:
+  case ISD::ADJCALLSTACKUP:
+    Select(N.getOperand(0));
+    Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
+    
+    Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
+      Alpha::ADJUSTSTACKUP;
+    BuildMI(BB, Opc, 1).addImm(Tmp1);
+    return;
+  }
+  assert(0 && "Should not be reached!");
+}
+
+
+/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
+/// into a machine code representation using pattern matching and a machine
+/// description file.
+///
+FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
+  return new ISel(TM);  
+}