Index: gcc/llvm-convert.cpp
===================================================================
--- gcc/llvm-convert.cpp        (revision 121798)
+++ gcc/llvm-convert.cpp        (revision 122002)
@@ -38,7 +38,6 @@
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/SmallVector.h"
 #include <iostream>
 
 extern "C" {
Index: gcc/llvm-internal.h
===================================================================
--- gcc/llvm-internal.h (revision 121798)
+++ gcc/llvm-internal.h (revision 122002)
@@ -32,6 +32,7 @@
 #include <cassert>
 #include <map>
 #include <string>
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Support/Streams.h"
 
@@ -469,6 +470,17 @@
   Value *EmitINTEGER_CST(tree_node *exp);
   Value *EmitREAL_CST(tree_node *exp);
   Value *EmitCONSTRUCTOR(tree_node *exp, Value *DestLoc);
+
+  // Optional target defined builtin intrinsic expanding function.
+  bool TargetIntrinsicLower(unsigned FnCode,
+                            Value *DestLoc,
+                            Value *&Result,
+                            const Type *ResultType,
+                            std::vector<Value*> &Ops,
+                            SmallVector<tree_node *, 8> &Args,
+                            BasicBlock *CurBB,
+                            bool ResIsSigned,
+                            bool ExpIsSigned);
 };
 
 /// TreeConstantToLLVM - An instance of this class is created and used to 
