Specify the correct number of operands
[oota-llvm.git] / lib / Target / PowerPC / PPCISelPattern.cpp
index 3281313617dafdc5fa3c18b705f0f1e5b84e8381..efdb8b5b28940ff4943d51458f15507b976dfcea 100644 (file)
@@ -17,9 +17,9 @@
 #include "PowerPCInstrBuilder.h"
 #include "PowerPCInstrInfo.h"
 #include "PPC32TargetMachine.h"
-#include "llvm/Constants.h"                   // FIXME: REMOVE
+#include "llvm/Constants.h"
 #include "llvm/Function.h"
-#include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE
+#include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/SelectionDAG.h"
@@ -64,13 +64,19 @@ namespace {
       setOperationAction(ISD::SREM, MVT::i32, Expand);
       setOperationAction(ISD::UREM, MVT::i32, Expand);
 
-      // We don't support sin/cos/sqrt
+      // We don't support sin/cos/sqrt/fmod
       setOperationAction(ISD::FSIN , MVT::f64, Expand);
       setOperationAction(ISD::FCOS , MVT::f64, Expand);
-      setOperationAction(ISD::FSQRT, MVT::f64, Expand);
+      setOperationAction(ISD::SREM , MVT::f64, Expand);
       setOperationAction(ISD::FSIN , MVT::f32, Expand);
       setOperationAction(ISD::FCOS , MVT::f32, Expand);
-      setOperationAction(ISD::FSQRT, MVT::f32, Expand);
+      setOperationAction(ISD::SREM , MVT::f32, Expand);
+
+      // If we're enabling GP optimizations, use hardware square root
+      if (!GPOPT) {
+        setOperationAction(ISD::FSQRT, MVT::f64, Expand);
+        setOperationAction(ISD::FSQRT, MVT::f32, Expand);
+      }
 
       //PowerPC does not have CTPOP or CTTZ
       setOperationAction(ISD::CTPOP, MVT::i32  , Expand);
@@ -91,15 +97,16 @@ 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);
+    LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC,
+                bool isTailCall, SDOperand Callee, ArgListTy &Args,
+                SelectionDAG &DAG);
 
-    virtual std::pair<SDOperand, SDOperand>
-    LowerVAStart(SDOperand Chain, 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);
+      LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
+                 const Type *ArgTy, SelectionDAG &DAG);
 
     virtual std::pair<SDOperand, SDOperand>
     LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
@@ -179,7 +186,8 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
         } else {
           int FI = MFI->CreateFixedObject(4, ArgOffset+4);
           SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
-          argLo = DAG.getLoad(MVT::i32, DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL));
+          argLo = DAG.getLoad(MVT::i32, DAG.getEntryNode(), FIN,
+                              DAG.getSrcValue(NULL));
         }
         // Build the outgoing arg thingy
         argt = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, argLo, argHi);
@@ -214,7 +222,8 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
       SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
       FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN,
                         DAG.getConstant(SubregOffset, MVT::i32));
-      argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL));
+      argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN,
+                                   DAG.getSrcValue(NULL));
     }
 
     // Every 4 bytes of argument space consumes one of the GPRs available for
@@ -279,6 +288,7 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
 std::pair<SDOperand, SDOperand>
 PPC32TargetLowering::LowerCallTo(SDOperand Chain,
                                  const Type *RetTy, bool isVarArg,
+                                 unsigned CallingConv, bool isTailCall,
                                  SDOperand Callee, ArgListTy &Args,
                                  SelectionDAG &DAG) {
   // args_to_use will accumulate outgoing args for the ISD::CALL case in
@@ -290,7 +300,7 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
   unsigned NumBytes = 24;
 
   if (Args.empty()) {
-    Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
+    Chain = DAG.getNode(ISD::CALLSEQ_START, MVT::Other, Chain,
                         DAG.getConstant(NumBytes, getPointerTy()));
   } else {
     for (unsigned i = 0, e = Args.size(); i != e; ++i)
@@ -315,7 +325,7 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
 
     // Adjust the stack pointer for the new arguments...
     // These operations are automatically eliminated by the prolog/epilog pass
-    Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
+    Chain = DAG.getNode(ISD::CALLSEQ_START, MVT::Other, Chain,
                         DAG.getConstant(NumBytes, getPointerTy()));
 
     // Set up a copy of the stack pointer for use loading and storing any
@@ -358,7 +368,8 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
           --GPR_remaining;
         } else {
           MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                       Args[i].first, PtrOff, DAG.getSrcValue(NULL)));
+                                       Args[i].first, PtrOff,
+                                       DAG.getSrcValue(NULL)));
         }
         ArgOffset += 4;
         break;
@@ -384,7 +395,8 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
           }
         } else {
           MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                       Args[i].first, PtrOff, DAG.getSrcValue(NULL)));
+                                       Args[i].first, PtrOff,
+                                       DAG.getSrcValue(NULL)));
         }
         ArgOffset += 8;
         break;
@@ -395,11 +407,13 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
           --FPR_remaining;
           if (isVarArg) {
             SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                          Args[i].first, PtrOff, DAG.getSrcValue(NULL));
+                                          Args[i].first, PtrOff,
+                                          DAG.getSrcValue(NULL));
             MemOps.push_back(Store);
             // Float varargs are always shadowed in available integer registers
             if (GPR_remaining > 0) {
-              SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff, DAG.getSrcValue(NULL));
+              SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff,
+                                           DAG.getSrcValue(NULL));
               MemOps.push_back(Load);
               args_to_use.push_back(Load);
               --GPR_remaining;
@@ -407,7 +421,8 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
             if (GPR_remaining > 0 && MVT::f64 == ArgVT) {
               SDOperand ConstFour = DAG.getConstant(4, getPointerTy());
               PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour);
-              SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff, DAG.getSrcValue(NULL));
+              SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff,
+                                           DAG.getSrcValue(NULL));
               MemOps.push_back(Load);
               args_to_use.push_back(Load);
               --GPR_remaining;
@@ -427,7 +442,8 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
           }
         } else {
           MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                       Args[i].first, PtrOff, DAG.getSrcValue(NULL)));
+                                       Args[i].first, PtrOff,
+                                       DAG.getSrcValue(NULL)));
         }
         ArgOffset += (ArgVT == MVT::f32) ? 4 : 8;
         break;
@@ -446,36 +462,41 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
   SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
                                             Chain, Callee, args_to_use), 0);
   Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
-  Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
+  Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
                       DAG.getConstant(NumBytes, getPointerTy()));
   return std::make_pair(TheCall, Chain);
 }
 
-std::pair<SDOperand, SDOperand>
-PPC32TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
-  //vastart just returns the address of the VarArgsFrameIndex slot.
-  return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32), Chain);
+SDOperand PPC32TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
+                                            Value *VAListV, SelectionDAG &DAG) {
+  // vastart just stores the address of the VarArgsFrameIndex slot into the
+  // memory location argument.
+  SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32);
+  return DAG.getNode(ISD::STORE, MVT::Other, Chain, FR, VAListP,
+                     DAG.getSrcValue(VAListV));
 }
 
-std::pair<SDOperand,SDOperand> PPC32TargetLowering::
-LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
-               const Type *ArgTy, SelectionDAG &DAG) {
+std::pair<SDOperand,SDOperand>
+PPC32TargetLowering::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, DAG.getSrcValue(NULL));
-  } else {
-    unsigned Amt;
-    if (ArgVT == MVT::i32 || ArgVT == MVT::f32)
-      Amt = 4;
-    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 VAList =
+    DAG.getLoad(MVT::i32, Chain, VAListP, DAG.getSrcValue(VAListV));
+  SDOperand Result = DAG.getLoad(ArgVT, Chain, VAList, DAG.getSrcValue(NULL));
+  unsigned Amt;
+  if (ArgVT == MVT::i32 || ArgVT == MVT::f32)
+    Amt = 4;
+  else {
+    assert((ArgVT == MVT::i64 || ArgVT == MVT::f64) &&
+           "Other types should have been promoted for varargs!");
+    Amt = 8;
   }
+  VAList = DAG.getNode(ISD::ADD, VAList.getValueType(), VAList,
+                      DAG.getConstant(Amt, VAList.getValueType()));
+  Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                      VAList, VAListP, DAG.getSrcValue(VAListV));
   return std::make_pair(Result, Chain);
 }
 
