new nodes
[oota-llvm.git] / lib / Target / IA64 / IA64ISelPattern.cpp
index 996f722cbe7cd1e7e1e29d178f1c839a99a1fe07..3aeb1598b6013ea171f12a662f52df43eee6b65b 100644 (file)
@@ -1,10 +1,10 @@
 //===-- IA64ISelPattern.cpp - A pattern matching inst selector for IA64 ---===//
-// 
+//
 //                     The LLVM Compiler Infrastructure
 //
 // This file was developed by Duraid Madina 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 IA64.
@@ -28,6 +28,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/ADT/Statistic.h"
 #include <set>
+#include <map>
 #include <algorithm>
 using namespace llvm;
 
@@ -36,7 +37,7 @@ using namespace llvm;
 namespace {
   class IA64TargetLowering : public TargetLowering {
     int VarArgsFrameIndex;            // FrameIndex for start of varargs area.
-    
+
     //int ReturnAddrIndex;              // FrameIndex for return slot.
     unsigned GP, SP, RP; // FIXME - clean this mess up
   public:
@@ -45,41 +46,70 @@ namespace {
    // for ISD::RET down below. add an accessor instead? FIXME
 
    IA64TargetLowering(TargetMachine &TM) : TargetLowering(TM) {
-      
+
       // register class for general registers
       addRegisterClass(MVT::i64, IA64::GRRegisterClass);
 
       // register class for FP registers
       addRegisterClass(MVT::f64, IA64::FPRegisterClass);
-      
-      // register class for predicate registers 
+
+      // register class for predicate registers
       addRegisterClass(MVT::i1, IA64::PRRegisterClass);
-      
+
       setOperationAction(ISD::BRCONDTWOWAY     , MVT::Other, Expand);
+      setOperationAction(ISD::BRTWOWAY_CC      , MVT::Other, Expand);
       setOperationAction(ISD::FP_ROUND_INREG   , MVT::f32  , Expand);
 
-      setSetCCResultType(MVT::i1); 
+      setSetCCResultType(MVT::i1);
       setShiftAmountType(MVT::i64);
 
       setOperationAction(ISD::EXTLOAD          , MVT::i1   , Promote);
-      setOperationAction(ISD::EXTLOAD          , MVT::f32  , Promote);
 
       setOperationAction(ISD::ZEXTLOAD         , MVT::i1   , 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);
+      setOperationAction(ISD::SEXTLOAD         , MVT::i32  , Expand);
 
-      setOperationAction(ISD::SREM             , MVT::f32  , Expand);
-      setOperationAction(ISD::SREM             , MVT::f64  , Expand);
+      setOperationAction(ISD::FREM             , MVT::f32  , Expand);
+      setOperationAction(ISD::FREM             , MVT::f64  , Expand);
 
       setOperationAction(ISD::UREM             , MVT::f32  , Expand);
       setOperationAction(ISD::UREM             , MVT::f64  , Expand);
-      
+
       setOperationAction(ISD::MEMMOVE          , MVT::Other, Expand);
       setOperationAction(ISD::MEMSET           , MVT::Other, Expand);
       setOperationAction(ISD::MEMCPY           , MVT::Other, Expand);
+      
+      setOperationAction(ISD::SINT_TO_FP       , MVT::i1   , Promote);
+      setOperationAction(ISD::UINT_TO_FP       , MVT::i1   , Promote);
+      
+      // 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);
+
+      //IA64 has these, but they are not implemented
+      setOperationAction(ISD::CTTZ , MVT::i64  , Expand);
+      setOperationAction(ISD::CTLZ , MVT::i64  , Expand);
+      setOperationAction(ISD::ROTL , MVT::i64  , Expand);
+      setOperationAction(ISD::ROTR , MVT::i64  , Expand);
+      // FIXME: implement mulhs (xma.h) and mulhu (xma.hu)
+      setOperationAction(ISD::MULHS , MVT::i64  , Expand);
+      setOperationAction(ISD::MULHU , MVT::i64  , Expand);
+
+      // We don't have line number support yet.
+      setOperationAction(ISD::LOCATION, MVT::Other, Expand);
+      setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
+      setOperationAction(ISD::DEBUG_LABEL, MVT::Other, Expand);
+
+      // Not implemented yet.
+      setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 
+      setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
 
       computeRegisterProperties();
 
@@ -97,19 +127,15 @@ namespace {
     /// 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,
-                SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
-
-    virtual std::pair<SDOperand, SDOperand>
-    LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
+    LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC,
+                bool isTailCall, SDOperand Callee, ArgListTy &Args,
+                SelectionDAG &DAG);
 
+    virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
+                                   Value *VAListV, 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);
+      LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
+                 const Type *ArgTy, SelectionDAG &DAG);
 
     void restoreGP_SP_RP(MachineBasicBlock* BB)
     {
@@ -155,80 +181,84 @@ IA64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
 
   MachineBasicBlock& BB = MF.front();
 
-  unsigned args_int[] = {IA64::r32, IA64::r33, IA64::r34, IA64::r35, 
+  unsigned args_int[] = {IA64::r32, IA64::r33, IA64::r34, IA64::r35,
                          IA64::r36, IA64::r37, IA64::r38, IA64::r39};
-  unsigned args_FP[] = {IA64::F8, IA64::F9, IA64::F10, IA64::F11, 
+
+  unsigned args_FP[] = {IA64::F8, IA64::F9, IA64::F10, IA64::F11,
                         IA64::F12,IA64::F13,IA64::F14, IA64::F15};
+
   unsigned argVreg[8];
   unsigned argPreg[8];
   unsigned argOpc[8];
 
   unsigned used_FPArgs = 0; // how many FP args have been used so far?
+
   unsigned ArgOffset = 0;
   int count = 0;
-  
+
   for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
     {
       SDOperand newroot, argt;
       if(count < 8) { // need to fix this logic? maybe.
-         
-       switch (getValueType(I->getType())) {
-         default:
-           std::cerr << "ERROR in LowerArgs: unknown type "
-             << getValueType(I->getType()) << "\n";
-           abort();
-         case MVT::f32:
-           // fixme? (well, will need to for weird FP structy stuff, 
-           // see intel ABI docs)
-         case MVT::f64:
-           BuildMI(&BB, IA64::IDEF, 0, args_FP[used_FPArgs]);
-           // floating point args go into f8..f15 as-needed, the increment
-           argVreg[count] =                              // is below..:
-           MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::f64));
-           // FP args go into f8..f15 as needed: (hence the ++)
-           argPreg[count] = args_FP[used_FPArgs++];
-           argOpc[count] = IA64::FMOV;
-           argt = newroot = DAG.getCopyFromReg(argVreg[count],
-               getValueType(I->getType()), DAG.getRoot());
-           break;
-         case MVT::i1: // NOTE: as far as C abi stuff goes,
-                       // bools are just boring old ints
-         case MVT::i8:
-         case MVT::i16:
-         case MVT::i32:
-         case MVT::i64:
-           BuildMI(&BB, IA64::IDEF, 0, args_int[count]);
-           argVreg[count] = 
-           MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
-           argPreg[count] = args_int[count];
-           argOpc[count] = IA64::MOV; 
-           argt = newroot =
-             DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot());
-           if ( getValueType(I->getType()) != MVT::i64)
-             argt = DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()),
-                 newroot);
-           break;
-       }
+
+        switch (getValueType(I->getType())) {
+          default:
+            std::cerr << "ERROR in LowerArgs: unknown type "
+              << getValueType(I->getType()) << "\n";
+            abort();
+          case MVT::f32:
+            // fixme? (well, will need to for weird FP structy stuff,
+            // see intel ABI docs)
+          case MVT::f64:
+//XXX            BuildMI(&BB, IA64::IDEF, 0, args_FP[used_FPArgs]);
+            MF.addLiveIn(args_FP[used_FPArgs]); // mark this reg as liveIn
+            // floating point args go into f8..f15 as-needed, the increment
+            argVreg[count] =                              // is below..:
+            MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::f64));
+            // FP args go into f8..f15 as needed: (hence the ++)
+            argPreg[count] = args_FP[used_FPArgs++];
+            argOpc[count] = IA64::FMOV;
+            argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), argVreg[count],
+                                                MVT::f64);
+            if (I->getType() == Type::FloatTy)
+              argt = DAG.getNode(ISD::FP_ROUND, MVT::f32, argt);
+            break;
+          case MVT::i1: // NOTE: as far as C abi stuff goes,
+                        // bools are just boring old ints
+          case MVT::i8:
+          case MVT::i16:
+          case MVT::i32:
+          case MVT::i64:
+//XXX            BuildMI(&BB, IA64::IDEF, 0, args_int[count]);
+            MF.addLiveIn(args_int[count]); // mark this register as liveIn
+            argVreg[count] =
+            MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
+            argPreg[count] = args_int[count];
+            argOpc[count] = IA64::MOV;
+            argt = newroot =
+              DAG.getCopyFromReg(DAG.getRoot(), argVreg[count], MVT::i64);
+            if ( getValueType(I->getType()) != MVT::i64)
+              argt = DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()),
+                  newroot);
+            break;
+        }
       } else { // more than 8 args go into the frame
-       // Create the frame index object for this incoming parameter...
-       ArgOffset = 16 + 8 * (count - 8);
-       int FI = MFI->CreateFixedObject(8, ArgOffset);
-         
-       // Create the SelectionDAG nodes corresponding to a load 
-       //from this parameter
-       SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
-       argt = newroot = DAG.getLoad(getValueType(I->getType()), 
-           DAG.getEntryNode(), FIN);
+        // Create the frame index object for this incoming parameter...
+        ArgOffset = 16 + 8 * (count - 8);
+        int FI = MFI->CreateFixedObject(8, ArgOffset);
+
+        // Create the SelectionDAG nodes corresponding to a load
+        //from this parameter
+        SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
+        argt = newroot = DAG.getLoad(getValueType(I->getType()),
+                                     DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL));
       }
       ++count;
       DAG.setRoot(newroot.getValue(1));
       ArgValues.push_back(argt);
-    }    
+    }
+
 
-       
   // Create a vreg to hold the output of (what will become)
   // the "alloc" instruction
   VirtGPR = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
@@ -250,14 +280,14 @@ IA64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
   // ..hmm.
 
   unsigned tempOffset=0;
+
   // if this is a varargs function, we simply lower llvm.va_start by
   // pointing to the first entry
   if(F.isVarArg()) {
     tempOffset=0;
     VarArgsFrameIndex = MFI->CreateFixedObject(8, tempOffset);
   }
+
   // here we actually do the moving of args, and store them to the stack
   // too if this is a varargs function:
   for (int i = 0; i < count && i < 8; ++i) {
@@ -272,13 +302,33 @@ IA64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
     }
   }
 
+  // Finally, inform the code generator which regs we return values in.
+  // (see the ISD::RET: case down below)
+  switch (getValueType(F.getReturnType())) {
+  default: assert(0 && "i have no idea where to return this type!");
+  case MVT::isVoid: break;
+  case MVT::i1:
+  case MVT::i8:
+  case MVT::i16:
+  case MVT::i32:
+  case MVT::i64:
+    MF.addLiveOut(IA64::r8);
+    break;
+  case MVT::f32:
+  case MVT::f64:
+    MF.addLiveOut(IA64::F8);
+    break;
+  }
+
   return ArgValues;
 }
-  
+
 std::pair<SDOperand, SDOperand>
 IA64TargetLowering::LowerCallTo(SDOperand Chain,
-                                const Type *RetTy, bool isVarArg,
-         SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG) {
+                                const Type *RetTy, bool isVarArg,
+                                unsigned CallingConv, bool isTailCall,
+                                SDOperand Callee, ArgListTy &Args,
+                                SelectionDAG &DAG) {
 
   MachineFunction &MF = DAG.getMachineFunction();
 
@@ -291,17 +341,17 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
   } else {
     outRegsUsed = Args.size();
   }
+
   // FIXME? this WILL fail if we ever try to pass around an arg that
   // consumes more than a single output slot (a 'real' double, int128
   // some sort of aggregate etc.), as we'll underestimate how many 'outX'
   // registers we use. Hopefully, the assembler will notice.
   MF.getInfo<IA64FunctionInfo>()->outRegsUsed=
     std::max(outRegsUsed, MF.getInfo<IA64FunctionInfo>()->outRegsUsed);
-  
-  Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
+
+  Chain = DAG.getNode(ISD::CALLSEQ_START, MVT::Other, Chain,
                         DAG.getConstant(NumBytes, getPointerTy()));
+
   std::vector<SDOperand> args_to_use;
   for (unsigned i = 0, e = Args.size(); i != e; ++i)
     {
@@ -311,18 +361,18 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
       case MVT::i8:
       case MVT::i16:
       case MVT::i32:
-       //promote to 64-bits, sign/zero extending based on type
-       //of the argument
-       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;
+        //promote to 64-bits, sign/zero extending based on type
+        //of the argument
+        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::f32:
-       //promote to 64-bits
-       Args[i].first = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Args[i].first);
+        //promote to 64-bits
+        Args[i].first = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Args[i].first);
       case MVT::f64:
       case MVT::i64:
         break;
@@ -337,51 +387,46 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
   RetVals.push_back(MVT::Other);
 
   SDOperand TheCall = SDOperand(DAG.getCall(RetVals, Chain,
-       Callee, args_to_use), 0);
+                                            Callee, args_to_use), 0);
   Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