Index: gcc/config/rs6000/llvm-rs6000.cpp
===================================================================
--- gcc/config/rs6000/llvm-rs6000.cpp   (revision 121798)
+++ gcc/config/rs6000/llvm-rs6000.cpp   (revision 122002)
@@ -0,0 +1,402 @@
+/* APPLE LOCAL begin LLVM (ENTIRE FILE!)  */
+/* High-level LLVM backend interface 
+Copyright (C) 2005 Free Software Foundation, Inc.
+Contributed by Jim Laskey (jlaskey@apple.com)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+//===----------------------------------------------------------------------===//
+// This is a C++ source file that implements specific llvm powerpc ABI.
+//===----------------------------------------------------------------------===//
+
+#include "llvm-abi.h"
+#include "llvm-internal.h"
+#include "llvm-debug.h"
+#include "llvm/CallingConv.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/InlineAsm.h"
+#include "llvm/Instructions.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Module.h"
+#include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include <iostream>
+
+extern "C" {
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "tree-iterator.h"
+#include "output.h"
+#include "diagnostic.h"
+#include "real.h"
+#include "langhooks.h"
+#include "function.h"
+#include "toplev.h"
+#include "flags.h"
+#include "target.h"
+#include "hard-reg-set.h"
+}
+
+/* MERGE_INT_PTR_OPERAND - This merges the int and pointer operands of a GCC
+ * intrinsic into a single operand for the LLVM intrinsic.  For example, this
+ * turns LVX(4, p) -> llvm.lvx(gep P, 4).  OPNUM specifies the operand number
+ * of the integer to contract with its following pointer and NAME specifies the
+ * name of the resultant intrinsic.
+ */
+#define MERGE_INT_PTR_OPERAND(OPNUM, NAME, DESTTY, OPS, CURBB, RESULT) \
+  { static Function *Cache = 0; \
+    const Type *VoidPtrTy = PointerType::get(Type::Int8Ty); \
+    if (Cache == 0) { \
+      std::vector<const Type*> ArgTys; \
+      for (unsigned i = 0, e = OPS.size(); i != e; ++i) \
+        ArgTys.push_back(OPS[i]->getType()); \
+      ArgTys.erase(ArgTys.begin()+OPNUM); \
+      ArgTys[OPNUM] = VoidPtrTy; \
+      FunctionType *FT = FunctionType::get(DESTTY, ArgTys, false); \
+      Module *M = CURBB->getParent()->getParent(); \
+      Cache = M->getOrInsertFunction(NAME, FT); \
+    } \
+    Value *Offset = OPS[OPNUM], *Ptr = OPS[OPNUM+1]; \
+    Ptr = CastToType(Instruction::BitCast, Ptr, VoidPtrTy); \
+    if (!isa<Constant>(Offset) || !cast<Constant>(Offset)->isNullValue()) \
+      Ptr = new GetElementPtrInst(Ptr, Offset, "tmp", CURBB); \
+    OPS.erase(OPS.begin()+OPNUM); \
+    OPS[OPNUM] = Ptr; \
+    Value *V = new CallInst(Cache, OPS, "", CURBB); \
+    if (V->getType() != Type::VoidTy) { \
+      V->setName("tmp"); \
+      RESULT = V; \
+    } \
+  }
+
+/* GET_ALTIVEC_TYPENUM_FROM_TYPE - Given an LLVM type, return a unique ID for
+ * the type in the range 0-3.
+ */
+#define GET_ALTIVEC_TYPENUM_FROM_TYPE(TY) \
+         ((TY == Type::Int32Ty) ? 0 : \
+          ((TY == Type::Int16Ty) ? 1 : \
+           ((TY == Type::Int8Ty) ? 2 : \
+            ((TY == Type::FloatTy) ? 3 : -1))))
+
+/* GET_ALTIVEC_LETTER_FROM_TYPE - Given an LLVM type, return the altivec letter
+ * for the type, e.g. int -> w.
+ */
+#define GET_ALTIVEC_LETTER_FROM_TYPE(TY) \
+         ((TY == Type::Int32Ty) ? 'w' : \
+          ((TY == Type::Int16Ty) ? 'h' : \
+           ((TY == Type::Int8Ty) ? 'b' : \
+            ((TY == Type::FloatTy) ? 'f' : 'x'))))
+                  
+
+/* LLVM_TARGET_INTRINSIC_CAST_RESULT - This macro just provides a frequently
+ * used sequence for use inside LLVM_TARGET_INTRINSIC_LOWER. Note that this
+ * macro assumes it is being invoked from inside LLVM_TARGET_INTRINSC_LOWER
+ * (see below) because it requires the "ResIsSigned" and "ExpIsSigned" macro 
+ * arguments in order to derive signedness for the cast.
+ */
+#define LLVM_TARGET_INTRINSIC_CAST_RESULT(RESULT, RESISSIGNED, DESTTY, \
+                                          EXPISSIGNED) \
+  { Instruction::CastOps opcode = CastInst::getCastOpcode(RESULT, \
+        RESISSIGNED, DESTTY, EXPISSIGNED); \
+    RESULT = CastInst::create(opcode, RESULT, DESTTY, "tmp", CurBB); \
+  } 
+
+/* LLVM_INTRINSIC_OP_IS_SIGNED - This macro determines if a given operand
+ * to the intrinsic is signed or not. Note that this macro assumes it is being
+ * invoked from inside LLVM_TARGET_INTRINSIC_LOWER (see below) because it 
+ * requires the "ARGS" macro argument in order to determine signedness
+ */
+#define LLVM_INTRINSIC_OP_IS_SIGNED(ARGS, OPNUM) \
+  !TYPE_UNSIGNED(TREE_TYPE(ARGS[OPNUM]))
+
+/* TargetIntrinsicLower - To handle builtins, we want to expand the
+ * invocation into normal LLVM code.  If the target can handle the builtin, this
+ * function should emit the expanded code and return true.
+ */
+bool TreeToLLVM::TargetIntrinsicLower(unsigned FnCode,
+                                      Value *DestLoc,
+                                      Value *&Result,
+                                      const Type *ResultType,
+                                      std::vector<Value*> &Ops,
+                                      SmallVector<tree, 8> &Args,
+                                      BasicBlock *CurBB,
+                                      bool ResIsSigned,
+                                      bool ExpIsSigned) {
+  switch (FnCode) {
+  default: break;
+  case ALTIVEC_BUILTIN_VADDFP:
+  case ALTIVEC_BUILTIN_VADDUBM:
+  case ALTIVEC_BUILTIN_VADDUHM:
+  case ALTIVEC_BUILTIN_VADDUWM:
+    Result = BinaryOperator::createAdd(Ops[0], Ops[1], "tmp", CurBB);
+    return true;
+  case ALTIVEC_BUILTIN_VSUBFP:
+  case ALTIVEC_BUILTIN_VSUBUBM:
+  case ALTIVEC_BUILTIN_VSUBUHM:
+  case ALTIVEC_BUILTIN_VSUBUWM:
+    Result = BinaryOperator::createSub(Ops[0], Ops[1], "tmp", CurBB);
+    return true;
+  case ALTIVEC_BUILTIN_VAND:
+    Result = BinaryOperator::createAnd(Ops[0], Ops[1], "tmp", CurBB);
+    return true;
+  case ALTIVEC_BUILTIN_VANDC:
+    Ops[1] = BinaryOperator::createNot(Ops[1], "tmp", CurBB);
+    Result = BinaryOperator::createAnd(Ops[0], Ops[1], "tmp", CurBB);
+    return true;
+  case ALTIVEC_BUILTIN_VOR:
+    Result = BinaryOperator::createOr(Ops[0], Ops[1], "tmp", CurBB);
+    return true;
+  case ALTIVEC_BUILTIN_VNOR:
+    Result = BinaryOperator::createOr(Ops[0], Ops[1], "tmp", CurBB);
+    Result = BinaryOperator::createNot(Result, "tmp", CurBB);
+    return true;
+  case ALTIVEC_BUILTIN_VXOR:
+    Result = BinaryOperator::createXor(Ops[0], Ops[1], "tmp", CurBB);
+    return true;
+  case ALTIVEC_BUILTIN_LVSL:
+    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvsl",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_LVSR:
+    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvsr",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_LVX:
+    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvx",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_LVXL:
+    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvxl",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_LVEBX:
+    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvebx",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_LVEHX:
+    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvehx",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_LVEWX:
+    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvewx",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_STVX:
+    MERGE_INT_PTR_OPERAND(1, "llvm.ppc.altivec.stvx",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_STVEBX:
+    MERGE_INT_PTR_OPERAND(1, "llvm.ppc.altivec.stvebx",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_STVEHX:
+    MERGE_INT_PTR_OPERAND(1, "llvm.ppc.altivec.stvehx",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_STVEWX:
+    MERGE_INT_PTR_OPERAND(1, "llvm.ppc.altivec.stvewx",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_STVXL:
+    MERGE_INT_PTR_OPERAND(1, "llvm.ppc.altivec.stvxl",
+                          ResultType, Ops, CurBB, Result);
+    return true;
+  case ALTIVEC_BUILTIN_VSPLTISB:
+    if (Constant *Elt = dyn_cast<ConstantInt>(Ops[0])) {
+      Elt = ConstantExpr::getIntegerCast(Elt, Type::Int8Ty, true);
+      Result = BuildVector(Elt, Elt, Elt, Elt,  Elt, Elt, Elt, Elt,
+                           Elt, Elt, Elt, Elt,  Elt, Elt, Elt, Elt, NULL);
+      return true;
+    }
+    return false;
+  case ALTIVEC_BUILTIN_VSPLTISH:
+    if (Constant *Elt = dyn_cast<ConstantInt>(Ops[0])) {
+      Elt = ConstantExpr::getIntegerCast(Elt, Type::Int16Ty, true);
+      Result = BuildVector(Elt, Elt, Elt, Elt,  Elt, Elt, Elt, Elt, NULL);
+      return true;
+    }
+    return false;
+  case ALTIVEC_BUILTIN_VSPLTISW:
+    if (Constant *Elt = dyn_cast<ConstantInt>(Ops[0])) {
+      Elt = ConstantExpr::getIntegerCast(Elt, Type::Int32Ty, true);
+      Result = BuildVector(Elt, Elt, Elt, Elt, NULL);
+      return true;
+    }
+    return false;
+  case ALTIVEC_BUILTIN_VSPLTB:
+    if (ConstantInt *Elt = dyn_cast<ConstantInt>(Ops[1])) {
+      int EV = Elt->getZExtValue();
+      Result = BuildVectorShuffle(Ops[0], Ops[0],
+                                  EV, EV, EV, EV, EV, EV, EV, EV,
+                                  EV, EV, EV, EV, EV, EV, EV, EV);
+      return true;
+    }
+    return false;
+  case ALTIVEC_BUILTIN_VSPLTH:
+    if (ConstantInt *Elt = dyn_cast<ConstantInt>(Ops[1])) {
+      int EV = Elt->getZExtValue();
+      Result = BuildVectorShuffle(Ops[0], Ops[0],
+                                  EV, EV, EV, EV, EV, EV, EV, EV);
+      return true;
+    }
+    return false;
+  case ALTIVEC_BUILTIN_VSPLTW:
+    if (ConstantInt *Elt = dyn_cast<ConstantInt>(Ops[1])) {
+      int EV = Elt->getZExtValue();
+      Result = BuildVectorShuffle(Ops[0], Ops[0], EV, EV, EV, EV);
+      return true;
+    }
+    return false;
+  case ALTIVEC_BUILTIN_VSLDOI_16QI:
+  case ALTIVEC_BUILTIN_VSLDOI_8HI:
+  case ALTIVEC_BUILTIN_VSLDOI_4SI:
+  case ALTIVEC_BUILTIN_VSLDOI_4SF:
+    if (ConstantInt *Elt = dyn_cast<ConstantInt>(Ops[2])) {
+      /* Map all of these to a shuffle. */
+      unsigned Amt = Elt->getZExtValue() & 15;
+      PackedType *v16i8 = PackedType::get(Type::Int8Ty, 16);
+      Value *Op0 = Ops[0];
+      Instruction::CastOps opc = CastInst::getCastOpcode(Op0,
+        LLVM_INTRINSIC_OP_IS_SIGNED(Args,0), ResultType, false);
+      Ops[0] = CastToType(opc, Op0, v16i8);
+      Value *Op1 = Ops[1];
+      opc = CastInst::getCastOpcode(Op1,
+        LLVM_INTRINSIC_OP_IS_SIGNED(Args,1), ResultType, false);
+      Ops[1] = CastToType(opc, Op1, v16i8);
+      Result = BuildVectorShuffle(Ops[0], Ops[1],
+                                  Amt, Amt+1, Amt+2, Amt+3,
+                                  Amt+4, Amt+5, Amt+6, Amt+7,
+                                  Amt+8, Amt+9, Amt+10, Amt+11,
+                                  Amt+12, Amt+13, Amt+14, Amt+15);
+      return true;
+    }
+    return false;
+  case ALTIVEC_BUILTIN_VPKUHUM: {
+    Value *Op0 = Ops[0];
+    Instruction::CastOps opc = CastInst::getCastOpcode(Op0,
+        LLVM_INTRINSIC_OP_IS_SIGNED(Args,0), ResultType, ExpIsSigned);
+    Ops[0] = CastInst::create(opc, Op0, ResultType, Op0->getName(), CurBB);
+    Value *Op1 = Ops[1];
+    opc = CastInst::getCastOpcode(Op1,
+        LLVM_INTRINSIC_OP_IS_SIGNED(Args,1), ResultType, ExpIsSigned);
+    Ops[1] = CastInst::create(opc, Op1, ResultType, Op1->getName(), CurBB);
+    Result = BuildVectorShuffle(Ops[0], Ops[1], 1, 3, 5, 7, 9, 11, 13, 15,
+                                17, 19, 21, 23, 25, 27, 29, 31);
+    return true;
+  }
+  case ALTIVEC_BUILTIN_VPKUWUM: {
+    Value *Op0 = Ops[0];
+    Instruction::CastOps opc = CastInst::getCastOpcode(Op0,
+        LLVM_INTRINSIC_OP_IS_SIGNED(Args,0), ResultType, ExpIsSigned);
+    Ops[0] = CastInst::create(opc, Op0, ResultType, Op0->getName(), CurBB);
+    Value *Op1 = Ops[1];
+    opc = CastInst::getCastOpcode(Op1,
+        LLVM_INTRINSIC_OP_IS_SIGNED(Args,1), ResultType, ExpIsSigned);
+    Ops[1] = CastInst::create(opc, Op1, ResultType, Op1->getName(), CurBB);
+    Result = BuildVectorShuffle(Ops[0], Ops[1], 1, 3, 5, 7, 9, 11, 13, 15);
+    return true;
+  }
+  case ALTIVEC_BUILTIN_VMRGHB:
+    Result = BuildVectorShuffle(Ops[0], Ops[1],
+                                0, 16, 1, 17, 2, 18, 3, 19,
+                                4, 20, 5, 21, 6, 22, 7, 23);
+    return true;
+  case ALTIVEC_BUILTIN_VMRGHH:
+    Result = BuildVectorShuffle(Ops[0], Ops[1], 0, 8, 1, 9, 2, 10, 3, 11);
+    return true;
+  case ALTIVEC_BUILTIN_VMRGHW:
+    Result = BuildVectorShuffle(Ops[0], Ops[1], 0, 4, 1, 5);
+    return true;
+  case ALTIVEC_BUILTIN_VMRGLB:
+    Result = BuildVectorShuffle(Ops[0], Ops[1],
+                                 8, 24,  9, 25, 10, 26, 11, 27,
+                                12, 28, 13, 29, 14, 30, 15, 31);
+    return true;
+  case ALTIVEC_BUILTIN_VMRGLH:
+    Result = BuildVectorShuffle(Ops[0], Ops[1], 4, 12, 5, 13, 6, 14, 7, 15);
+    return true;
+  case ALTIVEC_BUILTIN_VMRGLW:
+    Result = BuildVectorShuffle(Ops[0], Ops[1], 2, 6, 3, 7);
+    return true;
+  case ALTIVEC_BUILTIN_ABS_V4SF: {
+    /* and out sign bits */
+    PackedType *v4i32 = PackedType::get(Type::Int32Ty, 4);
+    Ops[0] = new BitCastInst(Ops[0], v4i32, Ops[0]->getName(),CurBB);
+    Constant *C = ConstantInt::get(Type::Int32Ty, 0x7FFFFFFF);
+    C = ConstantPacked::get(std::vector<Constant*>(4, C));
+    Result = BinaryOperator::createAnd(Ops[0], C, "tmp", CurBB);
+    LLVM_TARGET_INTRINSIC_CAST_RESULT(Result,ResIsSigned,
+                                      ResultType,ExpIsSigned);
+    return true;
+  }
+  case ALTIVEC_BUILTIN_ABS_V4SI:
+  case ALTIVEC_BUILTIN_ABS_V8HI:
+  case ALTIVEC_BUILTIN_ABS_V16QI: { /* iabs(x) -> smax(x, 0-x) */
+    Result = BinaryOperator::createNeg(Ops[0], "tmp", CurBB);
+    /* get the right smax intrinsic. */
+    static Function *smax[3];
+    const PackedType *PTy = cast<PackedType>(ResultType);
+    unsigned N = GET_ALTIVEC_TYPENUM_FROM_TYPE(PTy->getElementType());
+    if (smax[N] == 0) {
+      Module *M = CurBB->getParent()->getParent();
+      smax[N] = M->getOrInsertFunction(std::string("llvm.ppc.altivec.vmaxs")+
+                         GET_ALTIVEC_LETTER_FROM_TYPE(PTy->getElementType()),
+                                      ResultType, ResultType, ResultType, NULL);
+    }
+    Result = new CallInst(smax[N], Ops[0], Result, "tmp", CurBB);
+    return true;
+  }
+  case ALTIVEC_BUILTIN_ABSS_V4SI:
+  case ALTIVEC_BUILTIN_ABSS_V8HI:
+  case ALTIVEC_BUILTIN_ABSS_V16QI: { /* iabss(x) -> smax(x, satsub(0,x)) */
+    static Function *sxs[3], *smax[3];
+    /* get the right satsub intrinsic. */
+    const PackedType *PTy = cast<PackedType>(ResultType);
+    unsigned N = GET_ALTIVEC_TYPENUM_FROM_TYPE(PTy->getElementType());
+    if (sxs[N] == 0) {
+      Module *M = CurBB->getParent()->getParent();
+      sxs[N] = M->getOrInsertFunction(std::string("llvm.ppc.altivec.vsubs")+
+                     GET_ALTIVEC_LETTER_FROM_TYPE(PTy->getElementType())+"s",
+                                      ResultType, ResultType, ResultType, NULL);
+    }
+    Result = Constant::getNullValue(ResultType);
+    Result = new CallInst(sxs[N], Result, Ops[0], "tmp", CurBB);
+    /* get the right smax intrinsic. */
+    if (smax[N] == 0) {
+      Module *M = CurBB->getParent()->getParent();
+      smax[N] = M->getOrInsertFunction(std::string("llvm.ppc.altivec.vmaxs")+
+                         GET_ALTIVEC_LETTER_FROM_TYPE(PTy->getElementType()),
+                                      ResultType, ResultType, ResultType, NULL);
+    }
+    Result = new CallInst(smax[N], Ops[0], Result, "tmp", CurBB);
+    return true;
+  }
+  }
+
+  return false;
+}
+
+/* APPLE LOCAL end LLVM (ENTIRE FILE!)  */
+
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h  (revision 121798)
+++ gcc/config/rs6000/rs6000.h  (revision 122002)
@@ -3635,335 +3635,16 @@
 #define LLVM_OVERRIDE_TARGET_ARCH() \
   (TARGET_64BIT ? "powerpc64" : "powerpc")
 
-/* MERGE_INT_PTR_OPERAND - This merges the int and pointer operands of a GCC
- * intrinsic into a single operand for the LLVM intrinsic.  For example, this
- * turns LVX(4, p) -> llvm.lvx(gep P, 4).  OPNUM specifies the operand number
- * of the integer to contract with its following pointer and NAME specifies the
- * name of the resultant intrinsic.
+/* LLVM_TARGET_INTRINSIC_LOWER - To handle builtins, we want to expand the
+ * invocation into normal LLVM code.  If the target can handle the builtin, this
+ * macro should call the target TreeToLLVM::TargetIntrinsicLower method and
+ *  return true.This macro is invoked from a method in the TreeToLLVM class.
  */
-#define MERGE_INT_PTR_OPERAND(OPNUM, NAME, DESTTY, OPS, CURBB, RESULT)        \
-  { static Function *Cache = 0;                                               \
-    const Type *VoidPtrTy = PointerType::get(Type::Int8Ty);                  \
-    if (Cache == 0) {                                                         \
-      std::vector<const Type*> ArgTys;                                        \
-      for (unsigned i = 0, e = OPS.size(); i != e; ++i)                       \
-        ArgTys.push_back(OPS[i]->getType());                                  \
-      ArgTys.erase(ArgTys.begin()+OPNUM);                                     \
-      ArgTys[OPNUM] = VoidPtrTy;                                              \
-      FunctionType *FT = FunctionType::get(DESTTY, ArgTys, false);            \
-      Module *M = CURBB->getParent()->getParent();                            \
-      Cache = M->getOrInsertFunction(NAME, FT);                               \
-    }                                                                         \
-    Value *Offset = OPS[OPNUM], *Ptr = OPS[OPNUM+1];                          \
-    Ptr = CastToType(Instruction::BitCast, Ptr, VoidPtrTy);                   \
-    if (!isa<Constant>(Offset) || !cast<Constant>(Offset)->isNullValue())     \
-      Ptr = new GetElementPtrInst(Ptr, Offset, "tmp", CURBB);                 \
-    OPS.erase(OPS.begin()+OPNUM);                                             \
-    OPS[OPNUM] = Ptr;                                                         \
-    Value *V = new CallInst(Cache, OPS, "", CURBB);                           \
-    if (V->getType() != Type::VoidTy) {                                       \
-      V->setName("tmp");                                                      \
-      RESULT = V;                                                             \
-    }                                                                         \
-  }
-
-/* GET_ALTIVEC_TYPENUM_FROM_TYPE - Given an LLVM type, return a unique ID for
- * the type in the range 0-3.
- */
-#define GET_ALTIVEC_TYPENUM_FROM_TYPE(TY)               \
-         ((TY == Type::Int32Ty) ? 0 :                     \
-          ((TY == Type::Int16Ty) ? 1 :                  \
-           ((TY == Type::Int8Ty) ? 2 :                 \
-            ((TY == Type::FloatTy) ? 3 : -1))))
-
-/* GET_ALTIVEC_LETTER_FROM_TYPE - Given an LLVM type, return the altivec letter
- * for the type, e.g. int -> w.
- */
-#define GET_ALTIVEC_LETTER_FROM_TYPE(TY)                \
-         ((TY == Type::Int32Ty) ? 'w' :                   \
-          ((TY == Type::Int16Ty) ? 'h' :                \
-           ((TY == Type::Int8Ty) ? 'b' :               \
-            ((TY == Type::FloatTy) ? 'f' : 'x'))))
-                  
-/* LLVM_TARGET_INTRINSIC_CAST_RESULT - This macro just provides a frequently
- * used sequence for use inside LLVM_TARGET_INTRINSIC_LOWER. Note that this
- * macro assumes it is being invoked from inside LLVM_TARGET_INTRINSC_LOWER
- * (see below) because it requires the "ResIsSigned" and "ExpIsSigned" macro 
- * arguments in order to derive signedness for the cast.
- */
-#define LLVM_TARGET_INTRINSIC_CAST_RESULT(RESULT, RESISSIGNED, DESTTY,        \
-                                          EXPISSIGNED)                        \
-  { Instruction::CastOps opcode = CastInst::getCastOpcode(RESULT,             \
-        RESISSIGNED, DESTTY, EXPISSIGNED);                                    \
-    RESULT = CastInst::create(opcode, RESULT, DESTTY, "tmp", CurBB);          \
-  } 
-
-/* LLVM_INTRINSIC_OP_IS_SIGNED - This macro determines if a given operand
- * to the intrinsic is signed or not. Note that this macro assumes it is being
- * invoked from inside LLVM_TARGET_INTRINSIC_LOWER (see below) because it 
- * requires the "ARGS" macro argument in order to determine signedness
- */
-#define LLVM_INTRINSIC_OP_IS_SIGNED(ARGS, OPNUM) \
-  !TYPE_UNSIGNED(TREE_TYPE(ARGS[OPNUM]))
-
-/* LLVM_TARGET_INTRINSIC_LOWER - For builtins that we want to expand to normal
- * LLVM code, emit the code now.  If we can handle the code, this macro should
- * emit the code, return true.  Note that this would be much better as a
- * function implemented in a target-specific .cpp file, but we don't have that
- * yet.  This code is expanded in a method in the TreeToLLVM class, so it can
- * use methods it defines.
- */
 #define LLVM_TARGET_INTRINSIC_LOWER(BUILTIN_CODE, DESTLOC, RESULT,            \
                                     DESTTY, OPS, ARGS, CURBB,                 \
                                     RESISSIGNED, EXPISSIGNED)                 \
-  switch (BUILTIN_CODE) {                                                     \
-  default: break;                                                             \
-  case ALTIVEC_BUILTIN_VADDFP:                                                \
-  case ALTIVEC_BUILTIN_VADDUBM:                                               \
-  case ALTIVEC_BUILTIN_VADDUHM:                                               \
-  case ALTIVEC_BUILTIN_VADDUWM:                                               \
-    RESULT = BinaryOperator::createAdd(OPS[0], OPS[1], "tmp", CURBB);         \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VSUBFP:                                                \
-  case ALTIVEC_BUILTIN_VSUBUBM:                                               \
-  case ALTIVEC_BUILTIN_VSUBUHM:                                               \
-  case ALTIVEC_BUILTIN_VSUBUWM:                                               \
-    RESULT = BinaryOperator::createSub(OPS[0], OPS[1], "tmp", CURBB);         \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VAND:                                                  \
-    RESULT = BinaryOperator::createAnd(OPS[0], OPS[1], "tmp", CURBB);         \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VANDC:                                                 \
-    OPS[1] = BinaryOperator::createNot(OPS[1], "tmp", CURBB);                 \
-    RESULT = BinaryOperator::createAnd(OPS[0], OPS[1], "tmp", CURBB);         \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VOR:                                                   \
-    RESULT = BinaryOperator::createOr(OPS[0], OPS[1], "tmp", CURBB);          \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VNOR:                                                  \
-    RESULT = BinaryOperator::createOr(OPS[0], OPS[1], "tmp", CURBB);          \
-    RESULT = BinaryOperator::createNot(RESULT, "tmp", CURBB);                 \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VXOR:                                                  \
-    RESULT = BinaryOperator::createXor(OPS[0], OPS[1], "tmp", CURBB);         \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_LVSL:                                                  \
-    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvsl",                         \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_LVSR:                                                  \
-    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvsr",                         \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_LVX:                                                   \
-    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvx",                          \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_LVXL:                                                  \
-    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvxl",                         \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_LVEBX:                                                 \
-    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvebx",                        \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_LVEHX:                                                 \
-    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvehx",                        \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_LVEWX:                                                 \
-    MERGE_INT_PTR_OPERAND(0, "llvm.ppc.altivec.lvewx",                        \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_STVX:                                                  \
-    MERGE_INT_PTR_OPERAND(1, "llvm.ppc.altivec.stvx",                         \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_STVEBX:                                                \
-    MERGE_INT_PTR_OPERAND(1, "llvm.ppc.altivec.stvebx",                       \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_STVEHX:                                                \
-    MERGE_INT_PTR_OPERAND(1, "llvm.ppc.altivec.stvehx",                       \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_STVEWX:                                                \
-    MERGE_INT_PTR_OPERAND(1, "llvm.ppc.altivec.stvewx",                       \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_STVXL:                                                 \
-    MERGE_INT_PTR_OPERAND(1, "llvm.ppc.altivec.stvxl",                        \
-                          DESTTY, OPS, CURBB, RESULT);                        \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VSPLTISB:                                              \
-    if (Constant *Elt = dyn_cast<ConstantInt>(OPS[0])) {                      \
-      Elt = ConstantExpr::getIntegerCast(Elt, Type::Int8Ty, true);           \
-      RESULT = BuildVector(Elt, Elt, Elt, Elt,  Elt, Elt, Elt, Elt,           \
-                           Elt, Elt, Elt, Elt,  Elt, Elt, Elt, Elt, NULL);    \
-      return true;                                                            \
-    }                                                                         \
-    return false;                                                             \
-  case ALTIVEC_BUILTIN_VSPLTISH:                                              \
-    if (Constant *Elt = dyn_cast<ConstantInt>(OPS[0])) {                      \
-      Elt = ConstantExpr::getIntegerCast(Elt, Type::Int16Ty, true);           \
-      RESULT = BuildVector(Elt, Elt, Elt, Elt,  Elt, Elt, Elt, Elt, NULL);    \
-      return true;                                                            \
-    }                                                                         \
-    return false;                                                             \
-  case ALTIVEC_BUILTIN_VSPLTISW:                                              \
-    if (Constant *Elt = dyn_cast<ConstantInt>(OPS[0])) {                      \
-      Elt = ConstantExpr::getIntegerCast(Elt, Type::Int32Ty, true);             \
-      RESULT = BuildVector(Elt, Elt, Elt, Elt, NULL);                         \
-      return true;                                                            \
-    }                                                                         \
-    return false;                                                             \
-  case ALTIVEC_BUILTIN_VSPLTB:                                                \
-    if (ConstantInt *Elt = dyn_cast<ConstantInt>(OPS[1])) {                   \
-      int EV = Elt->getZExtValue();                                           \
-      RESULT = BuildVectorShuffle(OPS[0], OPS[0],                             \
-                                  EV, EV, EV, EV, EV, EV, EV, EV,             \
-                                  EV, EV, EV, EV, EV, EV, EV, EV);            \
-      return true;                                                            \
-    }                                                                         \
-    return false;                                                             \
-  case ALTIVEC_BUILTIN_VSPLTH:                                                \
-    if (ConstantInt *Elt = dyn_cast<ConstantInt>(OPS[1])) {                   \
-      int EV = Elt->getZExtValue();                                           \
-      RESULT = BuildVectorShuffle(OPS[0], OPS[0],                             \
-                                  EV, EV, EV, EV, EV, EV, EV, EV);            \
-      return true;                                                            \
-    }                                                                         \
-    return false;                                                             \
-  case ALTIVEC_BUILTIN_VSPLTW:                                                \
-    if (ConstantInt *Elt = dyn_cast<ConstantInt>(OPS[1])) {                   \
-      int EV = Elt->getZExtValue();                                           \
-      RESULT = BuildVectorShuffle(OPS[0], OPS[0], EV, EV, EV, EV);            \
-      return true;                                                            \
-    }                                                                         \
-    return false;                                                             \
-  case ALTIVEC_BUILTIN_VSLDOI_16QI:                                           \
-  case ALTIVEC_BUILTIN_VSLDOI_8HI:                                            \
-  case ALTIVEC_BUILTIN_VSLDOI_4SI:                                            \
-  case ALTIVEC_BUILTIN_VSLDOI_4SF:                                            \
-    if (ConstantInt *Elt = dyn_cast<ConstantInt>(OPS[2])) {                   \
-      /* Map all of these to a shuffle. */                                    \
-      unsigned Amt = Elt->getZExtValue() & 15;                                \
-      PackedType *v16i8 = PackedType::get(Type::Int8Ty, 16);                  \
-      Value *Op0 = OPS[0];                                                    \
-      Instruction::CastOps opc = CastInst::getCastOpcode(Op0,                 \
-        LLVM_INTRINSIC_OP_IS_SIGNED(ARGS,0), DESTTY, false);                  \
-      OPS[0] = CastToType(opc, Op0, v16i8);                                   \
-      Value *Op1 = OPS[1];                                                    \
-      opc = CastInst::getCastOpcode(Op1,                                      \
-        LLVM_INTRINSIC_OP_IS_SIGNED(ARGS,1), DESTTY, false);                  \
-      OPS[1] = CastToType(opc, Op1, v16i8);                                   \
-      RESULT = BuildVectorShuffle(OPS[0], OPS[1],                             \
-                                  Amt, Amt+1, Amt+2, Amt+3,                   \
-                                  Amt+4, Amt+5, Amt+6, Amt+7,                 \
-                                  Amt+8, Amt+9, Amt+10, Amt+11,               \
-                                  Amt+12, Amt+13, Amt+14, Amt+15);            \
-      return true;                                                            \
-    }                                                                         \
-    return false;                                                             \
-  case ALTIVEC_BUILTIN_VPKUHUM: {                                             \
-    Value *Op0 = OPS[0];                                                      \
-    Instruction::CastOps opc = CastInst::getCastOpcode(Op0,                   \
-        LLVM_INTRINSIC_OP_IS_SIGNED(ARGS,0), DESTTY, EXPISSIGNED);            \
-    OPS[0] = CastInst::create(opc, Op0, DESTTY, Op0->getName(), CurBB);       \
-    Value *Op1 = OPS[1];                                                      \
-    opc = CastInst::getCastOpcode(Op1,                                        \
-        LLVM_INTRINSIC_OP_IS_SIGNED(ARGS,1), DESTTY, EXPISSIGNED);            \
-    OPS[1] = CastInst::create(opc, Op1, DESTTY, Op1->getName(), CurBB);       \
-    RESULT = BuildVectorShuffle(OPS[0], OPS[1], 1, 3, 5, 7, 9, 11, 13, 15,    \
-                                17, 19, 21, 23, 25, 27, 29, 31);              \
-    return true;                                                              \
-  }                                                                           \
-  case ALTIVEC_BUILTIN_VPKUWUM: {                                             \
-    Value *Op0 = OPS[0];                                                      \
-    Instruction::CastOps opc = CastInst::getCastOpcode(Op0,                   \
-        LLVM_INTRINSIC_OP_IS_SIGNED(ARGS,0), DESTTY, EXPISSIGNED);            \
-    OPS[0] = CastInst::create(opc, Op0, DESTTY, Op0->getName(), CurBB);       \
-    Value *Op1 = OPS[1];                                                      \
-    opc = CastInst::getCastOpcode(Op1,                                        \
-        LLVM_INTRINSIC_OP_IS_SIGNED(ARGS,1), DESTTY, EXPISSIGNED);            \
-    OPS[1] = CastInst::create(opc, Op1, DESTTY, Op1->getName(), CurBB);       \
-    RESULT = BuildVectorShuffle(OPS[0], OPS[1], 1, 3, 5, 7, 9, 11, 13, 15);   \
-    return true;                                                              \
-  }                                                                           \
-  case ALTIVEC_BUILTIN_VMRGHB:                                                \
-    RESULT = BuildVectorShuffle(OPS[0], OPS[1],                               \
-                                0, 16, 1, 17, 2, 18, 3, 19,                   \
-                                4, 20, 5, 21, 6, 22, 7, 23);                  \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VMRGHH:                                                \
-    RESULT = BuildVectorShuffle(OPS[0], OPS[1], 0, 8, 1, 9, 2, 10, 3, 11);    \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VMRGHW:                                                \
-    RESULT = BuildVectorShuffle(OPS[0], OPS[1], 0, 4, 1, 5);                  \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VMRGLB:                                                \
-    RESULT = BuildVectorShuffle(OPS[0], OPS[1],                               \
-                                 8, 24,  9, 25, 10, 26, 11, 27,               \
-                                12, 28, 13, 29, 14, 30, 15, 31);              \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VMRGLH:                                                \
-    RESULT = BuildVectorShuffle(OPS[0], OPS[1], 4, 12, 5, 13, 6, 14, 7, 15);  \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_VMRGLW:                                                \
-    RESULT = BuildVectorShuffle(OPS[0], OPS[1], 2, 6, 3, 7);                  \
-    return true;                                                              \
-  case ALTIVEC_BUILTIN_ABS_V4SF: {                                            \
-    /* and out sign bits */                                                   \
-    PackedType *v4i32 = PackedType::get(Type::Int32Ty, 4);                      \
-    OPS[0] = new BitCastInst(OPS[0], v4i32, OPS[0]->getName(),CurBB);         \
-    Constant *C = ConstantInt::get(Type::Int32Ty, 0x7FFFFFFF);                  \
-    C = ConstantPacked::get(std::vector<Constant*>(4, C));                    \
-    RESULT = BinaryOperator::createAnd(OPS[0], C, "tmp", CurBB);              \
-    LLVM_TARGET_INTRINSIC_CAST_RESULT(RESULT,RESISSIGNED,DESTTY,EXPISSIGNED); \
-    return true;                                                              \
-  }                                                                           \
-  case ALTIVEC_BUILTIN_ABS_V4SI:                                              \
-  case ALTIVEC_BUILTIN_ABS_V8HI:                                              \
-  case ALTIVEC_BUILTIN_ABS_V16QI: { /* iabs(x) -> smax(x, 0-x) */             \
-    RESULT = BinaryOperator::createNeg(OPS[0], "tmp", CurBB);                 \
-    /* get the right smax intrinsic. */                                       \
-    static Function *smax[3];                                                 \
-    const PackedType *PTy = cast<PackedType>(DESTTY);                         \
-    unsigned N = GET_ALTIVEC_TYPENUM_FROM_TYPE(PTy->getElementType());        \
-    if (smax[N] == 0) {                                                       \
-      Module *M = CURBB->getParent()->getParent();                            \
-      smax[N] = M->getOrInsertFunction(std::string("llvm.ppc.altivec.vmaxs")+ \
-                         GET_ALTIVEC_LETTER_FROM_TYPE(PTy->getElementType()), \
-                                               DESTTY, DESTTY, DESTTY, NULL); \
-    }                                                                         \
-    RESULT = new CallInst(smax[N], OPS[0], RESULT, "tmp", CurBB);             \
-    return true;                                                              \
-  }                                                                           \
-  case ALTIVEC_BUILTIN_ABSS_V4SI:                                             \
-  case ALTIVEC_BUILTIN_ABSS_V8HI:                                             \
-  case ALTIVEC_BUILTIN_ABSS_V16QI: { /* iabss(x) -> smax(x, satsub(0,x)) */   \
-    static Function *sxs[3], *smax[3];                                        \
-    /* get the right satsub intrinsic. */                                     \
-    const PackedType *PTy = cast<PackedType>(DESTTY);                         \
-    unsigned N = GET_ALTIVEC_TYPENUM_FROM_TYPE(PTy->getElementType());        \
-    if (sxs[N] == 0) {                                                        \
-      Module *M = CURBB->getParent()->getParent();                            \
-      sxs[N] = M->getOrInsertFunction(std::string("llvm.ppc.altivec.vsubs")+  \
-                     GET_ALTIVEC_LETTER_FROM_TYPE(PTy->getElementType())+"s", \
-                                               DESTTY, DESTTY, DESTTY, NULL); \
-    }                                                                         \
-    RESULT = Constant::getNullValue(DESTTY);                                  \
-    RESULT = new CallInst(sxs[N], RESULT, OPS[0], "tmp", CurBB);              \
-    /* get the right smax intrinsic. */                                       \
-    if (smax[N] == 0) {                                                       \
-      Module *M = CURBB->getParent()->getParent();                            \
-      smax[N] = M->getOrInsertFunction(std::string("llvm.ppc.altivec.vmaxs")+ \
-                         GET_ALTIVEC_LETTER_FROM_TYPE(PTy->getElementType()), \
-                                               DESTTY, DESTTY, DESTTY, NULL); \
-    }                                                                         \
-    RESULT = new CallInst(smax[N], OPS[0], RESULT, "tmp", CurBB);             \
-    return true;                                                              \
-  }                                                                           \
-  }
+        return TargetIntrinsicLower(BUILTIN_CODE, DESTLOC, RESULT,            \
+                                    DESTTY, OPS, ARGS, CURBB,                 \
+                                    RESISSIGNED, EXPISSIGNED);
 
 /* APPLE LOCAL end LLVM */
