More ppc32 byval handling (bug fixes). Things
[oota-llvm.git] / lib / Target / PowerPC / PPCISelLowering.cpp
index cfebef1edd661c85a4816a75a9178e115ef113ea..7647d4e223344e4ab435419e8142d6882da40ebe 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by Chris Lattner and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -23,8 +23,9 @@
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
 #include "llvm/CodeGen/SelectionDAG.h"
-#include "llvm/CodeGen/SSARegMap.h"
 #include "llvm/Constants.h"
 #include "llvm/Function.h"
 #include "llvm/Intrinsics.h"
@@ -52,12 +53,11 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
   addRegisterClass(MVT::f64, PPC::F8RCRegisterClass);
   
   // PowerPC has an i16 but no i8 (or i1) SEXTLOAD
-  setLoadXAction(ISD::SEXTLOAD, MVT::i1, Expand);
+  setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote);
   setLoadXAction(ISD::SEXTLOAD, MVT::i8, Expand);
-  
-  // PowerPC does not have truncstore for i1.
-  setStoreXAction(MVT::i1, Promote);
 
+  setTruncStoreAction(MVT::f64, MVT::f32, Expand);
+    
   // PowerPC has pre-inc load and store's.
   setIndexedLoadAction(ISD::PRE_INC, MVT::i1, Legal);
   setIndexedLoadAction(ISD::PRE_INC, MVT::i8, Legal);
@@ -70,27 +70,47 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
   setIndexedStoreAction(ISD::PRE_INC, MVT::i32, Legal);
   setIndexedStoreAction(ISD::PRE_INC, MVT::i64, Legal);
 
-  setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
-  setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
+  // Shortening conversions involving ppcf128 get expanded (2 regs -> 1 reg)
+  setConvertAction(MVT::ppcf128, MVT::f64, Expand);
+  setConvertAction(MVT::ppcf128, MVT::f32, Expand);
+  // This is used in the ppcf128->int sequence.  Note it has different semantics
+  // from FP_ROUND:  that rounds to nearest, this rounds to zero.
+  setOperationAction(ISD::FP_ROUND_INREG, MVT::ppcf128, Custom);
 
   // PowerPC has no intrinsics for these particular operations
   setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
   setOperationAction(ISD::MEMSET, MVT::Other, Expand);
   setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
-  
+  setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
+  setOperationAction(ISD::PREFETCH, MVT::Other, Expand);
+
   // PowerPC has no SREM/UREM instructions
   setOperationAction(ISD::SREM, MVT::i32, Expand);
   setOperationAction(ISD::UREM, MVT::i32, Expand);
   setOperationAction(ISD::SREM, MVT::i64, Expand);
   setOperationAction(ISD::UREM, MVT::i64, Expand);
-  
-  // We don't support sin/cos/sqrt/fmod
+
+  // Don't use SMUL_LOHI/UMUL_LOHI or SDIVREM/UDIVREM to lower SREM/UREM.
+  setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
+  setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
+  setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
+  setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
+  setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
+  setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
+  setOperationAction(ISD::UDIVREM, MVT::i64, Expand);
+  setOperationAction(ISD::SDIVREM, MVT::i64, Expand);
+  
+  // We don't support sin/cos/sqrt/fmod/pow
   setOperationAction(ISD::FSIN , MVT::f64, Expand);
   setOperationAction(ISD::FCOS , MVT::f64, Expand);
   setOperationAction(ISD::FREM , MVT::f64, Expand);
+  setOperationAction(ISD::FPOW , MVT::f64, Expand);
   setOperationAction(ISD::FSIN , MVT::f32, Expand);
   setOperationAction(ISD::FCOS , MVT::f32, Expand);
   setOperationAction(ISD::FREM , MVT::f32, Expand);
+  setOperationAction(ISD::FPOW , MVT::f32, Expand);
+
+  setOperationAction(ISD::FLT_ROUNDS_, MVT::i32, Custom);
   
   // If we're enabling GP optimizations, use hardware square root
   if (!TM.getSubtarget<PPCSubtarget>().hasFSQRT()) {
@@ -148,14 +168,12 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
   // Support label based line numbers.
   setOperationAction(ISD::LOCATION, MVT::Other, Expand);
   setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
-  if (!TM.getSubtarget<PPCSubtarget>().isDarwin()) {
-    setOperationAction(ISD::LABEL, MVT::Other, Expand);
-  } else {
-    setOperationAction(ISD::EXCEPTIONADDR, MVT::i64, Expand);
-    setOperationAction(ISD::EHSELECTION,   MVT::i64, Expand);
-    setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand);
-    setOperationAction(ISD::EHSELECTION,   MVT::i32, Expand);
-  }
+  
+  setOperationAction(ISD::EXCEPTIONADDR, MVT::i64, Expand);
+  setOperationAction(ISD::EHSELECTION,   MVT::i64, Expand);
+  setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand);
+  setOperationAction(ISD::EHSELECTION,   MVT::i32, Expand);
+  
   
   // We want to legalize GlobalAddress and ConstantPool nodes into the 
   // appropriate instructions to materialize the address.
@@ -212,12 +230,16 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
   }
 
   if (TM.getSubtarget<PPCSubtarget>().use64BitRegs()) {
-    // 64 bit PowerPC implementations can support i64 types directly
+    // 64-bit PowerPC implementations can support i64 types directly
     addRegisterClass(MVT::i64, PPC::G8RCRegisterClass);
     // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
     setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
+    // 64-bit PowerPC wants to expand i128 shifts itself.
+    setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom);
+    setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom);
+    setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom);
   } else {
-    // 32 bit PowerPC wants to expand i64 shifts itself.
+    // 32-bit PowerPC wants to expand i64 shifts itself.
     setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom);
     setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom);
     setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom);
@@ -261,8 +283,15 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
       setOperationAction(ISD::EXTRACT_VECTOR_ELT, (MVT::ValueType)VT, Expand);
       setOperationAction(ISD::INSERT_VECTOR_ELT, (MVT::ValueType)VT, Expand);
       setOperationAction(ISD::BUILD_VECTOR, (MVT::ValueType)VT, Expand);
-
+      setOperationAction(ISD::UMUL_LOHI, (MVT::ValueType)VT, Expand);
+      setOperationAction(ISD::SMUL_LOHI, (MVT::ValueType)VT, Expand);
+      setOperationAction(ISD::UDIVREM, (MVT::ValueType)VT, Expand);
+      setOperationAction(ISD::SDIVREM, (MVT::ValueType)VT, Expand);
       setOperationAction(ISD::SCALAR_TO_VECTOR, (MVT::ValueType)VT, Expand);
+      setOperationAction(ISD::FPOW, (MVT::ValueType)VT, Expand);
+      setOperationAction(ISD::CTPOP, (MVT::ValueType)VT, Expand);
+      setOperationAction(ISD::CTLZ, (MVT::ValueType)VT, Expand);
+      setOperationAction(ISD::CTTZ, (MVT::ValueType)VT, Expand);
     }
 
     // We can custom expand all VECTOR_SHUFFLEs to VPERM, others we can handle
@@ -315,9 +344,29 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
   setTargetDAGCombine(ISD::BR_CC);
   setTargetDAGCombine(ISD::BSWAP);
   
+  // Darwin long double math library functions have $LDBL128 appended.
+  if (TM.getSubtarget<PPCSubtarget>().isDarwin()) {
+    setLibcallName(RTLIB::COS_PPCF128, "cosl$LDBL128");
+    setLibcallName(RTLIB::POW_PPCF128, "powl$LDBL128");
+    setLibcallName(RTLIB::REM_PPCF128, "fmodl$LDBL128");
+    setLibcallName(RTLIB::SIN_PPCF128, "sinl$LDBL128");
+    setLibcallName(RTLIB::SQRT_PPCF128, "sqrtl$LDBL128");
+  }
+
   computeRegisterProperties();
 }
 
+/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate
+/// function arguments in the caller parameter area.
+unsigned PPCTargetLowering::getByValTypeAlignment(const Type *Ty) const {
+  TargetMachine &TM = getTargetMachine();
+  // Darwin passes everything on 4 byte boundary.
+  if (TM.getSubtarget<PPCSubtarget>().isDarwin())
+    return 4;
+  // FIXME Elf TBD
+  return 4;
+}
+
 const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
   switch (Opcode) {
   default: return 0;
@@ -350,6 +399,11 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case PPCISD::LBRX:          return "PPCISD::LBRX";
   case PPCISD::STBRX:         return "PPCISD::STBRX";
   case PPCISD::COND_BRANCH:   return "PPCISD::COND_BRANCH";
+  case PPCISD::MFFS:          return "PPCISD::MFFS";
+  case PPCISD::MTFSB0:        return "PPCISD::MTFSB0";
+  case PPCISD::MTFSB1:        return "PPCISD::MTFSB1";
+  case PPCISD::FADDRTZ:       return "PPCISD::FADDRTZ";
+  case PPCISD::MTFSF:         return "PPCISD::MTFSF";
   }
 }
 