-  Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
+  Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
                       DAG.getConstant(NumBytes, getPointerTy()));
   return std::make_pair(TheCall, Chain);
 }
 
-std::pair<SDOperand, SDOperand>
-IA64TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
-  // vastart just returns the address of the VarArgsFrameIndex slot.
-  return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
+SDOperand
+IA64TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
+                                 Value *VAListV, SelectionDAG &DAG) {
+  // vastart just stores the address of the VarArgsFrameIndex slot.
+  SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64);
+  return DAG.getNode(ISD::STORE, MVT::Other, Chain, FR,
+                     VAListP, DAG.getSrcValue(VAListV));
 }
 
 std::pair<SDOperand,SDOperand> IA64TargetLowering::
-LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
-               const Type *ArgTy, SelectionDAG &DAG) {
+LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
+           const Type *ArgTy, SelectionDAG &DAG) {
 
   MVT::ValueType ArgVT = getValueType(ArgTy);
-  SDOperand Result;
-  if (!isVANext) {
-    Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList);
-  } else {
-    unsigned Amt;
-    if (ArgVT == MVT::i32 || ArgVT == MVT::f32)
-      Amt = 8;
-    else {
-      assert((ArgVT == MVT::i64 || ArgVT == MVT::f64) &&
-             "Other types should have been promoted for varargs!");
-      Amt = 8;
-    }
-    Result = DAG.getNode(ISD::ADD, VAList.getValueType(), VAList,
-                         DAG.getConstant(Amt, VAList.getValueType()));
+  SDOperand Val = DAG.getLoad(MVT::i64, Chain,
+                              VAListP, DAG.getSrcValue(VAListV));
+  SDOperand Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), Val,
+                                 DAG.getSrcValue(NULL));
+  unsigned Amt;
+  if (ArgVT == MVT::i32 || ArgVT == MVT::f32)
+    Amt = 8;
+  else {
+    assert((ArgVT == MVT::i64 || ArgVT == MVT::f64) &&
+           "Other types should have been promoted for varargs!");
+    Amt = 8;
   }
+  Val = DAG.getNode(ISD::ADD, Val.getValueType(), Val,
+                    DAG.getConstant(Amt, Val.getValueType()));
+  Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                      Val, VAListP, DAG.getSrcValue(VAListV));
   return std::make_pair(Result, Chain);
 }
 