@@ -490,7 +511,7 @@ LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
 namespace {
 Statistic<>Recorded("ppc-codegen", "Number of recording ops emitted");
 Statistic<>FusedFP("ppc-codegen", "Number of fused fp operations");
-Statistic<>MultiBranch("ppc-codegen", "Number of setcc logical ops collapsed");
+Statistic<>FrameOff("ppc-codegen", "Number of frame idx offsets collapsed");
 //===--------------------------------------------------------------------===//
 /// ISel - PPC32 specific code to select PPC32 machine instructions for
 /// SelectionDAG operations.
@@ -546,10 +567,9 @@ public:
   unsigned SelectCC(SDOperand CC, unsigned &Opc, bool &Inv, unsigned &Idx);
   unsigned SelectCCExpr(SDOperand N, unsigned& Opc, bool &Inv, unsigned &Idx);
   unsigned SelectExpr(SDOperand N, bool Recording=false);
-  unsigned SelectExprFP(SDOperand N, unsigned Result);
   void Select(SDOperand N);
 
-  bool SelectAddr(SDOperand N, unsigned& Reg, int& offset);
+  unsigned SelectAddr(SDOperand N, unsigned& Reg, int& offset);
   void SelectBranchCC(SDOperand N);
 };
 
@@ -934,8 +954,11 @@ unsigned ISel::getConstDouble(double doubleVal, unsigned Result=0) {
   MachineConstantPool *CP = BB->getParent()->getConstantPool();
   ConstantFP *CFP = ConstantFP::get(Type::DoubleTy, doubleVal);
   unsigned CPI = CP->getConstantPoolIndex(CFP);
-  BuildMI(BB, PPC::LOADHiAddr, 2, Tmp1).addReg(getGlobalBaseReg())
-    .addConstantPoolIndex(CPI);
+  if (PICEnabled)
+    BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg())
+      .addConstantPoolIndex(CPI);
+  else
+    BuildMI(BB, PPC::LIS, 1, Tmp1).addConstantPoolIndex(CPI);
   BuildMI(BB, PPC::LFD, 2, Result).addConstantPoolIndex(CPI).addReg(Tmp1);
   return Result;
 }