@@ -700,15 +754,21 @@ bool PPCTargetLowering::SelectAddressRegReg(SDOperand N, SDOperand &Base,
     // If this is an or of disjoint bitfields, we can codegen this as an add
     // (for better address arithmetic) if the LHS and RHS of the OR are provably
     // disjoint.
-    uint64_t LHSKnownZero, LHSKnownOne;
-    uint64_t RHSKnownZero, RHSKnownOne;
-    DAG.ComputeMaskedBits(N.getOperand(0), ~0U, LHSKnownZero, LHSKnownOne);
+    APInt LHSKnownZero, LHSKnownOne;
+    APInt RHSKnownZero, RHSKnownOne;
+    DAG.ComputeMaskedBits(N.getOperand(0),
+                          APInt::getAllOnesValue(N.getOperand(0)
+                            .getValueSizeInBits()),
+                          LHSKnownZero, LHSKnownOne);
     
-    if (LHSKnownZero) {
-      DAG.ComputeMaskedBits(N.getOperand(1), ~0U, RHSKnownZero, RHSKnownOne);
+    if (LHSKnownZero.getBoolValue()) {
+      DAG.ComputeMaskedBits(N.getOperand(1),
+                            APInt::getAllOnesValue(N.getOperand(1)
+                              .getValueSizeInBits()),
+                            RHSKnownZero, RHSKnownOne);
       // If all of the bits are known zero on the LHS or RHS, the add won't
       // carry.
-      if ((LHSKnownZero | RHSKnownZero) == ~0U) {
+      if (~(LHSKnownZero | RHSKnownZero) == 0) {
         Base = N.getOperand(0);
         Index = N.getOperand(1);
         return true;
@@ -755,9 +815,11 @@ bool PPCTargetLowering::SelectAddressRegImm(SDOperand N, SDOperand &Disp,
       // If this is an or of disjoint bitfields, we can codegen this as an add
       // (for better address arithmetic) if the LHS and RHS of the OR are
       // provably disjoint.
-      uint64_t LHSKnownZero, LHSKnownOne;
-      DAG.ComputeMaskedBits(N.getOperand(0), ~0U, LHSKnownZero, LHSKnownOne);
-      if ((LHSKnownZero|~(unsigned)imm) == ~0U) {
+      APInt LHSKnownZero, LHSKnownOne;
+      DAG.ComputeMaskedBits(N.getOperand(0),
+                            APInt::getAllOnesValue(32),
+                            LHSKnownZero, LHSKnownOne);
+      if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) {
         // If all of the bits are known zero on the LHS or RHS, the add won't
         // carry.
         Base = N.getOperand(0);
@@ -863,9 +925,11 @@ bool PPCTargetLowering::SelectAddressRegImmShift(SDOperand N, SDOperand &Disp,
       // If this is an or of disjoint bitfields, we can codegen this as an add
       // (for better address arithmetic) if the LHS and RHS of the OR are
       // provably disjoint.
-      uint64_t LHSKnownZero, LHSKnownOne;
-      DAG.ComputeMaskedBits(N.getOperand(0), ~0U, LHSKnownZero, LHSKnownOne);
-      if ((LHSKnownZero|~(unsigned)imm) == ~0U) {
+      APInt LHSKnownZero, LHSKnownOne;
+      DAG.ComputeMaskedBits(N.getOperand(0),
+                            APInt::getAllOnesValue(32),
+                            LHSKnownZero, LHSKnownOne);
+      if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) {
         // If all of the bits are known zero on the LHS or RHS, the add won't
         // carry.
         Base = N.getOperand(0);
@@ -924,12 +988,12 @@ bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDOperand &Base,
   MVT::ValueType VT;
   if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
     Ptr = LD->getBasePtr();
-    VT = LD->getLoadedVT();
+    VT = LD->getMemoryVT();
     
   } else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
     ST = ST;
     Ptr = ST->getBasePtr();
-    VT  = ST->getStoredVT();
+    VT  = ST->getMemoryVT();
   } else
     return false;
 
@@ -953,7 +1017,7 @@ bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDOperand &Base,
   if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
     // PPC64 doesn't have lwau, but it does have lwaux.  Reject preinc load of
     // sext i32 to i64 when addr mode is r+i.
-    if (LD->getValueType(0) == MVT::i64 && LD->getLoadedVT() == MVT::i32 &&
+    if (LD->getValueType(0) == MVT::i64 && LD->getMemoryVT() == MVT::i32 &&
         LD->getExtensionType() == ISD::SEXTLOAD &&
         isa<ConstantSDNode>(Offset))
       return false;
@@ -967,7 +1031,8 @@ bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDOperand &Base,
 //  LowerOperation implementation
 //===----------------------------------------------------------------------===//
 
-static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerConstantPool(SDOperand Op, 
+                                             SelectionDAG &DAG) {
   MVT::ValueType PtrVT = Op.getValueType();
   ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
   Constant *C = CP->getConstVal();
@@ -998,7 +1063,7 @@ static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
   return Lo;
 }
 
-static SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerJumpTable(SDOperand Op, SelectionDAG &DAG) {
   MVT::ValueType PtrVT = Op.getValueType();
   JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
   SDOperand JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
@@ -1028,15 +1093,20 @@ static SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG) {
   return Lo;
 }
 
-static SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerGlobalTLSAddress(SDOperand Op, 
+                                                   SelectionDAG &DAG) {
   assert(0 && "TLS not implemented for PPC.");
 }
 
-static SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerGlobalAddress(SDOperand Op, 
+                                                SelectionDAG &DAG) {
   MVT::ValueType PtrVT = Op.getValueType();
   GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
   GlobalValue *GV = GSDN->getGlobal();
   SDOperand GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
+  // If it's a debug information descriptor, don't mess with it.
+  if (DAG.isVerifiedDebugInfoDesc(Op))
+    return GA;
   SDOperand Zero = DAG.getConstant(0, PtrVT);
   
   const TargetMachine &TM = DAG.getTarget();
@@ -1069,7 +1139,7 @@ static SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
   return DAG.getLoad(PtrVT, DAG.getEntryNode(), Lo, NULL, 0);
 }
 
-static SDOperand LowerSETCC(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerSETCC(SDOperand Op, SelectionDAG &DAG) {
   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
   
   // If we're comparing for equality to zero, expose the fact that this is
@@ -1111,7 +1181,7 @@ static SDOperand LowerSETCC(SDOperand Op, SelectionDAG &DAG) {
   return SDOperand();
 }
 
-static SDOperand LowerVAARG(SDOperand Op, SelectionDAG &DAG,
+SDOperand PPCTargetLowering::LowerVAARG(SDOperand Op, SelectionDAG &DAG,
                               int VarArgsFrameIndex,
                               int VarArgsStackOffset,
                               unsigned VarArgsNumGPR,
@@ -1121,7 +1191,7 @@ static SDOperand LowerVAARG(SDOperand Op, SelectionDAG &DAG,
   assert(0 && "VAARG in ELF32 ABI not implemented yet!");
 }
 
-static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
+SDOperand PPCTargetLowering::LowerVASTART(SDOperand Op, SelectionDAG &DAG,
                               int VarArgsFrameIndex,
                               int VarArgsStackOffset,
                               unsigned VarArgsNumGPR,
@@ -1133,9 +1203,8 @@ static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
     // memory location argument.
     MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
     SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
-    SrcValueSDNode *SV = cast<SrcValueSDNode>(Op.getOperand(2));
-    return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV->getValue(),
-                        SV->getOffset());
+    const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
+    return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV, 0);
   }
 
   // For ELF 32 ABI we follow the layout of the va_list struct.
@@ -1169,37 +1238,41 @@ static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
 
   MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
   
-  SDOperand StackOffset = DAG.getFrameIndex(VarArgsStackOffset, PtrVT);
+  SDOperand StackOffsetFI = DAG.getFrameIndex(VarArgsStackOffset, PtrVT);
   SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
   
-  SDOperand ConstFrameOffset = DAG.getConstant(MVT::getSizeInBits(PtrVT)/8,
-                                               PtrVT);
-  SDOperand ConstStackOffset = DAG.getConstant(MVT::getSizeInBits(PtrVT)/8 - 1,
-                                               PtrVT);
-  SDOperand ConstFPROffset   = DAG.getConstant(1, PtrVT);
+  uint64_t FrameOffset = MVT::getSizeInBits(PtrVT)/8;
+  SDOperand ConstFrameOffset = DAG.getConstant(FrameOffset, PtrVT);
+
+  uint64_t StackOffset = MVT::getSizeInBits(PtrVT)/8 - 1;
+  SDOperand ConstStackOffset = DAG.getConstant(StackOffset, PtrVT);
+
+  uint64_t FPROffset = 1;
+  SDOperand ConstFPROffset = DAG.getConstant(FPROffset, PtrVT);
   
-  SrcValueSDNode *SV = cast<SrcValueSDNode>(Op.getOperand(2));
+  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
   
   // Store first byte : number of int regs
   SDOperand firstStore = DAG.getStore(Op.getOperand(0), ArgGPR,
-                                      Op.getOperand(1), SV->getValue(),
-                                      SV->getOffset());
+                                      Op.getOperand(1), SV, 0);
+  uint64_t nextOffset = FPROffset;
   SDOperand nextPtr = DAG.getNode(ISD::ADD, PtrVT, Op.getOperand(1),
                                   ConstFPROffset);
   
   // Store second byte : number of float regs
-  SDOperand secondStore = DAG.getStore(firstStore, ArgFPR, nextPtr,
-                                       SV->getValue(), SV->getOffset());
+  SDOperand secondStore =
+    DAG.getStore(firstStore, ArgFPR, nextPtr, SV, nextOffset);
+  nextOffset += StackOffset;
   nextPtr = DAG.getNode(ISD::ADD, PtrVT, nextPtr, ConstStackOffset);
   
   // Store second word : arguments given on stack
-  SDOperand thirdStore = DAG.getStore(secondStore, StackOffset, nextPtr,
-                                      SV->getValue(), SV->getOffset());
+  SDOperand thirdStore =
+    DAG.getStore(secondStore, StackOffsetFI, nextPtr, SV, nextOffset);
+  nextOffset += FrameOffset;
   nextPtr = DAG.getNode(ISD::ADD, PtrVT, nextPtr, ConstFrameOffset);
 
   // Store third word : arguments given in registers
-  return DAG.getStore(thirdStore, FR, nextPtr, SV->getValue(),
-                      SV->getOffset());
+  return DAG.getStore(thirdStore, FR, nextPtr, SV, nextOffset);
 
 }
 
@@ -1224,17 +1297,19 @@ static const unsigned *GetFPR(const PPCSubtarget &Subtarget) {
   return FPR;
 }
 
-static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
-                                       int &VarArgsFrameIndex,
-                                       int &VarArgsStackOffset,
-                                       unsigned &VarArgsNumGPR,
-                                       unsigned &VarArgsNumFPR,
-                                       const PPCSubtarget &Subtarget) {
+SDOperand
+PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, 
+                                         SelectionDAG &DAG,
+                                         int &VarArgsFrameIndex,
+                                         int &VarArgsStackOffset,
+                                         unsigned &VarArgsNumGPR,
+                                         unsigned &VarArgsNumFPR,
+                                         const PPCSubtarget &Subtarget) {
   // TODO: add description of PPC stack frame format, or at least some docs.
   //
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo *MFI = MF.getFrameInfo();
-  SSARegMap *RegMap = MF.getSSARegMap();
+  MachineRegisterInfo &RegInfo = MF.getRegInfo();
   SmallVector<SDOperand, 8> ArgValues;
   SDOperand Root = Op.getOperand(0);
   
@@ -1278,6 +1353,8 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
   // represented with two words (long long or double) must be copied to an
   // even GPR_idx value or to an even ArgOffset value.
 
+  SmallVector<SDOperand, 8> MemOps;
+
   for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
     SDOperand ArgVal;
     bool needsLoad = false;
@@ -1286,38 +1363,113 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
     unsigned ArgSize = ObjSize;
     unsigned Flags = cast<ConstantSDNode>(Op.getOperand(ArgNo+3))->getValue();
     unsigned AlignFlag = 1 << ISD::ParamFlags::OrigAlignmentOffs;
+    unsigned isByVal = Flags & ISD::ParamFlags::ByVal;
     // See if next argument requires stack alignment in ELF
     bool Expand = (ObjectVT == MVT::f64) || ((ArgNo + 1 < e) &&
       (cast<ConstantSDNode>(Op.getOperand(ArgNo+4))->getValue() & AlignFlag) &&
       (!(Flags & AlignFlag)));
 
     unsigned CurArgOffset = ArgOffset;
+
+    // FIXME alignment for ELF may not be right
+    // FIXME the codegen can be much improved in some cases.
+    // We do not have to keep everything in memory.
+    if (isByVal) {
+      // ObjSize is the true size, ArgSize rounded up to multiple of registers.
+      ObjSize = (Flags & ISD::ParamFlags::ByValSize) >>
+                      ISD::ParamFlags::ByValSizeOffs;
+      ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
+      // Double word align in ELF
+      if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2);
+      // Objects of size 1 and 2 are right justified, everything else is
+      // left justified.  This means the memory address is adjusted forwards.
+      if (ObjSize==1 || ObjSize==2) {
+        CurArgOffset = CurArgOffset + (4 - ObjSize);
+      }
+      // The value of the object is its address.
+      int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset);
+      SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
+      ArgValues.push_back(FIN);
+      if (ObjSize==1 || ObjSize==2) {
+        if (GPR_idx != Num_GPR_Regs) {
+          unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
+          RegInfo.addLiveIn(GPR[GPR_idx], VReg);
+          SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
+          SDOperand Store = DAG.getTruncStore(Val.getValue(1), Val, FIN, 
+                               NULL, 0, ObjSize==1 ? MVT::i8 : MVT::i16 );
+          MemOps.push_back(Store);
+          ++GPR_idx;
+          if (isMachoABI) ArgOffset += PtrByteSize;
+        } else {
+          ArgOffset += PtrByteSize;
+        }
+        continue;
+      }
+      for (unsigned j = 0; j < ArgSize; j += PtrByteSize) {
+        // Store whatever pieces of the object are in registers
+        // to memory.  ArgVal will be address of the beginning of
+        // the object.
+        if (GPR_idx != Num_GPR_Regs) {
+          unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
+          RegInfo.addLiveIn(GPR[GPR_idx], VReg);
+          int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset);
+          SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
+          SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
+          SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
+          MemOps.push_back(Store);
+          ++GPR_idx;
+          if (isMachoABI) ArgOffset += PtrByteSize;
+        } else {
+          ArgOffset += ArgSize - (ArgOffset-CurArgOffset);
+          break;
+        }
+      }
+      continue;
+    }
+
     switch (ObjectVT) {
     default: assert(0 && "Unhandled argument type!");
     case MVT::i32:
-      // Double word align in ELF
-      if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2);
-      if (GPR_idx != Num_GPR_Regs) {
-        unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
-        MF.addLiveIn(GPR[GPR_idx], VReg);
-        ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
-        ++GPR_idx;
-      } else {
-        needsLoad = true;
-        ArgSize = PtrByteSize;
+      if (!isPPC64) {
+        // Double word align in ELF
+        if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2);
+
+        if (GPR_idx != Num_GPR_Regs) {
+          unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
+          RegInfo.addLiveIn(GPR[GPR_idx], VReg);
+          ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
+          ++GPR_idx;
+        } else {
+          needsLoad = true;
+          ArgSize = PtrByteSize;
+        }
+        // Stack align in ELF
+        if (needsLoad && Expand && isELF32_ABI) 
+          ArgOffset += ((ArgOffset/4) % 2) * PtrByteSize;
+        // All int arguments reserve stack space in Macho ABI.
+        if (isMachoABI || needsLoad) ArgOffset += PtrByteSize;
+        break;
       }
-      // Stack align in ELF
-      if (needsLoad && Expand && isELF32_ABI) 
-        ArgOffset += ((ArgOffset/4) % 2) * PtrByteSize;
-      // All int arguments reserve stack space in Macho ABI.
-      if (isMachoABI || needsLoad) ArgOffset += PtrByteSize;
-      break;
-      
+      // FALLTHROUGH
     case MVT::i64:  // PPC64
       if (GPR_idx != Num_GPR_Regs) {
-        unsigned VReg = RegMap->createVirtualRegister(&PPC::G8RCRegClass);
-        MF.addLiveIn(GPR[GPR_idx], VReg);
+        unsigned VReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
+        RegInfo.addLiveIn(GPR[GPR_idx], VReg);
         ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64);
+
+        if (ObjectVT == MVT::i32) {
+          // PPC64 passes i8, i16, and i32 values in i64 registers. Promote
+          // value to MVT::i64 and then truncate to the correct register size.
+          if (Flags & ISD::ParamFlags::SExt)
+            ArgVal = DAG.getNode(ISD::AssertSext, MVT::i64, ArgVal,
+                                 DAG.getValueType(ObjectVT));
+          else if (Flags & ISD::ParamFlags::ZExt)
+            ArgVal = DAG.getNode(ISD::AssertZext, MVT::i64, ArgVal,
+                                 DAG.getValueType(ObjectVT));
+
+          ArgVal = DAG.getNode(ISD::TRUNCATE, MVT::i32, ArgVal);
+        }
+
         ++GPR_idx;
       } else {
         needsLoad = true;
@@ -1338,10 +1490,10 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
       if (FPR_idx != Num_FPR_Regs) {
         unsigned VReg;
         if (ObjectVT == MVT::f32)
-          VReg = RegMap->createVirtualRegister(&PPC::F4RCRegClass);
+          VReg = RegInfo.createVirtualRegister(&PPC::F4RCRegClass);
         else
-          VReg = RegMap->createVirtualRegister(&PPC::F8RCRegClass);
-        MF.addLiveIn(FPR[FPR_idx], VReg);
+          VReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
+        RegInfo.addLiveIn(FPR[FPR_idx], VReg);
         ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
         ++FPR_idx;
       } else {
@@ -1360,8 +1512,8 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
     case MVT::v16i8:
       // Note that vector arguments in registers don't reserve stack space.
       if (VR_idx != Num_VR_Regs) {
-        unsigned VReg = RegMap->createVirtualRegister(&PPC::VRRCRegClass);
-        MF.addLiveIn(VR[VR_idx], VReg);
+        unsigned VReg = RegInfo.createVirtualRegister(&PPC::VRRCRegClass);
+        RegInfo.addLiveIn(VR[VR_idx], VReg);
         ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
         ++VR_idx;
       } else {
@@ -1374,24 +1526,17 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
     }
     
     // We need to load the argument to a virtual register if we determined above
-    // that we ran out of physical registers of the appropriate type
+    // that we ran out of physical registers of the appropriate type.
     if (needsLoad) {
-      // If the argument is actually used, emit a load from the right stack
-      // slot.
-      if (!Op.Val->hasNUsesOfValue(0, ArgNo)) {
-        int FI = MFI->CreateFixedObject(ObjSize,
-                                        CurArgOffset + (ArgSize - ObjSize));
-        SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
-        ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
-      } else {
-        // Don't emit a dead load.
-        ArgVal = DAG.getNode(ISD::UNDEF, ObjectVT);
-      }
+      int FI = MFI->CreateFixedObject(ObjSize,
+                                      CurArgOffset + (ArgSize - ObjSize));
+      SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
+      ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
     }
     
     ArgValues.push_back(ArgVal);
   }
-  
+
   // If the function takes variable number of arguments, make a frame index for
   // the start of the first vararg value... for expansion of llvm.va_start.
   bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
@@ -1419,8 +1564,6 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
                                                depth);
     SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
     
-    SmallVector<SDOperand, 8> MemOps;
-    
     // In ELF 32 ABI, the fixed integer arguments of a variadic function are
     // stored to the VarArgsFrameIndex on the stack.
     if (isELF32_ABI) {
@@ -1440,11 +1583,11 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
     for (; GPR_idx != Num_GPR_Regs; ++GPR_idx) {
       unsigned VReg;
       if (isPPC64)
-        VReg = RegMap->createVirtualRegister(&PPC::G8RCRegClass);
+        VReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
       else
-        VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
+        VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
 
-      MF.addLiveIn(GPR[GPR_idx], VReg);
+      RegInfo.addLiveIn(GPR[GPR_idx], VReg);
       SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
       SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
       MemOps.push_back(Store);
@@ -1468,9 +1611,9 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
 
       for (; FPR_idx != Num_FPR_Regs; ++FPR_idx) {
         unsigned VReg;
-        VReg = RegMap->createVirtualRegister(&PPC::F8RCRegClass);
+        VReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
 
-        MF.addLiveIn(FPR[FPR_idx], VReg);
+        RegInfo.addLiveIn(FPR[FPR_idx], VReg);
         SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::f64);
         SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
         MemOps.push_back(Store);
@@ -1480,11 +1623,11 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
         FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
       }
     }
-
-    if (!MemOps.empty())
-      Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
   }
   
+  if (!MemOps.empty())
+    Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
+
   ArgValues.push_back(Root);
  
   // Return the new list of results.
@@ -1504,12 +1647,29 @@ static SDNode *isBLACompatibleAddress(SDOperand Op, SelectionDAG &DAG) {
       (Addr << 6 >> 6) != Addr)
     return 0;  // Top 6 bits have to be sext of immediate.
   
-  return DAG.getConstant((int)C->getValue() >> 2, MVT::i32).Val;
+  return DAG.getConstant((int)C->getValue() >> 2,
+                         DAG.getTargetLoweringInfo().getPointerTy()).Val;
 }
 
+/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified
+/// by "Src" to address "Dst" of size "Size".  Alignment information is 
+/// specified by the specific parameter attribute. The copy will be passed as
+/// a byval function parameter.
+/// Sometimes what we are copying is the end of a larger object, the part that
+/// does not fit in registers.
+static SDOperand 
+CreateCopyOfByValArgument(SDOperand Src, SDOperand Dst, SDOperand Chain,
+                          unsigned Flags, SelectionDAG &DAG, unsigned Size) {
+  unsigned Align = 1 <<
+    ((Flags & ISD::ParamFlags::ByValAlign) >> ISD::ParamFlags::ByValAlignOffs);
+  SDOperand AlignNode    = DAG.getConstant(Align, MVT::i32);
+  SDOperand SizeNode     = DAG.getConstant(Size, MVT::i32);
+  SDOperand AlwaysInline = DAG.getConstant(0, MVT::i32);
+  return DAG.getMemcpy(Chain, Dst, Src, SizeNode, AlignNode, AlwaysInline);
+}
 
-static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG,
-                           const PPCSubtarget &Subtarget) {
+SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG,
+                                       const PPCSubtarget &Subtarget) {
   SDOperand Chain  = Op.getOperand(0);
   bool isVarArg    = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
   SDOperand Callee = Op.getOperand(4);
@@ -1533,8 +1693,12 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG,
   
   // Add up all the space actually used.
   for (unsigned i = 0; i != NumOps; ++i) {
+    unsigned Flags = cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
     unsigned ArgSize =MVT::getSizeInBits(Op.getOperand(5+2*i).getValueType())/8;
-    ArgSize = std::max(ArgSize, PtrByteSize);
+    if (Flags & ISD::ParamFlags::ByVal)
+      ArgSize = (Flags & ISD::ParamFlags::ByValSize) >> 
+                ISD::ParamFlags::ByValSizeOffs;
+    ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
     NumBytes += ArgSize;
   }
 
@@ -1550,6 +1714,7 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG,
   // These operations are automatically eliminated by the prolog/epilog pass
   Chain = DAG.getCALLSEQ_START(Chain,
                                DAG.getConstant(NumBytes, PtrVT));
+  SDOperand CallSeqStart = Chain;
   
   // Set up a copy of the stack pointer for use loading and storing any
   // arguments that may not fit in the registers available for argument
@@ -1616,10 +1781,67 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG,
     // On PPC64, promote integers to 64-bit values.
     if (isPPC64 && Arg.getValueType() == MVT::i32) {
       unsigned ExtOp = (Flags & 1) ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
-
       Arg = DAG.getNode(ExtOp, MVT::i64, Arg);
     }
-    
+
+    // FIXME Elf untested, what are alignment rules?
+    // FIXME memcpy is used way more than necessary.  Correctness first.
+    if (Flags & ISD::ParamFlags::ByVal) {
+      unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >>
+                      ISD::ParamFlags::ByValSizeOffs;
+      if (isELF32_ABI && Expand) GPR_idx += (GPR_idx % 2);
+      if (Size==1 || Size==2) {
+        // Very small objects are passed right-justified.
+        // Everything else is passed left-justified.
+        MVT::ValueType VT = (Size==1) ? MVT::i8 : MVT::i16;
+        if (GPR_idx != NumGPRs) {
+          SDOperand Load = DAG.getExtLoad(ISD::EXTLOAD, PtrVT, Chain, Arg, 
+                                          NULL, 0, VT);
+          MemOpChains.push_back(Load.getValue(1));
+          RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load));
+          if (isMachoABI)
+            ArgOffset += PtrByteSize;
+        } else {
+          SDOperand Const = DAG.getConstant(4 - Size, PtrOff.getValueType());
+          SDOperand AddPtr = DAG.getNode(ISD::ADD, PtrVT, PtrOff, Const);
+          SDOperand MemcpyCall = CreateCopyOfByValArgument(Arg, AddPtr,
+                                CallSeqStart.Val->getOperand(0), 
+                                Flags, DAG, Size);
+          // This must go outside the CALLSEQ_START..END.
+          SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall,
+                               CallSeqStart.Val->getOperand(1));
+          DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val);
+          Chain = CallSeqStart = NewCallSeqStart;
+          ArgOffset += PtrByteSize;
+        }
+        continue;
+      }
+      for (unsigned j=0; j<Size; j+=PtrByteSize) {
+        SDOperand Const = DAG.getConstant(j, PtrOff.getValueType());
+        SDOperand AddArg = DAG.getNode(ISD::ADD, PtrVT, Arg, Const);
+        if (GPR_idx != NumGPRs) {
+          SDOperand Load = DAG.getLoad(PtrVT, Chain, AddArg, NULL, 0);
+          MemOpChains.push_back(Load.getValue(1));
+          RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load));
+          if (isMachoABI)
+            ArgOffset += PtrByteSize;
+        } else {
+          SDOperand AddPtr = DAG.getNode(ISD::ADD, PtrVT, PtrOff, Const);
+          SDOperand MemcpyCall = CreateCopyOfByValArgument(AddArg, AddPtr,
+                                CallSeqStart.Val->getOperand(0), 
+                                Flags, DAG, Size - j);
+          // This must go outside the CALLSEQ_START..END.
+          SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall,
+                               CallSeqStart.Val->getOperand(1));
+          DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val);
+          Chain = CallSeqStart = NewCallSeqStart;
+          ArgOffset += ((Size - j + 3)/4)*4;
+          break;
+        }
+      }
+      continue;
+    }
+
     switch (Arg.getValueType()) {
     default: assert(0 && "Unexpected ValueType for argument!");
     case MVT::i32:
@@ -1782,6 +2004,13 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG,
   Chain = DAG.getNode(CallOpc, NodeTys, &Ops[0], Ops.size());
   InFlag = Chain.getValue(1);
 
+  Chain = DAG.getCALLSEQ_END(Chain,
+                             DAG.getConstant(NumBytes, PtrVT),
+                             DAG.getConstant(0, PtrVT),
+                             InFlag);
+  if (Op.Val->getValueType(0) != MVT::Other)
+    InFlag = Chain.getValue(1);
+
   SDOperand ResultVals[3];
   unsigned NumResults = 0;
   NodeTys.clear();
@@ -1807,13 +2036,35 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG,
     NodeTys.push_back(MVT::i32);
     break;
   case MVT::i64:
-    Chain = DAG.getCopyFromReg(Chain, PPC::X3, MVT::i64, InFlag).getValue(1);
-    ResultVals[0] = Chain.getValue(0);
-    NumResults = 1;
+    if (Op.Val->getValueType(1) == MVT::i64) {
+      Chain = DAG.getCopyFromReg(Chain, PPC::X3, MVT::i64, InFlag).getValue(1);
+      ResultVals[0] = Chain.getValue(0);
+      Chain = DAG.getCopyFromReg(Chain, PPC::X4, MVT::i64,
+                                 Chain.getValue(2)).getValue(1);
+      ResultVals[1] = Chain.getValue(0);
+      NumResults = 2;
+      NodeTys.push_back(MVT::i64);
+    } else {
+      Chain = DAG.getCopyFromReg(Chain, PPC::X3, MVT::i64, InFlag).getValue(1);
+      ResultVals[0] = Chain.getValue(0);
+      NumResults = 1;
+    }
     NodeTys.push_back(MVT::i64);
     break;
-  case MVT::f32:
   case MVT::f64:
+    if (Op.Val->getValueType(1) == MVT::f64) {
+      Chain = DAG.getCopyFromReg(Chain, PPC::F1, MVT::f64, InFlag).getValue(1);
+      ResultVals[0] = Chain.getValue(0);
+      Chain = DAG.getCopyFromReg(Chain, PPC::F2, MVT::f64,
+                                 Chain.getValue(2)).getValue(1);
+      ResultVals[1] = Chain.getValue(0);
+      NumResults = 2;
+      NodeTys.push_back(MVT::f64);
+      NodeTys.push_back(MVT::f64);
+      break;
+    } 
+    // else fall through
+  case MVT::f32:
     Chain = DAG.getCopyFromReg(Chain, PPC::F1, Op.Val->getValueType(0),
                                InFlag).getValue(1);
     ResultVals[0] = Chain.getValue(0);
@@ -1832,8 +2083,6 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG,
     break;
   }
   