-std::pair<SDOperand, SDOperand> IA64TargetLowering::
-LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
-                        SelectionDAG &DAG) {
-
-  assert(0 && "LowerFrameReturnAddress not done yet\n");
-  abort();
-}
-
-
 namespace {
 
   //===--------------------------------------------------------------------===//
@@ -392,6 +437,9 @@ namespace {
     /// IA64Lowering - This object fully describes how to lower LLVM code to an
     /// IA64-specific SelectionDAG.
     IA64TargetLowering IA64Lowering;
+    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
@@ -400,8 +448,8 @@ namespace {
     std::set<SDOperand> LoweredTokens;
 
   public:
-    ISel(TargetMachine &TM) : SelectionDAGISel(IA64Lowering), IA64Lowering(TM) {
-    }
+    ISel(TargetMachine &TM) : SelectionDAGISel(IA64Lowering), IA64Lowering(TM),
+                              ISelDAG(0) { }
 
     /// InstructionSelectBasicBlock - This callback is invoked by
     /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
@@ -409,6 +457,10 @@ namespace {
 
     unsigned SelectExpr(SDOperand N);
     void Select(SDOperand N);
+    // a dag->dag to transform mul-by-constant-int to shifts+adds/subs
+    SDOperand BuildConstmulSequence(SDOperand N);
+
+    const char *getPassName() const { return "IA64 Instruction Selector"; }
   };
 }
 
@@ -417,23 +469,403 @@ namespace {
 void ISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
 
   // Codegen the basic block.
+  ISelDAG = &DAG;
   Select(DAG.getRoot());
 
   // Clear state used for selection.
   ExprMap.clear();
   LoweredTokens.clear();
+  ISelDAG = 0;
 }
 
-/// ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N.  It
-/// returns zero when the input is not exactly a power of two.
-static uint64_t ExactLog2(uint64_t Val) {
-  if (Val == 0 || (Val & (Val-1))) return 0;
-  unsigned Count = 0;
-  while (Val != 1) {
-    Val >>= 1;
-    ++Count;
+// strip leading '0' characters from a string
+void munchLeadingZeros(std::string& inString) {
+  while(inString.c_str()[0]=='0') {
+    inString.erase(0, 1);
   }
-  return Count;
+}
+
+// strip trailing '0' characters from a string
+void munchTrailingZeros(std::string& inString) {
+  int curPos=inString.length()-1;
+
+  while(inString.c_str()[curPos]=='0') {
+    inString.erase(curPos, 1);
+    curPos--;
+  }
+}
+
+// return how many consecutive '0' characters are at the end of a string
+unsigned int countTrailingZeros(std::string& inString) {
+  int curPos=inString.length()-1;
+  unsigned int zeroCount=0;
+  // assert goes here
+  while(inString.c_str()[curPos--]=='0') {
+    zeroCount++;
+  }
+  return zeroCount;
+}
+
+// booth encode a string of '1' and '0' characters (returns string of 'P' (+1)
+// '0' and 'N' (-1) characters)
+void boothEncode(std::string inString, std::string& boothEncodedString) {
+
+  int curpos=0;
+  int replacements=0;
+  int lim=inString.size();
+
+  while(curpos<lim) {
+    if(inString[curpos]=='1') { // if we see a '1', look for a run of them
+      int runlength=0;
+      std::string replaceString="N";
+
+      // find the run length
+      for(;inString[curpos+runlength]=='1';runlength++) ;
+
+      for(int i=0; i<runlength-1; i++)
+        replaceString+="0";
+      replaceString+="1";
+
+      if(runlength>1) {
+        inString.replace(curpos, runlength+1, replaceString);
+        curpos+=runlength-1;
+      } else
+        curpos++;
+    } else { // a zero, we just keep chugging along
+      curpos++;
+    }
+  }
+
+  // clean up (trim the string, reverse it and turn '1's into 'P's)
+  munchTrailingZeros(inString);
+  boothEncodedString="";
+
+  for(int i=inString.size()-1;i>=0;i--)
+    if(inString[i]=='1')
+      boothEncodedString+="P";
+    else
+      boothEncodedString+=inString[i];
+
+}
+
+struct shiftaddblob { // this encodes stuff like (x=) "A << B [+-] C << D"
+  unsigned firstVal;    // A
+  unsigned firstShift;  // B
+  unsigned secondVal;   // C
+  unsigned secondShift; // D
+  bool isSub;
+};
+
+/* this implements Lefevre's "pattern-based" constant multiplication,
+ * see "Multiplication by an Integer Constant", INRIA report 1999-06
+ *
+ * TODO: implement a method to try rewriting P0N<->0PP / N0P<->0NN
+ * to get better booth encodings - this does help in practice
+ * TODO: weight shifts appropriately (most architectures can't
+ * fuse a shift and an add for arbitrary shift amounts) */
+unsigned lefevre(const std::string inString,
+                 std::vector<struct shiftaddblob> &ops) {
+  std::string retstring;
+  std::string s = inString;
+  munchTrailingZeros(s);
+
+  int length=s.length()-1;
+
+  if(length==0) {
+    return(0);
+  }
+
+  std::vector<int> p,n;
+
+  for(int i=0; i<=length; i++) {
+    if (s.c_str()[length-i]=='P') {
+      p.push_back(i);
+    } else if (s.c_str()[length-i]=='N') {
+      n.push_back(i);
+    }
+  }
+
+  std::string t, u;
+  int c = 0;
+  bool f;
+  std::map<const int, int> w;
+
+  for(unsigned i=0; i<p.size(); i++) {
+    for(unsigned j=0; j<i; j++) {
+      w[p[i]-p[j]]++;
+    }
+  }
+
+  for(unsigned i=1; i<n.size(); i++) {
+    for(unsigned j=0; j<i; j++) {
+      w[n[i]-n[j]]++;
+    }
+  }
+
+  for(unsigned i=0; i<p.size(); i++) {
+    for(unsigned j=0; j<n.size(); j++) {
+      w[-abs(p[i]-n[j])]++;
+    }
+  }
+
+  std::map<const int, int>::const_iterator ii;
+  std::vector<int> d;
+  std::multimap<int, int> sorted_by_value;
+
+  for(ii = w.begin(); ii!=w.end(); ii++)
+    sorted_by_value.insert(std::pair<int, int>((*ii).second,(*ii).first));
+
+  for (std::multimap<int, int>::iterator it = sorted_by_value.begin();
+       it != sorted_by_value.end(); ++it) {
+    d.push_back((*it).second);
+  }
+
+  int int_W=0;
+  int int_d;
+
+  while(d.size()>0 && (w[int_d=d.back()] > int_W)) {
+    d.pop_back();
+    retstring=s; // hmmm
+    int x=0;
+    int z=abs(int_d)-1;
+
+    if(int_d>0) {
+
+      for(unsigned base=0; base<retstring.size(); base++) {
+        if( ((base+z+1) < retstring.size()) &&
+           retstring.c_str()[base]=='P' &&
+           retstring.c_str()[base+z+1]=='P')
+        {
+          // match
+          x++;
+          retstring.replace(base, 1, "0");
+          retstring.replace(base+z+1, 1, "p");
+        }
+      }
+
+      for(unsigned base=0; base<retstring.size(); base++) {
+        if( ((base+z+1) < retstring.size()) &&
+           retstring.c_str()[base]=='N' &&
+           retstring.c_str()[base+z+1]=='N')
+        {
+          // match
+          x++;
+          retstring.replace(base, 1, "0");
+          retstring.replace(base+z+1, 1, "n");
+        }
+      }
+
+    } else {
+      for(unsigned base=0; base<retstring.size(); base++) {
+        if( ((base+z+1) < retstring.size()) &&
+            ((retstring.c_str()[base]=='P' &&
+             retstring.c_str()[base+z+1]=='N') ||
+            (retstring.c_str()[base]=='N' &&
+             retstring.c_str()[base+z+1]=='P')) ) {
+          // match
+          x++;
+
+          if(retstring.c_str()[base]=='P') {
+            retstring.replace(base, 1, "0");
+            retstring.replace(base+z+1, 1, "p");
+          } else { // retstring[base]=='N'
+            retstring.replace(base, 1, "0");
+            retstring.replace(base+z+1, 1, "n");
+          }
+        }
+      }
+    }
+
+    if(x>int_W) {
+      int_W = x;
+      t = retstring;
+      c = int_d; // tofix
+    }
+
+  } d.pop_back(); // hmm
+
+  u = t;
+
+  for(unsigned i=0; i<t.length(); i++) {
+    if(t.c_str()[i]=='p' || t.c_str()[i]=='n')
+      t.replace(i, 1, "0");
+  }
+
+  for(unsigned i=0; i<u.length(); i++) {
+    if(u[i]=='P' || u[i]=='N')
+      u.replace(i, 1, "0");
+    if(u[i]=='p')
+      u.replace(i, 1, "P");
+    if(u[i]=='n')
+      u.replace(i, 1, "N");
+  }
+
+  if( c<0 ) {
+    f=true;
+    c=-c;
+  } else
+    f=false;
+
+  int pos=0;
+  while(u[pos]=='0')
+    pos++;
+
+  bool hit=(u[pos]=='N');
+
+  int g=0;
+  if(hit) {
+    g=1;
+    for(unsigned p=0; p<u.length(); p++) {
+      bool isP=(u[p]=='P');
+      bool isN=(u[p]=='N');
+
+      if(isP)
+        u.replace(p, 1, "N");
+      if(isN)
+        u.replace(p, 1, "P");
+    }
+  }
+
+  munchLeadingZeros(u);
+
+  int i = lefevre(u, ops);
+
+  shiftaddblob blob;
+
+  blob.firstVal=i; blob.firstShift=c;
+  blob.isSub=f;
+  blob.secondVal=i; blob.secondShift=0;
+
+  ops.push_back(blob);
+
+  i = ops.size();
+
+  munchLeadingZeros(t);
+
+  if(t.length()==0)
+    return i;
+
+  if(t.c_str()[0]!='P') {
+    g=2;
+    for(unsigned p=0; p<t.length(); p++) {
+      bool isP=(t.c_str()[p]=='P');
+      bool isN=(t.c_str()[p]=='N');
+
+      if(isP)
+        t.replace(p, 1, "N");
+      if(isN)
+        t.replace(p, 1, "P");
+    }
+  }
+
+  int j = lefevre(t, ops);
+
+  int trail=countTrailingZeros(u);
+  blob.secondVal=i; blob.secondShift=trail;
+
+  trail=countTrailingZeros(t);
+  blob.firstVal=j; blob.firstShift=trail;
+
+  switch(g) {
+    case 0:
+      blob.isSub=false; // first + second
+      break;
+    case 1:
+      blob.isSub=true; // first - second
+      break;
+    case 2:
+      blob.isSub=true; // second - first
+      int tmpval, tmpshift;
+      tmpval=blob.firstVal;
+      tmpshift=blob.firstShift;
+      blob.firstVal=blob.secondVal;
+      blob.firstShift=blob.secondShift;
+      blob.secondVal=tmpval;
+      blob.secondShift=tmpshift;
+      break;
+      //assert
+  }
+
+  ops.push_back(blob);
+  return ops.size();
+}
+
+SDOperand ISel::BuildConstmulSequence(SDOperand N) {
+  //FIXME: we should shortcut this stuff for multiplies by 2^n+1
+  //       in particular, *3 is nicer as *2+1, not *4-1
+  int64_t constant=cast<ConstantSDNode>(N.getOperand(1))->getValue();
+
+  bool flippedSign;
+  unsigned preliminaryShift=0;
+
+  assert(constant != 0 && "erk, you're trying to multiply by constant zero\n");
+
+  // first, we make the constant to multiply by positive
+  if(constant<0) {
+    constant=-constant;
+    flippedSign=true;
+  } else {
+    flippedSign=false;
+  }
+
+  // next, we make it odd.
+  for(; (constant%2==0); preliminaryShift++)
+    constant>>=1;
+
+  //OK, we have a positive, odd number of 64 bits or less. Convert it
+  //to a binary string, constantString[0] is the LSB
+  char constantString[65];
+  for(int i=0; i<64; i++)
+    constantString[i]='0'+((constant>>i)&0x1);
+  constantString[64]=0;
+
+  // now, Booth encode it
+  std::string boothEncodedString;
+  boothEncode(constantString, boothEncodedString);
+
+  std::vector<struct shiftaddblob> ops;
+  // do the transformation, filling out 'ops'
+  lefevre(boothEncodedString, ops);
+
+  assert(ops.size() < 80 && "constmul code has gone haywire\n");
+  SDOperand results[80]; // temporary results (of adds/subs of shifts)
+
+  // now turn 'ops' into DAG bits
+  for(unsigned i=0; i<ops.size(); i++) {
+    SDOperand amt = ISelDAG->getConstant(ops[i].firstShift, MVT::i64);
+    SDOperand val = (ops[i].firstVal == 0) ? N.getOperand(0) :
+      results[ops[i].firstVal-1];
+    SDOperand left = ISelDAG->getNode(ISD::SHL, MVT::i64, val, amt);
+    amt = ISelDAG->getConstant(ops[i].secondShift, MVT::i64);
+    val = (ops[i].secondVal == 0) ? N.getOperand(0) :
+      results[ops[i].secondVal-1];
+    SDOperand right = ISelDAG->getNode(ISD::SHL, MVT::i64, val, amt);
+    if(ops[i].isSub)
+      results[i] = ISelDAG->getNode(ISD::SUB, MVT::i64, left, right);
+    else
+      results[i] = ISelDAG->getNode(ISD::ADD, MVT::i64, left, right);
+  }
+
+  // don't forget flippedSign and preliminaryShift!
+  SDOperand shiftedresult;
+  if(preliminaryShift) {
+    SDOperand finalshift = ISelDAG->getConstant(preliminaryShift, MVT::i64);
+    shiftedresult = ISelDAG->getNode(ISD::SHL, MVT::i64,
+        results[ops.size()-1], finalshift);
+  } else { // there was no preliminary divide-by-power-of-2 required
+    shiftedresult = results[ops.size()-1];
+  }
+
+  SDOperand finalresult;
+  if(flippedSign) { // if we were multiplying by a negative constant:
+    SDOperand zero = ISelDAG->getConstant(0, MVT::i64);
+    // subtract the result from 0 to flip its sign
+    finalresult = ISelDAG->getNode(ISD::SUB, MVT::i64, zero, shiftedresult);
+  } else { // there was no preliminary multiply by -1 required
+    finalresult = shiftedresult;
+  }
+
+  return finalresult;
 }
 
 /// ponderIntegerDivisionBy - When handling integer divides, if the divide
@@ -448,10 +880,25 @@ static unsigned ponderIntegerDivisionBy(SDOperand N, bool isSigned,
 
   int64_t v = (int64_t)cast<ConstantSDNode>(N)->getSignExtended();
 
-  if ((Imm = ExactLog2(v))) { // if a division by a power of two, say so 
+  if (isPowerOf2_64(v)) { // if a division by a power of two, say so
+    Imm = Log2_64(v);
     return 1;
-  } 
-  
+  }
+
+  return 0; // fallthrough
+}
+
+static unsigned ponderIntegerAndWith(SDOperand N, unsigned& Imm) {
+  if (N.getOpcode() != ISD::Constant) return 0; // if not ANDing with
+                                                // a constant, give up.
+
+  int64_t v = (int64_t)cast<ConstantSDNode>(N)->getSignExtended();
+
+  if (isMask_64(v)) { // if ANDing with ((2^n)-1) for some n
+    Imm = Log2_64(v) + 1;
+    return 1; // say so
+  }
+
   return 0; // fallthrough
 }
 
@@ -463,7 +910,7 @@ static unsigned ponderIntegerAdditionWith(SDOperand N, unsigned& Imm) {
   if (v <= 8191 && v >= -8192) { // if this constants fits in 14 bits, say so
     Imm = v & 0x3FFF; // 14 bits
     return 1;
-  } 
+  }
   return 0; // fallthrough
 }
 
@@ -475,7 +922,7 @@ static unsigned ponderIntegerSubtractionFrom(SDOperand N, unsigned& Imm) {
   if (v <= 127 && v >= -128) { // if this constants fits in 8 bits, say so
     Imm = v & 0xFF; // 8 bits
     return 1;
-  } 
+  }
   return 0; // fallthrough
 }
 
@@ -492,12 +939,12 @@ unsigned ISel::SelectExpr(SDOperand N) {
 
   if (Node->getOpcode() == ISD::CopyFromReg)
     // Just use the specified register as our input.
-    return dyn_cast<RegSDNode>(Node)->getReg();
-  
+    return cast<RegisterSDNode>(Node->getOperand(1))->getReg();
+
   unsigned &Reg = ExprMap[N];
   if (Reg) return Reg;
-  
-  if (N.getOpcode() != ISD::CALL)
+
+  if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::TAILCALL)
     Reg = Result = (N.getValueType() != MVT::Other) ?
       MakeReg(N.getValueType()) : 1;
   else {
@@ -513,7 +960,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
       ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1;
     }
   }
-  
+
   switch (N.getOpcode()) {
   default:
     Node->dump();
@@ -526,7 +973,8 @@ unsigned ISel::SelectExpr(SDOperand N) {
   }
 
   case ISD::ConstantPool: {
-    Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
+    Tmp1 = BB->getParent()->getConstantPool()->
+          getConstantPoolIndex(cast<ConstantPoolSDNode>(N)->get());
     IA64Lowering.restoreGP(BB); // FIXME: do i really need this?
     BuildMI(BB, IA64::ADD, 2, Result).addConstantPoolIndex(Tmp1)
       .addReg(IA64::r1);
@@ -550,7 +998,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
     if (Tmp1 != Result)
       // we multiply by +1.0, negate (this is FNMA), and then add 0.0
       BuildMI(BB, IA64::FNMA, 3, Result).addReg(Tmp1).addReg(IA64::F1)
-       .addReg(IA64::F0);
+        .addReg(IA64::F0);
     return Result;
   }
 
@@ -571,15 +1019,15 @@ unsigned ISel::SelectExpr(SDOperand N) {
                 << " the stack alignment yet!";
       abort();
     }
-/*    
+
+/*
     Select(N.getOperand(0));
     if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
     {
       if (CN->getValue() < 32000)
       {
         BuildMI(BB, IA64::ADDIMM22, 2, IA64::r12).addReg(IA64::r12)
-         .addImm(-CN->getValue());
+          .addImm(-CN->getValue());
       } else {
         Tmp1 = SelectExpr(N.getOperand(1));
         // Subtract size from stack pointer, thereby allocating some space.
@@ -600,50 +1048,77 @@ unsigned ISel::SelectExpr(SDOperand N) {
     BuildMI(BB, IA64::MOV, 1, Result).addReg(IA64::r12);
     return Result;
   }
-    
+
   case ISD::SELECT: {
       Tmp1 = SelectExpr(N.getOperand(0)); //Cond
       Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
       Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
 
       unsigned bogoResult;
-      
+
       switch (N.getOperand(1).getValueType()) {
-       default: assert(0 &&
-       "ISD::SELECT: 'select'ing something other than i64 or f64!\n");
-       case MVT::i64:
-         bogoResult=MakeReg(MVT::i64);
-         break;
-       case MVT::f64:
-         bogoResult=MakeReg(MVT::f64);
-         break;
+        default: assert(0 &&
+        "ISD::SELECT: 'select'ing something other than i1, i64 or f64!\n");
+        // for i1, we load the condition into an integer register, then
+        // conditionally copy Tmp2 and Tmp3 to Tmp1 in parallel (only one
+        // of them will go through, since the integer register will hold
+        // either 0 or 1)
+        case MVT::i1: {
+          bogoResult=MakeReg(MVT::i1);
+
+          // load the condition into an integer register
+          unsigned condReg=MakeReg(MVT::i64);
+          unsigned dummy=MakeReg(MVT::i64);
+          BuildMI(BB, IA64::MOV, 1, dummy).addReg(IA64::r0);
+          BuildMI(BB, IA64::TPCADDIMM22, 2, condReg).addReg(dummy)
+            .addImm(1).addReg(Tmp1);
+
+          // initialize Result (bool) to false (hence UNC) and if
+          // the select condition (condReg) is false (0), copy Tmp3
+          BuildMI(BB, IA64::PCMPEQUNC, 3, bogoResult)
+            .addReg(condReg).addReg(IA64::r0).addReg(Tmp3);
+
+          // now, if the selection condition is true, write 1 to the
+          // result if Tmp2 is 1
+          BuildMI(BB, IA64::TPCMPNE, 3, Result).addReg(bogoResult)
+            .addReg(condReg).addReg(IA64::r0).addReg(Tmp2);
+          break;
+        }
+        // for i64/f64, we just copy Tmp3 and then conditionally overwrite it
+        // with Tmp2 if Tmp1 is true
+        case MVT::i64:
+          bogoResult=MakeReg(MVT::i64);
+          BuildMI(BB, IA64::MOV, 1, bogoResult).addReg(Tmp3);
+          BuildMI(BB, IA64::CMOV, 2, Result).addReg(bogoResult).addReg(Tmp2)
+            .addReg(Tmp1);
+          break;
+        case MVT::f64:
+          bogoResult=MakeReg(MVT::f64);
+          BuildMI(BB, IA64::FMOV, 1, bogoResult).addReg(Tmp3);
+          BuildMI(BB, IA64::CFMOV, 2, Result).addReg(bogoResult).addReg(Tmp2)
+            .addReg(Tmp1);
+          break;
       }
 
-      BuildMI(BB, IA64::MOV, 1, bogoResult).addReg(Tmp3);
-      BuildMI(BB, IA64::CMOV, 2, Result).addReg(bogoResult).addReg(Tmp2)
-       .addReg(Tmp1); // FIXME: should be FMOV/FCMOV sometimes,
-                       // though this will work for now (no JIT)
       return Result;
   }
-  
+
   case ISD::Constant: {
     unsigned depositPos=0;
     unsigned depositLen=0;
     switch (N.getValueType()) {
       default: assert(0 && "Cannot use constants of this type!");
       case MVT::i1: { // if a bool, we don't 'load' so much as generate
-                     // the constant:
-                     if(cast<ConstantSDNode>(N)->getValue())  // true:
-                       BuildMI(BB, IA64::CMPEQ, 2, Result)
-                         .addReg(IA64::r0).addReg(IA64::r0);
-                     else // false:
-                       BuildMI(BB, IA64::CMPNE, 2, Result)
-                         .addReg(IA64::r0).addReg(IA64::r0);
-                     return Result; // early exit
-                   }
+        // the constant:
+        if(cast<ConstantSDNode>(N)->getValue())  // true:
+          BuildMI(BB, IA64::CMPEQ, 2, Result).addReg(IA64::r0).addReg(IA64::r0);
+        else // false:
+          BuildMI(BB, IA64::CMPNE, 2, Result).addReg(IA64::r0).addReg(IA64::r0);
+        return Result; // early exit
+      }
       case MVT::i64: break;
     }
-   
+
     int64_t immediate = cast<ConstantSDNode>(N)->getValue();
 
     if(immediate==0) { // if the constant is just zero,
@@ -656,18 +1131,18 @@ unsigned ISel::SelectExpr(SDOperand N) {
       // turn into:   "adds rDest=imm,r0"  (and _not_ "andl"...)
       BuildMI(BB, IA64::MOVSIMM14, 1, Result).addSImm(immediate);
       return Result; // early exit
-    } 
+    }
 
     if (immediate <= 2097151 && immediate >= -2097152) {
       // if this constants fits in 22 bits, we use a mov the assembler will
       // turn into:   "addl rDest=imm,r0"
       BuildMI(BB, IA64::MOVSIMM22, 1, Result).addSImm(immediate);
       return Result; // early exit
-    } 
+    }
 
     /* otherwise, our immediate is big, so we use movl */
     uint64_t Imm = immediate;
-    BuildMI(BB, IA64::MOVLIMM64, 1, Result).addU64Imm(Imm);
+    BuildMI(BB, IA64::MOVLIMM64, 1, Result).addImm64(Imm);
     return Result;
   }
 
@@ -675,7 +1150,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
     BuildMI(BB, IA64::IDEF, 0, Result);
     return Result;
   }
-    
+
   case ISD::GlobalAddress: {
     GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
     unsigned Tmp1 = MakeReg(MVT::i64);
@@ -685,7 +1160,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
 
     return Result;
   }