@@ -945,7 +968,7 @@ unsigned ISel::getConstDouble(double doubleVal, unsigned Result=0) {
 void ISel::MoveCRtoGPR(unsigned CCReg, bool Inv, unsigned Idx, unsigned Result){
   unsigned IntCR = MakeReg(MVT::i32);
   BuildMI(BB, PPC::MCRF, 1, PPC::CR7).addReg(CCReg);
-  BuildMI(BB, PPC::MFCR, 1, IntCR).addReg(PPC::CR7);
+  BuildMI(BB, GPOPT ? PPC::MFOCRF : PPC::MFCR, 1, IntCR).addReg(PPC::CR7);
   if (Inv) {
     unsigned Tmp1 = MakeReg(MVT::i32);
     BuildMI(BB, PPC::RLWINM, 4, Tmp1).addReg(IntCR).addImm(32-(3-Idx))
@@ -969,8 +992,12 @@ void ISel::MoveCRtoGPR(unsigned CCReg, bool Inv, unsigned Idx, unsigned Result){
 bool ISel::SelectBitfieldInsert(SDOperand OR, unsigned Result) {
   bool IsRotate = false;
   unsigned TgtMask = 0xFFFFFFFF, InsMask = 0xFFFFFFFF, Amount = 0;
-  unsigned Op0Opc = OR.getOperand(0).getOpcode();
-  unsigned Op1Opc = OR.getOperand(1).getOpcode();
+
+  SDOperand Op0 = OR.getOperand(0);
+  SDOperand Op1 = OR.getOperand(1);
+
+  unsigned Op0Opc = Op0.getOpcode();
+  unsigned Op1Opc = Op1.getOpcode();
 
   // Verify that we have the correct opcodes
   if (ISD::SHL != Op0Opc && ISD::SRL != Op0Opc && ISD::AND != Op0Opc)
@@ -980,7 +1007,7 @@ bool ISel::SelectBitfieldInsert(SDOperand OR, unsigned Result) {
 
   // Generate Mask value for Target
   if (ConstantSDNode *CN =
-      dyn_cast<ConstantSDNode>(OR.getOperand(0).getOperand(1).Val)) {
+      dyn_cast<ConstantSDNode>(Op0.getOperand(1).Val)) {
     switch(Op0Opc) {
     case ISD::SHL: TgtMask <<= (unsigned)CN->getValue(); break;
     case ISD::SRL: TgtMask >>= (unsigned)CN->getValue(); break;
@@ -992,7 +1019,7 @@ bool ISel::SelectBitfieldInsert(SDOperand OR, unsigned Result) {
 
   // Generate Mask value for Insert
   if (ConstantSDNode *CN =
-      dyn_cast<ConstantSDNode>(OR.getOperand(1).getOperand(1).Val)) {
+      dyn_cast<ConstantSDNode>(Op1.getOperand(1).Val)) {
     switch(Op1Opc) {
     case ISD::SHL:
       Amount = CN->getValue();
@@ -1013,27 +1040,55 @@ bool ISel::SelectBitfieldInsert(SDOperand OR, unsigned Result) {
     return false;
   }
 
+  unsigned Tmp3 = 0;
+
+  // If both of the inputs are ANDs and one of them has a logical shift by
+  // constant as its input, make that the inserted value so that we can combine
+  // the shift into the rotate part of the rlwimi instruction
+  if (Op0Opc == ISD::AND && Op1Opc == ISD::AND) {
+    if (Op1.getOperand(0).getOpcode() == ISD::SHL ||
+        Op1.getOperand(0).getOpcode() == ISD::SRL) {
+      if (ConstantSDNode *CN =
+          dyn_cast<ConstantSDNode>(Op1.getOperand(0).getOperand(1).Val)) {
+        Amount = Op1.getOperand(0).getOpcode() == ISD::SHL ?
+          CN->getValue() : 32 - CN->getValue();
+        Tmp3 = SelectExpr(Op1.getOperand(0).getOperand(0));
+      }
+    } else if (Op0.getOperand(0).getOpcode() == ISD::SHL ||
+               Op0.getOperand(0).getOpcode() == ISD::SRL) {
+      if (ConstantSDNode *CN =
+          dyn_cast<ConstantSDNode>(Op0.getOperand(0).getOperand(1).Val)) {
+        std::swap(Op0, Op1);
+        std::swap(TgtMask, InsMask);
+        Amount = Op1.getOperand(0).getOpcode() == ISD::SHL ?
+          CN->getValue() : 32 - CN->getValue();
+        Tmp3 = SelectExpr(Op1.getOperand(0).getOperand(0));
+      }
+    }
+  }
+
   // Verify that the Target mask and Insert mask together form a full word mask
   // and that the Insert mask is a run of set bits (which implies both are runs
   // of set bits).  Given that, Select the arguments and generate the rlwimi
   // instruction.
   unsigned MB, ME;
-  if (((TgtMask ^ InsMask) == 0xFFFFFFFF) && IsRunOfOnes(InsMask, MB, ME)) {
+  if (((TgtMask & InsMask) == 0) && IsRunOfOnes(InsMask, MB, ME)) {
     unsigned Tmp1, Tmp2;
+    bool fullMask = (TgtMask ^ InsMask) == 0xFFFFFFFF;
     // Check for rotlwi / rotrwi here, a special case of bitfield insert
     // where both bitfield halves are sourced from the same value.
-    if (IsRotate &&
+    if (IsRotate && fullMask &&
         OR.getOperand(0).getOperand(0) == OR.getOperand(1).getOperand(0)) {
       Tmp1 = SelectExpr(OR.getOperand(0).getOperand(0));
       BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(Amount)
         .addImm(0).addImm(31);
       return true;
     }
-    if (Op0Opc == ISD::AND)
-      Tmp1 = SelectExpr(OR.getOperand(0).getOperand(0));
+    if (Op0Opc == ISD::AND && fullMask)
+      Tmp1 = SelectExpr(Op0.getOperand(0));
     else
-      Tmp1 = SelectExpr(OR.getOperand(0));
-    Tmp2 = SelectExpr(OR.getOperand(1).getOperand(0));
+      Tmp1 = SelectExpr(Op0);
+    Tmp2 = Tmp3 ? Tmp3 : SelectExpr(Op1.getOperand(0));
     BuildMI(BB, PPC::RLWIMI, 5, Result).addReg(Tmp1).addReg(Tmp2)
       .addImm(Amount).addImm(MB).addImm(ME);
     return true;
@@ -1106,8 +1161,6 @@ unsigned ISel::SelectCC(SDOperand CC, unsigned& Opc, bool &Inv, unsigned& Idx) {
       BuildMI(BB, CompareOpc, 2, Result).addReg(Tmp1).addReg(Tmp2);
     }
   } else {
-    if (PPCCRopts)
-      return SelectCCExpr(CC, Opc, Inv, Idx);
     // If this isn't a SetCC, then select the value and compare it against zero,
     // treating it as if it were a boolean.
     Opc = PPC::BNE;
@@ -1136,7 +1189,6 @@ unsigned ISel::SelectCCExpr(SDOperand N, unsigned& Opc, bool &Inv,
     break;
   case ISD::OR:
   case ISD::AND:
-    ++MultiBranch;
     Tmp1 = SelectCCExpr(N.getOperand(0), Opc, Inv0, Idx0);
     Tmp2 = SelectCCExpr(N.getOperand(1), Opc1, Inv1, Idx1);
     CROpc = getCROpForSetCC(N.getOpcode(), Inv0, Inv1);
@@ -1160,21 +1212,30 @@ unsigned ISel::SelectCCExpr(SDOperand N, unsigned& Opc, bool &Inv,
 }
 
 /// Check to see if the load is a constant offset from a base register
-bool ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset)
+unsigned ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset)
 {
   unsigned imm = 0, opcode = N.getOpcode();
   if (N.getOpcode() == ISD::ADD) {
-    Reg = SelectExpr(N.getOperand(0));
+    bool isFrame = N.getOperand(0).getOpcode() == ISD::FrameIndex;
     if (1 == getImmediateForOpcode(N.getOperand(1), opcode, imm)) {
       offset = imm;
-      return false;
+      if (isFrame) {
+        ++FrameOff;
+        Reg = cast<FrameIndexSDNode>(N.getOperand(0))->getIndex();
+        return 1;
+      } else {
+        Reg = SelectExpr(N.getOperand(0));
+        return 0;
+      }
+    } else {
+      Reg = SelectExpr(N.getOperand(0));
+      offset = SelectExpr(N.getOperand(1));
+      return 2;
     }
-    offset = SelectExpr(N.getOperand(1));
-    return true;
   }
   Reg = SelectExpr(N);
   offset = 0;
-  return false;
+  return 0;
 }
 
 void ISel::SelectBranchCC(SDOperand N)
@@ -1187,9 +1248,9 @@ void ISel::SelectBranchCC(SDOperand N)
   Select(N.getOperand(0));  //chain
   CCReg = SelectCC(N.getOperand(1), Opc, Inv, Idx);
 
-  // Iterate to the next basic block, unless we're already at the end of the
-  ilist<MachineBasicBlock>::iterator It = BB, E = BB->getParent()->end();
-  if (++It == E) It = BB;
+  // Iterate to the next basic block
+  ilist<MachineBasicBlock>::iterator It = BB;
+  ++It;
 
   // If this is a two way branch, then grab the fallthrough basic block argument
   // and build a PowerPC branch pseudo-op, suitable for long branch conversion
@@ -1211,427 +1272,135 @@ void ISel::SelectBranchCC(SDOperand N)
       }
     }
   } else {
+    // If the fallthrough path is off the end of the function, which would be
+    // undefined behavior, set it to be the same as the current block because
+    // we have nothing better to set it to, and leaving it alone will cause the
+    // PowerPC Branch Selection pass to crash.
+    if (It == BB->getParent()->end()) It = Dest;
     BuildMI(BB, PPC::COND_BRANCH, 4).addReg(CCReg).addImm(Opc)
       .addMBB(Dest).addMBB(It);
   }
   return;
 }
 
-unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
-{
+unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
+  unsigned Result;
   unsigned Tmp1, Tmp2, Tmp3;
   unsigned Opc = 0;
+  unsigned opcode = N.getOpcode();
+
   SDNode *Node = N.Val;
   MVT::ValueType DestType = N.getValueType();
-  unsigned opcode = N.getOpcode();
+
+  if (Node->getOpcode() == ISD::CopyFromReg &&
+      MRegisterInfo::isVirtualRegister(cast<RegSDNode>(Node)->getReg()))
+    // Just use the specified register as our input.
+    return cast<RegSDNode>(Node)->getReg();
+
+  unsigned &Reg = ExprMap[N];
+  if (Reg) return Reg;
+
+  switch (N.getOpcode()) {
+  default:
+    Reg = Result = (N.getValueType() != MVT::Other) ?
+                            MakeReg(N.getValueType()) : 1;
+    break;
+  case ISD::TAILCALL:
+  case ISD::CALL:
+    // If this is a call instruction, make sure to prepare ALL of the result
+    // values as well as the chain.
+    if (Node->getNumValues() == 1)
+      Reg = Result = 1;  // Void call, just a chain.
+    else {
+      Result = MakeReg(Node->getValueType(0));
+      ExprMap[N.getValue(0)] = Result;
+      for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
+        ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
+      ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1;
+    }
+    break;
+  case ISD::ADD_PARTS:
+  case ISD::SUB_PARTS:
+  case ISD::SHL_PARTS:
+  case ISD::SRL_PARTS:
+  case ISD::SRA_PARTS:
+    Result = MakeReg(Node->getValueType(0));
+    ExprMap[N.getValue(0)] = Result;
+    for (unsigned i = 1, e = N.Val->getNumValues(); i != e; ++i)
+      ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
+    break;
+  }
 
   switch (opcode) {
   default:
     Node->dump();
     assert(0 && "Node not handled!\n");
+  case ISD::UNDEF:
+    BuildMI(BB, PPC::IMPLICIT_DEF, 0, Result);
+    return Result;
+  case ISD::DYNAMIC_STACKALLOC:
+    // Generate both result values.  FIXME: Need a better commment here?
+    if (Result != 1)
+      ExprMap[N.getValue(1)] = 1;
+    else
+      Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
 
-  case ISD::SELECT: {
-    // Attempt to generate FSEL.  We can do this whenever we have an FP result,
-    // and an FP comparison in the SetCC node.
-    SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(N.getOperand(0).Val);
-    if (SetCC && N.getOperand(0).getOpcode() == ISD::SETCC &&
-        !MVT::isInteger(SetCC->getOperand(0).getValueType()) &&
-        SetCC->getCondition() != ISD::SETEQ &&
-        SetCC->getCondition() != ISD::SETNE) {
-      MVT::ValueType VT = SetCC->getOperand(0).getValueType();
-      unsigned TV = SelectExpr(N.getOperand(1)); // Use if TRUE
-      unsigned FV = SelectExpr(N.getOperand(2)); // Use if FALSE
-
-      ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1));
-      if (CN && (CN->isExactlyValue(-0.0) || CN->isExactlyValue(0.0))) {
-        switch(SetCC->getCondition()) {
-        default: assert(0 && "Invalid FSEL condition"); abort();
-        case ISD::SETULT:
-        case ISD::SETLT:
-          std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt
-        case ISD::SETUGE:
-        case ISD::SETGE:
-          Tmp1 = SelectExpr(SetCC->getOperand(0));   // Val to compare against
-          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp1).addReg(TV).addReg(FV);
-          return Result;
-        case ISD::SETUGT:
-        case ISD::SETGT:
-          std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt
-        case ISD::SETULE:
-        case ISD::SETLE: {
-          if (SetCC->getOperand(0).getOpcode() == ISD::FNEG) {
-            Tmp2 = SelectExpr(SetCC->getOperand(0).getOperand(0));
-          } else {
-            Tmp2 = MakeReg(VT);
-            Tmp1 = SelectExpr(SetCC->getOperand(0));   // Val to compare against
-            BuildMI(BB, PPC::FNEG, 1, Tmp2).addReg(Tmp1);
-          }
-          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp2).addReg(TV).addReg(FV);
-          return Result;
-        }
-        }
-      } else {
-        Opc = (MVT::f64 == VT) ? PPC::FSUB : PPC::FSUBS;
-        Tmp1 = SelectExpr(SetCC->getOperand(0));   // Val to compare against
-        Tmp2 = SelectExpr(SetCC->getOperand(1));
-        Tmp3 =  MakeReg(VT);
-        switch(SetCC->getCondition()) {
-        default: assert(0 && "Invalid FSEL condition"); abort();
-        case ISD::SETULT:
-        case ISD::SETLT:
-          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
-          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(FV).addReg(TV);
-          return Result;
-        case ISD::SETUGE:
-        case ISD::SETGE:
-          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
-          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(TV).addReg(FV);
-          return Result;
-        case ISD::SETUGT:
-        case ISD::SETGT:
-          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp2).addReg(Tmp1);
-          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(FV).addReg(TV);
-          return Result;
-        case ISD::SETULE:
-        case ISD::SETLE:
-          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp2).addReg(Tmp1);
-          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(TV).addReg(FV);
-          return Result;
-        }
-      }
-      assert(0 && "Should never get here");
-      return 0;
+    // FIXME: We are currently ignoring the requested alignment for handling
+    // greater than the stack alignment.  This will need to be revisited at some
+    // point.  Align = N.getOperand(2);
+    if (!isa<ConstantSDNode>(N.getOperand(2)) ||
+        cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
+      std::cerr << "Cannot allocate stack object with greater alignment than"
+                << " the stack alignment yet!";
+      abort();
     }
+    Select(N.getOperand(0));
+    Tmp1 = SelectExpr(N.getOperand(1));
+    // Subtract size from stack pointer, thereby allocating some space.
+    BuildMI(BB, PPC::SUBF, 2, PPC::R1).addReg(Tmp1).addReg(PPC::R1);
+    // Put a pointer to the space into the result register by copying the SP
+    BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R1).addReg(PPC::R1);
+    return Result;
 
-    bool Inv;
-    unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE
-    unsigned FalseValue = SelectExpr(N.getOperand(2)); //Use if FALSE
-    unsigned CCReg = SelectCC(N.getOperand(0), Opc, Inv, Tmp3);
-
-    // Create an iterator with which to insert the MBB for copying the false
-    // value and the MBB to hold the PHI instruction for this SetCC.
-    MachineBasicBlock *thisMBB = BB;
-    const BasicBlock *LLVM_BB = BB->getBasicBlock();
-    ilist<MachineBasicBlock>::iterator It = BB;
-    ++It;
-
-    //  thisMBB:
-    //  ...
-    //   TrueVal = ...
-    //   cmpTY ccX, r1, r2
-    //   bCC copy1MBB
-    //   fallthrough --> copy0MBB
-    MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
-    MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
-    BuildMI(BB, Opc, 2).addReg(CCReg).addMBB(sinkMBB);
-    MachineFunction *F = BB->getParent();
-    F->getBasicBlockList().insert(It, copy0MBB);
-    F->getBasicBlockList().insert(It, sinkMBB);
-    // Update machine-CFG edges
-    BB->addSuccessor(copy0MBB);
-    BB->addSuccessor(sinkMBB);
-
-    //  copy0MBB:
-    //   %FalseValue = ...
-    //   # fallthrough to sinkMBB
-    BB = copy0MBB;
-    // Update machine-CFG edges
-    BB->addSuccessor(sinkMBB);
+  case ISD::ConstantPool:
+    Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
+    Tmp2 = MakeReg(MVT::i32);
+    if (PICEnabled)
+      BuildMI(BB, PPC::ADDIS, 2, Tmp2).addReg(getGlobalBaseReg())
+        .addConstantPoolIndex(Tmp1);
+    else
+      BuildMI(BB, PPC::LIS, 1, Tmp2).addConstantPoolIndex(Tmp1);
+    BuildMI(BB, PPC::LA, 2, Result).addReg(Tmp2).addConstantPoolIndex(Tmp1);
+    return Result;
 
-    //  sinkMBB:
-    //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
-    //  ...
-    BB = sinkMBB;
-    BuildMI(BB, PPC::PHI, 4, Result).addReg(FalseValue)
-      .addMBB(copy0MBB).addReg(TrueValue).addMBB(thisMBB);
+  case ISD::FrameIndex:
+    Tmp1 = cast<FrameIndexSDNode>(N)->getIndex();
+    addFrameReference(BuildMI(BB, PPC::ADDI, 2, Result), (int)Tmp1, 0, false);
     return Result;
-  }
 
-  case ISD::FNEG:
-    if (!NoExcessFPPrecision &&
-        ISD::ADD == N.getOperand(0).getOpcode() &&
-        N.getOperand(0).Val->hasOneUse() &&
-        ISD::MUL == N.getOperand(0).getOperand(0).getOpcode() &&
-        N.getOperand(0).getOperand(0).Val->hasOneUse()) {
-      ++FusedFP; // Statistic
-      Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
-      Tmp2 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(1));
-      Tmp3 = SelectExpr(N.getOperand(0).getOperand(1));
-      Opc = DestType == MVT::f64 ? PPC::FNMADD : PPC::FNMADDS;
-      BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
-    } else if (!NoExcessFPPrecision &&
-        ISD::ADD == N.getOperand(0).getOpcode() &&
-        N.getOperand(0).Val->hasOneUse() &&
-        ISD::MUL == N.getOperand(0).getOperand(1).getOpcode() &&
-        N.getOperand(0).getOperand(1).Val->hasOneUse()) {
-      ++FusedFP; // Statistic
-      Tmp1 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
-      Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(1));
-      Tmp3 = SelectExpr(N.getOperand(0).getOperand(0));
-      Opc = DestType == MVT::f64 ? PPC::FNMADD : PPC::FNMADDS;
-      BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
-    } else if (ISD::FABS == N.getOperand(0).getOpcode()) {
-      Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
-      BuildMI(BB, PPC::FNABS, 1, Result).addReg(Tmp1);
+  case ISD::GlobalAddress: {
+    GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
+    Tmp1 = MakeReg(MVT::i32);
+    if (PICEnabled)
+      BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg())
+        .addGlobalAddress(GV);
+    else
+      BuildMI(BB, PPC::LIS, 1, Tmp1).addGlobalAddress(GV);
+    if (GV->hasWeakLinkage() || GV->isExternal()) {
+      BuildMI(BB, PPC::LWZ, 2, Result).addGlobalAddress(GV).addReg(Tmp1);
     } else {
-      Tmp1 = SelectExpr(N.getOperand(0));
-      BuildMI(BB, PPC::FNEG, 1, Result).addReg(Tmp1);
+      BuildMI(BB, PPC::LA, 2, Result).addReg(Tmp1).addGlobalAddress(GV);
     }
     return Result;
+  }
 
-  case ISD::FABS:
-    Tmp1 = SelectExpr(N.getOperand(0));
-    BuildMI(BB, PPC::FABS, 1, Result).addReg(Tmp1);
-    return Result;
-
-  case ISD::FP_ROUND:
-    assert (DestType == MVT::f32 &&
-            N.getOperand(0).getValueType() == MVT::f64 &&
-            "only f64 to f32 conversion supported here");
-    Tmp1 = SelectExpr(N.getOperand(0));
-    BuildMI(BB, PPC::FRSP, 1, Result).addReg(Tmp1);
-    return Result;
-
-  case ISD::FP_EXTEND:
-    assert (DestType == MVT::f64 &&
-            N.getOperand(0).getValueType() == MVT::f32 &&
-            "only f32 to f64 conversion supported here");
-    Tmp1 = SelectExpr(N.getOperand(0));
-    BuildMI(BB, PPC::FMR, 1, Result).addReg(Tmp1);
-    return Result;
-
-  case ISD::CopyFromReg:
-    if (Result == 1)
-      Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
-    Tmp1 = dyn_cast<RegSDNode>(Node)->getReg();
-    BuildMI(BB, PPC::FMR, 1, Result).addReg(Tmp1);
-    return Result;
-
-  case ISD::ConstantFP: {
-    ConstantFPSDNode *CN = cast<ConstantFPSDNode>(N);
-    Result = getConstDouble(CN->getValue(), Result);
-    return Result;
-  }
-
-  case ISD::ADD:
-    if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::MUL &&
-        N.getOperand(0).Val->hasOneUse()) {
-      ++FusedFP; // Statistic
-      Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
-      Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
-      Tmp3 = SelectExpr(N.getOperand(1));
-      Opc = DestType == MVT::f64 ? PPC::FMADD : PPC::FMADDS;
-      BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
-      return Result;
-    }
-    if (!NoExcessFPPrecision && N.getOperand(1).getOpcode() == ISD::MUL &&
-        N.getOperand(1).Val->hasOneUse()) {
-      ++FusedFP; // Statistic
-      Tmp1 = SelectExpr(N.getOperand(1).getOperand(0));
-      Tmp2 = SelectExpr(N.getOperand(1).getOperand(1));
-      Tmp3 = SelectExpr(N.getOperand(0));
-      Opc = DestType == MVT::f64 ? PPC::FMADD : PPC::FMADDS;
-      BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
-      return Result;
-    }
-    Opc = DestType == MVT::f64 ? PPC::FADD : PPC::FADDS;
-    Tmp1 = SelectExpr(N.getOperand(0));
-    Tmp2 = SelectExpr(N.getOperand(1));
-    BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
-    return Result;
-
-  case ISD::SUB:
-    if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::MUL &&
-        N.getOperand(0).Val->hasOneUse()) {
-      ++FusedFP; // Statistic
-      Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
-      Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
-      Tmp3 = SelectExpr(N.getOperand(1));
-      Opc = DestType == MVT::f64 ? PPC::FMSUB : PPC::FMSUBS;
-      BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
-      return Result;
-    }
-    if (!NoExcessFPPrecision && N.getOperand(1).getOpcode() == ISD::MUL &&
-        N.getOperand(1).Val->hasOneUse()) {
-      ++FusedFP; // Statistic
-      Tmp1 = SelectExpr(N.getOperand(1).getOperand(0));
-      Tmp2 = SelectExpr(N.getOperand(1).getOperand(1));
-      Tmp3 = SelectExpr(N.getOperand(0));
-      Opc = DestType == MVT::f64 ? PPC::FNMSUB : PPC::FNMSUBS;
-      BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
-      return Result;
-    }
-    Opc = DestType == MVT::f64 ? PPC::FSUB : PPC::FSUBS;
-    Tmp1 = SelectExpr(N.getOperand(0));
-    Tmp2 = SelectExpr(N.getOperand(1));
-    BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
-    return Result;
-
-  case ISD::MUL:
-  case ISD::SDIV:
-    switch( opcode ) {
-    case ISD::MUL:  Opc = DestType == MVT::f64 ? PPC::FMUL : PPC::FMULS; break;
-    case ISD::SDIV: Opc = DestType == MVT::f64 ? PPC::FDIV : PPC::FDIVS; break;
-    };
-    Tmp1 = SelectExpr(N.getOperand(0));
-    Tmp2 = SelectExpr(N.getOperand(1));
-    BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
-    return Result;
-
-  case ISD::UINT_TO_FP:
-  case ISD::SINT_TO_FP: {
-    assert (N.getOperand(0).getValueType() == MVT::i32
-            && "int to float must operate on i32");
-    bool IsUnsigned = (ISD::UINT_TO_FP == opcode);
-    Tmp1 = SelectExpr(N.getOperand(0));  // Get the operand register
-    Tmp2 = MakeReg(MVT::f64); // temp reg to load the integer value into
-    Tmp3 = MakeReg(MVT::i32); // temp reg to hold the conversion constant
-
-    int FrameIdx = BB->getParent()->getFrameInfo()->CreateStackObject(8, 8);
-    MachineConstantPool *CP = BB->getParent()->getConstantPool();
-
-    if (IsUnsigned) {
-      unsigned ConstF = getConstDouble(0x1.000000p52);
-      // Store the hi & low halves of the fp value, currently in int regs
-      BuildMI(BB, PPC::LIS, 1, Tmp3).addSImm(0x4330);
-      addFrameReference(BuildMI(BB, PPC::STW, 3).addReg(Tmp3), FrameIdx);
-      addFrameReference(BuildMI(BB, PPC::STW, 3).addReg(Tmp1), FrameIdx, 4);
-      addFrameReference(BuildMI(BB, PPC::LFD, 2, Tmp2), FrameIdx);
-      // Generate the return value with a subtract
-      BuildMI(BB, PPC::FSUB, 2, Result).addReg(Tmp2).addReg(ConstF);
-    } else {
-      unsigned ConstF = getConstDouble(0x1.000008p52);
-      unsigned TmpL = MakeReg(MVT::i32);
-      // Store the hi & low halves of the fp value, currently in int regs
-      BuildMI(BB, PPC::LIS, 1, Tmp3).addSImm(0x4330);
-      addFrameReference(BuildMI(BB, PPC::STW, 3).addReg(Tmp3), FrameIdx);
-      BuildMI(BB, PPC::XORIS, 2, TmpL).addReg(Tmp1).addImm(0x8000);
-      addFrameReference(BuildMI(BB, PPC::STW, 3).addReg(TmpL), FrameIdx, 4);
-      addFrameReference(BuildMI(BB, PPC::LFD, 2, Tmp2), FrameIdx);
-      // Generate the return value with a subtract
-      BuildMI(BB, PPC::FSUB, 2, Result).addReg(Tmp2).addReg(ConstF);
-    }
-    return Result;
-  }
-  }
-  assert(0 && "Should never get here");
-  return 0;
-}
-
-unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
-  unsigned Result;
-  unsigned Tmp1, Tmp2, Tmp3;
-  unsigned Opc = 0;
-  unsigned opcode = N.getOpcode();
-
-  SDNode *Node = N.Val;
-  MVT::ValueType DestType = N.getValueType();
-
-  unsigned &Reg = ExprMap[N];
-  if (Reg) return Reg;
-
-  switch (N.getOpcode()) {
-  default:
-    Reg = Result = (N.getValueType() != MVT::Other) ?
-                            MakeReg(N.getValueType()) : 1;
-    break;
-  case ISD::CALL:
-    // If this is a call instruction, make sure to prepare ALL of the result
-    // values as well as the chain.
-    if (Node->getNumValues() == 1)
-      Reg = Result = 1;  // Void call, just a chain.
-    else {
-      Result = MakeReg(Node->getValueType(0));
-      ExprMap[N.getValue(0)] = Result;
-      for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
-        ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
-      ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1;
-    }
-    break;
-  case ISD::ADD_PARTS:
-  case ISD::SUB_PARTS:
-  case ISD::SHL_PARTS:
-  case ISD::SRL_PARTS:
-  case ISD::SRA_PARTS:
-    Result = MakeReg(Node->getValueType(0));
-    ExprMap[N.getValue(0)] = Result;
-    for (unsigned i = 1, e = N.Val->getNumValues(); i != e; ++i)
-      ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
-    break;
-  }
-
-  if (ISD::CopyFromReg == opcode)
-    DestType = N.getValue(0).getValueType();
-
-  if (DestType == MVT::f64 || DestType == MVT::f32)
-    if (ISD::LOAD != opcode && ISD::EXTLOAD != opcode &&
-        ISD::UNDEF != opcode && ISD::CALL != opcode)
-      return SelectExprFP(N, Result);
-
-  switch (opcode) {
-  default:
-    Node->dump();
-    assert(0 && "Node not handled!\n");
-  case ISD::UNDEF:
-    BuildMI(BB, PPC::IMPLICIT_DEF, 0, Result);
-    return Result;
-  case ISD::DYNAMIC_STACKALLOC:
-    // Generate both result values.  FIXME: Need a better commment here?
-    if (Result != 1)
-      ExprMap[N.getValue(1)] = 1;
-    else
-      Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
-
-    // FIXME: We are currently ignoring the requested alignment for handling
-    // greater than the stack alignment.  This will need to be revisited at some
-    // point.  Align = N.getOperand(2);
-    if (!isa<ConstantSDNode>(N.getOperand(2)) ||
-        cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
-      std::cerr << "Cannot allocate stack object with greater alignment than"
-                << " the stack alignment yet!";
-      abort();
-    }
-    Select(N.getOperand(0));
-    Tmp1 = SelectExpr(N.getOperand(1));
-    // Subtract size from stack pointer, thereby allocating some space.
-    BuildMI(BB, PPC::SUBF, 2, PPC::R1).addReg(Tmp1).addReg(PPC::R1);
-    // Put a pointer to the space into the result register by copying the SP
-    BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R1).addReg(PPC::R1);
-    return Result;
-
-  case ISD::ConstantPool:
-    Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
-    Tmp2 = MakeReg(MVT::i32);
-    BuildMI(BB, PPC::LOADHiAddr, 2, Tmp2).addReg(getGlobalBaseReg())
-      .addConstantPoolIndex(Tmp1);
-    BuildMI(BB, PPC::LA, 2, Result).addReg(Tmp2).addConstantPoolIndex(Tmp1);
-    return Result;
-
-  case ISD::FrameIndex:
-    Tmp1 = cast<FrameIndexSDNode>(N)->getIndex();
-    addFrameReference(BuildMI(BB, PPC::ADDI, 2, Result), (int)Tmp1, 0, false);
-    return Result;
-
-  case ISD::GlobalAddress: {
-    GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
-    Tmp1 = MakeReg(MVT::i32);
-    BuildMI(BB, PPC::LOADHiAddr, 2, Tmp1).addReg(getGlobalBaseReg())
-      .addGlobalAddress(GV);
-    if (GV->hasWeakLinkage() || GV->isExternal()) {
-      BuildMI(BB, PPC::LWZ, 2, Result).addGlobalAddress(GV).addReg(Tmp1);
-    } else {
-      BuildMI(BB, PPC::LA, 2, Result).addReg(Tmp1).addGlobalAddress(GV);
-    }
-    return Result;
-  }
-
-  case ISD::LOAD:
-  case ISD::EXTLOAD:
-  case ISD::ZEXTLOAD:
-  case ISD::SEXTLOAD: {
-    MVT::ValueType TypeBeingLoaded = (ISD::LOAD == opcode) ?
-      Node->getValueType(0) : cast<MVTSDNode>(Node)->getExtraValueType();
-    bool sext = (ISD::SEXTLOAD == opcode);
+  case ISD::LOAD:
+  case ISD::EXTLOAD:
+  case ISD::ZEXTLOAD:
+  case ISD::SEXTLOAD: {
+    MVT::ValueType TypeBeingLoaded = (ISD::LOAD == opcode) ?
+      Node->getValueType(0) : cast<VTSDNode>(Node->getOperand(3))->getVT();
+    bool sext = (ISD::SEXTLOAD == opcode);
 
     // Make sure we generate both values.
     if (Result != 1)
@@ -1656,26 +1425,50 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
     if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
       Tmp1 = MakeReg(MVT::i32);
       int CPI = CP->getIndex();
-      BuildMI(BB, PPC::LOADHiAddr, 2, Tmp1).addReg(getGlobalBaseReg())
-        .addConstantPoolIndex(CPI);
+      if (PICEnabled)
+        BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg())
+          .addConstantPoolIndex(CPI);
+      else
+        BuildMI(BB, PPC::LIS, 1, Tmp1).addConstantPoolIndex(CPI);
       BuildMI(BB, Opc, 2, Result).addConstantPoolIndex(CPI).addReg(Tmp1);
-    }
-    else if(Address.getOpcode() == ISD::FrameIndex) {
+    } else if (Address.getOpcode() == ISD::FrameIndex) {
       Tmp1 = cast<FrameIndexSDNode>(Address)->getIndex();
       addFrameReference(BuildMI(BB, Opc, 2, Result), (int)Tmp1);
+    } else if(GlobalAddressSDNode *GN = dyn_cast<GlobalAddressSDNode>(Address)){
+      GlobalValue *GV = GN->getGlobal();
+      Tmp1 = MakeReg(MVT::i32);
+      if (PICEnabled)
+        BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg())
+          .addGlobalAddress(GV);
+      else
+        BuildMI(BB, PPC::LIS, 1, Tmp1).addGlobalAddress(GV);
+      if (GV->hasWeakLinkage() || GV->isExternal()) {
+        Tmp2 = MakeReg(MVT::i32);
+        BuildMI(BB, PPC::LWZ, 2, Tmp2).addGlobalAddress(GV).addReg(Tmp1);
+        BuildMI(BB, Opc, 2, Result).addSImm(0).addReg(Tmp2);
+      } else {
+        BuildMI(BB, Opc, 2, Result).addGlobalAddress(GV).addReg(Tmp1);
+      }
     } else {
       int offset;
-      bool idx = SelectAddr(Address, Tmp1, offset);
-      if (idx) {
+      switch(SelectAddr(Address, Tmp1, offset)) {
+      default: assert(0 && "Unhandled return value from SelectAddr");
+      case 0:   // imm offset, no frame, no index
+        BuildMI(BB, Opc, 2, Result).addSImm(offset).addReg(Tmp1);
+        break;
+      case 1:   // imm offset + frame index
+        addFrameReference(BuildMI(BB, Opc, 2, Result), (int)Tmp1, offset);
+        break;
+      case 2:   // base+index addressing
         Opc = IndexedOpForOp(Opc);
         BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(offset);
-      } else {
-        BuildMI(BB, Opc, 2, Result).addSImm(offset).addReg(Tmp1);
+        break;
       }
     }
     return Result;
   }
 