-  Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
-                      DAG.getConstant(NumBytes, PtrVT));
   NodeTys.push_back(MVT::Other);
   
   // If the function returns void, just return the chain.
@@ -1847,7 +2096,8 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG,
   return Res.getValue(Op.ResNo);
 }
 
-static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG, TargetMachine &TM) {
+SDOperand PPCTargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG, 
+                                      TargetMachine &TM) {
   SmallVector<CCValAssign, 16> RVLocs;
   unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
   bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
@@ -1856,9 +2106,9 @@ static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG, TargetMachine &TM) {
   
   // If this is the first return lowered for this function, add the regs to the
   // liveout set for the function.
-  if (DAG.getMachineFunction().liveout_empty()) {
+  if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
     for (unsigned i = 0; i != RVLocs.size(); ++i)
-      DAG.getMachineFunction().addLiveOut(RVLocs[i].getLocReg());
+      DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
   }
 
   SDOperand Chain = Op.getOperand(0);
@@ -1878,7 +2128,7 @@ static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG, TargetMachine &TM) {
     return DAG.getNode(PPCISD::RET_FLAG, MVT::Other, Chain);
 }
 
-static SDOperand LowerSTACKRESTORE(SDOperand Op, SelectionDAG &DAG,
+SDOperand PPCTargetLowering::LowerSTACKRESTORE(SDOperand Op, SelectionDAG &DAG,
                                    const PPCSubtarget &Subtarget) {
   // When we pop the dynamic allocation we need to restore the SP link.
   
@@ -1904,7 +2154,8 @@ static SDOperand LowerSTACKRESTORE(SDOperand Op, SelectionDAG &DAG,
   return DAG.getStore(Chain, LoadLinkSP, StackPtr, NULL, 0);
 }
 
-static SDOperand LowerDYNAMIC_STACKALLOC(SDOperand Op, SelectionDAG &DAG,
+SDOperand PPCTargetLowering::LowerDYNAMIC_STACKALLOC(SDOperand Op, 
+                                         SelectionDAG &DAG,
                                          const PPCSubtarget &Subtarget) {
   MachineFunction &MF = DAG.getMachineFunction();
   bool IsPPC64 = Subtarget.isPPC64();
@@ -1946,7 +2197,7 @@ static SDOperand LowerDYNAMIC_STACKALLOC(SDOperand Op, SelectionDAG &DAG,
 
 /// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when
 /// possible.
-static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
   // Not FP? Not a fsel.
   if (!MVT::isFloatingPoint(Op.getOperand(0).getValueType()) ||
       !MVT::isFloatingPoint(Op.getOperand(2).getValueType()))
@@ -1990,7 +2241,7 @@ static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
                          DAG.getNode(ISD::FNEG, MVT::f64, LHS), TV, FV);
     }
       
-      SDOperand Cmp;
+  SDOperand Cmp;
   switch (CC) {
   default: break;       // SETUO etc aren't handled by fsel.
   case ISD::SETULT:
@@ -2025,7 +2276,8 @@ static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
   return SDOperand();
 }
 
-static SDOperand LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
+// FIXME: Split this code up when LegalizeDAGTypes lands.
+SDOperand PPCTargetLowering::LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
   assert(MVT::isFloatingPoint(Op.getOperand(0).getValueType()));
   SDOperand Src = Op.getOperand(0);
   if (Src.getValueType() == MVT::f32)
@@ -2043,18 +2295,84 @@ static SDOperand LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
   }
   
   // Convert the FP value to an int value through memory.
-  SDOperand Bits = DAG.getNode(ISD::BIT_CONVERT, MVT::i64, Tmp);
+  SDOperand FIPtr = DAG.CreateStackTemporary(MVT::f64);
+  
+  // Emit a store to the stack slot.
+  SDOperand Chain = DAG.getStore(DAG.getEntryNode(), Tmp, FIPtr, NULL, 0);
+
+  // Result is a load from the stack slot.  If loading 4 bytes, make sure to
+  // add in a bias.
   if (Op.getValueType() == MVT::i32)
-    Bits = DAG.getNode(ISD::TRUNCATE, MVT::i32, Bits);
-  return Bits;
+    FIPtr = DAG.getNode(ISD::ADD, FIPtr.getValueType(), FIPtr,
+                        DAG.getConstant(4, FIPtr.getValueType()));
+  return DAG.getLoad(Op.getValueType(), Chain, FIPtr, NULL, 0);
 }
 
-static SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerFP_ROUND_INREG(SDOperand Op, 
+                                                 SelectionDAG &DAG) {
+  assert(Op.getValueType() == MVT::ppcf128);
+  SDNode *Node = Op.Val;
+  assert(Node->getOperand(0).getValueType() == MVT::ppcf128);
+  assert(Node->getOperand(0).Val->getOpcode() == ISD::BUILD_PAIR);
+  SDOperand Lo = Node->getOperand(0).Val->getOperand(0);
+  SDOperand Hi = Node->getOperand(0).Val->getOperand(1);
+
+  // This sequence changes FPSCR to do round-to-zero, adds the two halves
+  // of the long double, and puts FPSCR back the way it was.  We do not
+  // actually model FPSCR.
+  std::vector<MVT::ValueType> NodeTys;
+  SDOperand Ops[4], Result, MFFSreg, InFlag, FPreg;
+
+  NodeTys.push_back(MVT::f64);   // Return register
+  NodeTys.push_back(MVT::Flag);    // Returns a flag for later insns
+  Result = DAG.getNode(PPCISD::MFFS, NodeTys, &InFlag, 0);
+  MFFSreg = Result.getValue(0);
+  InFlag = Result.getValue(1);
+
+  NodeTys.clear();
+  NodeTys.push_back(MVT::Flag);   // Returns a flag
+  Ops[0] = DAG.getConstant(31, MVT::i32);
+  Ops[1] = InFlag;
+  Result = DAG.getNode(PPCISD::MTFSB1, NodeTys, Ops, 2);
+  InFlag = Result.getValue(0);
+
+  NodeTys.clear();
+  NodeTys.push_back(MVT::Flag);   // Returns a flag
+  Ops[0] = DAG.getConstant(30, MVT::i32);
+  Ops[1] = InFlag;
+  Result = DAG.getNode(PPCISD::MTFSB0, NodeTys, Ops, 2);
+  InFlag = Result.getValue(0);
+
+  NodeTys.clear();
+  NodeTys.push_back(MVT::f64);    // result of add
+  NodeTys.push_back(MVT::Flag);   // Returns a flag
+  Ops[0] = Lo;
+  Ops[1] = Hi;
+  Ops[2] = InFlag;
+  Result = DAG.getNode(PPCISD::FADDRTZ, NodeTys, Ops, 3);
+  FPreg = Result.getValue(0);
+  InFlag = Result.getValue(1);
+
+  NodeTys.clear();
+  NodeTys.push_back(MVT::f64);
+  Ops[0] = DAG.getConstant(1, MVT::i32);
+  Ops[1] = MFFSreg;
+  Ops[2] = FPreg;
+  Ops[3] = InFlag;
+  Result = DAG.getNode(PPCISD::MTFSF, NodeTys, Ops, 4);
+  FPreg = Result.getValue(0);
+
+  // We know the low half is about to be thrown away, so just use something
+  // convenient.
+  return DAG.getNode(ISD::BUILD_PAIR, Lo.getValueType(), FPreg, FPreg);
+}
+
+SDOperand PPCTargetLowering::LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
   if (Op.getOperand(0).getValueType() == MVT::i64) {
     SDOperand Bits = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, Op.getOperand(0));
     SDOperand FP = DAG.getNode(PPCISD::FCFID, MVT::f64, Bits);
     if (Op.getValueType() == MVT::f32)
-      FP = DAG.getNode(ISD::FP_ROUND, MVT::f32, FP);
+      FP = DAG.getNode(ISD::FP_ROUND, MVT::f32, FP, DAG.getIntPtrConstant(0));
     return FP;
   }
   