-  
+
   case ISD::ExternalSymbol: {
     const char *Sym = cast<ExternalSymbolSDNode>(N)->getSymbol();
 // assert(0 && "sorry, but what did you want an ExternalSymbol for again?");
@@ -699,82 +1174,46 @@ unsigned ISel::SelectExpr(SDOperand N) {
     return Result;
   }
 
+  case ISD::ANY_EXTEND:
   case ISD::ZERO_EXTEND: {
     Tmp1 = SelectExpr(N.getOperand(0)); // value
-    
-    switch (N.getOperand(0).getValueType()) {
-    default: assert(0 && "Cannot zero-extend this type!");
-    case MVT::i8:  Opc = IA64::ZXT1; break;
-    case MVT::i16: Opc = IA64::ZXT2; break;
-    case MVT::i32: Opc = IA64::ZXT4; break;
-
-    // we handle bools differently! : 
-    case MVT::i1: { // if the predicate reg has 1, we want a '1' in our GR.
-                   unsigned dummy = MakeReg(MVT::i64);
-                   // first load zero:
-                   BuildMI(BB, IA64::MOV, 1, dummy).addReg(IA64::r0);
-                   // ...then conditionally (PR:Tmp1) add 1:
-                   BuildMI(BB, IA64::TPCADDIMM22, 2, Result).addReg(dummy)
-                     .addImm(1).addReg(Tmp1);
-                   return Result; // XXX early exit!
-                 }
-    }
-
-    BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
-    return Result;
-   }
 
-  case ISD::SIGN_EXTEND: {   // we should only have to handle i1 -> i64 here!!!
+    assert(N.getOperand(0).getValueType() == MVT::i1 && 
+           "Cannot zero-extend this type!");
+
+    // if the predicate reg has 1, we want a '1' in our GR.
+    unsigned dummy = MakeReg(MVT::i64);
+    // first load zero:
+    BuildMI(BB, IA64::MOV, 1, dummy).addReg(IA64::r0);
+    // ...then conditionally (PR:Tmp1) add 1:
+    BuildMI(BB, IA64::TPCADDIMM22, 2, Result).addReg(dummy)
+      .addImm(1).addReg(Tmp1);
+    return Result; // XXX early exit!
+  }
 
-assert(0 && "hmm, ISD::SIGN_EXTEND: shouldn't ever be reached. bad luck!\n");
+  case ISD::SIGN_EXTEND:
+    assert(N.getOperand(0).getValueType() == MVT::i1 && 
+           "Cannot zero-extend this type!");
 
     Tmp1 = SelectExpr(N.getOperand(0)); // value
-    
-    switch (N.getOperand(0).getValueType()) {
-    default: assert(0 && "Cannot sign-extend this type!");
-    case MVT::i1:  assert(0 && "trying to sign extend a bool? ow.\n");
-                  Opc = IA64::SXT1; break;
-                  // FIXME: for now, we treat bools the same as i8s
-    case MVT::i8:  Opc = IA64::SXT1; break;
-    case MVT::i16: Opc = IA64::SXT2; break;
-    case MVT::i32: Opc = IA64::SXT4; break;
-    }
+    assert(0 && "don't know how to sign_extend from bool yet!");
+    abort();
 
-    BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
-    return Result;
-   }
-
-  case ISD::TRUNCATE: {
+  case ISD::TRUNCATE:
     // we use the funky dep.z (deposit (zero)) instruction to deposit bits
     // of R0 appropriately.
-    switch (N.getOperand(0).getValueType()) {
-    default: assert(0 && "Unknown truncate!");
-    case MVT::i64: break;
-    }
+    assert(N.getOperand(0).getValueType() == MVT::i64 && 
+           N.getValueType() == MVT::i1 && "Unknown truncate!");
     Tmp1 = SelectExpr(N.getOperand(0));
-    unsigned depositPos, depositLen;
 
-    switch (N.getValueType()) {
-    default: assert(0 && "Unknown truncate!");
-    case MVT::i1: {
-      // if input (normal reg) is 0, 0!=0 -> false (0), if 1, 1!=0 ->true (1):
-                   BuildMI(BB, IA64::CMPNE, 2, Result).addReg(Tmp1)
-                     .addReg(IA64::r0);
-                   return Result; // XXX early exit!
-                 }
-    case MVT::i8:  depositPos=0; depositLen=8;  break;
-    case MVT::i16: depositPos=0; depositLen=16; break;
-    case MVT::i32: depositPos=0; depositLen=32; break;
-    }
-    BuildMI(BB, IA64::DEPZ, 1, Result).addReg(Tmp1)
-      .addImm(depositPos).addImm(depositLen);
-    return Result;
-  }
+    // if input (normal reg) is 0, 0!=0 -> false (0), if 1, 1!=0 ->true (1):
+    BuildMI(BB, IA64::CMPNE, 2, Result).addReg(Tmp1).addReg(IA64::r0);
+    return Result; // XXX early exit!
 
-/*                     
+/*
   case ISD::FP_ROUND: {
     assert (DestType == MVT::f32 && N.getOperand(0).getValueType() == MVT::f64 &&
-       "error: trying to FP_ROUND something other than f64 -> f32!\n");
+  "error: trying to FP_ROUND something other than f64 -> f32!\n");
     Tmp1 = SelectExpr(N.getOperand(0));
     BuildMI(BB, IA64::FADDS, 2, Result).addReg(Tmp1).addReg(IA64::F0);
     // we add 0.0 using a single precision add to do rounding
@@ -818,78 +1257,112 @@ assert(0 && "hmm, ISD::SIGN_EXTEND: shouldn't ever be reached. bad luck!\n");
     BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(Tmp2);
     return Result;
   }
-
-  case ISD::ADD: {
-    if(DestType == MVT::f64 && N.getOperand(0).getOpcode() == ISD::MUL &&
-       N.getOperand(0).Val->hasOneUse()) { // if we can fold this add
-                                           // into an fma, do so:
-      // ++FusedFP; // Statistic
+    
+  case ISD::FADD: {
+    if (N.getOperand(0).getOpcode() == ISD::FMUL &&
+        N.getOperand(0).Val->hasOneUse()) { // if we can fold this add
+                                            // into an fma, do so:
+                                            // ++FusedFP; // Statistic
       Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
       Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
       Tmp3 = SelectExpr(N.getOperand(1));
       BuildMI(BB, IA64::FMA, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
       return Result; // early exit
     }
+    
+    //else, fallthrough:
     Tmp1 = SelectExpr(N.getOperand(0));
-    if(DestType != MVT::f64) { // integer addition:
-        switch (ponderIntegerAdditionWith(N.getOperand(1), Tmp3)) {
-         case 1: // adding a constant that's 14 bits
-           BuildMI(BB, IA64::ADDIMM14, 2, Result).addReg(Tmp1).addSImm(Tmp3);
-           return Result; // early exit
-       } // fallthrough and emit a reg+reg ADD:
-       Tmp2 = SelectExpr(N.getOperand(1));
-       BuildMI(BB, IA64::ADD, 2, Result).addReg(Tmp1).addReg(Tmp2);
-    } else { // this is a floating point addition
-      Tmp2 = SelectExpr(N.getOperand(1));
-      BuildMI(BB, IA64::FADD, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, IA64::FADD, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+  }
+
+  case ISD::ADD: {
+    if (N.getOperand(0).getOpcode() == ISD::SHL &&
+        N.getOperand(0).Val->hasOneUse()) { // if we might be able to fold
+                                            // this add into a shladd, try:
+      ConstantSDNode *CSD = NULL;
+      if((CSD = dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) &&
+          (CSD->getValue() >= 1) && (CSD->getValue() <= 4) ) { // we can:
+
+        // ++FusedSHLADD; // Statistic
+        Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
+        int shl_amt = CSD->getValue();
+        Tmp3 = SelectExpr(N.getOperand(1));
+
+        BuildMI(BB, IA64::SHLADD, 3, Result)
+          .addReg(Tmp1).addImm(shl_amt).addReg(Tmp3);
+        return Result; // early exit
+      }
     }
+
+    //else, fallthrough:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    switch (ponderIntegerAdditionWith(N.getOperand(1), Tmp3)) {
+      case 1: // adding a constant that's 14 bits
+        BuildMI(BB, IA64::ADDIMM14, 2, Result).addReg(Tmp1).addSImm(Tmp3);
+        return Result; // early exit
+    } // fallthrough and emit a reg+reg ADD:
+    Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, IA64::ADD, 2, Result).addReg(Tmp1).addReg(Tmp2);
     return Result;
   }
 
-  case ISD::MUL: {
+  case ISD::FMUL: 
     Tmp1 = SelectExpr(N.getOperand(0));
     Tmp2 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, IA64::FMPY, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+    
+  case ISD::MUL: {
 
-    if(DestType != MVT::f64) { // TODO: speed!
+    // TODO: speed!
+/* FIXME if(N.getOperand(1).getOpcode() != ISD::Constant) { // if not a const mul
+ */
       // boring old integer multiply with xma
+      Tmp1 = SelectExpr(N.getOperand(0));
+      Tmp2 = SelectExpr(N.getOperand(1));
+
       unsigned TempFR1=MakeReg(MVT::f64);
       unsigned TempFR2=MakeReg(MVT::f64);
       unsigned TempFR3=MakeReg(MVT::f64);
       BuildMI(BB, IA64::SETFSIG, 1, TempFR1).addReg(Tmp1);
       BuildMI(BB, IA64::SETFSIG, 1, TempFR2).addReg(Tmp2);
       BuildMI(BB, IA64::XMAL, 1, TempFR3).addReg(TempFR1).addReg(TempFR2)
-       .addReg(IA64::F0);
+        .addReg(IA64::F0);
       BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(TempFR3);
-    }
-    else  // floating point multiply
-      BuildMI(BB, IA64::FMPY, 2, Result).addReg(Tmp1).addReg(Tmp2);
-    return Result;
+      return Result; // early exit
+   /* FIXME } else { // we are multiplying by an integer constant! yay
+      return Reg = SelectExpr(BuildConstmulSequence(N)); // avert your eyes!
+    } */
   }