+  case ISD::TAILCALL:
   case ISD::CALL: {
     unsigned GPR_idx = 0, FPR_idx = 0;
     static const unsigned GPR[] = {
@@ -1767,7 +1560,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
   case ISD::SIGN_EXTEND:
   case ISD::SIGN_EXTEND_INREG:
     Tmp1 = SelectExpr(N.getOperand(0));
-    switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
+    switch(cast<VTSDNode>(Node->getOperand(1))->getVT()) {
     default: Node->dump(); assert(0 && "Unhandled SIGN_EXTEND type"); break;
     case MVT::i16:
       BuildMI(BB, PPC::EXTSH, 1, Result).addReg(Tmp1);
@@ -1782,10 +1575,14 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
     return Result;
 
   case ISD::CopyFromReg:
+    DestType = N.getValue(0).getValueType();
     if (Result == 1)
-      Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
+      Result = ExprMap[N.getValue(0)] = MakeReg(DestType);
     Tmp1 = dyn_cast<RegSDNode>(Node)->getReg();
-    BuildMI(BB, PPC::OR, 2, Result).addReg(Tmp1).addReg(Tmp1);
+    if (MVT::isInteger(DestType))
+      BuildMI(BB, PPC::OR, 2, Result).addReg(Tmp1).addReg(Tmp1);
+    else
+      BuildMI(BB, PPC::FMR, 1, Result).addReg(Tmp1);
     return Result;
 
   case ISD::SHL:
@@ -1829,7 +1626,33 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
     return Result;
 
   case ISD::ADD:
-    assert (DestType == MVT::i32 && "Only do arithmetic on i32s!");
+    if (!MVT::isInteger(DestType)) {
+      if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::MUL &&
+          N.getOperand(0).Val->hasOneUse()) {
+        ++FusedFP; // Statistic
+        Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
+        Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
+        Tmp3 = SelectExpr(N.getOperand(1));
+        Opc = DestType == MVT::f64 ? PPC::FMADD : PPC::FMADDS;
+        BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
+        return Result;
+      }
+      if (!NoExcessFPPrecision && N.getOperand(1).getOpcode() == ISD::MUL &&
+          N.getOperand(1).Val->hasOneUse()) {
+        ++FusedFP; // Statistic
+        Tmp1 = SelectExpr(N.getOperand(1).getOperand(0));
+        Tmp2 = SelectExpr(N.getOperand(1).getOperand(1));
+        Tmp3 = SelectExpr(N.getOperand(0));
+        Opc = DestType == MVT::f64 ? PPC::FMADD : PPC::FMADDS;
+        BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
+        return Result;
+      }
+      Opc = DestType == MVT::f64 ? PPC::FADD : PPC::FADDS;
+      Tmp1 = SelectExpr(N.getOperand(0));
+      Tmp2 = SelectExpr(N.getOperand(1));
+      BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
+      return Result;
+    }
     Tmp1 = SelectExpr(N.getOperand(0));
     switch(getImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) {
       default: assert(0 && "unhandled result code");
@@ -1847,18 +1670,6 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
     return Result;
 
   case ISD::AND:
-    if (PPCCRopts) {
-      if (N.getOperand(0).getOpcode() == ISD::SETCC ||
-          N.getOperand(1).getOpcode() == ISD::SETCC) {
-        bool Inv;
-        Tmp1 = SelectCCExpr(N, Opc, Inv, Tmp2);
-        MoveCRtoGPR(Tmp1, Inv, Tmp2, Result);
-        return Result;
-      }
-    }
-    // FIXME: should add check in getImmediateForOpcode to return a value
-    // indicating the immediate is a run of set bits so we can emit a bitfield
-    // clear with RLWINM instead.
     switch(getImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) {
       default: assert(0 && "unhandled result code");
       case 0: // No immediate
@@ -1890,6 +1701,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
         Tmp3 = Tmp2 >> 16;  // MB
         Tmp2 &= 0xFFFF;     // ME
 
+        // FIXME: Catch SHL-AND in addition to SRL-AND in this block.
         if (N.getOperand(0).getOpcode() == ISD::SRL)
           if (ConstantSDNode *SA =
               dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
@@ -1916,15 +1728,6 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
   case ISD::OR:
     if (SelectBitfieldInsert(N, Result))
       return Result;
-    if (PPCCRopts) {
-      if (N.getOperand(0).getOpcode() == ISD::SETCC ||
-          N.getOperand(1).getOpcode() == ISD::SETCC) {
-        bool Inv;
-        Tmp1 = SelectCCExpr(N, Opc, Inv, Tmp2);
-        MoveCRtoGPR(Tmp1, Inv, Tmp2, Result);
-        return Result;
-      }
-    }
     Tmp1 = SelectExpr(N.getOperand(0));
     switch(getImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) {
       default: assert(0 && "unhandled result code");
@@ -1997,6 +1800,33 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
   }
 
   case ISD::SUB:
+    if (!MVT::isInteger(DestType)) {
+      if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::MUL &&
+          N.getOperand(0).Val->hasOneUse()) {
+        ++FusedFP; // Statistic
+        Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
+        Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
+        Tmp3 = SelectExpr(N.getOperand(1));
+        Opc = DestType == MVT::f64 ? PPC::FMSUB : PPC::FMSUBS;
+        BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
+        return Result;
+      }
+      if (!NoExcessFPPrecision && N.getOperand(1).getOpcode() == ISD::MUL &&
+          N.getOperand(1).Val->hasOneUse()) {
+        ++FusedFP; // Statistic
+        Tmp1 = SelectExpr(N.getOperand(1).getOperand(0));
+        Tmp2 = SelectExpr(N.getOperand(1).getOperand(1));
+        Tmp3 = SelectExpr(N.getOperand(0));
+        Opc = DestType == MVT::f64 ? PPC::FNMSUB : PPC::FNMSUBS;
+        BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
+        return Result;
+      }
+      Opc = DestType == MVT::f64 ? PPC::FSUB : PPC::FSUBS;
+      Tmp1 = SelectExpr(N.getOperand(0));
+      Tmp2 = SelectExpr(N.getOperand(1));
+      BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
+      return Result;
+    }
     if (1 == getImmediateForOpcode(N.getOperand(0), opcode, Tmp1, true)) {
       Tmp2 = SelectExpr(N.getOperand(1));
       BuildMI(BB, PPC::SUBFIC, 2, Result).addReg(Tmp2).addSImm(Tmp1);
@@ -2016,7 +1846,13 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
       BuildMI(BB, PPC::MULLI, 2, Result).addReg(Tmp1).addSImm(Tmp2);
     else {
       Tmp2 = SelectExpr(N.getOperand(1));
-      BuildMI(BB, PPC::MULLW, 2, Result).addReg(Tmp1).addReg(Tmp2);
+      switch (DestType) {
+      default: assert(0 && "Unknown type to ISD::MUL"); break;
+      case MVT::i32: Opc = PPC::MULLW; break;
+      case MVT::f32: Opc = PPC::FMULS; break;
+      case MVT::f64: Opc = PPC::FMUL; break;
+      }
+      BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
     }
     return Result;
 
@@ -2057,7 +1893,12 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
     }
     Tmp1 = SelectExpr(N.getOperand(0));
     Tmp2 = SelectExpr(N.getOperand(1));
-    Opc = (ISD::UDIV == opcode) ? PPC::DIVWU : PPC::DIVW;
+    switch (DestType) {
+    default: assert(0 && "Unknown type to ISD::SDIV"); break;
+    case MVT::i32: Opc = (ISD::UDIV == opcode) ? PPC::DIVWU : PPC::DIVW; break;
+    case MVT::f32: Opc = PPC::FDIVS; break;
+    case MVT::f64: Opc = PPC::FDIV; break;
+    }
     BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
     return Result;
 
@@ -2294,6 +2135,78 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
     return 0;
 
   case ISD::SELECT: {
+    SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(N.getOperand(0).Val);
+    if (SetCC && N.getOperand(0).getOpcode() == ISD::SETCC &&
+        !MVT::isInteger(SetCC->getOperand(0).getValueType()) &&
+        !MVT::isInteger(N.getOperand(1).getValueType()) &&
+        !MVT::isInteger(N.getOperand(2).getValueType()) &&
+        SetCC->getCondition() != ISD::SETEQ &&
+        SetCC->getCondition() != ISD::SETNE) {
+      MVT::ValueType VT = SetCC->getOperand(0).getValueType();
+      unsigned TV = SelectExpr(N.getOperand(1)); // Use if TRUE
+      unsigned FV = SelectExpr(N.getOperand(2)); // Use if FALSE
+
+      ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1));
+      if (CN && (CN->isExactlyValue(-0.0) || CN->isExactlyValue(0.0))) {
+        switch(SetCC->getCondition()) {
+        default: assert(0 && "Invalid FSEL condition"); abort();
+        case ISD::SETULT:
+        case ISD::SETLT:
+          std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt
+        case ISD::SETUGE:
+        case ISD::SETGE:
+          Tmp1 = SelectExpr(SetCC->getOperand(0));   // Val to compare against
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp1).addReg(TV).addReg(FV);
+          return Result;
+        case ISD::SETUGT:
+        case ISD::SETGT:
+          std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt
+        case ISD::SETULE:
+        case ISD::SETLE: {
+          if (SetCC->getOperand(0).getOpcode() == ISD::FNEG) {
+            Tmp2 = SelectExpr(SetCC->getOperand(0).getOperand(0));
+          } else {
+            Tmp2 = MakeReg(VT);
+            Tmp1 = SelectExpr(SetCC->getOperand(0));   // Val to compare against
+            BuildMI(BB, PPC::FNEG, 1, Tmp2).addReg(Tmp1);
+          }
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp2).addReg(TV).addReg(FV);
+          return Result;
+        }
+        }
+      } else {
+        Opc = (MVT::f64 == VT) ? PPC::FSUB : PPC::FSUBS;
+        Tmp1 = SelectExpr(SetCC->getOperand(0));   // Val to compare against
+        Tmp2 = SelectExpr(SetCC->getOperand(1));
+        Tmp3 =  MakeReg(VT);
+        switch(SetCC->getCondition()) {
+        default: assert(0 && "Invalid FSEL condition"); abort();
+        case ISD::SETULT:
+        case ISD::SETLT:
+          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(FV).addReg(TV);
+          return Result;
+        case ISD::SETUGE:
+        case ISD::SETGE:
+          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(TV).addReg(FV);
+          return Result;
+        case ISD::SETUGT:
+        case ISD::SETGT:
+          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp2).addReg(Tmp1);
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(FV).addReg(TV);
+          return Result;
+        case ISD::SETULE:
+        case ISD::SETLE:
+          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp2).addReg(Tmp1);
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(TV).addReg(FV);
+          return Result;
+        }
+      }
+      assert(0 && "Should never get here");
+      return 0;
+    }
+
     bool Inv;
     unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE
     unsigned FalseValue = SelectExpr(N.getOperand(2)); //Use if FALSE