@@ -2073,91 +2391,166 @@ static SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
                                 Op.getOperand(0));
   
   // STD the extended value into the stack slot.
+  MemOperand MO(PseudoSourceValue::getFixedStack(),
+                MemOperand::MOStore, FrameIdx, 8, 8);
   SDOperand Store = DAG.getNode(PPCISD::STD_32, MVT::Other,
                                 DAG.getEntryNode(), Ext64, FIdx,
-                                DAG.getSrcValue(NULL));
+                                DAG.getMemOperand(MO));
   // Load the value as a double.
   SDOperand Ld = DAG.getLoad(MVT::f64, Store, FIdx, NULL, 0);
   
   // FCFID it and return it.
   SDOperand FP = DAG.getNode(PPCISD::FCFID, MVT::f64, Ld);
   if (Op.getValueType() == MVT::f32)
-    FP = DAG.getNode(ISD::FP_ROUND, MVT::f32, FP);
+    FP = DAG.getNode(ISD::FP_ROUND, MVT::f32, FP, DAG.getIntPtrConstant(0));
   return FP;
 }
 
-static SDOperand LowerSHL_PARTS(SDOperand Op, SelectionDAG &DAG) {
-  assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
-         Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SHL!");
+SDOperand PPCTargetLowering::LowerFLT_ROUNDS_(SDOperand Op, SelectionDAG &DAG) {
+  /*
+   The rounding mode is in bits 30:31 of FPSR, and has the following
+   settings:
+     00 Round to nearest
+     01 Round to 0
+     10 Round to +inf
+     11 Round to -inf
+
+  FLT_ROUNDS, on the other hand, expects the following:
+    -1 Undefined
+     0 Round to 0
+     1 Round to nearest
+     2 Round to +inf
+     3 Round to -inf
+
+  To perform the conversion, we do:
+    ((FPSCR & 0x3) ^ ((~FPSCR & 0x3) >> 1))
+  */
+
+  MachineFunction &MF = DAG.getMachineFunction();
+  MVT::ValueType VT = Op.getValueType();
+  MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
+  std::vector<MVT::ValueType> NodeTys;
+  SDOperand MFFSreg, InFlag;
+
+  // Save FP Control Word to register
+  NodeTys.push_back(MVT::f64);    // return register
+  NodeTys.push_back(MVT::Flag);   // unused in this context
+  SDOperand Chain = DAG.getNode(PPCISD::MFFS, NodeTys, &InFlag, 0);
+
+  // Save FP register to stack slot
+  int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
+  SDOperand StackSlot = DAG.getFrameIndex(SSFI, PtrVT);
+  SDOperand Store = DAG.getStore(DAG.getEntryNode(), Chain,
+                                 StackSlot, NULL, 0);
+
+  // Load FP Control Word from low 32 bits of stack slot.
+  SDOperand Four = DAG.getConstant(4, PtrVT);
+  SDOperand Addr = DAG.getNode(ISD::ADD, PtrVT, StackSlot, Four);
+  SDOperand CWD = DAG.getLoad(MVT::i32, Store, Addr, NULL, 0);
+
+  // Transform as necessary
+  SDOperand CWD1 =
+    DAG.getNode(ISD::AND, MVT::i32,
+                CWD, DAG.getConstant(3, MVT::i32));
+  SDOperand CWD2 =
+    DAG.getNode(ISD::SRL, MVT::i32,
+                DAG.getNode(ISD::AND, MVT::i32,
+                            DAG.getNode(ISD::XOR, MVT::i32,
+                                        CWD, DAG.getConstant(3, MVT::i32)),
+                            DAG.getConstant(3, MVT::i32)),
+                DAG.getConstant(1, MVT::i8));
+
+  SDOperand RetVal =
+    DAG.getNode(ISD::XOR, MVT::i32, CWD1, CWD2);
+
+  return DAG.getNode((MVT::getSizeInBits(VT) < 16 ?
+                      ISD::TRUNCATE : ISD::ZERO_EXTEND), VT, RetVal);
+}
+
+SDOperand PPCTargetLowering::LowerSHL_PARTS(SDOperand Op, SelectionDAG &DAG) {
+  MVT::ValueType VT = Op.getValueType();
+  unsigned BitWidth = MVT::getSizeInBits(VT);
+  assert(Op.getNumOperands() == 3 &&
+         VT == Op.getOperand(1).getValueType() &&
+         "Unexpected SHL!");
   
   // Expand into a bunch of logical ops.  Note that these ops
   // depend on the PPC behavior for oversized shift amounts.
   SDOperand Lo = Op.getOperand(0);
   SDOperand Hi = Op.getOperand(1);
   SDOperand Amt = Op.getOperand(2);
-  
-  SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
-                               DAG.getConstant(32, MVT::i32), Amt);
-  SDOperand Tmp2 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Amt);
-  SDOperand Tmp3 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Tmp1);
-  SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
-  SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
-                               DAG.getConstant(-32U, MVT::i32));
-  SDOperand Tmp6 = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Tmp5);
-  SDOperand OutHi = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6);
-  SDOperand OutLo = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Amt);
+  MVT::ValueType AmtVT = Amt.getValueType();
+  
+  SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT,
+                               DAG.getConstant(BitWidth, AmtVT), Amt);
+  SDOperand Tmp2 = DAG.getNode(PPCISD::SHL, VT, Hi, Amt);
+  SDOperand Tmp3 = DAG.getNode(PPCISD::SRL, VT, Lo, Tmp1);
+  SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3);
+  SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt,
+                               DAG.getConstant(-BitWidth, AmtVT));
+  SDOperand Tmp6 = DAG.getNode(PPCISD::SHL, VT, Lo, Tmp5);
+  SDOperand OutHi = DAG.getNode(ISD::OR, VT, Tmp4, Tmp6);
+  SDOperand OutLo = DAG.getNode(PPCISD::SHL, VT, Lo, Amt);
   SDOperand OutOps[] = { OutLo, OutHi };