-  
-  case ISD::SUB: {
-    if(DestType == MVT::f64 && N.getOperand(0).getOpcode() == ISD::MUL &&
+
+  case ISD::FSUB:
+    if(N.getOperand(0).getOpcode() == ISD::FMUL &&
        N.getOperand(0).Val->hasOneUse()) { // if we can fold this sub
                                            // into an fms, do so:
-      // ++FusedFP; // Statistic
+                                           // ++FusedFP; // Statistic
       Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
       Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
       Tmp3 = SelectExpr(N.getOperand(1));
       BuildMI(BB, IA64::FMS, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
       return Result; // early exit
     }
+
     Tmp2 = SelectExpr(N.getOperand(1));
-    if(DestType != MVT::f64) { // integer subtraction:
-        switch (ponderIntegerSubtractionFrom(N.getOperand(0), Tmp3)) {
-         case 1: // subtracting *from* an 8 bit constant:
-           BuildMI(BB, IA64::SUBIMM8, 2, Result).addSImm(Tmp3).addReg(Tmp2);
-           return Result; // early exit
-       } // fallthrough and emit a reg+reg SUB:
-       Tmp1 = SelectExpr(N.getOperand(0));
-       BuildMI(BB, IA64::SUB, 2, Result).addReg(Tmp1).addReg(Tmp2);
-    } else { // this is a floating point subtraction
-      Tmp1 = SelectExpr(N.getOperand(0));
-      BuildMI(BB, IA64::FSUB, 2, Result).addReg(Tmp1).addReg(Tmp2);
-    }
+    Tmp1 = SelectExpr(N.getOperand(0));
+    BuildMI(BB, IA64::FSUB, 2, Result).addReg(Tmp1).addReg(Tmp2);
+    return Result;
+    
+  case ISD::SUB: {
+    Tmp2 = SelectExpr(N.getOperand(1));
+    switch (ponderIntegerSubtractionFrom(N.getOperand(0), Tmp3)) {
+      case 1: // subtracting *from* an 8 bit constant:
+        BuildMI(BB, IA64::SUBIMM8, 2, Result).addSImm(Tmp3).addReg(Tmp2);
+        return Result; // early exit
+    } // fallthrough and emit a reg+reg SUB:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    BuildMI(BB, IA64::SUB, 2, Result).addReg(Tmp1).addReg(Tmp2);
     return Result;
   }
 
@@ -899,11 +1372,11 @@ assert(0 && "hmm, ISD::SIGN_EXTEND: shouldn't ever be reached. bad luck!\n");
     BuildMI(BB, IA64::FABS, 1, Result).addReg(Tmp1);
     return Result;
   }
+
   case ISD::FNEG: {
     assert(DestType == MVT::f64 && "trying to fneg something other than f64?");
 
-    if (ISD::FABS == N.getOperand(0).getOpcode()) { // && hasOneUse()? 
+    if (ISD::FABS == N.getOperand(0).getOpcode()) { // && hasOneUse()?
       Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
       BuildMI(BB, IA64::FNEGABS, 1, Result).addReg(Tmp1); // fold in abs
     } else {
@@ -913,14 +1386,14 @@ assert(0 && "hmm, ISD::SIGN_EXTEND: shouldn't ever be reached. bad luck!\n");
 
     return Result;
   }
-        
+
   case ISD::AND: {
      switch (N.getValueType()) {
     default: assert(0 && "Cannot AND this type!");
     case MVT::i1: { // if a bool, we emit a pseudocode AND
       unsigned pA = SelectExpr(N.getOperand(0));
       unsigned pB = SelectExpr(N.getOperand(1));
-       
+
 /* our pseudocode for AND is:
  *
 (pA) cmp.eq.unc pC,p0 = r0,r0   // pC = pA
@@ -932,36 +1405,56 @@ assert(0 && "hmm, ISD::SIGN_EXTEND: shouldn't ever be reached. bad luck!\n");
 
 */
       unsigned pTemp = MakeReg(MVT::i1);
-     
+
       unsigned bogusTemp1 = MakeReg(MVT::i1);
       unsigned bogusTemp2 = MakeReg(MVT::i1);
       unsigned bogusTemp3 = MakeReg(MVT::i1);
       unsigned bogusTemp4 = MakeReg(MVT::i1);
-    
+
       BuildMI(BB, IA64::PCMPEQUNC, 3, bogusTemp1)
-       .addReg(IA64::r0).addReg(IA64::r0).addReg(pA);
+        .addReg(IA64::r0).addReg(IA64::r0).addReg(pA);
       BuildMI(BB, IA64::CMPEQ, 2, bogusTemp2)
-       .addReg(IA64::r0).addReg(IA64::r0);
+        .addReg(IA64::r0).addReg(IA64::r0);
       BuildMI(BB, IA64::TPCMPNE, 3, pTemp)
-       .addReg(bogusTemp2).addReg(IA64::r0).addReg(IA64::r0).addReg(pB);
+        .addReg(bogusTemp2).addReg(IA64::r0).addReg(IA64::r0).addReg(pB);
       BuildMI(BB, IA64::TPCMPNE, 3, Result)
-       .addReg(bogusTemp1).addReg(IA64::r0).addReg(IA64::r0).addReg(pTemp);
+        .addReg(bogusTemp1).addReg(IA64::r0).addReg(IA64::r0).addReg(pTemp);
       break;
     }
+
     // if not a bool, we just AND away:
     case MVT::i8:
     case MVT::i16:
     case MVT::i32:
     case MVT::i64: {
       Tmp1 = SelectExpr(N.getOperand(0));
+      switch (ponderIntegerAndWith(N.getOperand(1), Tmp3)) {
+        case 1: // ANDing a constant that is 2^n-1 for some n
+          switch (Tmp3) {
+            case 8:  // if AND 0x00000000000000FF, be quaint and use zxt1
+              BuildMI(BB, IA64::ZXT1, 1, Result).addReg(Tmp1);
+              break;
+            case 16: // if AND 0x000000000000FFFF, be quaint and use zxt2
+              BuildMI(BB, IA64::ZXT2, 1, Result).addReg(Tmp1);
+              break;
+            case 32: // if AND 0x00000000FFFFFFFF, be quaint and use zxt4
+              BuildMI(BB, IA64::ZXT4, 1, Result).addReg(Tmp1);
+              break;
+            default: // otherwise, use dep.z to paste zeros
+            // FIXME: assert the dep.z is in bounds
+             BuildMI(BB, IA64::DEPZ, 3, Result).addReg(Tmp1)
+                .addImm(0).addImm(Tmp3);
+              break;
+         }
+         return Result; // early exit
+      } // fallthrough and emit a simple AND:
       Tmp2 = SelectExpr(N.getOperand(1));
       BuildMI(BB, IA64::AND, 2, Result).addReg(Tmp1).addReg(Tmp2);
-      break;
     }
     }
     return Result;
   }
+
   case ISD::OR: {
   switch (N.getValueType()) {
     default: assert(0 && "Cannot OR this type!");
@@ -970,22 +1463,22 @@ assert(0 && "hmm, ISD::SIGN_EXTEND: shouldn't ever be reached. bad luck!\n");
       unsigned pB = SelectExpr(N.getOperand(1));
 
       unsigned pTemp1 = MakeReg(MVT::i1);
-       
+
 /* our pseudocode for OR is:
  *
 
 pC = pA OR pB
 -------------
 
-(pA)   cmp.eq.unc pC,p0 = r0,r0  // pC = pA
      ;;
-(pB)   cmp.eq pC,p0 = r0,r0    // if (pB) pC = 1
+(pA) cmp.eq.unc pC,p0 = r0,r0  // pC = pA
+ ;;
+(pB) cmp.eq pC,p0 = r0,r0 // if (pB) pC = 1
 
 */
       BuildMI(BB, IA64::PCMPEQUNC, 3, pTemp1)
-       .addReg(IA64::r0).addReg(IA64::r0).addReg(pA);
-      BuildMI(BB, IA64::TPCMPEQ, 3, Result)
-       .addReg(pTemp1).addReg(IA64::r0).addReg(IA64::r0).addReg(pB);
+        .addReg(IA64::r0).addReg(IA64::r0).addReg(pA);
+      BuildMI(BB, IA64::TPCMPEQ, 4, Result)
+        .addReg(pTemp1).addReg(IA64::r0).addReg(IA64::r0).addReg(pB);
       break;
     }
     // if not a bool, we just OR away:
@@ -1001,7 +1494,7 @@ pC = pA OR pB
     }
     return Result;
   }
-        
+
   case ISD::XOR: {
      switch (N.getValueType()) {
     default: assert(0 && "Cannot XOR this type!");
@@ -1049,11 +1542,11 @@ pC = pA OR pB
 
       BuildMI(BB, IA64::MOV, 1, bogoGR).addReg(IA64::r0);
       BuildMI(BB, IA64::PCMPEQUNC, 3, bogoPR)
-       .addReg(IA64::r0).addReg(IA64::r0).addReg(pZ);
+        .addReg(IA64::r0).addReg(IA64::r0).addReg(pZ);
       BuildMI(BB, IA64::TPCADDIMM22, 2, rt)
-       .addReg(bogoGR).addImm(1).addReg(pZ);
+        .addReg(bogoGR).addImm(1).addReg(pZ);
       BuildMI(BB, IA64::TPCMPIMM8NE, 3, Result)
-       .addReg(bogoPR).addImm(1).addReg(rt).addReg(pY);
+        .addReg(bogoPR).addImm(1).addReg(rt).addReg(pY);
       break;
     }
     // if not a bool, we just XOR away:
@@ -1070,6 +1563,12 @@ pC = pA OR pB
     return Result;
   }
 
+  case ISD::CTPOP: {
+    Tmp1 = SelectExpr(N.getOperand(0));
+    BuildMI(BB, IA64::POPCNT, 1, Result).addReg(Tmp1);
+    return Result;
+  }
+
   case ISD::SHL: {
     Tmp1 = SelectExpr(N.getOperand(0));
     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
@@ -1081,7 +1580,7 @@ pC = pA OR pB
     }
     return Result;
   }
-                
+
   case ISD::SRL: {
     Tmp1 = SelectExpr(N.getOperand(0));
     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
@@ -1093,7 +1592,7 @@ pC = pA OR pB
     }
     return Result;
   }
-                
+
   case ISD::SRA: {
     Tmp1 = SelectExpr(N.getOperand(0));
     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
@@ -1106,6 +1605,7 @@ pC = pA OR pB
     return Result;
   }
 
+  case ISD::FDIV:
   case ISD::SDIV:
   case ISD::UDIV:
   case ISD::SREM:
@@ -1123,37 +1623,39 @@ pC = pA OR pB
     bool isSigned=false;
 
     switch(N.getOpcode()) {
+      case ISD::FDIV:
       case ISD::SDIV:  isModulus=false; isSigned=true;  break;
       case ISD::UDIV:  isModulus=false; isSigned=false; break;
+      case ISD::FREM:
       case ISD::SREM:  isModulus=true;  isSigned=true;  break;
       case ISD::UREM:  isModulus=true;  isSigned=false; break;
     }
 
     if(!isModulus && !isFP) { // if this is an integer divide,
       switch (ponderIntegerDivisionBy(N.getOperand(1), isSigned, Tmp3)) {
-       case 1: // division by a constant that's a power of 2
-         Tmp1 = SelectExpr(N.getOperand(0));
-         if(isSigned) {  // argument could be negative, so emit some code:
-           unsigned divAmt=Tmp3;
-           unsigned tempGR1=MakeReg(MVT::i64);
-           unsigned tempGR2=MakeReg(MVT::i64);
-           unsigned tempGR3=MakeReg(MVT::i64);
-           BuildMI(BB, IA64::SHRS, 2, tempGR1)
-             .addReg(Tmp1).addImm(divAmt-1);
-           BuildMI(BB, IA64::EXTRU, 3, tempGR2)
-             .addReg(tempGR1).addImm(64-divAmt).addImm(divAmt);
-           BuildMI(BB, IA64::ADD, 2, tempGR3)
-             .addReg(Tmp1).addReg(tempGR2);
-           BuildMI(BB, IA64::SHRS, 2, Result)
-             .addReg(tempGR3).addImm(divAmt);
-         }
-         else // unsigned div-by-power-of-2 becomes a simple shift right:
-           BuildMI(BB, IA64::SHRU, 2, Result).addReg(Tmp1).addImm(Tmp3);
-         return Result; // early exit
+        case 1: // division by a constant that's a power of 2
+          Tmp1 = SelectExpr(N.getOperand(0));
+          if(isSigned) {  // argument could be negative, so emit some code:
+            unsigned divAmt=Tmp3;
+            unsigned tempGR1=MakeReg(MVT::i64);
+            unsigned tempGR2=MakeReg(MVT::i64);
+            unsigned tempGR3=MakeReg(MVT::i64);
+            BuildMI(BB, IA64::SHRS, 2, tempGR1)
+              .addReg(Tmp1).addImm(divAmt-1);
+            BuildMI(BB, IA64::EXTRU, 3, tempGR2)
+              .addReg(tempGR1).addImm(64-divAmt).addImm(divAmt);
+            BuildMI(BB, IA64::ADD, 2, tempGR3)
+              .addReg(Tmp1).addReg(tempGR2);
+            BuildMI(BB, IA64::SHRS, 2, Result)
+              .addReg(tempGR3).addImm(divAmt);
+          }
+          else // unsigned div-by-power-of-2 becomes a simple shift right:
+            BuildMI(BB, IA64::SHRU, 2, Result).addReg(Tmp1).addImm(Tmp3);
+          return Result; // early exit
       }
     }
 
-    unsigned TmpPR=MakeReg(MVT::i1);  // we need two scratch 
+    unsigned TmpPR=MakeReg(MVT::i1);  // we need two scratch
     unsigned TmpPR2=MakeReg(MVT::i1); // predicate registers,
     unsigned TmpF1=MakeReg(MVT::f64); // and one metric truckload of FP regs.
     unsigned TmpF2=MakeReg(MVT::f64); // lucky we have IA64?
@@ -1170,23 +1672,23 @@ pC = pA OR pB
     unsigned TmpF13=MakeReg(MVT::f64);
     unsigned TmpF14=MakeReg(MVT::f64);
     unsigned TmpF15=MakeReg(MVT::f64);
+
     // OK, emit some code:
 
     if(!isFP) {
       // first, load the inputs into FP regs.
       BuildMI(BB, IA64::SETFSIG, 1, TmpF1).addReg(Tmp1);
       BuildMI(BB, IA64::SETFSIG, 1, TmpF2).addReg(Tmp2);
-      
+
       // next, convert the inputs to FP
       if(isSigned) {
-       BuildMI(BB, IA64::FCVTXF, 1, TmpF3).addReg(TmpF1);
-       BuildMI(BB, IA64::FCVTXF, 1, TmpF4).addReg(TmpF2);
+        BuildMI(BB, IA64::FCVTXF, 1, TmpF3).addReg(TmpF1);
+        BuildMI(BB, IA64::FCVTXF, 1, TmpF4).addReg(TmpF2);
       } else {
-       BuildMI(BB, IA64::FCVTXUFS1, 1, TmpF3).addReg(TmpF1);
-       BuildMI(BB, IA64::FCVTXUFS1, 1, TmpF4).addReg(TmpF2);
+        BuildMI(BB, IA64::FCVTXUFS1, 1, TmpF3).addReg(TmpF1);
+        BuildMI(BB, IA64::FCVTXUFS1, 1, TmpF4).addReg(TmpF2);
       }
-      
+
     } else { // this is an FP divide/remainder, so we 'leak' some temp
              // regs and assign TmpF3=Tmp1, TmpF4=Tmp2
       TmpF3=Tmp1;
@@ -1205,7 +1707,7 @@ pC = pA OR pB
                                        // TPCMPNE below
       BuildMI(BB, IA64::CMPEQ, 2, bogusPR).addReg(IA64::r0).addReg(IA64::r0);
       BuildMI(BB, IA64::TPCMPNE, 3, TmpPR2).addReg(bogusPR)
-       .addReg(IA64::r0).addReg(IA64::r0).addReg(TmpPR);
+        .addReg(IA64::r0).addReg(IA64::r0).addReg(TmpPR);
     }
 
     // now we apply newton's method, thrice! (FIXME: this is ~72 bits of
@@ -1242,9 +1744,9 @@ pC = pA OR pB
     if(!isFP) {
       // round to an integer
       if(isSigned)
-       BuildMI(BB, IA64::FCVTFXTRUNCS1, 1, TmpF15).addReg(TmpF14);
+        BuildMI(BB, IA64::FCVTFXTRUNCS1, 1, TmpF15).addReg(TmpF14);
       else
-       BuildMI(BB, IA64::FCVTFXUTRUNCS1, 1, TmpF15).addReg(TmpF14);
+        BuildMI(BB, IA64::FCVTFXUTRUNCS1, 1, TmpF15).addReg(TmpF14);
     } else {
       BuildMI(BB, IA64::FMOV, 1, TmpF15).addReg(TmpF14);
      // EXERCISE: can you see why TmpF15=TmpF14 does not work here, and
@@ -1258,55 +1760,36 @@ pC = pA OR pB
       // we do a 'conditional fmov' (of the correct result, depending
       // on how the frcpa predicate turned out)
       BuildMI(BB, IA64::PFMOV, 2, bogoResult)
-       .addReg(TmpF12).addReg(TmpPR2); 
+        .addReg(TmpF12).addReg(TmpPR2);
       BuildMI(BB, IA64::CFMOV, 2, Result)
-       .addReg(bogoResult).addReg(TmpF15).addReg(TmpPR);
+        .addReg(bogoResult).addReg(TmpF15).addReg(TmpPR);
       }
       else {
-       BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(TmpF15);
+        BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(TmpF15);
       }
     } else { // this is a modulus
       if(!isFP) {
-       // answer = q * (-b) + a
-       unsigned ModulusResult = MakeReg(MVT::f64);
-       unsigned TmpF = MakeReg(MVT::f64);
-       unsigned TmpI = MakeReg(MVT::i64);
-       
-       BuildMI(BB, IA64::SUB, 2, TmpI).addReg(IA64::r0).addReg(Tmp2);
-       BuildMI(BB, IA64::SETFSIG, 1, TmpF).addReg(TmpI);
-       BuildMI(BB, IA64::XMAL, 3, ModulusResult)
-         .addReg(TmpF15).addReg(TmpF).addReg(TmpF1);
-       BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(ModulusResult);
+        // answer = q * (-b) + a
+        unsigned ModulusResult = MakeReg(MVT::f64);
+        unsigned TmpF = MakeReg(MVT::f64);
+        unsigned TmpI = MakeReg(MVT::i64);
+
+        BuildMI(BB, IA64::SUB, 2, TmpI).addReg(IA64::r0).addReg(Tmp2);
+        BuildMI(BB, IA64::SETFSIG, 1, TmpF).addReg(TmpI);
+        BuildMI(BB, IA64::XMAL, 3, ModulusResult)
+          .addReg(TmpF15).addReg(TmpF).addReg(TmpF1);
+        BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(ModulusResult);
       } else { // FP modulus! The horror... the horror....
-       assert(0 && "sorry, no FP modulus just yet!\n!\n");
+        assert(0 && "sorry, no FP modulus just yet!\n!\n");
       }
     }
 
     return Result;
   }
 