@@ -2358,13 +2271,113 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
       }
     }
     return Result;
+
+  case ISD::ConstantFP: {
+    ConstantFPSDNode *CN = cast<ConstantFPSDNode>(N);
+    Result = getConstDouble(CN->getValue(), Result);
+    return Result;
   }
 
+  case ISD::FNEG:
+    if (!NoExcessFPPrecision &&
+        ISD::ADD == N.getOperand(0).getOpcode() &&
+        N.getOperand(0).Val->hasOneUse() &&
+        ISD::MUL == N.getOperand(0).getOperand(0).getOpcode() &&
+        N.getOperand(0).getOperand(0).Val->hasOneUse()) {
+      ++FusedFP; // Statistic
+      Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
+      Tmp2 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(1));
+      Tmp3 = SelectExpr(N.getOperand(0).getOperand(1));
+      Opc = DestType == MVT::f64 ? PPC::FNMADD : PPC::FNMADDS;
+      BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
+    } else if (!NoExcessFPPrecision &&
+        ISD::ADD == N.getOperand(0).getOpcode() &&
+        N.getOperand(0).Val->hasOneUse() &&
+        ISD::MUL == N.getOperand(0).getOperand(1).getOpcode() &&
+        N.getOperand(0).getOperand(1).Val->hasOneUse()) {
+      ++FusedFP; // Statistic
+      Tmp1 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
+      Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(1));
+      Tmp3 = SelectExpr(N.getOperand(0).getOperand(0));
+      Opc = DestType == MVT::f64 ? PPC::FNMADD : PPC::FNMADDS;
+      BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
+    } else if (ISD::FABS == N.getOperand(0).getOpcode()) {
+      Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
+      BuildMI(BB, PPC::FNABS, 1, Result).addReg(Tmp1);
+    } else {
+      Tmp1 = SelectExpr(N.getOperand(0));
+      BuildMI(BB, PPC::FNEG, 1, Result).addReg(Tmp1);
+    }
+    return Result;
+
+  case ISD::FABS:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    BuildMI(BB, PPC::FABS, 1, Result).addReg(Tmp1);
+    return Result;
+
+  case ISD::FSQRT:
+    Tmp1 = SelectExpr(N.getOperand(0));
+    Opc = DestType == MVT::f64 ? PPC::FSQRT : PPC::FSQRTS;
+    BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
+    return Result;
+
+  case ISD::FP_ROUND:
+    assert (DestType == MVT::f32 &&
+            N.getOperand(0).getValueType() == MVT::f64 &&
+            "only f64 to f32 conversion supported here");
+    Tmp1 = SelectExpr(N.getOperand(0));
+    BuildMI(BB, PPC::FRSP, 1, Result).addReg(Tmp1);
+    return Result;
+
+  case ISD::FP_EXTEND:
+    assert (DestType == MVT::f64 &&
+            N.getOperand(0).getValueType() == MVT::f32 &&
+            "only f32 to f64 conversion supported here");
+    Tmp1 = SelectExpr(N.getOperand(0));
+    BuildMI(BB, PPC::FMR, 1, Result).addReg(Tmp1);
+    return Result;
+
+  case ISD::UINT_TO_FP:
+  case ISD::SINT_TO_FP: {
+    assert (N.getOperand(0).getValueType() == MVT::i32
+            && "int to float must operate on i32");
+    bool IsUnsigned = (ISD::UINT_TO_FP == opcode);
+    Tmp1 = SelectExpr(N.getOperand(0));  // Get the operand register
+    Tmp2 = MakeReg(MVT::f64); // temp reg to load the integer value into
+    Tmp3 = MakeReg(MVT::i32); // temp reg to hold the conversion constant
+
+    int FrameIdx = BB->getParent()->getFrameInfo()->CreateStackObject(8, 8);
+    MachineConstantPool *CP = BB->getParent()->getConstantPool();
+
+    if (IsUnsigned) {
+      unsigned ConstF = getConstDouble(0x1.000000p52);
+      // Store the hi & low halves of the fp value, currently in int regs
+      BuildMI(BB, PPC::LIS, 1, Tmp3).addSImm(0x4330);
+      addFrameReference(BuildMI(BB, PPC::STW, 3).addReg(Tmp3), FrameIdx);
+      addFrameReference(BuildMI(BB, PPC::STW, 3).addReg(Tmp1), FrameIdx, 4);
+      addFrameReference(BuildMI(BB, PPC::LFD, 2, Tmp2), FrameIdx);
+      // Generate the return value with a subtract
+      BuildMI(BB, PPC::FSUB, 2, Result).addReg(Tmp2).addReg(ConstF);
+    } else {
+      unsigned ConstF = getConstDouble(0x1.000008p52);
+      unsigned TmpL = MakeReg(MVT::i32);
+      // Store the hi & low halves of the fp value, currently in int regs
+      BuildMI(BB, PPC::LIS, 1, Tmp3).addSImm(0x4330);
+      addFrameReference(BuildMI(BB, PPC::STW, 3).addReg(Tmp3), FrameIdx);
+      BuildMI(BB, PPC::XORIS, 2, TmpL).addReg(Tmp1).addImm(0x8000);
+      addFrameReference(BuildMI(BB, PPC::STW, 3).addReg(TmpL), FrameIdx, 4);
+      addFrameReference(BuildMI(BB, PPC::LFD, 2, Tmp2), FrameIdx);
+      // Generate the return value with a subtract
+      BuildMI(BB, PPC::FSUB, 2, Result).addReg(Tmp2).addReg(ConstF);
+    }
+    return Result;
+  }
+  }
   return 0;
 }
 
 void ISel::Select(SDOperand N) {
-  unsigned Tmp1, Tmp2, Opc;
+  unsigned Tmp1, Tmp2, Tmp3, Opc;
   unsigned opcode = N.getOpcode();
 
   if (!ExprMap.insert(std::make_pair(N, 1)).second)
@@ -2381,11 +2394,11 @@ void ISel::Select(SDOperand N) {
     for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
       Select(Node->getOperand(i));
     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 ? PPC::ADJCALLSTACKDOWN :
+    Opc = N.getOpcode() == ISD::CALLSEQ_START ? PPC::ADJCALLSTACKDOWN :
       PPC::ADJCALLSTACKUP;
     BuildMI(BB, Opc, 1).addImm(Tmp1);
     return;
@@ -2452,54 +2465,72 @@ void ISel::Select(SDOperand N) {
     BuildMI(BB, PPC::BLR, 0); // Just emit a 'ret' instruction
     return;
   case ISD::TRUNCSTORE:
-  case ISD::STORE:
-    {
-      SDOperand Chain   = N.getOperand(0);
-      SDOperand Value   = N.getOperand(1);
-      SDOperand Address = N.getOperand(2);
-      Select(Chain);
-
-      Tmp1 = SelectExpr(Value); //value
-
-      if (opcode == ISD::STORE) {
-        switch(Value.getValueType()) {
-        default: assert(0 && "unknown Type in store");
-        case MVT::i32: Opc = PPC::STW; break;
-        case MVT::f64: Opc = PPC::STFD; break;
-        case MVT::f32: Opc = PPC::STFS; break;
-        }
-      } else { //ISD::TRUNCSTORE
-        switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
-        default: assert(0 && "unknown Type in store");
-        case MVT::i1:
-        case MVT::i8: Opc  = PPC::STB; break;
-        case MVT::i16: Opc = PPC::STH; break;
-        }
-      }
+  case ISD::STORE: {
+    SDOperand Chain   = N.getOperand(0);
+    SDOperand Value   = N.getOperand(1);
+    SDOperand Address = N.getOperand(2);
+    Select(Chain);
 
-      if(Address.getOpcode() == ISD::FrameIndex)
-      {
-        Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
-        addFrameReference(BuildMI(BB, Opc, 3).addReg(Tmp1), (int)Tmp2);
+    Tmp1 = SelectExpr(Value); //value
+
+    if (opcode == ISD::STORE) {
+      switch(Value.getValueType()) {
+      default: assert(0 && "unknown Type in store");
+      case MVT::i32: Opc = PPC::STW; break;
+      case MVT::f64: Opc = PPC::STFD; break;
+      case MVT::f32: Opc = PPC::STFS; break;
       }
+    } else { //ISD::TRUNCSTORE
+      switch(cast<VTSDNode>(Node->getOperand(4))->getVT()) {
+      default: assert(0 && "unknown Type in store");
+      case MVT::i1:
+      case MVT::i8: Opc  = PPC::STB; break;
+      case MVT::i16: Opc = PPC::STH; break;
+      }
+    }
+
+    if(Address.getOpcode() == ISD::FrameIndex) {
+      Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
+      addFrameReference(BuildMI(BB, Opc, 3).addReg(Tmp1), (int)Tmp2);
+    } else if(GlobalAddressSDNode *GN = dyn_cast<GlobalAddressSDNode>(Address)){
+      GlobalValue *GV = GN->getGlobal();
+      Tmp2 = MakeReg(MVT::i32);
+      if (PICEnabled)
+        BuildMI(BB, PPC::ADDIS, 2, Tmp2).addReg(getGlobalBaseReg())
+          .addGlobalAddress(GV);
       else
-      {
-        int offset;
-        bool idx = SelectAddr(Address, Tmp2, offset);
-        if (idx) {
-          Opc = IndexedOpForOp(Opc);
-          BuildMI(BB, Opc, 3).addReg(Tmp1).addReg(Tmp2).addReg(offset);
-        } else {
-          BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
-        }
+        BuildMI(BB, PPC::LIS, 1, Tmp2).addGlobalAddress(GV);
+      if (GV->hasWeakLinkage() || GV->isExternal()) {
+        Tmp3 = MakeReg(MVT::i32);
+        BuildMI(BB, PPC::LWZ, 2, Tmp3).addGlobalAddress(GV).addReg(Tmp2);
+        BuildMI(BB, Opc, 3).addReg(Tmp1).addSImm(0).addReg(Tmp3);
+      } else {
+        BuildMI(BB, Opc, 3).addReg(Tmp1).addGlobalAddress(GV).addReg(Tmp2);
+      }
+    } else {
+      int offset;
+      switch(SelectAddr(Address, Tmp2, offset)) {
+      default: assert(0 && "Unhandled return value from SelectAddr");
+      case 0:   // imm offset, no frame, no index
+        BuildMI(BB, Opc, 3).addReg(Tmp1).addSImm(offset).addReg(Tmp2);
+        break;
+      case 1:   // imm offset + frame index
+        addFrameReference(BuildMI(BB, Opc, 3).addReg(Tmp1), (int)Tmp2, offset);
+        break;
+      case 2:   // base+index addressing
+        Opc = IndexedOpForOp(Opc);
+        BuildMI(BB, Opc, 3).addReg(Tmp1).addReg(Tmp2).addReg(offset);
+        break;
       }
-      return;
     }
+    return;
+  }
   case ISD::EXTLOAD:
   case ISD::SEXTLOAD:
   case ISD::ZEXTLOAD:
   case ISD::LOAD:
   case ISD::CopyFromReg:
+  case ISD::TAILCALL:
   case ISD::CALL:
   case ISD::DYNAMIC_STACKALLOC:
     ExprMap.erase(N);