-  return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(MVT::i32, MVT::i32),
+  return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT),
                      OutOps, 2);
 }
 
-static SDOperand LowerSRL_PARTS(SDOperand Op, SelectionDAG &DAG) {
-  assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
-         Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SRL!");
+SDOperand PPCTargetLowering::LowerSRL_PARTS(SDOperand Op, SelectionDAG &DAG) {
+  MVT::ValueType VT = Op.getValueType();
+  unsigned BitWidth = MVT::getSizeInBits(VT);
+  assert(Op.getNumOperands() == 3 &&
+         VT == Op.getOperand(1).getValueType() &&
+         "Unexpected SRL!");
   
-  // Otherwise, expand into a bunch of logical ops.  Note that these ops
+  // Expand into a bunch of logical ops.  Note that these ops
   // depend on the PPC behavior for oversized shift amounts.
   SDOperand Lo = Op.getOperand(0);
   SDOperand Hi = Op.getOperand(1);
   SDOperand Amt = Op.getOperand(2);
-  
-  SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
-                               DAG.getConstant(32, MVT::i32), Amt);
-  SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt);
-  SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1);
-  SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
-  SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
-                               DAG.getConstant(-32U, MVT::i32));
-  SDOperand Tmp6 = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Tmp5);
-  SDOperand OutLo = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6);
-  SDOperand OutHi = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Amt);
+  MVT::ValueType AmtVT = Amt.getValueType();
+  
+  SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT,
+                               DAG.getConstant(BitWidth, AmtVT), Amt);
+  SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, VT, Lo, Amt);
+  SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, VT, Hi, Tmp1);
+  SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3);
+  SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt,
+                               DAG.getConstant(-BitWidth, AmtVT));
+  SDOperand Tmp6 = DAG.getNode(PPCISD::SRL, VT, Hi, Tmp5);
+  SDOperand OutLo = DAG.getNode(ISD::OR, VT, Tmp4, Tmp6);
+  SDOperand OutHi = DAG.getNode(PPCISD::SRL, VT, Hi, Amt);
   SDOperand OutOps[] = { OutLo, OutHi };