-  case ISD::ZERO_EXTEND_INREG: {
-    Tmp1 = SelectExpr(N.getOperand(0));
-    MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
-    switch(MVN->getExtraValueType())
-    {
-    default:
-      Node->dump();
-      assert(0 && "don't know how to zero extend this type");
-      break;
-    case MVT::i8: Opc = IA64::ZXT1; break;
-    case MVT::i16: Opc = IA64::ZXT2; break;
-    case MVT::i32: Opc = IA64::ZXT4; break;
-    }
-    BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
-    return Result;
-  }
   case ISD::SIGN_EXTEND_INREG: {
     Tmp1 = SelectExpr(N.getOperand(0));
-    MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
-    switch(MVN->getExtraValueType())
-    {
+    switch(cast<VTSDNode>(Node->getOperand(1))->getVT()) {
     default:
       Node->dump();
       assert(0 && "don't know how to sign extend this type");
@@ -1321,109 +1804,103 @@ pC = pA OR pB
 
   case ISD::SETCC: {
     Tmp1 = SelectExpr(N.getOperand(0));
-
-    if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
-      if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
-
-       if(ConstantSDNode *CSDN =
-            dyn_cast<ConstantSDNode>(N.getOperand(1))) {
-       // if we are comparing against a constant zero
-       if(CSDN->getValue()==0)
-         Tmp2 = IA64::r0; // then we can just compare against r0
-       else
-         Tmp2 = SelectExpr(N.getOperand(1));
-       } else // not comparing against a constant
-         Tmp2 = SelectExpr(N.getOperand(1));
-       
-       switch (SetCC->getCondition()) {
-       default: assert(0 && "Unknown integer comparison!");
-       case ISD::SETEQ:
-         BuildMI(BB, IA64::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETGT:
-         BuildMI(BB, IA64::CMPGT, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETGE:
-         BuildMI(BB, IA64::CMPGE, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETLT:
-         BuildMI(BB, IA64::CMPLT, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETLE:
-         BuildMI(BB, IA64::CMPLE, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETNE:
-         BuildMI(BB, IA64::CMPNE, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETULT:
-         BuildMI(BB, IA64::CMPLTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETUGT:
-         BuildMI(BB, IA64::CMPGTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETULE:
-         BuildMI(BB, IA64::CMPLEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETUGE:
-         BuildMI(BB, IA64::CMPGEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       }
+    ISD::CondCode CC = cast<CondCodeSDNode>(Node->getOperand(2))->get();
+    if (MVT::isInteger(N.getOperand(0).getValueType())) {
+
+      if(ConstantSDNode *CSDN =
+           dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+      // if we are comparing against a constant zero
+      if(CSDN->getValue()==0)
+        Tmp2 = IA64::r0; // then we can just compare against r0
+      else
+        Tmp2 = SelectExpr(N.getOperand(1));
+      } else // not comparing against a constant
+        Tmp2 = SelectExpr(N.getOperand(1));
+
+      switch (CC) {
+      default: assert(0 && "Unknown integer comparison!");
+      case ISD::SETEQ:
+        BuildMI(BB, IA64::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETGT:
+        BuildMI(BB, IA64::CMPGT, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETGE:
+        BuildMI(BB, IA64::CMPGE, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETLT:
+        BuildMI(BB, IA64::CMPLT, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETLE:
+        BuildMI(BB, IA64::CMPLE, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETNE:
+        BuildMI(BB, IA64::CMPNE, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETULT:
+        BuildMI(BB, IA64::CMPLTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETUGT:
+        BuildMI(BB, IA64::CMPGTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETULE:
+        BuildMI(BB, IA64::CMPLEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETUGE:
+        BuildMI(BB, IA64::CMPGEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
       }
-      else { // if not integer, should be FP. FIXME: what about bools? ;)
-       assert(SetCC->getOperand(0).getValueType() != MVT::f32 &&
-           "error: SETCC should have had incoming f32 promoted to f64!\n");
-
-       if(ConstantFPSDNode *CFPSDN =
-            dyn_cast<ConstantFPSDNode>(N.getOperand(1))) {
-
-         // if we are comparing against a constant +0.0 or +1.0
-         if(CFPSDN->isExactlyValue(+0.0))
-           Tmp2 = IA64::F0; // then we can just compare against f0
-         else if(CFPSDN->isExactlyValue(+1.0))
-           Tmp2 = IA64::F1; // or f1
-         else
-           Tmp2 = SelectExpr(N.getOperand(1));
-       } else // not comparing against a constant
-         Tmp2 = SelectExpr(N.getOperand(1));
-
-       switch (SetCC->getCondition()) {
-       default: assert(0 && "Unknown FP comparison!");
-       case ISD::SETEQ:
-         BuildMI(BB, IA64::FCMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETGT:
-         BuildMI(BB, IA64::FCMPGT, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETGE:
-         BuildMI(BB, IA64::FCMPGE, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETLT:
-         BuildMI(BB, IA64::FCMPLT, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETLE:
-         BuildMI(BB, IA64::FCMPLE, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETNE:
-         BuildMI(BB, IA64::FCMPNE, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETULT:
-         BuildMI(BB, IA64::FCMPLTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETUGT:
-         BuildMI(BB, IA64::FCMPGTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETULE:
-         BuildMI(BB, IA64::FCMPLEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       case ISD::SETUGE:
-         BuildMI(BB, IA64::FCMPGEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
-         break;
-       }
+    } else { // if not integer, should be FP.
+      assert(N.getOperand(0).getValueType() != MVT::f32 &&
+          "error: SETCC should have had incoming f32 promoted to f64!\n");
+
+      if(ConstantFPSDNode *CFPSDN =
+           dyn_cast<ConstantFPSDNode>(N.getOperand(1))) {
+
+        // if we are comparing against a constant +0.0 or +1.0
+        if(CFPSDN->isExactlyValue(+0.0))
+          Tmp2 = IA64::F0; // then we can just compare against f0
+        else if(CFPSDN->isExactlyValue(+1.0))
+          Tmp2 = IA64::F1; // or f1
+        else
+          Tmp2 = SelectExpr(N.getOperand(1));
+      } else // not comparing against a constant
+        Tmp2 = SelectExpr(N.getOperand(1));
+
+      switch (CC) {
+      default: assert(0 && "Unknown FP comparison!");
+      case ISD::SETEQ:
+        BuildMI(BB, IA64::FCMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETGT:
+        BuildMI(BB, IA64::FCMPGT, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETGE:
+        BuildMI(BB, IA64::FCMPGE, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETLT:
+        BuildMI(BB, IA64::FCMPLT, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETLE:
+        BuildMI(BB, IA64::FCMPLE, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETNE:
+        BuildMI(BB, IA64::FCMPNE, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETULT:
+        BuildMI(BB, IA64::FCMPLTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETUGT:
+        BuildMI(BB, IA64::FCMPGTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETULE:
+        BuildMI(BB, IA64::FCMPLEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
+      case ISD::SETUGE:
+        BuildMI(BB, IA64::FCMPGEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
+        break;
       }
     }
-    else
-      assert(0 && "this setcc not implemented yet");
-
     return Result;
   }
 
@@ -1437,32 +1914,33 @@ pC = pA OR pB
       Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
 
     bool isBool=false;
-    
+
     if(opcode == ISD::LOAD) { // this is a LOAD
       switch (Node->getValueType(0)) {
-       default: assert(0 && "Cannot load this type!");
-       case MVT::i1:  Opc = IA64::LD1; isBool=true; break;
-             // FIXME: for now, we treat bool loads the same as i8 loads */
-       case MVT::i8:  Opc = IA64::LD1; break;
-       case MVT::i16: Opc = IA64::LD2; break;
-       case MVT::i32: Opc = IA64::LD4; break;
-       case MVT::i64: Opc = IA64::LD8; break;
-                      
-       case MVT::f32: Opc = IA64::LDF4; break;
-       case MVT::f64: Opc = IA64::LDF8; break;
+        default: assert(0 && "Cannot load this type!");
+        case MVT::i1:  Opc = IA64::LD1; isBool=true; break;
+              // FIXME: for now, we treat bool loads the same as i8 loads */
+        case MVT::i8:  Opc = IA64::LD1; break;
+        case MVT::i16: Opc = IA64::LD2; break;
+        case MVT::i32: Opc = IA64::LD4; break;
+        case MVT::i64: Opc = IA64::LD8; break;
+
+        case MVT::f32: Opc = IA64::LDF4; break;
+        case MVT::f64: Opc = IA64::LDF8; break;
       }
     } else { // this is an EXTLOAD or ZEXTLOAD
-      MVT::ValueType TypeBeingLoaded = cast<MVTSDNode>(Node)->getExtraValueType();
+      MVT::ValueType TypeBeingLoaded =
+        cast<VTSDNode>(Node->getOperand(3))->getVT();
       switch (TypeBeingLoaded) {
-       default: assert(0 && "Cannot extload/zextload this type!");
-       // FIXME: bools?
-       case MVT::i8: Opc = IA64::LD1; break;
-       case MVT::i16: Opc = IA64::LD2; break;
-       case MVT::i32: Opc = IA64::LD4; break;
-       case MVT::f32: Opc = IA64::LDF4; break;
+        default: assert(0 && "Cannot extload/zextload this type!");
+        // FIXME: bools?
+        case MVT::i8: Opc = IA64::LD1; break;
+        case MVT::i16: Opc = IA64::LD2; break;
+        case MVT::i32: Opc = IA64::LD4; break;
+        case MVT::f32: Opc = IA64::LDF4; break;
       }
     }
-    
+
     SDOperand Chain = N.getOperand(0);
     SDOperand Address = N.getOperand(1);
 
@@ -1471,144 +1949,152 @@ pC = pA OR pB
       unsigned dummy = MakeReg(MVT::i64);
       unsigned dummy2 = MakeReg(MVT::i64);
       BuildMI(BB, IA64::ADD, 2, dummy)
-       .addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal())
-       .addReg(IA64::r1);
+        .addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal())
+        .addReg(IA64::r1);
       BuildMI(BB, IA64::LD8, 1, dummy2).addReg(dummy);
       if(!isBool)
-       BuildMI(BB, Opc, 1, Result).addReg(dummy2);
+        BuildMI(BB, Opc, 1, Result).addReg(dummy2);
       else { // emit a little pseudocode to load a bool (stored in one byte)
-            // into a predicate register
-       assert(Opc==IA64::LD1 && "problem loading a bool");
-       unsigned dummy3 = MakeReg(MVT::i64);
-       BuildMI(BB, Opc, 1, dummy3).addReg(dummy2);
-       // we compare to 0. true? 0. false? 1.
-       BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy3).addReg(IA64::r0);
+             // into a predicate register
+        assert(Opc==IA64::LD1 && "problem loading a bool");
+        unsigned dummy3 = MakeReg(MVT::i64);
+        BuildMI(BB, Opc, 1, dummy3).addReg(dummy2);
+        // we compare to 0. true? 0. false? 1.
+        BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy3).addReg(IA64::r0);
       }
     } else if(ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
+      unsigned CPIdx = BB->getParent()->getConstantPool()->
+                           getConstantPoolIndex(CP->get());
       Select(Chain);
       IA64Lowering.restoreGP(BB);
       unsigned dummy = MakeReg(MVT::i64);
-      BuildMI(BB, IA64::ADD, 2, dummy).addConstantPoolIndex(CP->getIndex())
-       .addReg(IA64::r1); // CPI+GP
+      unsigned dummy2 = MakeReg(MVT::i64);
+      BuildMI(BB, IA64::MOVLIMM64, 1, dummy2).addConstantPoolIndex(CPIdx);
+      BuildMI(BB, IA64::ADD, 2, dummy).addReg(dummy2).addReg(IA64::r1); //CPI+GP
+
+
+ // OLD     BuildMI(BB, IA64::ADD, 2, dummy).addConstantPoolIndex(CPIdx)
+ // (FIXME!)      .addReg(IA64::r1); // CPI+GP
       if(!isBool)
-       BuildMI(BB, Opc, 1, Result).addReg(dummy);
+        BuildMI(BB, Opc, 1, Result).addReg(dummy);
       else { // emit a little pseudocode to load a bool (stored in one byte)
-            // into a predicate register
-       assert(Opc==IA64::LD1 && "problem loading a bool");
-       unsigned dummy3 = MakeReg(MVT::i64);
-       BuildMI(BB, Opc, 1, dummy3).addReg(dummy);
-       // we compare to 0. true? 0. false? 1.
-       BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy3).addReg(IA64::r0);
+             // into a predicate register
+        assert(Opc==IA64::LD1 && "problem loading a bool");
+        unsigned dummy3 = MakeReg(MVT::i64);
+        BuildMI(BB, Opc, 1, dummy3).addReg(dummy);
+        // we compare to 0. true? 0. false? 1.
+        BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy3).addReg(IA64::r0);
       }
     } else if(Address.getOpcode() == ISD::FrameIndex) {
       Select(Chain);  // FIXME ? what about bools?
       unsigned dummy = MakeReg(MVT::i64);
       BuildMI(BB, IA64::MOV, 1, dummy)
-       .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex());
+        .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex());
       if(!isBool)
-       BuildMI(BB, Opc, 1, Result).addReg(dummy);
+        BuildMI(BB, Opc, 1, Result).addReg(dummy);
       else { // emit a little pseudocode to load a bool (stored in one byte)
-            // into a predicate register
-       assert(Opc==IA64::LD1 && "problem loading a bool");
-       unsigned dummy3 = MakeReg(MVT::i64);
-       BuildMI(BB, Opc, 1, dummy3).addReg(dummy);
-       // we compare to 0. true? 0. false? 1.
-       BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy3).addReg(IA64::r0);
+             // into a predicate register
+        assert(Opc==IA64::LD1 && "problem loading a bool");
+        unsigned dummy3 = MakeReg(MVT::i64);
+        BuildMI(BB, Opc, 1, dummy3).addReg(dummy);
+        // we compare to 0. true? 0. false? 1.
+        BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy3).addReg(IA64::r0);
       }
-    } else { // none of the above... 
+    } else { // none of the above...
       Select(Chain);
       Tmp2 = SelectExpr(Address);
       if(!isBool)
-       BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
+        BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
       else { // emit a little pseudocode to load a bool (stored in one byte)
-            // into a predicate register
-       assert(Opc==IA64::LD1 && "problem loading a bool");
-       unsigned dummy = MakeReg(MVT::i64);
-       BuildMI(BB, Opc, 1, dummy).addReg(Tmp2);
-       // we compare to 0. true? 0. false? 1.
-       BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy).addReg(IA64::r0);
-      }        
+             // into a predicate register
+        assert(Opc==IA64::LD1 && "problem loading a bool");
+        unsigned dummy = MakeReg(MVT::i64);
+        BuildMI(BB, Opc, 1, dummy).addReg(Tmp2);
+        // we compare to 0. true? 0. false? 1.
+        BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy).addReg(IA64::r0);
+      }
     }
 
     return Result;
   }
-  
+
   case ISD::CopyFromReg: {
     if (Result == 1)
-        Result = ExprMap[N.getValue(0)] = 
-         MakeReg(N.getValue(0).getValueType());
-                                                                                
+        Result = ExprMap[N.getValue(0)] =
+          MakeReg(N.getValue(0).getValueType());
+
       SDOperand Chain   = N.getOperand(0);
 
       Select(Chain);
-      unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
+      unsigned r = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
 
       if(N.getValueType() == MVT::i1) // if a bool, we use pseudocode
-       BuildMI(BB, IA64::PCMPEQUNC, 3, Result)
-         .addReg(IA64::r0).addReg(IA64::r0).addReg(r);
+        BuildMI(BB, IA64::PCMPEQUNC, 3, Result)
+          .addReg(IA64::r0).addReg(IA64::r0).addReg(r);
                             // (r) Result =cmp.eq.unc(r0,r0)
       else
-       BuildMI(BB, IA64::MOV, 1, Result).addReg(r); // otherwise MOV
+        BuildMI(BB, IA64::MOV, 1, Result).addReg(r); // otherwise MOV
       return Result;
   }
 
+  case ISD::TAILCALL:
   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;
 
       for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
-       argvregs.push_back(SelectExpr(N.getOperand(i)));
-      
-      // see section 8.5.8 of "Itanium Software Conventions and 
+        argvregs.push_back(SelectExpr(N.getOperand(i)));
+
+      // see section 8.5.8 of "Itanium Software Conventions and
       // Runtime Architecture Guide to see some examples of what's going
       // on here. (in short: int args get mapped 1:1 'slot-wise' to out0->out7,
       // while FP args get mapped to F8->F15 as needed)
 
       unsigned used_FPArgs=0; // how many FP Args have been used so far?
-      
+
       // in reg args
       for(int i = 0, e = std::min(8, (int)argvregs.size()); i < e; ++i)
       {
-       unsigned intArgs[] = {IA64::out0, IA64::out1, IA64::out2, IA64::out3, 
-                             IA64::out4, IA64::out5, IA64::out6, IA64::out7 };
-       unsigned FPArgs[] = {IA64::F8, IA64::F9, IA64::F10, IA64::F11,
-                            IA64::F12, IA64::F13, IA64::F14, IA64::F15 };
-
-       switch(N.getOperand(i+2).getValueType())
-       {
-         default:  // XXX do we need to support MVT::i1 here?
-           Node->dump();
-           N.getOperand(i).Val->dump();
-           std::cerr << "Type for " << i << " is: " << 
-             N.getOperand(i+2).getValueType() << std::endl;
-           assert(0 && "Unknown value type for call");
-         case MVT::i64:
-           BuildMI(BB, IA64::MOV, 1, intArgs[i]).addReg(argvregs[i]);
-           break;
-         case MVT::f64:
-           BuildMI(BB, IA64::FMOV, 1, FPArgs[used_FPArgs++])
-             .addReg(argvregs[i]);
-           // FIXME: we don't need to do this _all_ the time:
-           BuildMI(BB, IA64::GETFD, 1, intArgs[i]).addReg(argvregs[i]);
-           break;
-         }
+        unsigned intArgs[] = {IA64::out0, IA64::out1, IA64::out2, IA64::out3,
+                              IA64::out4, IA64::out5, IA64::out6, IA64::out7 };
+        unsigned FPArgs[] = {IA64::F8, IA64::F9, IA64::F10, IA64::F11,
+                             IA64::F12, IA64::F13, IA64::F14, IA64::F15 };
+
+        switch(N.getOperand(i+2).getValueType())
+        {
+          default:  // XXX do we need to support MVT::i1 here?
+            Node->dump();
+            N.getOperand(i).Val->dump();
+            std::cerr << "Type for " << i << " is: " <<
+              N.getOperand(i+2).getValueType() << std::endl;
+            assert(0 && "Unknown value type for call");
+          case MVT::i64:
+            BuildMI(BB, IA64::MOV, 1, intArgs[i]).addReg(argvregs[i]);
+            break;
+          case MVT::f64:
+            BuildMI(BB, IA64::FMOV, 1, FPArgs[used_FPArgs++])
+              .addReg(argvregs[i]);
+            // FIXME: we don't need to do this _all_ the time:
+            BuildMI(BB, IA64::GETFD, 1, intArgs[i]).addReg(argvregs[i]);
+            break;
+          }
       }
 
       //in mem args
       for (int i = 8, e = argvregs.size(); i < e; ++i)
       {
-       unsigned tempAddr = MakeReg(MVT::i64);
-       
+        unsigned tempAddr = MakeReg(MVT::i64);
+
         switch(N.getOperand(i+2).getValueType()) {
-        default: 
-          Node->dump(); 
+        default:
+          Node->dump();
           N.getOperand(i).Val->dump();
-          std::cerr << "Type for " << i << " is: " << 
+          std::cerr << "Type for " << i << " is: " <<
             N.getOperand(i+2).getValueType() << "\n";
           assert(0 && "Unknown value type for call");
         case MVT::i1: // FIXME?
@@ -1616,44 +2102,43 @@ pC = pA OR pB
         case MVT::i16:
         case MVT::i32:
         case MVT::i64:
-         BuildMI(BB, IA64::ADDIMM22, 2, tempAddr)
-           .addReg(IA64::r12).addImm(16 + (i - 8) * 8); // r12 is SP
-         BuildMI(BB, IA64::ST8, 2).addReg(tempAddr).addReg(argvregs[i]);
+          BuildMI(BB, IA64::ADDIMM22, 2, tempAddr)
+            .addReg(IA64::r12).addImm(16 + (i - 8) * 8); // r12 is SP
+          BuildMI(BB, IA64::ST8, 2).addReg(tempAddr).addReg(argvregs[i]);
           break;
         case MVT::f32:
         case MVT::f64:
           BuildMI(BB, IA64::ADDIMM22, 2, tempAddr)
-           .addReg(IA64::r12).addImm(16 + (i - 8) * 8); // r12 is SP
-         BuildMI(BB, IA64::STF8, 2).addReg(tempAddr).addReg(argvregs[i]);
+            .addReg(IA64::r12).addImm(16 + (i - 8) * 8); // r12 is SP
+          BuildMI(BB, IA64::STF8, 2).addReg(tempAddr).addReg(argvregs[i]);
           break;
         }
       }
 
-      /*  XXX we want to re-enable direct branches! crippling them now
-       *  to stress-test indirect branches.: 
-    //build the right kind of call
+    // build the right kind of call. if we can branch directly, do so:
     if (GlobalAddressSDNode *GASD =
-               dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) 
+               dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
       {
-       BuildMI(BB, IA64::BRCALL, 1).addGlobalAddress(GASD->getGlobal(),true);
-       IA64Lowering.restoreGP_SP_RP(BB);
-      }
-             ^^^^^^^^^^^^^ we want this code one day XXX */ 
+        BuildMI(BB, IA64::BRCALL, 1).addGlobalAddress(GASD->getGlobal(),true);
+        IA64Lowering.restoreGP_SP_RP(BB);
+      } else
     if (ExternalSymbolSDNode *ESSDN =
-            dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) 
+             dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
       { // FIXME : currently need this case for correctness, to avoid
-       // "non-pic code with imm relocation against dynamic symbol" errors
-       BuildMI(BB, IA64::BRCALL, 1)
-         .addExternalSymbol(ESSDN->getSymbol(), true);
-       IA64Lowering.restoreGP_SP_RP(BB);
+        // "non-pic code with imm relocation against dynamic symbol" errors
+        BuildMI(BB, IA64::BRCALL, 1)
+          .addExternalSymbol(ESSDN->getSymbol(), true);
+        IA64Lowering.restoreGP_SP_RP(BB);
       }
-    else {
+    else { // otherwise we need to get the function descriptor
+           // load the branch target (function)'s entry point and
+           // GP, then branch
       Tmp1 = SelectExpr(N.getOperand(1));
 
       unsigned targetEntryPoint=MakeReg(MVT::i64);
       unsigned targetGPAddr=MakeReg(MVT::i64);
       unsigned currentGP=MakeReg(MVT::i64);
-      
+
       // b6 is a scratch branch register, we load the target entry point
       // from the base of the function descriptor
       BuildMI(BB, IA64::LD8, 1, targetEntryPoint).addReg(Tmp1);
@@ -1661,12 +2146,12 @@ pC = pA OR pB
 
       // save the current GP:
       BuildMI(BB, IA64::MOV, 1, currentGP).addReg(IA64::r1);
-     
+
       /* TODO: we need to make sure doing this never, ever loads a
        * bogus value into r1 (GP). */
       // load the target GP (which is at mem[functiondescriptor+8])
       BuildMI(BB, IA64::ADDIMM22, 2, targetGPAddr)
-       .addReg(Tmp1).addImm(8); // FIXME: addimm22? why not postincrement ld
+        .addReg(Tmp1).addImm(8); // FIXME: addimm22? why not postincrement ld
       BuildMI(BB, IA64::LD8, 1, IA64::r1).addReg(targetGPAddr);
 
       // and then jump: (well, call)
@@ -1681,7 +2166,7 @@ pC = pA OR pB
     case MVT::Other: return 1;
     case MVT::i1:
       BuildMI(BB, IA64::CMPNE, 2, Result)
-       .addReg(IA64::r8).addReg(IA64::r0);
+        .addReg(IA64::r8).addReg(IA64::r0);
       break;
     case MVT::i8:
     case MVT::i16:
@@ -1696,7 +2181,7 @@ pC = pA OR pB
     return Result+N.ResNo;
   }
 
-  } // <- uhhh XXX 
+  } // <- uhhh XXX
   return 0;
 }
 
@@ -1715,7 +2200,7 @@ void ISel::Select(SDOperand N) {
     assert(0 && "Node not handled yet!");
 
   case ISD::EntryToken: return;  // Noop
-  
+
   case ISD::TokenFactor: {
     for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
       Select(Node->getOperand(i));
@@ -1724,21 +2209,23 @@ void ISel::Select(SDOperand N) {
 
   case ISD::CopyToReg: {
     Select(N.getOperand(0));
-    Tmp1 = SelectExpr(N.getOperand(1));   
-    Tmp2 = cast<RegSDNode>(N)->getReg();
-    
+    Tmp1 = SelectExpr(N.getOperand(2));
+    Tmp2 = cast<RegisterSDNode>(N.getOperand(1))->getReg();
+
     if (Tmp1 != Tmp2) {
-      if(N.getValueType() == MVT::i1) // if a bool, we use pseudocode
-       BuildMI(BB, IA64::PCMPEQUNC, 3, Tmp2)
-         .addReg(IA64::r0).addReg(IA64::r0).addReg(Tmp1);
+      // if a bool, we use pseudocode
+      if (N.getOperand(2).getValueType() == MVT::i1)
+        BuildMI(BB, IA64::PCMPEQUNC, 3, Tmp2)
+          .addReg(IA64::r0).addReg(IA64::r0).addReg(Tmp1);
                                    // (Tmp1) Tmp2 = cmp.eq.unc(r0,r0)
       else
-       BuildMI(BB, IA64::MOV, 1, Tmp2).addReg(Tmp1);
+        BuildMI(BB, IA64::MOV, 1, Tmp2).addReg(Tmp1);
                       // XXX is this the right way 'round? ;)
+      // FIXME: WHAT ABOUT FLOATING POINT?
     }
     return;
   }
-  
+
   case ISD::RET: {
 
   /* what the heck is going on here:
@@ -1759,7 +2246,7 @@ void ISel::Select(SDOperand N) {
 <_sabre_> these operand often define chains, they are the last operand
 <_sabre_> they are printed as 'ch' if you do DAG.dump()
   */
-  
+
     switch (N.getNumOperands()) {
     default:
       assert(0 && "Unknown return instruction!");
@@ -1768,13 +2255,18 @@ void ISel::Select(SDOperand N) {
         Tmp1 = SelectExpr(N.getOperand(1));
       switch (N.getOperand(1).getValueType()) {
       default: assert(0 && "All other types should have been promoted!!");
-              // FIXME: do I need to add support for bools here?
-              // (return '0' or '1' r8, basically...)
+               // FIXME: do I need to add support for bools here?
+               // (return '0' or '1' r8, basically...)
+               //
+               // FIXME: need to round floats - 80 bits is bad, the tester
+               // told me so
       case MVT::i64:
-       BuildMI(BB, IA64::MOV, 1, IA64::r8).addReg(Tmp1);
-       break;
+        // we mark r8 as live on exit up above in LowerArguments()
+        BuildMI(BB, IA64::MOV, 1, IA64::r8).addReg(Tmp1);
+        break;
       case MVT::f64:
-       BuildMI(BB, IA64::FMOV, 1, IA64::F8).addReg(Tmp1);
+        // we mark F8 as live on exit up above in LowerArguments()
+        BuildMI(BB, IA64::FMOV, 1, IA64::F8).addReg(Tmp1);
       }
       break;
     case 1:
@@ -1786,7 +2278,7 @@ void ISel::Select(SDOperand N) {
     BuildMI(BB, IA64::RET, 0); // and then just emit a 'ret' instruction
     return;
   }
-  
+
   case ISD::BR: {
     Select(N.getOperand(0));
     MachineBasicBlock *Dest =
@@ -1796,12 +2288,6 @@ void ISel::Select(SDOperand N) {
     return;
   }
 
-  case ISD::ImplicitDef: {
-    Select(N.getOperand(0));
-    BuildMI(BB, IA64::IDEF, 0, cast<RegSDNode>(N)->getReg());
-    return;
-  }
-
   case ISD::BRCOND: {
     MachineBasicBlock *Dest =
       cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
@@ -1812,11 +2298,12 @@ void ISel::Select(SDOperand N) {
     // XXX HACK! we do _not_ need long branches all the time
     return;
   }
-  
+
   case ISD::EXTLOAD:
   case ISD::ZEXTLOAD:
   case ISD::SEXTLOAD:
   case ISD::LOAD:
+  case ISD::TAILCALL:
   case ISD::CALL:
   case ISD::CopyFromReg:
   case ISD::DYNAMIC_STACKALLOC:
@@ -1829,85 +2316,85 @@ void ISel::Select(SDOperand N) {
       Tmp1 = SelectExpr(N.getOperand(1)); // value
 
       bool isBool=false;
-     
+
       if(opcode == ISD::STORE) {
-       switch (N.getOperand(1).getValueType()) {
-         default: assert(0 && "Cannot store this type!");
-         case MVT::i1:  Opc = IA64::ST1; isBool=true; break;
-             // FIXME?: for now, we treat bool loads the same as i8 stores */
-         case MVT::i8:  Opc = IA64::ST1; break;
-         case MVT::i16: Opc = IA64::ST2; break;
-         case MVT::i32: Opc = IA64::ST4; break;
-         case MVT::i64: Opc = IA64::ST8; break;
-                        
-         case MVT::f32: Opc = IA64::STF4; break;
-         case MVT::f64: Opc = IA64::STF8; break;
-       }
+        switch (N.getOperand(1).getValueType()) {
+          default: assert(0 && "Cannot store this type!");
+          case MVT::i1:  Opc = IA64::ST1; isBool=true; break;
+              // FIXME?: for now, we treat bool loads the same as i8 stores */
+          case MVT::i8:  Opc = IA64::ST1; break;
+          case MVT::i16: Opc = IA64::ST2; break;
+          case MVT::i32: Opc = IA64::ST4; break;
+          case MVT::i64: Opc = IA64::ST8; break;
+
+          case MVT::f32: Opc = IA64::STF4; break;
+          case MVT::f64: Opc = IA64::STF8; break;
+        }
       } else { // truncstore
-       switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
-         default: assert(0 && "unknown type in truncstore");
-         case MVT::i1: Opc = IA64::ST1; isBool=true; break;
-                       //FIXME: DAG does not promote this load?
-         case MVT::i8: Opc = IA64::ST1; break;
-         case MVT::i16: Opc = IA64::ST2; break;
-         case MVT::i32: Opc = IA64::ST4; break;
-         case MVT::f32: Opc = IA64::STF4; break; 
-       }
+        switch(cast<VTSDNode>(Node->getOperand(4))->getVT()) {
+          default: assert(0 && "unknown type in truncstore");
+          case MVT::i1: Opc = IA64::ST1; isBool=true; break;
+                        //FIXME: DAG does not promote this load?
+          case MVT::i8: Opc = IA64::ST1; break;
+          case MVT::i16: Opc = IA64::ST2; break;
+          case MVT::i32: Opc = IA64::ST4; break;
+          case MVT::f32: Opc = IA64::STF4; break;
+        }
       }
 
       if(N.getOperand(2).getOpcode() == ISD::GlobalAddress) {
-       unsigned dummy = MakeReg(MVT::i64);
-       unsigned dummy2 = MakeReg(MVT::i64);
-       BuildMI(BB, IA64::ADD, 2, dummy)
-         .addGlobalAddress(cast<GlobalAddressSDNode>
-             (N.getOperand(2))->getGlobal()).addReg(IA64::r1);
-       BuildMI(BB, IA64::LD8, 1, dummy2).addReg(dummy);
-      
-       if(!isBool)
-         BuildMI(BB, Opc, 2).addReg(dummy2).addReg(Tmp1);
-       else { // we are storing a bool, so emit a little pseudocode
-              // to store a predicate register as one byte
-         assert(Opc==IA64::ST1);
-         unsigned dummy3 = MakeReg(MVT::i64);
-         unsigned dummy4 = MakeReg(MVT::i64);
-         BuildMI(BB, IA64::MOV, 1, dummy3).addReg(IA64::r0);
-         BuildMI(BB, IA64::TPCADDIMM22, 2, dummy4)
-           .addReg(dummy3).addImm(1).addReg(Tmp1); // if(Tmp1) dummy=0+1;
-         BuildMI(BB, Opc, 2).addReg(dummy2).addReg(dummy4);
-       }
+        unsigned dummy = MakeReg(MVT::i64);
+        unsigned dummy2 = MakeReg(MVT::i64);
+        BuildMI(BB, IA64::ADD, 2, dummy)
+          .addGlobalAddress(cast<GlobalAddressSDNode>
+              (N.getOperand(2))->getGlobal()).addReg(IA64::r1);
+        BuildMI(BB, IA64::LD8, 1, dummy2).addReg(dummy);
+
+        if(!isBool)
+          BuildMI(BB, Opc, 2).addReg(dummy2).addReg(Tmp1);
+        else { // we are storing a bool, so emit a little pseudocode
+               // to store a predicate register as one byte
+          assert(Opc==IA64::ST1);
+          unsigned dummy3 = MakeReg(MVT::i64);
+          unsigned dummy4 = MakeReg(MVT::i64);
+          BuildMI(BB, IA64::MOV, 1, dummy3).addReg(IA64::r0);
+          BuildMI(BB, IA64::TPCADDIMM22, 2, dummy4)
+            .addReg(dummy3).addImm(1).addReg(Tmp1); // if(Tmp1) dummy=0+1;
+          BuildMI(BB, Opc, 2).addReg(dummy2).addReg(dummy4);
+        }
       } else if(N.getOperand(2).getOpcode() == ISD::FrameIndex) {
 
-       // FIXME? (what about bools?)
-       
-       unsigned dummy = MakeReg(MVT::i64);
-       BuildMI(BB, IA64::MOV, 1, dummy)
-         .addFrameIndex(cast<FrameIndexSDNode>(N.getOperand(2))->getIndex());
-       BuildMI(BB, Opc, 2).addReg(dummy).addReg(Tmp1);
+        // FIXME? (what about bools?)
+
+        unsigned dummy = MakeReg(MVT::i64);
+        BuildMI(BB, IA64::MOV, 1, dummy)
+          .addFrameIndex(cast<FrameIndexSDNode>(N.getOperand(2))->getIndex());
+        BuildMI(BB, Opc, 2).addReg(dummy).addReg(Tmp1);
       } else { // otherwise
-       Tmp2 = SelectExpr(N.getOperand(2)); //address
-       if(!isBool) 
-         BuildMI(BB, Opc, 2).addReg(Tmp2).addReg(Tmp1);
-       else { // we are storing a bool, so emit a little pseudocode
-              // to store a predicate register as one byte
-         assert(Opc==IA64::ST1);
-         unsigned dummy3 = MakeReg(MVT::i64);
-         unsigned dummy4 = MakeReg(MVT::i64);
-         BuildMI(BB, IA64::MOV, 1, dummy3).addReg(IA64::r0);
-         BuildMI(BB, IA64::TPCADDIMM22, 2, dummy4)
-           .addReg(dummy3).addImm(1).addReg(Tmp1); // if(Tmp1) dummy=0+1;
-         BuildMI(BB, Opc, 2).addReg(Tmp2).addReg(dummy4);
-       }
+        Tmp2 = SelectExpr(N.getOperand(2)); //address
+        if(!isBool)
+          BuildMI(BB, Opc, 2).addReg(Tmp2).addReg(Tmp1);
+        else { // we are storing a bool, so emit a little pseudocode
+               // to store a predicate register as one byte
+          assert(Opc==IA64::ST1);
+          unsigned dummy3 = MakeReg(MVT::i64);
+          unsigned dummy4 = MakeReg(MVT::i64);
+          BuildMI(BB, IA64::MOV, 1, dummy3).addReg(IA64::r0);
+          BuildMI(BB, IA64::TPCADDIMM22, 2, dummy4)
+            .addReg(dummy3).addImm(1).addReg(Tmp1); // if(Tmp1) dummy=0+1;
+          BuildMI(BB, Opc, 2).addReg(Tmp2).addReg(dummy4);
+        }
       }
     return;
   }
-  
-  case ISD::ADJCALLSTACKDOWN:
-  case ISD::ADJCALLSTACKUP: {
+
+  case ISD::CALLSEQ_START:
+  case ISD::CALLSEQ_END: {
     Select(N.getOperand(0));
     Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
-   
-    Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? IA64::ADJUSTCALLSTACKDOWN :
-                                                   IA64::ADJUSTCALLSTACKUP;
+
+    Opc = N.getOpcode() == ISD::CALLSEQ_START ? IA64::ADJUSTCALLSTACKDOWN :
+                                                IA64::ADJUSTCALLSTACKUP;
     BuildMI(BB, Opc, 1).addImm(Tmp1);
     return;
   }
@@ -1923,7 +2410,7 @@ void ISel::Select(SDOperand N) {
 /// description file.
 ///
 FunctionPass *llvm::createIA64PatternInstructionSelector(TargetMachine &TM) {
-  return new ISel(TM);  
+  return new ISel(TM);
 }