-  return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(MVT::i32, MVT::i32),
+  return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT),
                      OutOps, 2);
 }
 
-static SDOperand LowerSRA_PARTS(SDOperand Op, SelectionDAG &DAG) {
-  assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
-         Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SRA!");
+SDOperand PPCTargetLowering::LowerSRA_PARTS(SDOperand Op, SelectionDAG &DAG) {
+  MVT::ValueType VT = Op.getValueType();
+  unsigned BitWidth = MVT::getSizeInBits(VT);
+  assert(Op.getNumOperands() == 3 &&
+         VT == Op.getOperand(1).getValueType() &&
+         "Unexpected SRA!");
   
-  // Otherwise, expand into a bunch of logical ops, followed by a select_cc.
+  // Expand into a bunch of logical ops, followed by a select_cc.
   SDOperand Lo = Op.getOperand(0);
   SDOperand Hi = Op.getOperand(1);
   SDOperand Amt = Op.getOperand(2);
-  
-  SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
-                               DAG.getConstant(32, MVT::i32), Amt);
-  SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt);
-  SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1);
-  SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
-  SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
-                               DAG.getConstant(-32U, MVT::i32));
-  SDOperand Tmp6 = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Tmp5);
-  SDOperand OutHi = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Amt);
-  SDOperand OutLo = DAG.getSelectCC(Tmp5, DAG.getConstant(0, MVT::i32),
+  MVT::ValueType AmtVT = Amt.getValueType();
+  
+  SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT,
+                               DAG.getConstant(BitWidth, AmtVT), Amt);
+  SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, VT, Lo, Amt);
+  SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, VT, Hi, Tmp1);
+  SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3);
+  SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt,
+                               DAG.getConstant(-BitWidth, AmtVT));
+  SDOperand Tmp6 = DAG.getNode(PPCISD::SRA, VT, Hi, Tmp5);
+  SDOperand OutHi = DAG.getNode(PPCISD::SRA, VT, Hi, Amt);
+  SDOperand OutLo = DAG.getSelectCC(Tmp5, DAG.getConstant(0, AmtVT),
                                     Tmp4, Tmp6, ISD::SETLE);
   SDOperand OutOps[] = { OutLo, OutHi };
-  return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(MVT::i32, MVT::i32),
+  return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT),
                      OutOps, 2);
 }
 
@@ -2328,7 +2721,8 @@ static SDOperand BuildVSLDOI(SDOperand LHS, SDOperand RHS, unsigned Amt,
 // selects to a single instruction, return Op.  Otherwise, if we can codegen
 // this case more efficiently than a constant pool load, lower it to the
 // sequence of ops that should be used.
-static SDOperand LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerBUILD_VECTOR(SDOperand Op, 
+                                               SelectionDAG &DAG) {
   // If this is a vector of constants or undefs, get the bits.  A bit in
   // UndefBits is set if the corresponding element of the vector is an 
   // ISD::UNDEF value.  For undefs, the corresponding VectorBits values are
@@ -2474,14 +2868,14 @@ static SDOperand LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG) {
     if (SextVal >= 0 && SextVal <= 31) {
       SDOperand LHS = BuildSplatI(SextVal-16, SplatSize, MVT::Other, DAG);
       SDOperand RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG);
-      LHS = DAG.getNode(ISD::SUB, Op.getValueType(), LHS, RHS);
+      LHS = DAG.getNode(ISD::SUB, LHS.getValueType(), LHS, RHS);
       return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), LHS);
     }
     // Odd, in range [-31,-17]:  (vsplti C)+(vsplti -16).
     if (SextVal >= -31 && SextVal <= 0) {
       SDOperand LHS = BuildSplatI(SextVal+16, SplatSize, MVT::Other, DAG);
       SDOperand RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG);
-      LHS = DAG.getNode(ISD::ADD, Op.getValueType(), LHS, RHS);
+      LHS = DAG.getNode(ISD::ADD, LHS.getValueType(), LHS, RHS);
       return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), LHS);
     }
   }
@@ -2570,7 +2964,8 @@ static SDOperand GeneratePerfectShuffle(unsigned PFEntry, SDOperand LHS,
 /// is a shuffle we can handle in a single instruction, return it.  Otherwise,
 /// return the code it can be lowered into.  Worst case, it can always be
 /// lowered into a vperm.
-static SDOperand LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerVECTOR_SHUFFLE(SDOperand Op, 
+                                                 SelectionDAG &DAG) {
   SDOperand V1 = Op.getOperand(0);
   SDOperand V2 = Op.getOperand(1);
   SDOperand PermMask = Op.getOperand(2);
@@ -2734,7 +3129,8 @@ static bool getAltivecCompareInfo(SDOperand Intrin, int &CompareOpc,
 
 /// LowerINTRINSIC_WO_CHAIN - If this is an intrinsic that we want to custom
 /// lower, do it, otherwise return null.
-static SDOperand LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerINTRINSIC_WO_CHAIN(SDOperand Op, 
+                                                     SelectionDAG &DAG) {
   // If this is a lowered altivec predicate compare, CompareOpc is set to the
   // opcode number of the comparison.
   int CompareOpc;
@@ -2800,7 +3196,8 @@ static SDOperand LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG) {
   return Flags;
 }
 
-static SDOperand LowerSCALAR_TO_VECTOR(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerSCALAR_TO_VECTOR(SDOperand Op, 
+                                                   SelectionDAG &DAG) {
   // Create a stack slot that is 16-byte aligned.
   MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo();
   int FrameIdx = FrameInfo->CreateStackObject(16, 16);
@@ -2814,7 +3211,7 @@ static SDOperand LowerSCALAR_TO_VECTOR(SDOperand Op, SelectionDAG &DAG) {
   return DAG.getLoad(Op.getValueType(), Store, FIdx, NULL, 0);
 }
 
-static SDOperand LowerMUL(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerMUL(SDOperand Op, SelectionDAG &DAG) {
   if (Op.getValueType() == MVT::v4i32) {
     SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1);
     
@@ -2905,6 +3302,8 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   case ISD::SELECT_CC:          return LowerSELECT_CC(Op, DAG);
   case ISD::FP_TO_SINT:         return LowerFP_TO_SINT(Op, DAG);
   case ISD::SINT_TO_FP:         return LowerSINT_TO_FP(Op, DAG);
+  case ISD::FP_ROUND_INREG:     return LowerFP_ROUND_INREG(Op, DAG);
+  case ISD::FLT_ROUNDS_:        return LowerFLT_ROUNDS_(Op, DAG);
 
   // Lower 64-bit shifts.
   case ISD::SHL_PARTS:          return LowerSHL_PARTS(Op, DAG);
@@ -2918,20 +3317,28 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   case ISD::SCALAR_TO_VECTOR:   return LowerSCALAR_TO_VECTOR(Op, DAG);
   case ISD::MUL:                return LowerMUL(Op, DAG);
   
-  // Frame & Return address.  Currently unimplemented
-  case ISD::RETURNADDR:         break;
+  // Frame & Return address.
+  case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG);
   case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);
   }
   return SDOperand();
 }
 
+SDNode *PPCTargetLowering::ExpandOperationResult(SDNode *N, SelectionDAG &DAG) {
+  switch (N->getOpcode()) {
+  default: assert(0 && "Wasn't expecting to be able to lower this!");
+  case ISD::FP_TO_SINT: return LowerFP_TO_SINT(SDOperand(N, 0), DAG).Val;
+  }
+}
+
+
 //===----------------------------------------------------------------------===//
 //  Other Lowering Code
 //===----------------------------------------------------------------------===//
 
 MachineBasicBlock *
-PPCTargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
-                                           MachineBasicBlock *BB) {
+PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
+                                               MachineBasicBlock *BB) {
   const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
   assert((MI->getOpcode() == PPC::SELECT_CC_I4 ||
           MI->getOpcode() == PPC::SELECT_CC_I8 ||
@@ -3031,7 +3438,8 @@ SDOperand PPCTargetLowering::PerformDAGCombine(SDNode *N,
         // Turn (sint_to_fp (fp_to_sint X)) -> fctidz/fcfid without load/stores.
         // We allow the src/dst to be either f32/f64, but the intermediate
         // type must be i64.
-        if (N->getOperand(0).getValueType() == MVT::i64) {
+        if (N->getOperand(0).getValueType() == MVT::i64 &&
+            N->getOperand(0).getOperand(0).getValueType() != MVT::ppcf128) {
           SDOperand Val = N->getOperand(0).getOperand(0);
           if (Val.getValueType() == MVT::f32) {
             Val = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Val);
@@ -3043,7 +3451,8 @@ SDOperand PPCTargetLowering::PerformDAGCombine(SDNode *N,
           Val = DAG.getNode(PPCISD::FCFID, MVT::f64, Val);
           DCI.AddToWorklist(Val.Val);
           if (N->getValueType(0) == MVT::f32) {
-            Val = DAG.getNode(ISD::FP_ROUND, MVT::f32, Val);
+            Val = DAG.getNode(ISD::FP_ROUND, MVT::f32, Val, 
+                              DAG.getIntPtrConstant(0));
             DCI.AddToWorklist(Val.Val);
           }
           return Val;
@@ -3057,8 +3466,10 @@ SDOperand PPCTargetLowering::PerformDAGCombine(SDNode *N,
   case ISD::STORE:
     // Turn STORE (FP_TO_SINT F) -> STFIWX(FCTIWZ(F)).
     if (TM.getSubtarget<PPCSubtarget>().hasSTFIWX() &&
+        !cast<StoreSDNode>(N)->isTruncatingStore() &&
         N->getOperand(1).getOpcode() == ISD::FP_TO_SINT &&
-        N->getOperand(1).getValueType() == MVT::i32) {
+        N->getOperand(1).getValueType() == MVT::i32 &&
+        N->getOperand(1).getOperand(0).getValueType() != MVT::ppcf128) {
       SDOperand Val = N->getOperand(1).getOperand(0);
       if (Val.getValueType() == MVT::f32) {
         Val = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Val);
@@ -3099,11 +3510,11 @@ SDOperand PPCTargetLowering::PerformDAGCombine(SDNode *N,
       std::vector<MVT::ValueType> VTs;
       VTs.push_back(MVT::i32);
       VTs.push_back(MVT::Other);
-      SDOperand SV = DAG.getSrcValue(LD->getSrcValue(), LD->getSrcValueOffset());
+      SDOperand MO = DAG.getMemOperand(LD->getMemOperand());
       SDOperand Ops[] = {
         LD->getChain(),    // Chain
         LD->getBasePtr(),  // Ptr
-        SV,                // SrcValue
+        MO,                // MemOperand
         DAG.getValueType(N->getValueType(0)) // VT
       };
       SDOperand BSLoad = DAG.getNode(PPCISD::LBRX, VTs, Ops, 4);
@@ -3251,13 +3662,12 @@ SDOperand PPCTargetLowering::PerformDAGCombine(SDNode *N,
 //===----------------------------------------------------------------------===//
 
 void PPCTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
-                                                       uint64_t Mask,
-                                                       uint64_t &KnownZero, 
-                                                       uint64_t &KnownOne,
+                                                       const APInt &Mask,
+                                                       APInt &KnownZero, 
+                                                       APInt &KnownOne,
                                                        const SelectionDAG &DAG,
                                                        unsigned Depth) const {
-  KnownZero = 0;
-  KnownOne = 0;
+  KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
   switch (Op.getOpcode()) {
   default: break;
   case PPCISD::LBRX: {
@@ -3448,8 +3858,36 @@ bool PPCTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
   return false; 
 }
 
-SDOperand PPCTargetLowering::LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG)
-{
+SDOperand PPCTargetLowering::LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG) {
+  // Depths > 0 not supported yet! 
+  if (cast<ConstantSDNode>(Op.getOperand(0))->getValue() > 0)
+    return SDOperand();
+
+  MachineFunction &MF = DAG.getMachineFunction();
+  PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
+  int RAIdx = FuncInfo->getReturnAddrSaveIndex();
+  if (RAIdx == 0) {
+    bool isPPC64 = PPCSubTarget.isPPC64();
+    int Offset = 
+      PPCFrameInfo::getReturnSaveOffset(isPPC64, PPCSubTarget.isMachoABI());
+
+    // Set up a frame object for the return address.
+    RAIdx = MF.getFrameInfo()->CreateFixedObject(isPPC64 ? 8 : 4, Offset);
+    
+    // Remember it for next time.
+    FuncInfo->setReturnAddrSaveIndex(RAIdx);
+    
+    // Make sure the function really does not optimize away the store of the RA
+    // to the stack.
+    FuncInfo->setLRStoreRequired();
+  }
+  
+  // Just load the return address off the stack.
+  SDOperand RetAddrFI =  DAG.getFrameIndex(RAIdx, getPointerTy());
+  return DAG.getLoad(getPointerTy(), DAG.getEntryNode(), RetAddrFI, NULL, 0);
+}
+
+SDOperand PPCTargetLowering::LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG) {
   // Depths > 0 not supported yet! 
   if (cast<ConstantSDNode>(Op.getOperand(0))->getValue() > 0)
     return SDOperand();