1*f4a2713aSLionel Sambuc //===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===// 2*f4a2713aSLionel Sambuc // 3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4*f4a2713aSLionel Sambuc // 5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7*f4a2713aSLionel Sambuc // 8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9*f4a2713aSLionel Sambuc // 10*f4a2713aSLionel Sambuc // This contains code to emit Builtin calls as LLVM code. 11*f4a2713aSLionel Sambuc // 12*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 13*f4a2713aSLionel Sambuc 14*f4a2713aSLionel Sambuc #include "CodeGenFunction.h" 15*f4a2713aSLionel Sambuc #include "CGObjCRuntime.h" 16*f4a2713aSLionel Sambuc #include "CodeGenModule.h" 17*f4a2713aSLionel Sambuc #include "TargetInfo.h" 18*f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h" 19*f4a2713aSLionel Sambuc #include "clang/AST/Decl.h" 20*f4a2713aSLionel Sambuc #include "clang/Basic/TargetBuiltins.h" 21*f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h" 22*f4a2713aSLionel Sambuc #include "clang/CodeGen/CGFunctionInfo.h" 23*f4a2713aSLionel Sambuc #include "llvm/IR/DataLayout.h" 24*f4a2713aSLionel Sambuc #include "llvm/IR/Intrinsics.h" 25*f4a2713aSLionel Sambuc 26*f4a2713aSLionel Sambuc using namespace clang; 27*f4a2713aSLionel Sambuc using namespace CodeGen; 28*f4a2713aSLionel Sambuc using namespace llvm; 29*f4a2713aSLionel Sambuc 30*f4a2713aSLionel Sambuc /// getBuiltinLibFunction - Given a builtin id for a function like 31*f4a2713aSLionel Sambuc /// "__builtin_fabsf", return a Function* for "fabsf". 32*f4a2713aSLionel Sambuc llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD, 33*f4a2713aSLionel Sambuc unsigned BuiltinID) { 34*f4a2713aSLionel Sambuc assert(Context.BuiltinInfo.isLibFunction(BuiltinID)); 35*f4a2713aSLionel Sambuc 36*f4a2713aSLionel Sambuc // Get the name, skip over the __builtin_ prefix (if necessary). 37*f4a2713aSLionel Sambuc StringRef Name; 38*f4a2713aSLionel Sambuc GlobalDecl D(FD); 39*f4a2713aSLionel Sambuc 40*f4a2713aSLionel Sambuc // If the builtin has been declared explicitly with an assembler label, 41*f4a2713aSLionel Sambuc // use the mangled name. This differs from the plain label on platforms 42*f4a2713aSLionel Sambuc // that prefix labels. 43*f4a2713aSLionel Sambuc if (FD->hasAttr<AsmLabelAttr>()) 44*f4a2713aSLionel Sambuc Name = getMangledName(D); 45*f4a2713aSLionel Sambuc else 46*f4a2713aSLionel Sambuc Name = Context.BuiltinInfo.GetName(BuiltinID) + 10; 47*f4a2713aSLionel Sambuc 48*f4a2713aSLionel Sambuc llvm::FunctionType *Ty = 49*f4a2713aSLionel Sambuc cast<llvm::FunctionType>(getTypes().ConvertType(FD->getType())); 50*f4a2713aSLionel Sambuc 51*f4a2713aSLionel Sambuc return GetOrCreateLLVMFunction(Name, Ty, D, /*ForVTable=*/false); 52*f4a2713aSLionel Sambuc } 53*f4a2713aSLionel Sambuc 54*f4a2713aSLionel Sambuc /// Emit the conversions required to turn the given value into an 55*f4a2713aSLionel Sambuc /// integer of the given size. 56*f4a2713aSLionel Sambuc static Value *EmitToInt(CodeGenFunction &CGF, llvm::Value *V, 57*f4a2713aSLionel Sambuc QualType T, llvm::IntegerType *IntType) { 58*f4a2713aSLionel Sambuc V = CGF.EmitToMemory(V, T); 59*f4a2713aSLionel Sambuc 60*f4a2713aSLionel Sambuc if (V->getType()->isPointerTy()) 61*f4a2713aSLionel Sambuc return CGF.Builder.CreatePtrToInt(V, IntType); 62*f4a2713aSLionel Sambuc 63*f4a2713aSLionel Sambuc assert(V->getType() == IntType); 64*f4a2713aSLionel Sambuc return V; 65*f4a2713aSLionel Sambuc } 66*f4a2713aSLionel Sambuc 67*f4a2713aSLionel Sambuc static Value *EmitFromInt(CodeGenFunction &CGF, llvm::Value *V, 68*f4a2713aSLionel Sambuc QualType T, llvm::Type *ResultType) { 69*f4a2713aSLionel Sambuc V = CGF.EmitFromMemory(V, T); 70*f4a2713aSLionel Sambuc 71*f4a2713aSLionel Sambuc if (ResultType->isPointerTy()) 72*f4a2713aSLionel Sambuc return CGF.Builder.CreateIntToPtr(V, ResultType); 73*f4a2713aSLionel Sambuc 74*f4a2713aSLionel Sambuc assert(V->getType() == ResultType); 75*f4a2713aSLionel Sambuc return V; 76*f4a2713aSLionel Sambuc } 77*f4a2713aSLionel Sambuc 78*f4a2713aSLionel Sambuc /// Utility to insert an atomic instruction based on Instrinsic::ID 79*f4a2713aSLionel Sambuc /// and the expression node. 80*f4a2713aSLionel Sambuc static RValue EmitBinaryAtomic(CodeGenFunction &CGF, 81*f4a2713aSLionel Sambuc llvm::AtomicRMWInst::BinOp Kind, 82*f4a2713aSLionel Sambuc const CallExpr *E) { 83*f4a2713aSLionel Sambuc QualType T = E->getType(); 84*f4a2713aSLionel Sambuc assert(E->getArg(0)->getType()->isPointerType()); 85*f4a2713aSLionel Sambuc assert(CGF.getContext().hasSameUnqualifiedType(T, 86*f4a2713aSLionel Sambuc E->getArg(0)->getType()->getPointeeType())); 87*f4a2713aSLionel Sambuc assert(CGF.getContext().hasSameUnqualifiedType(T, E->getArg(1)->getType())); 88*f4a2713aSLionel Sambuc 89*f4a2713aSLionel Sambuc llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0)); 90*f4a2713aSLionel Sambuc unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); 91*f4a2713aSLionel Sambuc 92*f4a2713aSLionel Sambuc llvm::IntegerType *IntType = 93*f4a2713aSLionel Sambuc llvm::IntegerType::get(CGF.getLLVMContext(), 94*f4a2713aSLionel Sambuc CGF.getContext().getTypeSize(T)); 95*f4a2713aSLionel Sambuc llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); 96*f4a2713aSLionel Sambuc 97*f4a2713aSLionel Sambuc llvm::Value *Args[2]; 98*f4a2713aSLionel Sambuc Args[0] = CGF.Builder.CreateBitCast(DestPtr, IntPtrType); 99*f4a2713aSLionel Sambuc Args[1] = CGF.EmitScalarExpr(E->getArg(1)); 100*f4a2713aSLionel Sambuc llvm::Type *ValueType = Args[1]->getType(); 101*f4a2713aSLionel Sambuc Args[1] = EmitToInt(CGF, Args[1], T, IntType); 102*f4a2713aSLionel Sambuc 103*f4a2713aSLionel Sambuc llvm::Value *Result = 104*f4a2713aSLionel Sambuc CGF.Builder.CreateAtomicRMW(Kind, Args[0], Args[1], 105*f4a2713aSLionel Sambuc llvm::SequentiallyConsistent); 106*f4a2713aSLionel Sambuc Result = EmitFromInt(CGF, Result, T, ValueType); 107*f4a2713aSLionel Sambuc return RValue::get(Result); 108*f4a2713aSLionel Sambuc } 109*f4a2713aSLionel Sambuc 110*f4a2713aSLionel Sambuc /// Utility to insert an atomic instruction based Instrinsic::ID and 111*f4a2713aSLionel Sambuc /// the expression node, where the return value is the result of the 112*f4a2713aSLionel Sambuc /// operation. 113*f4a2713aSLionel Sambuc static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF, 114*f4a2713aSLionel Sambuc llvm::AtomicRMWInst::BinOp Kind, 115*f4a2713aSLionel Sambuc const CallExpr *E, 116*f4a2713aSLionel Sambuc Instruction::BinaryOps Op) { 117*f4a2713aSLionel Sambuc QualType T = E->getType(); 118*f4a2713aSLionel Sambuc assert(E->getArg(0)->getType()->isPointerType()); 119*f4a2713aSLionel Sambuc assert(CGF.getContext().hasSameUnqualifiedType(T, 120*f4a2713aSLionel Sambuc E->getArg(0)->getType()->getPointeeType())); 121*f4a2713aSLionel Sambuc assert(CGF.getContext().hasSameUnqualifiedType(T, E->getArg(1)->getType())); 122*f4a2713aSLionel Sambuc 123*f4a2713aSLionel Sambuc llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0)); 124*f4a2713aSLionel Sambuc unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); 125*f4a2713aSLionel Sambuc 126*f4a2713aSLionel Sambuc llvm::IntegerType *IntType = 127*f4a2713aSLionel Sambuc llvm::IntegerType::get(CGF.getLLVMContext(), 128*f4a2713aSLionel Sambuc CGF.getContext().getTypeSize(T)); 129*f4a2713aSLionel Sambuc llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); 130*f4a2713aSLionel Sambuc 131*f4a2713aSLionel Sambuc llvm::Value *Args[2]; 132*f4a2713aSLionel Sambuc Args[1] = CGF.EmitScalarExpr(E->getArg(1)); 133*f4a2713aSLionel Sambuc llvm::Type *ValueType = Args[1]->getType(); 134*f4a2713aSLionel Sambuc Args[1] = EmitToInt(CGF, Args[1], T, IntType); 135*f4a2713aSLionel Sambuc Args[0] = CGF.Builder.CreateBitCast(DestPtr, IntPtrType); 136*f4a2713aSLionel Sambuc 137*f4a2713aSLionel Sambuc llvm::Value *Result = 138*f4a2713aSLionel Sambuc CGF.Builder.CreateAtomicRMW(Kind, Args[0], Args[1], 139*f4a2713aSLionel Sambuc llvm::SequentiallyConsistent); 140*f4a2713aSLionel Sambuc Result = CGF.Builder.CreateBinOp(Op, Result, Args[1]); 141*f4a2713aSLionel Sambuc Result = EmitFromInt(CGF, Result, T, ValueType); 142*f4a2713aSLionel Sambuc return RValue::get(Result); 143*f4a2713aSLionel Sambuc } 144*f4a2713aSLionel Sambuc 145*f4a2713aSLionel Sambuc /// EmitFAbs - Emit a call to fabs/fabsf/fabsl, depending on the type of ValTy, 146*f4a2713aSLionel Sambuc /// which must be a scalar floating point type. 147*f4a2713aSLionel Sambuc static Value *EmitFAbs(CodeGenFunction &CGF, Value *V, QualType ValTy) { 148*f4a2713aSLionel Sambuc const BuiltinType *ValTyP = ValTy->getAs<BuiltinType>(); 149*f4a2713aSLionel Sambuc assert(ValTyP && "isn't scalar fp type!"); 150*f4a2713aSLionel Sambuc 151*f4a2713aSLionel Sambuc StringRef FnName; 152*f4a2713aSLionel Sambuc switch (ValTyP->getKind()) { 153*f4a2713aSLionel Sambuc default: llvm_unreachable("Isn't a scalar fp type!"); 154*f4a2713aSLionel Sambuc case BuiltinType::Float: FnName = "fabsf"; break; 155*f4a2713aSLionel Sambuc case BuiltinType::Double: FnName = "fabs"; break; 156*f4a2713aSLionel Sambuc case BuiltinType::LongDouble: FnName = "fabsl"; break; 157*f4a2713aSLionel Sambuc } 158*f4a2713aSLionel Sambuc 159*f4a2713aSLionel Sambuc // The prototype is something that takes and returns whatever V's type is. 160*f4a2713aSLionel Sambuc llvm::FunctionType *FT = llvm::FunctionType::get(V->getType(), V->getType(), 161*f4a2713aSLionel Sambuc false); 162*f4a2713aSLionel Sambuc llvm::Value *Fn = CGF.CGM.CreateRuntimeFunction(FT, FnName); 163*f4a2713aSLionel Sambuc 164*f4a2713aSLionel Sambuc return CGF.EmitNounwindRuntimeCall(Fn, V, "abs"); 165*f4a2713aSLionel Sambuc } 166*f4a2713aSLionel Sambuc 167*f4a2713aSLionel Sambuc static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *Fn, 168*f4a2713aSLionel Sambuc const CallExpr *E, llvm::Value *calleeValue) { 169*f4a2713aSLionel Sambuc return CGF.EmitCall(E->getCallee()->getType(), calleeValue, E->getLocStart(), 170*f4a2713aSLionel Sambuc ReturnValueSlot(), E->arg_begin(), E->arg_end(), Fn); 171*f4a2713aSLionel Sambuc } 172*f4a2713aSLionel Sambuc 173*f4a2713aSLionel Sambuc /// \brief Emit a call to llvm.{sadd,uadd,ssub,usub,smul,umul}.with.overflow.* 174*f4a2713aSLionel Sambuc /// depending on IntrinsicID. 175*f4a2713aSLionel Sambuc /// 176*f4a2713aSLionel Sambuc /// \arg CGF The current codegen function. 177*f4a2713aSLionel Sambuc /// \arg IntrinsicID The ID for the Intrinsic we wish to generate. 178*f4a2713aSLionel Sambuc /// \arg X The first argument to the llvm.*.with.overflow.*. 179*f4a2713aSLionel Sambuc /// \arg Y The second argument to the llvm.*.with.overflow.*. 180*f4a2713aSLionel Sambuc /// \arg Carry The carry returned by the llvm.*.with.overflow.*. 181*f4a2713aSLionel Sambuc /// \returns The result (i.e. sum/product) returned by the intrinsic. 182*f4a2713aSLionel Sambuc static llvm::Value *EmitOverflowIntrinsic(CodeGenFunction &CGF, 183*f4a2713aSLionel Sambuc const llvm::Intrinsic::ID IntrinsicID, 184*f4a2713aSLionel Sambuc llvm::Value *X, llvm::Value *Y, 185*f4a2713aSLionel Sambuc llvm::Value *&Carry) { 186*f4a2713aSLionel Sambuc // Make sure we have integers of the same width. 187*f4a2713aSLionel Sambuc assert(X->getType() == Y->getType() && 188*f4a2713aSLionel Sambuc "Arguments must be the same type. (Did you forget to make sure both " 189*f4a2713aSLionel Sambuc "arguments have the same integer width?)"); 190*f4a2713aSLionel Sambuc 191*f4a2713aSLionel Sambuc llvm::Value *Callee = CGF.CGM.getIntrinsic(IntrinsicID, X->getType()); 192*f4a2713aSLionel Sambuc llvm::Value *Tmp = CGF.Builder.CreateCall2(Callee, X, Y); 193*f4a2713aSLionel Sambuc Carry = CGF.Builder.CreateExtractValue(Tmp, 1); 194*f4a2713aSLionel Sambuc return CGF.Builder.CreateExtractValue(Tmp, 0); 195*f4a2713aSLionel Sambuc } 196*f4a2713aSLionel Sambuc 197*f4a2713aSLionel Sambuc RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, 198*f4a2713aSLionel Sambuc unsigned BuiltinID, const CallExpr *E) { 199*f4a2713aSLionel Sambuc // See if we can constant fold this builtin. If so, don't emit it at all. 200*f4a2713aSLionel Sambuc Expr::EvalResult Result; 201*f4a2713aSLionel Sambuc if (E->EvaluateAsRValue(Result, CGM.getContext()) && 202*f4a2713aSLionel Sambuc !Result.hasSideEffects()) { 203*f4a2713aSLionel Sambuc if (Result.Val.isInt()) 204*f4a2713aSLionel Sambuc return RValue::get(llvm::ConstantInt::get(getLLVMContext(), 205*f4a2713aSLionel Sambuc Result.Val.getInt())); 206*f4a2713aSLionel Sambuc if (Result.Val.isFloat()) 207*f4a2713aSLionel Sambuc return RValue::get(llvm::ConstantFP::get(getLLVMContext(), 208*f4a2713aSLionel Sambuc Result.Val.getFloat())); 209*f4a2713aSLionel Sambuc } 210*f4a2713aSLionel Sambuc 211*f4a2713aSLionel Sambuc switch (BuiltinID) { 212*f4a2713aSLionel Sambuc default: break; // Handle intrinsics and libm functions below. 213*f4a2713aSLionel Sambuc case Builtin::BI__builtin___CFStringMakeConstantString: 214*f4a2713aSLionel Sambuc case Builtin::BI__builtin___NSStringMakeConstantString: 215*f4a2713aSLionel Sambuc return RValue::get(CGM.EmitConstantExpr(E, E->getType(), 0)); 216*f4a2713aSLionel Sambuc case Builtin::BI__builtin_stdarg_start: 217*f4a2713aSLionel Sambuc case Builtin::BI__builtin_va_start: 218*f4a2713aSLionel Sambuc case Builtin::BI__builtin_va_end: { 219*f4a2713aSLionel Sambuc Value *ArgValue = EmitVAListRef(E->getArg(0)); 220*f4a2713aSLionel Sambuc llvm::Type *DestType = Int8PtrTy; 221*f4a2713aSLionel Sambuc if (ArgValue->getType() != DestType) 222*f4a2713aSLionel Sambuc ArgValue = Builder.CreateBitCast(ArgValue, DestType, 223*f4a2713aSLionel Sambuc ArgValue->getName().data()); 224*f4a2713aSLionel Sambuc 225*f4a2713aSLionel Sambuc Intrinsic::ID inst = (BuiltinID == Builtin::BI__builtin_va_end) ? 226*f4a2713aSLionel Sambuc Intrinsic::vaend : Intrinsic::vastart; 227*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue)); 228*f4a2713aSLionel Sambuc } 229*f4a2713aSLionel Sambuc case Builtin::BI__builtin_va_copy: { 230*f4a2713aSLionel Sambuc Value *DstPtr = EmitVAListRef(E->getArg(0)); 231*f4a2713aSLionel Sambuc Value *SrcPtr = EmitVAListRef(E->getArg(1)); 232*f4a2713aSLionel Sambuc 233*f4a2713aSLionel Sambuc llvm::Type *Type = Int8PtrTy; 234*f4a2713aSLionel Sambuc 235*f4a2713aSLionel Sambuc DstPtr = Builder.CreateBitCast(DstPtr, Type); 236*f4a2713aSLionel Sambuc SrcPtr = Builder.CreateBitCast(SrcPtr, Type); 237*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall2(CGM.getIntrinsic(Intrinsic::vacopy), 238*f4a2713aSLionel Sambuc DstPtr, SrcPtr)); 239*f4a2713aSLionel Sambuc } 240*f4a2713aSLionel Sambuc case Builtin::BI__builtin_abs: 241*f4a2713aSLionel Sambuc case Builtin::BI__builtin_labs: 242*f4a2713aSLionel Sambuc case Builtin::BI__builtin_llabs: { 243*f4a2713aSLionel Sambuc Value *ArgValue = EmitScalarExpr(E->getArg(0)); 244*f4a2713aSLionel Sambuc 245*f4a2713aSLionel Sambuc Value *NegOp = Builder.CreateNeg(ArgValue, "neg"); 246*f4a2713aSLionel Sambuc Value *CmpResult = 247*f4a2713aSLionel Sambuc Builder.CreateICmpSGE(ArgValue, 248*f4a2713aSLionel Sambuc llvm::Constant::getNullValue(ArgValue->getType()), 249*f4a2713aSLionel Sambuc "abscond"); 250*f4a2713aSLionel Sambuc Value *Result = 251*f4a2713aSLionel Sambuc Builder.CreateSelect(CmpResult, ArgValue, NegOp, "abs"); 252*f4a2713aSLionel Sambuc 253*f4a2713aSLionel Sambuc return RValue::get(Result); 254*f4a2713aSLionel Sambuc } 255*f4a2713aSLionel Sambuc 256*f4a2713aSLionel Sambuc case Builtin::BI__builtin_conj: 257*f4a2713aSLionel Sambuc case Builtin::BI__builtin_conjf: 258*f4a2713aSLionel Sambuc case Builtin::BI__builtin_conjl: { 259*f4a2713aSLionel Sambuc ComplexPairTy ComplexVal = EmitComplexExpr(E->getArg(0)); 260*f4a2713aSLionel Sambuc Value *Real = ComplexVal.first; 261*f4a2713aSLionel Sambuc Value *Imag = ComplexVal.second; 262*f4a2713aSLionel Sambuc Value *Zero = 263*f4a2713aSLionel Sambuc Imag->getType()->isFPOrFPVectorTy() 264*f4a2713aSLionel Sambuc ? llvm::ConstantFP::getZeroValueForNegation(Imag->getType()) 265*f4a2713aSLionel Sambuc : llvm::Constant::getNullValue(Imag->getType()); 266*f4a2713aSLionel Sambuc 267*f4a2713aSLionel Sambuc Imag = Builder.CreateFSub(Zero, Imag, "sub"); 268*f4a2713aSLionel Sambuc return RValue::getComplex(std::make_pair(Real, Imag)); 269*f4a2713aSLionel Sambuc } 270*f4a2713aSLionel Sambuc case Builtin::BI__builtin_creal: 271*f4a2713aSLionel Sambuc case Builtin::BI__builtin_crealf: 272*f4a2713aSLionel Sambuc case Builtin::BI__builtin_creall: 273*f4a2713aSLionel Sambuc case Builtin::BIcreal: 274*f4a2713aSLionel Sambuc case Builtin::BIcrealf: 275*f4a2713aSLionel Sambuc case Builtin::BIcreall: { 276*f4a2713aSLionel Sambuc ComplexPairTy ComplexVal = EmitComplexExpr(E->getArg(0)); 277*f4a2713aSLionel Sambuc return RValue::get(ComplexVal.first); 278*f4a2713aSLionel Sambuc } 279*f4a2713aSLionel Sambuc 280*f4a2713aSLionel Sambuc case Builtin::BI__builtin_cimag: 281*f4a2713aSLionel Sambuc case Builtin::BI__builtin_cimagf: 282*f4a2713aSLionel Sambuc case Builtin::BI__builtin_cimagl: 283*f4a2713aSLionel Sambuc case Builtin::BIcimag: 284*f4a2713aSLionel Sambuc case Builtin::BIcimagf: 285*f4a2713aSLionel Sambuc case Builtin::BIcimagl: { 286*f4a2713aSLionel Sambuc ComplexPairTy ComplexVal = EmitComplexExpr(E->getArg(0)); 287*f4a2713aSLionel Sambuc return RValue::get(ComplexVal.second); 288*f4a2713aSLionel Sambuc } 289*f4a2713aSLionel Sambuc 290*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ctzs: 291*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ctz: 292*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ctzl: 293*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ctzll: { 294*f4a2713aSLionel Sambuc Value *ArgValue = EmitScalarExpr(E->getArg(0)); 295*f4a2713aSLionel Sambuc 296*f4a2713aSLionel Sambuc llvm::Type *ArgType = ArgValue->getType(); 297*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType); 298*f4a2713aSLionel Sambuc 299*f4a2713aSLionel Sambuc llvm::Type *ResultType = ConvertType(E->getType()); 300*f4a2713aSLionel Sambuc Value *ZeroUndef = Builder.getInt1(getTarget().isCLZForZeroUndef()); 301*f4a2713aSLionel Sambuc Value *Result = Builder.CreateCall2(F, ArgValue, ZeroUndef); 302*f4a2713aSLionel Sambuc if (Result->getType() != ResultType) 303*f4a2713aSLionel Sambuc Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, 304*f4a2713aSLionel Sambuc "cast"); 305*f4a2713aSLionel Sambuc return RValue::get(Result); 306*f4a2713aSLionel Sambuc } 307*f4a2713aSLionel Sambuc case Builtin::BI__builtin_clzs: 308*f4a2713aSLionel Sambuc case Builtin::BI__builtin_clz: 309*f4a2713aSLionel Sambuc case Builtin::BI__builtin_clzl: 310*f4a2713aSLionel Sambuc case Builtin::BI__builtin_clzll: { 311*f4a2713aSLionel Sambuc Value *ArgValue = EmitScalarExpr(E->getArg(0)); 312*f4a2713aSLionel Sambuc 313*f4a2713aSLionel Sambuc llvm::Type *ArgType = ArgValue->getType(); 314*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType); 315*f4a2713aSLionel Sambuc 316*f4a2713aSLionel Sambuc llvm::Type *ResultType = ConvertType(E->getType()); 317*f4a2713aSLionel Sambuc Value *ZeroUndef = Builder.getInt1(getTarget().isCLZForZeroUndef()); 318*f4a2713aSLionel Sambuc Value *Result = Builder.CreateCall2(F, ArgValue, ZeroUndef); 319*f4a2713aSLionel Sambuc if (Result->getType() != ResultType) 320*f4a2713aSLionel Sambuc Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, 321*f4a2713aSLionel Sambuc "cast"); 322*f4a2713aSLionel Sambuc return RValue::get(Result); 323*f4a2713aSLionel Sambuc } 324*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ffs: 325*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ffsl: 326*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ffsll: { 327*f4a2713aSLionel Sambuc // ffs(x) -> x ? cttz(x) + 1 : 0 328*f4a2713aSLionel Sambuc Value *ArgValue = EmitScalarExpr(E->getArg(0)); 329*f4a2713aSLionel Sambuc 330*f4a2713aSLionel Sambuc llvm::Type *ArgType = ArgValue->getType(); 331*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType); 332*f4a2713aSLionel Sambuc 333*f4a2713aSLionel Sambuc llvm::Type *ResultType = ConvertType(E->getType()); 334*f4a2713aSLionel Sambuc Value *Tmp = Builder.CreateAdd(Builder.CreateCall2(F, ArgValue, 335*f4a2713aSLionel Sambuc Builder.getTrue()), 336*f4a2713aSLionel Sambuc llvm::ConstantInt::get(ArgType, 1)); 337*f4a2713aSLionel Sambuc Value *Zero = llvm::Constant::getNullValue(ArgType); 338*f4a2713aSLionel Sambuc Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero, "iszero"); 339*f4a2713aSLionel Sambuc Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp, "ffs"); 340*f4a2713aSLionel Sambuc if (Result->getType() != ResultType) 341*f4a2713aSLionel Sambuc Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, 342*f4a2713aSLionel Sambuc "cast"); 343*f4a2713aSLionel Sambuc return RValue::get(Result); 344*f4a2713aSLionel Sambuc } 345*f4a2713aSLionel Sambuc case Builtin::BI__builtin_parity: 346*f4a2713aSLionel Sambuc case Builtin::BI__builtin_parityl: 347*f4a2713aSLionel Sambuc case Builtin::BI__builtin_parityll: { 348*f4a2713aSLionel Sambuc // parity(x) -> ctpop(x) & 1 349*f4a2713aSLionel Sambuc Value *ArgValue = EmitScalarExpr(E->getArg(0)); 350*f4a2713aSLionel Sambuc 351*f4a2713aSLionel Sambuc llvm::Type *ArgType = ArgValue->getType(); 352*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType); 353*f4a2713aSLionel Sambuc 354*f4a2713aSLionel Sambuc llvm::Type *ResultType = ConvertType(E->getType()); 355*f4a2713aSLionel Sambuc Value *Tmp = Builder.CreateCall(F, ArgValue); 356*f4a2713aSLionel Sambuc Value *Result = Builder.CreateAnd(Tmp, llvm::ConstantInt::get(ArgType, 1)); 357*f4a2713aSLionel Sambuc if (Result->getType() != ResultType) 358*f4a2713aSLionel Sambuc Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, 359*f4a2713aSLionel Sambuc "cast"); 360*f4a2713aSLionel Sambuc return RValue::get(Result); 361*f4a2713aSLionel Sambuc } 362*f4a2713aSLionel Sambuc case Builtin::BI__builtin_popcount: 363*f4a2713aSLionel Sambuc case Builtin::BI__builtin_popcountl: 364*f4a2713aSLionel Sambuc case Builtin::BI__builtin_popcountll: { 365*f4a2713aSLionel Sambuc Value *ArgValue = EmitScalarExpr(E->getArg(0)); 366*f4a2713aSLionel Sambuc 367*f4a2713aSLionel Sambuc llvm::Type *ArgType = ArgValue->getType(); 368*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType); 369*f4a2713aSLionel Sambuc 370*f4a2713aSLionel Sambuc llvm::Type *ResultType = ConvertType(E->getType()); 371*f4a2713aSLionel Sambuc Value *Result = Builder.CreateCall(F, ArgValue); 372*f4a2713aSLionel Sambuc if (Result->getType() != ResultType) 373*f4a2713aSLionel Sambuc Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, 374*f4a2713aSLionel Sambuc "cast"); 375*f4a2713aSLionel Sambuc return RValue::get(Result); 376*f4a2713aSLionel Sambuc } 377*f4a2713aSLionel Sambuc case Builtin::BI__builtin_expect: { 378*f4a2713aSLionel Sambuc Value *ArgValue = EmitScalarExpr(E->getArg(0)); 379*f4a2713aSLionel Sambuc llvm::Type *ArgType = ArgValue->getType(); 380*f4a2713aSLionel Sambuc 381*f4a2713aSLionel Sambuc Value *FnExpect = CGM.getIntrinsic(Intrinsic::expect, ArgType); 382*f4a2713aSLionel Sambuc Value *ExpectedValue = EmitScalarExpr(E->getArg(1)); 383*f4a2713aSLionel Sambuc 384*f4a2713aSLionel Sambuc Value *Result = Builder.CreateCall2(FnExpect, ArgValue, ExpectedValue, 385*f4a2713aSLionel Sambuc "expval"); 386*f4a2713aSLionel Sambuc return RValue::get(Result); 387*f4a2713aSLionel Sambuc } 388*f4a2713aSLionel Sambuc case Builtin::BI__builtin_bswap16: 389*f4a2713aSLionel Sambuc case Builtin::BI__builtin_bswap32: 390*f4a2713aSLionel Sambuc case Builtin::BI__builtin_bswap64: { 391*f4a2713aSLionel Sambuc Value *ArgValue = EmitScalarExpr(E->getArg(0)); 392*f4a2713aSLionel Sambuc llvm::Type *ArgType = ArgValue->getType(); 393*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::bswap, ArgType); 394*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall(F, ArgValue)); 395*f4a2713aSLionel Sambuc } 396*f4a2713aSLionel Sambuc case Builtin::BI__builtin_object_size: { 397*f4a2713aSLionel Sambuc // We rely on constant folding to deal with expressions with side effects. 398*f4a2713aSLionel Sambuc assert(!E->getArg(0)->HasSideEffects(getContext()) && 399*f4a2713aSLionel Sambuc "should have been constant folded"); 400*f4a2713aSLionel Sambuc 401*f4a2713aSLionel Sambuc // We pass this builtin onto the optimizer so that it can 402*f4a2713aSLionel Sambuc // figure out the object size in more complex cases. 403*f4a2713aSLionel Sambuc llvm::Type *ResType = ConvertType(E->getType()); 404*f4a2713aSLionel Sambuc 405*f4a2713aSLionel Sambuc // LLVM only supports 0 and 2, make sure that we pass along that 406*f4a2713aSLionel Sambuc // as a boolean. 407*f4a2713aSLionel Sambuc Value *Ty = EmitScalarExpr(E->getArg(1)); 408*f4a2713aSLionel Sambuc ConstantInt *CI = dyn_cast<ConstantInt>(Ty); 409*f4a2713aSLionel Sambuc assert(CI); 410*f4a2713aSLionel Sambuc uint64_t val = CI->getZExtValue(); 411*f4a2713aSLionel Sambuc CI = ConstantInt::get(Builder.getInt1Ty(), (val & 0x2) >> 1); 412*f4a2713aSLionel Sambuc // FIXME: Get right address space. 413*f4a2713aSLionel Sambuc llvm::Type *Tys[] = { ResType, Builder.getInt8PtrTy(0) }; 414*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::objectsize, Tys); 415*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall2(F, EmitScalarExpr(E->getArg(0)),CI)); 416*f4a2713aSLionel Sambuc } 417*f4a2713aSLionel Sambuc case Builtin::BI__builtin_prefetch: { 418*f4a2713aSLionel Sambuc Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0)); 419*f4a2713aSLionel Sambuc // FIXME: Technically these constants should of type 'int', yes? 420*f4a2713aSLionel Sambuc RW = (E->getNumArgs() > 1) ? EmitScalarExpr(E->getArg(1)) : 421*f4a2713aSLionel Sambuc llvm::ConstantInt::get(Int32Ty, 0); 422*f4a2713aSLionel Sambuc Locality = (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) : 423*f4a2713aSLionel Sambuc llvm::ConstantInt::get(Int32Ty, 3); 424*f4a2713aSLionel Sambuc Value *Data = llvm::ConstantInt::get(Int32Ty, 1); 425*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::prefetch); 426*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall4(F, Address, RW, Locality, Data)); 427*f4a2713aSLionel Sambuc } 428*f4a2713aSLionel Sambuc case Builtin::BI__builtin_readcyclecounter: { 429*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::readcyclecounter); 430*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall(F)); 431*f4a2713aSLionel Sambuc } 432*f4a2713aSLionel Sambuc case Builtin::BI__builtin_trap: { 433*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::trap); 434*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall(F)); 435*f4a2713aSLionel Sambuc } 436*f4a2713aSLionel Sambuc case Builtin::BI__debugbreak: { 437*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::debugtrap); 438*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall(F)); 439*f4a2713aSLionel Sambuc } 440*f4a2713aSLionel Sambuc case Builtin::BI__builtin_unreachable: { 441*f4a2713aSLionel Sambuc if (SanOpts->Unreachable) 442*f4a2713aSLionel Sambuc EmitCheck(Builder.getFalse(), "builtin_unreachable", 443*f4a2713aSLionel Sambuc EmitCheckSourceLocation(E->getExprLoc()), 444*f4a2713aSLionel Sambuc ArrayRef<llvm::Value *>(), CRK_Unrecoverable); 445*f4a2713aSLionel Sambuc else 446*f4a2713aSLionel Sambuc Builder.CreateUnreachable(); 447*f4a2713aSLionel Sambuc 448*f4a2713aSLionel Sambuc // We do need to preserve an insertion point. 449*f4a2713aSLionel Sambuc EmitBlock(createBasicBlock("unreachable.cont")); 450*f4a2713aSLionel Sambuc 451*f4a2713aSLionel Sambuc return RValue::get(0); 452*f4a2713aSLionel Sambuc } 453*f4a2713aSLionel Sambuc 454*f4a2713aSLionel Sambuc case Builtin::BI__builtin_powi: 455*f4a2713aSLionel Sambuc case Builtin::BI__builtin_powif: 456*f4a2713aSLionel Sambuc case Builtin::BI__builtin_powil: { 457*f4a2713aSLionel Sambuc Value *Base = EmitScalarExpr(E->getArg(0)); 458*f4a2713aSLionel Sambuc Value *Exponent = EmitScalarExpr(E->getArg(1)); 459*f4a2713aSLionel Sambuc llvm::Type *ArgType = Base->getType(); 460*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::powi, ArgType); 461*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall2(F, Base, Exponent)); 462*f4a2713aSLionel Sambuc } 463*f4a2713aSLionel Sambuc 464*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isgreater: 465*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isgreaterequal: 466*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isless: 467*f4a2713aSLionel Sambuc case Builtin::BI__builtin_islessequal: 468*f4a2713aSLionel Sambuc case Builtin::BI__builtin_islessgreater: 469*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isunordered: { 470*f4a2713aSLionel Sambuc // Ordered comparisons: we know the arguments to these are matching scalar 471*f4a2713aSLionel Sambuc // floating point values. 472*f4a2713aSLionel Sambuc Value *LHS = EmitScalarExpr(E->getArg(0)); 473*f4a2713aSLionel Sambuc Value *RHS = EmitScalarExpr(E->getArg(1)); 474*f4a2713aSLionel Sambuc 475*f4a2713aSLionel Sambuc switch (BuiltinID) { 476*f4a2713aSLionel Sambuc default: llvm_unreachable("Unknown ordered comparison"); 477*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isgreater: 478*f4a2713aSLionel Sambuc LHS = Builder.CreateFCmpOGT(LHS, RHS, "cmp"); 479*f4a2713aSLionel Sambuc break; 480*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isgreaterequal: 481*f4a2713aSLionel Sambuc LHS = Builder.CreateFCmpOGE(LHS, RHS, "cmp"); 482*f4a2713aSLionel Sambuc break; 483*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isless: 484*f4a2713aSLionel Sambuc LHS = Builder.CreateFCmpOLT(LHS, RHS, "cmp"); 485*f4a2713aSLionel Sambuc break; 486*f4a2713aSLionel Sambuc case Builtin::BI__builtin_islessequal: 487*f4a2713aSLionel Sambuc LHS = Builder.CreateFCmpOLE(LHS, RHS, "cmp"); 488*f4a2713aSLionel Sambuc break; 489*f4a2713aSLionel Sambuc case Builtin::BI__builtin_islessgreater: 490*f4a2713aSLionel Sambuc LHS = Builder.CreateFCmpONE(LHS, RHS, "cmp"); 491*f4a2713aSLionel Sambuc break; 492*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isunordered: 493*f4a2713aSLionel Sambuc LHS = Builder.CreateFCmpUNO(LHS, RHS, "cmp"); 494*f4a2713aSLionel Sambuc break; 495*f4a2713aSLionel Sambuc } 496*f4a2713aSLionel Sambuc // ZExt bool to int type. 497*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateZExt(LHS, ConvertType(E->getType()))); 498*f4a2713aSLionel Sambuc } 499*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isnan: { 500*f4a2713aSLionel Sambuc Value *V = EmitScalarExpr(E->getArg(0)); 501*f4a2713aSLionel Sambuc V = Builder.CreateFCmpUNO(V, V, "cmp"); 502*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()))); 503*f4a2713aSLionel Sambuc } 504*f4a2713aSLionel Sambuc 505*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isinf: { 506*f4a2713aSLionel Sambuc // isinf(x) --> fabs(x) == infinity 507*f4a2713aSLionel Sambuc Value *V = EmitScalarExpr(E->getArg(0)); 508*f4a2713aSLionel Sambuc V = EmitFAbs(*this, V, E->getArg(0)->getType()); 509*f4a2713aSLionel Sambuc 510*f4a2713aSLionel Sambuc V = Builder.CreateFCmpOEQ(V, ConstantFP::getInfinity(V->getType()),"isinf"); 511*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()))); 512*f4a2713aSLionel Sambuc } 513*f4a2713aSLionel Sambuc 514*f4a2713aSLionel Sambuc // TODO: BI__builtin_isinf_sign 515*f4a2713aSLionel Sambuc // isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 516*f4a2713aSLionel Sambuc 517*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isnormal: { 518*f4a2713aSLionel Sambuc // isnormal(x) --> x == x && fabsf(x) < infinity && fabsf(x) >= float_min 519*f4a2713aSLionel Sambuc Value *V = EmitScalarExpr(E->getArg(0)); 520*f4a2713aSLionel Sambuc Value *Eq = Builder.CreateFCmpOEQ(V, V, "iseq"); 521*f4a2713aSLionel Sambuc 522*f4a2713aSLionel Sambuc Value *Abs = EmitFAbs(*this, V, E->getArg(0)->getType()); 523*f4a2713aSLionel Sambuc Value *IsLessThanInf = 524*f4a2713aSLionel Sambuc Builder.CreateFCmpULT(Abs, ConstantFP::getInfinity(V->getType()),"isinf"); 525*f4a2713aSLionel Sambuc APFloat Smallest = APFloat::getSmallestNormalized( 526*f4a2713aSLionel Sambuc getContext().getFloatTypeSemantics(E->getArg(0)->getType())); 527*f4a2713aSLionel Sambuc Value *IsNormal = 528*f4a2713aSLionel Sambuc Builder.CreateFCmpUGE(Abs, ConstantFP::get(V->getContext(), Smallest), 529*f4a2713aSLionel Sambuc "isnormal"); 530*f4a2713aSLionel Sambuc V = Builder.CreateAnd(Eq, IsLessThanInf, "and"); 531*f4a2713aSLionel Sambuc V = Builder.CreateAnd(V, IsNormal, "and"); 532*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()))); 533*f4a2713aSLionel Sambuc } 534*f4a2713aSLionel Sambuc 535*f4a2713aSLionel Sambuc case Builtin::BI__builtin_isfinite: { 536*f4a2713aSLionel Sambuc // isfinite(x) --> x == x && fabs(x) != infinity; 537*f4a2713aSLionel Sambuc Value *V = EmitScalarExpr(E->getArg(0)); 538*f4a2713aSLionel Sambuc Value *Eq = Builder.CreateFCmpOEQ(V, V, "iseq"); 539*f4a2713aSLionel Sambuc 540*f4a2713aSLionel Sambuc Value *Abs = EmitFAbs(*this, V, E->getArg(0)->getType()); 541*f4a2713aSLionel Sambuc Value *IsNotInf = 542*f4a2713aSLionel Sambuc Builder.CreateFCmpUNE(Abs, ConstantFP::getInfinity(V->getType()),"isinf"); 543*f4a2713aSLionel Sambuc 544*f4a2713aSLionel Sambuc V = Builder.CreateAnd(Eq, IsNotInf, "and"); 545*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()))); 546*f4a2713aSLionel Sambuc } 547*f4a2713aSLionel Sambuc 548*f4a2713aSLionel Sambuc case Builtin::BI__builtin_fpclassify: { 549*f4a2713aSLionel Sambuc Value *V = EmitScalarExpr(E->getArg(5)); 550*f4a2713aSLionel Sambuc llvm::Type *Ty = ConvertType(E->getArg(5)->getType()); 551*f4a2713aSLionel Sambuc 552*f4a2713aSLionel Sambuc // Create Result 553*f4a2713aSLionel Sambuc BasicBlock *Begin = Builder.GetInsertBlock(); 554*f4a2713aSLionel Sambuc BasicBlock *End = createBasicBlock("fpclassify_end", this->CurFn); 555*f4a2713aSLionel Sambuc Builder.SetInsertPoint(End); 556*f4a2713aSLionel Sambuc PHINode *Result = 557*f4a2713aSLionel Sambuc Builder.CreatePHI(ConvertType(E->getArg(0)->getType()), 4, 558*f4a2713aSLionel Sambuc "fpclassify_result"); 559*f4a2713aSLionel Sambuc 560*f4a2713aSLionel Sambuc // if (V==0) return FP_ZERO 561*f4a2713aSLionel Sambuc Builder.SetInsertPoint(Begin); 562*f4a2713aSLionel Sambuc Value *IsZero = Builder.CreateFCmpOEQ(V, Constant::getNullValue(Ty), 563*f4a2713aSLionel Sambuc "iszero"); 564*f4a2713aSLionel Sambuc Value *ZeroLiteral = EmitScalarExpr(E->getArg(4)); 565*f4a2713aSLionel Sambuc BasicBlock *NotZero = createBasicBlock("fpclassify_not_zero", this->CurFn); 566*f4a2713aSLionel Sambuc Builder.CreateCondBr(IsZero, End, NotZero); 567*f4a2713aSLionel Sambuc Result->addIncoming(ZeroLiteral, Begin); 568*f4a2713aSLionel Sambuc 569*f4a2713aSLionel Sambuc // if (V != V) return FP_NAN 570*f4a2713aSLionel Sambuc Builder.SetInsertPoint(NotZero); 571*f4a2713aSLionel Sambuc Value *IsNan = Builder.CreateFCmpUNO(V, V, "cmp"); 572*f4a2713aSLionel Sambuc Value *NanLiteral = EmitScalarExpr(E->getArg(0)); 573*f4a2713aSLionel Sambuc BasicBlock *NotNan = createBasicBlock("fpclassify_not_nan", this->CurFn); 574*f4a2713aSLionel Sambuc Builder.CreateCondBr(IsNan, End, NotNan); 575*f4a2713aSLionel Sambuc Result->addIncoming(NanLiteral, NotZero); 576*f4a2713aSLionel Sambuc 577*f4a2713aSLionel Sambuc // if (fabs(V) == infinity) return FP_INFINITY 578*f4a2713aSLionel Sambuc Builder.SetInsertPoint(NotNan); 579*f4a2713aSLionel Sambuc Value *VAbs = EmitFAbs(*this, V, E->getArg(5)->getType()); 580*f4a2713aSLionel Sambuc Value *IsInf = 581*f4a2713aSLionel Sambuc Builder.CreateFCmpOEQ(VAbs, ConstantFP::getInfinity(V->getType()), 582*f4a2713aSLionel Sambuc "isinf"); 583*f4a2713aSLionel Sambuc Value *InfLiteral = EmitScalarExpr(E->getArg(1)); 584*f4a2713aSLionel Sambuc BasicBlock *NotInf = createBasicBlock("fpclassify_not_inf", this->CurFn); 585*f4a2713aSLionel Sambuc Builder.CreateCondBr(IsInf, End, NotInf); 586*f4a2713aSLionel Sambuc Result->addIncoming(InfLiteral, NotNan); 587*f4a2713aSLionel Sambuc 588*f4a2713aSLionel Sambuc // if (fabs(V) >= MIN_NORMAL) return FP_NORMAL else FP_SUBNORMAL 589*f4a2713aSLionel Sambuc Builder.SetInsertPoint(NotInf); 590*f4a2713aSLionel Sambuc APFloat Smallest = APFloat::getSmallestNormalized( 591*f4a2713aSLionel Sambuc getContext().getFloatTypeSemantics(E->getArg(5)->getType())); 592*f4a2713aSLionel Sambuc Value *IsNormal = 593*f4a2713aSLionel Sambuc Builder.CreateFCmpUGE(VAbs, ConstantFP::get(V->getContext(), Smallest), 594*f4a2713aSLionel Sambuc "isnormal"); 595*f4a2713aSLionel Sambuc Value *NormalResult = 596*f4a2713aSLionel Sambuc Builder.CreateSelect(IsNormal, EmitScalarExpr(E->getArg(2)), 597*f4a2713aSLionel Sambuc EmitScalarExpr(E->getArg(3))); 598*f4a2713aSLionel Sambuc Builder.CreateBr(End); 599*f4a2713aSLionel Sambuc Result->addIncoming(NormalResult, NotInf); 600*f4a2713aSLionel Sambuc 601*f4a2713aSLionel Sambuc // return Result 602*f4a2713aSLionel Sambuc Builder.SetInsertPoint(End); 603*f4a2713aSLionel Sambuc return RValue::get(Result); 604*f4a2713aSLionel Sambuc } 605*f4a2713aSLionel Sambuc 606*f4a2713aSLionel Sambuc case Builtin::BIalloca: 607*f4a2713aSLionel Sambuc case Builtin::BI_alloca: 608*f4a2713aSLionel Sambuc case Builtin::BI__builtin_alloca: { 609*f4a2713aSLionel Sambuc Value *Size = EmitScalarExpr(E->getArg(0)); 610*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateAlloca(Builder.getInt8Ty(), Size)); 611*f4a2713aSLionel Sambuc } 612*f4a2713aSLionel Sambuc case Builtin::BIbzero: 613*f4a2713aSLionel Sambuc case Builtin::BI__builtin_bzero: { 614*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Dest = 615*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(0)); 616*f4a2713aSLionel Sambuc Value *SizeVal = EmitScalarExpr(E->getArg(1)); 617*f4a2713aSLionel Sambuc Builder.CreateMemSet(Dest.first, Builder.getInt8(0), SizeVal, 618*f4a2713aSLionel Sambuc Dest.second, false); 619*f4a2713aSLionel Sambuc return RValue::get(Dest.first); 620*f4a2713aSLionel Sambuc } 621*f4a2713aSLionel Sambuc case Builtin::BImemcpy: 622*f4a2713aSLionel Sambuc case Builtin::BI__builtin_memcpy: { 623*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Dest = 624*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(0)); 625*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Src = 626*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(1)); 627*f4a2713aSLionel Sambuc Value *SizeVal = EmitScalarExpr(E->getArg(2)); 628*f4a2713aSLionel Sambuc unsigned Align = std::min(Dest.second, Src.second); 629*f4a2713aSLionel Sambuc Builder.CreateMemCpy(Dest.first, Src.first, SizeVal, Align, false); 630*f4a2713aSLionel Sambuc return RValue::get(Dest.first); 631*f4a2713aSLionel Sambuc } 632*f4a2713aSLionel Sambuc 633*f4a2713aSLionel Sambuc case Builtin::BI__builtin___memcpy_chk: { 634*f4a2713aSLionel Sambuc // fold __builtin_memcpy_chk(x, y, cst1, cst2) to memcpy iff cst1<=cst2. 635*f4a2713aSLionel Sambuc llvm::APSInt Size, DstSize; 636*f4a2713aSLionel Sambuc if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) || 637*f4a2713aSLionel Sambuc !E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext())) 638*f4a2713aSLionel Sambuc break; 639*f4a2713aSLionel Sambuc if (Size.ugt(DstSize)) 640*f4a2713aSLionel Sambuc break; 641*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Dest = 642*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(0)); 643*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Src = 644*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(1)); 645*f4a2713aSLionel Sambuc Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); 646*f4a2713aSLionel Sambuc unsigned Align = std::min(Dest.second, Src.second); 647*f4a2713aSLionel Sambuc Builder.CreateMemCpy(Dest.first, Src.first, SizeVal, Align, false); 648*f4a2713aSLionel Sambuc return RValue::get(Dest.first); 649*f4a2713aSLionel Sambuc } 650*f4a2713aSLionel Sambuc 651*f4a2713aSLionel Sambuc case Builtin::BI__builtin_objc_memmove_collectable: { 652*f4a2713aSLionel Sambuc Value *Address = EmitScalarExpr(E->getArg(0)); 653*f4a2713aSLionel Sambuc Value *SrcAddr = EmitScalarExpr(E->getArg(1)); 654*f4a2713aSLionel Sambuc Value *SizeVal = EmitScalarExpr(E->getArg(2)); 655*f4a2713aSLionel Sambuc CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, 656*f4a2713aSLionel Sambuc Address, SrcAddr, SizeVal); 657*f4a2713aSLionel Sambuc return RValue::get(Address); 658*f4a2713aSLionel Sambuc } 659*f4a2713aSLionel Sambuc 660*f4a2713aSLionel Sambuc case Builtin::BI__builtin___memmove_chk: { 661*f4a2713aSLionel Sambuc // fold __builtin_memmove_chk(x, y, cst1, cst2) to memmove iff cst1<=cst2. 662*f4a2713aSLionel Sambuc llvm::APSInt Size, DstSize; 663*f4a2713aSLionel Sambuc if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) || 664*f4a2713aSLionel Sambuc !E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext())) 665*f4a2713aSLionel Sambuc break; 666*f4a2713aSLionel Sambuc if (Size.ugt(DstSize)) 667*f4a2713aSLionel Sambuc break; 668*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Dest = 669*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(0)); 670*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Src = 671*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(1)); 672*f4a2713aSLionel Sambuc Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); 673*f4a2713aSLionel Sambuc unsigned Align = std::min(Dest.second, Src.second); 674*f4a2713aSLionel Sambuc Builder.CreateMemMove(Dest.first, Src.first, SizeVal, Align, false); 675*f4a2713aSLionel Sambuc return RValue::get(Dest.first); 676*f4a2713aSLionel Sambuc } 677*f4a2713aSLionel Sambuc 678*f4a2713aSLionel Sambuc case Builtin::BImemmove: 679*f4a2713aSLionel Sambuc case Builtin::BI__builtin_memmove: { 680*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Dest = 681*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(0)); 682*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Src = 683*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(1)); 684*f4a2713aSLionel Sambuc Value *SizeVal = EmitScalarExpr(E->getArg(2)); 685*f4a2713aSLionel Sambuc unsigned Align = std::min(Dest.second, Src.second); 686*f4a2713aSLionel Sambuc Builder.CreateMemMove(Dest.first, Src.first, SizeVal, Align, false); 687*f4a2713aSLionel Sambuc return RValue::get(Dest.first); 688*f4a2713aSLionel Sambuc } 689*f4a2713aSLionel Sambuc case Builtin::BImemset: 690*f4a2713aSLionel Sambuc case Builtin::BI__builtin_memset: { 691*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Dest = 692*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(0)); 693*f4a2713aSLionel Sambuc Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), 694*f4a2713aSLionel Sambuc Builder.getInt8Ty()); 695*f4a2713aSLionel Sambuc Value *SizeVal = EmitScalarExpr(E->getArg(2)); 696*f4a2713aSLionel Sambuc Builder.CreateMemSet(Dest.first, ByteVal, SizeVal, Dest.second, false); 697*f4a2713aSLionel Sambuc return RValue::get(Dest.first); 698*f4a2713aSLionel Sambuc } 699*f4a2713aSLionel Sambuc case Builtin::BI__builtin___memset_chk: { 700*f4a2713aSLionel Sambuc // fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. 701*f4a2713aSLionel Sambuc llvm::APSInt Size, DstSize; 702*f4a2713aSLionel Sambuc if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) || 703*f4a2713aSLionel Sambuc !E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext())) 704*f4a2713aSLionel Sambuc break; 705*f4a2713aSLionel Sambuc if (Size.ugt(DstSize)) 706*f4a2713aSLionel Sambuc break; 707*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Dest = 708*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(0)); 709*f4a2713aSLionel Sambuc Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), 710*f4a2713aSLionel Sambuc Builder.getInt8Ty()); 711*f4a2713aSLionel Sambuc Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); 712*f4a2713aSLionel Sambuc Builder.CreateMemSet(Dest.first, ByteVal, SizeVal, Dest.second, false); 713*f4a2713aSLionel Sambuc return RValue::get(Dest.first); 714*f4a2713aSLionel Sambuc } 715*f4a2713aSLionel Sambuc case Builtin::BI__builtin_dwarf_cfa: { 716*f4a2713aSLionel Sambuc // The offset in bytes from the first argument to the CFA. 717*f4a2713aSLionel Sambuc // 718*f4a2713aSLionel Sambuc // Why on earth is this in the frontend? Is there any reason at 719*f4a2713aSLionel Sambuc // all that the backend can't reasonably determine this while 720*f4a2713aSLionel Sambuc // lowering llvm.eh.dwarf.cfa()? 721*f4a2713aSLionel Sambuc // 722*f4a2713aSLionel Sambuc // TODO: If there's a satisfactory reason, add a target hook for 723*f4a2713aSLionel Sambuc // this instead of hard-coding 0, which is correct for most targets. 724*f4a2713aSLionel Sambuc int32_t Offset = 0; 725*f4a2713aSLionel Sambuc 726*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::eh_dwarf_cfa); 727*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall(F, 728*f4a2713aSLionel Sambuc llvm::ConstantInt::get(Int32Ty, Offset))); 729*f4a2713aSLionel Sambuc } 730*f4a2713aSLionel Sambuc case Builtin::BI__builtin_return_address: { 731*f4a2713aSLionel Sambuc Value *Depth = EmitScalarExpr(E->getArg(0)); 732*f4a2713aSLionel Sambuc Depth = Builder.CreateIntCast(Depth, Int32Ty, false); 733*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::returnaddress); 734*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall(F, Depth)); 735*f4a2713aSLionel Sambuc } 736*f4a2713aSLionel Sambuc case Builtin::BI__builtin_frame_address: { 737*f4a2713aSLionel Sambuc Value *Depth = EmitScalarExpr(E->getArg(0)); 738*f4a2713aSLionel Sambuc Depth = Builder.CreateIntCast(Depth, Int32Ty, false); 739*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::frameaddress); 740*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall(F, Depth)); 741*f4a2713aSLionel Sambuc } 742*f4a2713aSLionel Sambuc case Builtin::BI__builtin_extract_return_addr: { 743*f4a2713aSLionel Sambuc Value *Address = EmitScalarExpr(E->getArg(0)); 744*f4a2713aSLionel Sambuc Value *Result = getTargetHooks().decodeReturnAddress(*this, Address); 745*f4a2713aSLionel Sambuc return RValue::get(Result); 746*f4a2713aSLionel Sambuc } 747*f4a2713aSLionel Sambuc case Builtin::BI__builtin_frob_return_addr: { 748*f4a2713aSLionel Sambuc Value *Address = EmitScalarExpr(E->getArg(0)); 749*f4a2713aSLionel Sambuc Value *Result = getTargetHooks().encodeReturnAddress(*this, Address); 750*f4a2713aSLionel Sambuc return RValue::get(Result); 751*f4a2713aSLionel Sambuc } 752*f4a2713aSLionel Sambuc case Builtin::BI__builtin_dwarf_sp_column: { 753*f4a2713aSLionel Sambuc llvm::IntegerType *Ty 754*f4a2713aSLionel Sambuc = cast<llvm::IntegerType>(ConvertType(E->getType())); 755*f4a2713aSLionel Sambuc int Column = getTargetHooks().getDwarfEHStackPointer(CGM); 756*f4a2713aSLionel Sambuc if (Column == -1) { 757*f4a2713aSLionel Sambuc CGM.ErrorUnsupported(E, "__builtin_dwarf_sp_column"); 758*f4a2713aSLionel Sambuc return RValue::get(llvm::UndefValue::get(Ty)); 759*f4a2713aSLionel Sambuc } 760*f4a2713aSLionel Sambuc return RValue::get(llvm::ConstantInt::get(Ty, Column, true)); 761*f4a2713aSLionel Sambuc } 762*f4a2713aSLionel Sambuc case Builtin::BI__builtin_init_dwarf_reg_size_table: { 763*f4a2713aSLionel Sambuc Value *Address = EmitScalarExpr(E->getArg(0)); 764*f4a2713aSLionel Sambuc if (getTargetHooks().initDwarfEHRegSizeTable(*this, Address)) 765*f4a2713aSLionel Sambuc CGM.ErrorUnsupported(E, "__builtin_init_dwarf_reg_size_table"); 766*f4a2713aSLionel Sambuc return RValue::get(llvm::UndefValue::get(ConvertType(E->getType()))); 767*f4a2713aSLionel Sambuc } 768*f4a2713aSLionel Sambuc case Builtin::BI__builtin_eh_return: { 769*f4a2713aSLionel Sambuc Value *Int = EmitScalarExpr(E->getArg(0)); 770*f4a2713aSLionel Sambuc Value *Ptr = EmitScalarExpr(E->getArg(1)); 771*f4a2713aSLionel Sambuc 772*f4a2713aSLionel Sambuc llvm::IntegerType *IntTy = cast<llvm::IntegerType>(Int->getType()); 773*f4a2713aSLionel Sambuc assert((IntTy->getBitWidth() == 32 || IntTy->getBitWidth() == 64) && 774*f4a2713aSLionel Sambuc "LLVM's __builtin_eh_return only supports 32- and 64-bit variants"); 775*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(IntTy->getBitWidth() == 32 776*f4a2713aSLionel Sambuc ? Intrinsic::eh_return_i32 777*f4a2713aSLionel Sambuc : Intrinsic::eh_return_i64); 778*f4a2713aSLionel Sambuc Builder.CreateCall2(F, Int, Ptr); 779*f4a2713aSLionel Sambuc Builder.CreateUnreachable(); 780*f4a2713aSLionel Sambuc 781*f4a2713aSLionel Sambuc // We do need to preserve an insertion point. 782*f4a2713aSLionel Sambuc EmitBlock(createBasicBlock("builtin_eh_return.cont")); 783*f4a2713aSLionel Sambuc 784*f4a2713aSLionel Sambuc return RValue::get(0); 785*f4a2713aSLionel Sambuc } 786*f4a2713aSLionel Sambuc case Builtin::BI__builtin_unwind_init: { 787*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::eh_unwind_init); 788*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall(F)); 789*f4a2713aSLionel Sambuc } 790*f4a2713aSLionel Sambuc case Builtin::BI__builtin_extend_pointer: { 791*f4a2713aSLionel Sambuc // Extends a pointer to the size of an _Unwind_Word, which is 792*f4a2713aSLionel Sambuc // uint64_t on all platforms. Generally this gets poked into a 793*f4a2713aSLionel Sambuc // register and eventually used as an address, so if the 794*f4a2713aSLionel Sambuc // addressing registers are wider than pointers and the platform 795*f4a2713aSLionel Sambuc // doesn't implicitly ignore high-order bits when doing 796*f4a2713aSLionel Sambuc // addressing, we need to make sure we zext / sext based on 797*f4a2713aSLionel Sambuc // the platform's expectations. 798*f4a2713aSLionel Sambuc // 799*f4a2713aSLionel Sambuc // See: http://gcc.gnu.org/ml/gcc-bugs/2002-02/msg00237.html 800*f4a2713aSLionel Sambuc 801*f4a2713aSLionel Sambuc // Cast the pointer to intptr_t. 802*f4a2713aSLionel Sambuc Value *Ptr = EmitScalarExpr(E->getArg(0)); 803*f4a2713aSLionel Sambuc Value *Result = Builder.CreatePtrToInt(Ptr, IntPtrTy, "extend.cast"); 804*f4a2713aSLionel Sambuc 805*f4a2713aSLionel Sambuc // If that's 64 bits, we're done. 806*f4a2713aSLionel Sambuc if (IntPtrTy->getBitWidth() == 64) 807*f4a2713aSLionel Sambuc return RValue::get(Result); 808*f4a2713aSLionel Sambuc 809*f4a2713aSLionel Sambuc // Otherwise, ask the codegen data what to do. 810*f4a2713aSLionel Sambuc if (getTargetHooks().extendPointerWithSExt()) 811*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateSExt(Result, Int64Ty, "extend.sext")); 812*f4a2713aSLionel Sambuc else 813*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateZExt(Result, Int64Ty, "extend.zext")); 814*f4a2713aSLionel Sambuc } 815*f4a2713aSLionel Sambuc case Builtin::BI__builtin_setjmp: { 816*f4a2713aSLionel Sambuc // Buffer is a void**. 817*f4a2713aSLionel Sambuc Value *Buf = EmitScalarExpr(E->getArg(0)); 818*f4a2713aSLionel Sambuc 819*f4a2713aSLionel Sambuc // Store the frame pointer to the setjmp buffer. 820*f4a2713aSLionel Sambuc Value *FrameAddr = 821*f4a2713aSLionel Sambuc Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress), 822*f4a2713aSLionel Sambuc ConstantInt::get(Int32Ty, 0)); 823*f4a2713aSLionel Sambuc Builder.CreateStore(FrameAddr, Buf); 824*f4a2713aSLionel Sambuc 825*f4a2713aSLionel Sambuc // Store the stack pointer to the setjmp buffer. 826*f4a2713aSLionel Sambuc Value *StackAddr = 827*f4a2713aSLionel Sambuc Builder.CreateCall(CGM.getIntrinsic(Intrinsic::stacksave)); 828*f4a2713aSLionel Sambuc Value *StackSaveSlot = 829*f4a2713aSLionel Sambuc Builder.CreateGEP(Buf, ConstantInt::get(Int32Ty, 2)); 830*f4a2713aSLionel Sambuc Builder.CreateStore(StackAddr, StackSaveSlot); 831*f4a2713aSLionel Sambuc 832*f4a2713aSLionel Sambuc // Call LLVM's EH setjmp, which is lightweight. 833*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp); 834*f4a2713aSLionel Sambuc Buf = Builder.CreateBitCast(Buf, Int8PtrTy); 835*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall(F, Buf)); 836*f4a2713aSLionel Sambuc } 837*f4a2713aSLionel Sambuc case Builtin::BI__builtin_longjmp: { 838*f4a2713aSLionel Sambuc Value *Buf = EmitScalarExpr(E->getArg(0)); 839*f4a2713aSLionel Sambuc Buf = Builder.CreateBitCast(Buf, Int8PtrTy); 840*f4a2713aSLionel Sambuc 841*f4a2713aSLionel Sambuc // Call LLVM's EH longjmp, which is lightweight. 842*f4a2713aSLionel Sambuc Builder.CreateCall(CGM.getIntrinsic(Intrinsic::eh_sjlj_longjmp), Buf); 843*f4a2713aSLionel Sambuc 844*f4a2713aSLionel Sambuc // longjmp doesn't return; mark this as unreachable. 845*f4a2713aSLionel Sambuc Builder.CreateUnreachable(); 846*f4a2713aSLionel Sambuc 847*f4a2713aSLionel Sambuc // We do need to preserve an insertion point. 848*f4a2713aSLionel Sambuc EmitBlock(createBasicBlock("longjmp.cont")); 849*f4a2713aSLionel Sambuc 850*f4a2713aSLionel Sambuc return RValue::get(0); 851*f4a2713aSLionel Sambuc } 852*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_add: 853*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_sub: 854*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_or: 855*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_and: 856*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_xor: 857*f4a2713aSLionel Sambuc case Builtin::BI__sync_add_and_fetch: 858*f4a2713aSLionel Sambuc case Builtin::BI__sync_sub_and_fetch: 859*f4a2713aSLionel Sambuc case Builtin::BI__sync_and_and_fetch: 860*f4a2713aSLionel Sambuc case Builtin::BI__sync_or_and_fetch: 861*f4a2713aSLionel Sambuc case Builtin::BI__sync_xor_and_fetch: 862*f4a2713aSLionel Sambuc case Builtin::BI__sync_val_compare_and_swap: 863*f4a2713aSLionel Sambuc case Builtin::BI__sync_bool_compare_and_swap: 864*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_test_and_set: 865*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_release: 866*f4a2713aSLionel Sambuc case Builtin::BI__sync_swap: 867*f4a2713aSLionel Sambuc llvm_unreachable("Shouldn't make it through sema"); 868*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_add_1: 869*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_add_2: 870*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_add_4: 871*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_add_8: 872*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_add_16: 873*f4a2713aSLionel Sambuc return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Add, E); 874*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_sub_1: 875*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_sub_2: 876*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_sub_4: 877*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_sub_8: 878*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_sub_16: 879*f4a2713aSLionel Sambuc return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Sub, E); 880*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_or_1: 881*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_or_2: 882*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_or_4: 883*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_or_8: 884*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_or_16: 885*f4a2713aSLionel Sambuc return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Or, E); 886*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_and_1: 887*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_and_2: 888*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_and_4: 889*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_and_8: 890*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_and_16: 891*f4a2713aSLionel Sambuc return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::And, E); 892*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_xor_1: 893*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_xor_2: 894*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_xor_4: 895*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_xor_8: 896*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_xor_16: 897*f4a2713aSLionel Sambuc return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xor, E); 898*f4a2713aSLionel Sambuc 899*f4a2713aSLionel Sambuc // Clang extensions: not overloaded yet. 900*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_min: 901*f4a2713aSLionel Sambuc return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Min, E); 902*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_max: 903*f4a2713aSLionel Sambuc return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Max, E); 904*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_umin: 905*f4a2713aSLionel Sambuc return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::UMin, E); 906*f4a2713aSLionel Sambuc case Builtin::BI__sync_fetch_and_umax: 907*f4a2713aSLionel Sambuc return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::UMax, E); 908*f4a2713aSLionel Sambuc 909*f4a2713aSLionel Sambuc case Builtin::BI__sync_add_and_fetch_1: 910*f4a2713aSLionel Sambuc case Builtin::BI__sync_add_and_fetch_2: 911*f4a2713aSLionel Sambuc case Builtin::BI__sync_add_and_fetch_4: 912*f4a2713aSLionel Sambuc case Builtin::BI__sync_add_and_fetch_8: 913*f4a2713aSLionel Sambuc case Builtin::BI__sync_add_and_fetch_16: 914*f4a2713aSLionel Sambuc return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Add, E, 915*f4a2713aSLionel Sambuc llvm::Instruction::Add); 916*f4a2713aSLionel Sambuc case Builtin::BI__sync_sub_and_fetch_1: 917*f4a2713aSLionel Sambuc case Builtin::BI__sync_sub_and_fetch_2: 918*f4a2713aSLionel Sambuc case Builtin::BI__sync_sub_and_fetch_4: 919*f4a2713aSLionel Sambuc case Builtin::BI__sync_sub_and_fetch_8: 920*f4a2713aSLionel Sambuc case Builtin::BI__sync_sub_and_fetch_16: 921*f4a2713aSLionel Sambuc return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Sub, E, 922*f4a2713aSLionel Sambuc llvm::Instruction::Sub); 923*f4a2713aSLionel Sambuc case Builtin::BI__sync_and_and_fetch_1: 924*f4a2713aSLionel Sambuc case Builtin::BI__sync_and_and_fetch_2: 925*f4a2713aSLionel Sambuc case Builtin::BI__sync_and_and_fetch_4: 926*f4a2713aSLionel Sambuc case Builtin::BI__sync_and_and_fetch_8: 927*f4a2713aSLionel Sambuc case Builtin::BI__sync_and_and_fetch_16: 928*f4a2713aSLionel Sambuc return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::And, E, 929*f4a2713aSLionel Sambuc llvm::Instruction::And); 930*f4a2713aSLionel Sambuc case Builtin::BI__sync_or_and_fetch_1: 931*f4a2713aSLionel Sambuc case Builtin::BI__sync_or_and_fetch_2: 932*f4a2713aSLionel Sambuc case Builtin::BI__sync_or_and_fetch_4: 933*f4a2713aSLionel Sambuc case Builtin::BI__sync_or_and_fetch_8: 934*f4a2713aSLionel Sambuc case Builtin::BI__sync_or_and_fetch_16: 935*f4a2713aSLionel Sambuc return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Or, E, 936*f4a2713aSLionel Sambuc llvm::Instruction::Or); 937*f4a2713aSLionel Sambuc case Builtin::BI__sync_xor_and_fetch_1: 938*f4a2713aSLionel Sambuc case Builtin::BI__sync_xor_and_fetch_2: 939*f4a2713aSLionel Sambuc case Builtin::BI__sync_xor_and_fetch_4: 940*f4a2713aSLionel Sambuc case Builtin::BI__sync_xor_and_fetch_8: 941*f4a2713aSLionel Sambuc case Builtin::BI__sync_xor_and_fetch_16: 942*f4a2713aSLionel Sambuc return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Xor, E, 943*f4a2713aSLionel Sambuc llvm::Instruction::Xor); 944*f4a2713aSLionel Sambuc 945*f4a2713aSLionel Sambuc case Builtin::BI__sync_val_compare_and_swap_1: 946*f4a2713aSLionel Sambuc case Builtin::BI__sync_val_compare_and_swap_2: 947*f4a2713aSLionel Sambuc case Builtin::BI__sync_val_compare_and_swap_4: 948*f4a2713aSLionel Sambuc case Builtin::BI__sync_val_compare_and_swap_8: 949*f4a2713aSLionel Sambuc case Builtin::BI__sync_val_compare_and_swap_16: { 950*f4a2713aSLionel Sambuc QualType T = E->getType(); 951*f4a2713aSLionel Sambuc llvm::Value *DestPtr = EmitScalarExpr(E->getArg(0)); 952*f4a2713aSLionel Sambuc unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); 953*f4a2713aSLionel Sambuc 954*f4a2713aSLionel Sambuc llvm::IntegerType *IntType = 955*f4a2713aSLionel Sambuc llvm::IntegerType::get(getLLVMContext(), 956*f4a2713aSLionel Sambuc getContext().getTypeSize(T)); 957*f4a2713aSLionel Sambuc llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); 958*f4a2713aSLionel Sambuc 959*f4a2713aSLionel Sambuc Value *Args[3]; 960*f4a2713aSLionel Sambuc Args[0] = Builder.CreateBitCast(DestPtr, IntPtrType); 961*f4a2713aSLionel Sambuc Args[1] = EmitScalarExpr(E->getArg(1)); 962*f4a2713aSLionel Sambuc llvm::Type *ValueType = Args[1]->getType(); 963*f4a2713aSLionel Sambuc Args[1] = EmitToInt(*this, Args[1], T, IntType); 964*f4a2713aSLionel Sambuc Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType); 965*f4a2713aSLionel Sambuc 966*f4a2713aSLionel Sambuc Value *Result = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2], 967*f4a2713aSLionel Sambuc llvm::SequentiallyConsistent); 968*f4a2713aSLionel Sambuc Result = EmitFromInt(*this, Result, T, ValueType); 969*f4a2713aSLionel Sambuc return RValue::get(Result); 970*f4a2713aSLionel Sambuc } 971*f4a2713aSLionel Sambuc 972*f4a2713aSLionel Sambuc case Builtin::BI__sync_bool_compare_and_swap_1: 973*f4a2713aSLionel Sambuc case Builtin::BI__sync_bool_compare_and_swap_2: 974*f4a2713aSLionel Sambuc case Builtin::BI__sync_bool_compare_and_swap_4: 975*f4a2713aSLionel Sambuc case Builtin::BI__sync_bool_compare_and_swap_8: 976*f4a2713aSLionel Sambuc case Builtin::BI__sync_bool_compare_and_swap_16: { 977*f4a2713aSLionel Sambuc QualType T = E->getArg(1)->getType(); 978*f4a2713aSLionel Sambuc llvm::Value *DestPtr = EmitScalarExpr(E->getArg(0)); 979*f4a2713aSLionel Sambuc unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); 980*f4a2713aSLionel Sambuc 981*f4a2713aSLionel Sambuc llvm::IntegerType *IntType = 982*f4a2713aSLionel Sambuc llvm::IntegerType::get(getLLVMContext(), 983*f4a2713aSLionel Sambuc getContext().getTypeSize(T)); 984*f4a2713aSLionel Sambuc llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); 985*f4a2713aSLionel Sambuc 986*f4a2713aSLionel Sambuc Value *Args[3]; 987*f4a2713aSLionel Sambuc Args[0] = Builder.CreateBitCast(DestPtr, IntPtrType); 988*f4a2713aSLionel Sambuc Args[1] = EmitToInt(*this, EmitScalarExpr(E->getArg(1)), T, IntType); 989*f4a2713aSLionel Sambuc Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType); 990*f4a2713aSLionel Sambuc 991*f4a2713aSLionel Sambuc Value *OldVal = Args[1]; 992*f4a2713aSLionel Sambuc Value *PrevVal = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2], 993*f4a2713aSLionel Sambuc llvm::SequentiallyConsistent); 994*f4a2713aSLionel Sambuc Value *Result = Builder.CreateICmpEQ(PrevVal, OldVal); 995*f4a2713aSLionel Sambuc // zext bool to int. 996*f4a2713aSLionel Sambuc Result = Builder.CreateZExt(Result, ConvertType(E->getType())); 997*f4a2713aSLionel Sambuc return RValue::get(Result); 998*f4a2713aSLionel Sambuc } 999*f4a2713aSLionel Sambuc 1000*f4a2713aSLionel Sambuc case Builtin::BI__sync_swap_1: 1001*f4a2713aSLionel Sambuc case Builtin::BI__sync_swap_2: 1002*f4a2713aSLionel Sambuc case Builtin::BI__sync_swap_4: 1003*f4a2713aSLionel Sambuc case Builtin::BI__sync_swap_8: 1004*f4a2713aSLionel Sambuc case Builtin::BI__sync_swap_16: 1005*f4a2713aSLionel Sambuc return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E); 1006*f4a2713aSLionel Sambuc 1007*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_test_and_set_1: 1008*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_test_and_set_2: 1009*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_test_and_set_4: 1010*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_test_and_set_8: 1011*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_test_and_set_16: 1012*f4a2713aSLionel Sambuc return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E); 1013*f4a2713aSLionel Sambuc 1014*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_release_1: 1015*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_release_2: 1016*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_release_4: 1017*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_release_8: 1018*f4a2713aSLionel Sambuc case Builtin::BI__sync_lock_release_16: { 1019*f4a2713aSLionel Sambuc Value *Ptr = EmitScalarExpr(E->getArg(0)); 1020*f4a2713aSLionel Sambuc QualType ElTy = E->getArg(0)->getType()->getPointeeType(); 1021*f4a2713aSLionel Sambuc CharUnits StoreSize = getContext().getTypeSizeInChars(ElTy); 1022*f4a2713aSLionel Sambuc llvm::Type *ITy = llvm::IntegerType::get(getLLVMContext(), 1023*f4a2713aSLionel Sambuc StoreSize.getQuantity() * 8); 1024*f4a2713aSLionel Sambuc Ptr = Builder.CreateBitCast(Ptr, ITy->getPointerTo()); 1025*f4a2713aSLionel Sambuc llvm::StoreInst *Store = 1026*f4a2713aSLionel Sambuc Builder.CreateStore(llvm::Constant::getNullValue(ITy), Ptr); 1027*f4a2713aSLionel Sambuc Store->setAlignment(StoreSize.getQuantity()); 1028*f4a2713aSLionel Sambuc Store->setAtomic(llvm::Release); 1029*f4a2713aSLionel Sambuc return RValue::get(0); 1030*f4a2713aSLionel Sambuc } 1031*f4a2713aSLionel Sambuc 1032*f4a2713aSLionel Sambuc case Builtin::BI__sync_synchronize: { 1033*f4a2713aSLionel Sambuc // We assume this is supposed to correspond to a C++0x-style 1034*f4a2713aSLionel Sambuc // sequentially-consistent fence (i.e. this is only usable for 1035*f4a2713aSLionel Sambuc // synchonization, not device I/O or anything like that). This intrinsic 1036*f4a2713aSLionel Sambuc // is really badly designed in the sense that in theory, there isn't 1037*f4a2713aSLionel Sambuc // any way to safely use it... but in practice, it mostly works 1038*f4a2713aSLionel Sambuc // to use it with non-atomic loads and stores to get acquire/release 1039*f4a2713aSLionel Sambuc // semantics. 1040*f4a2713aSLionel Sambuc Builder.CreateFence(llvm::SequentiallyConsistent); 1041*f4a2713aSLionel Sambuc return RValue::get(0); 1042*f4a2713aSLionel Sambuc } 1043*f4a2713aSLionel Sambuc 1044*f4a2713aSLionel Sambuc case Builtin::BI__c11_atomic_is_lock_free: 1045*f4a2713aSLionel Sambuc case Builtin::BI__atomic_is_lock_free: { 1046*f4a2713aSLionel Sambuc // Call "bool __atomic_is_lock_free(size_t size, void *ptr)". For the 1047*f4a2713aSLionel Sambuc // __c11 builtin, ptr is 0 (indicating a properly-aligned object), since 1048*f4a2713aSLionel Sambuc // _Atomic(T) is always properly-aligned. 1049*f4a2713aSLionel Sambuc const char *LibCallName = "__atomic_is_lock_free"; 1050*f4a2713aSLionel Sambuc CallArgList Args; 1051*f4a2713aSLionel Sambuc Args.add(RValue::get(EmitScalarExpr(E->getArg(0))), 1052*f4a2713aSLionel Sambuc getContext().getSizeType()); 1053*f4a2713aSLionel Sambuc if (BuiltinID == Builtin::BI__atomic_is_lock_free) 1054*f4a2713aSLionel Sambuc Args.add(RValue::get(EmitScalarExpr(E->getArg(1))), 1055*f4a2713aSLionel Sambuc getContext().VoidPtrTy); 1056*f4a2713aSLionel Sambuc else 1057*f4a2713aSLionel Sambuc Args.add(RValue::get(llvm::Constant::getNullValue(VoidPtrTy)), 1058*f4a2713aSLionel Sambuc getContext().VoidPtrTy); 1059*f4a2713aSLionel Sambuc const CGFunctionInfo &FuncInfo = 1060*f4a2713aSLionel Sambuc CGM.getTypes().arrangeFreeFunctionCall(E->getType(), Args, 1061*f4a2713aSLionel Sambuc FunctionType::ExtInfo(), 1062*f4a2713aSLionel Sambuc RequiredArgs::All); 1063*f4a2713aSLionel Sambuc llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FuncInfo); 1064*f4a2713aSLionel Sambuc llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, LibCallName); 1065*f4a2713aSLionel Sambuc return EmitCall(FuncInfo, Func, ReturnValueSlot(), Args); 1066*f4a2713aSLionel Sambuc } 1067*f4a2713aSLionel Sambuc 1068*f4a2713aSLionel Sambuc case Builtin::BI__atomic_test_and_set: { 1069*f4a2713aSLionel Sambuc // Look at the argument type to determine whether this is a volatile 1070*f4a2713aSLionel Sambuc // operation. The parameter type is always volatile. 1071*f4a2713aSLionel Sambuc QualType PtrTy = E->getArg(0)->IgnoreImpCasts()->getType(); 1072*f4a2713aSLionel Sambuc bool Volatile = 1073*f4a2713aSLionel Sambuc PtrTy->castAs<PointerType>()->getPointeeType().isVolatileQualified(); 1074*f4a2713aSLionel Sambuc 1075*f4a2713aSLionel Sambuc Value *Ptr = EmitScalarExpr(E->getArg(0)); 1076*f4a2713aSLionel Sambuc unsigned AddrSpace = Ptr->getType()->getPointerAddressSpace(); 1077*f4a2713aSLionel Sambuc Ptr = Builder.CreateBitCast(Ptr, Int8Ty->getPointerTo(AddrSpace)); 1078*f4a2713aSLionel Sambuc Value *NewVal = Builder.getInt8(1); 1079*f4a2713aSLionel Sambuc Value *Order = EmitScalarExpr(E->getArg(1)); 1080*f4a2713aSLionel Sambuc if (isa<llvm::ConstantInt>(Order)) { 1081*f4a2713aSLionel Sambuc int ord = cast<llvm::ConstantInt>(Order)->getZExtValue(); 1082*f4a2713aSLionel Sambuc AtomicRMWInst *Result = 0; 1083*f4a2713aSLionel Sambuc switch (ord) { 1084*f4a2713aSLionel Sambuc case 0: // memory_order_relaxed 1085*f4a2713aSLionel Sambuc default: // invalid order 1086*f4a2713aSLionel Sambuc Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, 1087*f4a2713aSLionel Sambuc Ptr, NewVal, 1088*f4a2713aSLionel Sambuc llvm::Monotonic); 1089*f4a2713aSLionel Sambuc break; 1090*f4a2713aSLionel Sambuc case 1: // memory_order_consume 1091*f4a2713aSLionel Sambuc case 2: // memory_order_acquire 1092*f4a2713aSLionel Sambuc Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, 1093*f4a2713aSLionel Sambuc Ptr, NewVal, 1094*f4a2713aSLionel Sambuc llvm::Acquire); 1095*f4a2713aSLionel Sambuc break; 1096*f4a2713aSLionel Sambuc case 3: // memory_order_release 1097*f4a2713aSLionel Sambuc Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, 1098*f4a2713aSLionel Sambuc Ptr, NewVal, 1099*f4a2713aSLionel Sambuc llvm::Release); 1100*f4a2713aSLionel Sambuc break; 1101*f4a2713aSLionel Sambuc case 4: // memory_order_acq_rel 1102*f4a2713aSLionel Sambuc Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, 1103*f4a2713aSLionel Sambuc Ptr, NewVal, 1104*f4a2713aSLionel Sambuc llvm::AcquireRelease); 1105*f4a2713aSLionel Sambuc break; 1106*f4a2713aSLionel Sambuc case 5: // memory_order_seq_cst 1107*f4a2713aSLionel Sambuc Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, 1108*f4a2713aSLionel Sambuc Ptr, NewVal, 1109*f4a2713aSLionel Sambuc llvm::SequentiallyConsistent); 1110*f4a2713aSLionel Sambuc break; 1111*f4a2713aSLionel Sambuc } 1112*f4a2713aSLionel Sambuc Result->setVolatile(Volatile); 1113*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateIsNotNull(Result, "tobool")); 1114*f4a2713aSLionel Sambuc } 1115*f4a2713aSLionel Sambuc 1116*f4a2713aSLionel Sambuc llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn); 1117*f4a2713aSLionel Sambuc 1118*f4a2713aSLionel Sambuc llvm::BasicBlock *BBs[5] = { 1119*f4a2713aSLionel Sambuc createBasicBlock("monotonic", CurFn), 1120*f4a2713aSLionel Sambuc createBasicBlock("acquire", CurFn), 1121*f4a2713aSLionel Sambuc createBasicBlock("release", CurFn), 1122*f4a2713aSLionel Sambuc createBasicBlock("acqrel", CurFn), 1123*f4a2713aSLionel Sambuc createBasicBlock("seqcst", CurFn) 1124*f4a2713aSLionel Sambuc }; 1125*f4a2713aSLionel Sambuc llvm::AtomicOrdering Orders[5] = { 1126*f4a2713aSLionel Sambuc llvm::Monotonic, llvm::Acquire, llvm::Release, 1127*f4a2713aSLionel Sambuc llvm::AcquireRelease, llvm::SequentiallyConsistent 1128*f4a2713aSLionel Sambuc }; 1129*f4a2713aSLionel Sambuc 1130*f4a2713aSLionel Sambuc Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false); 1131*f4a2713aSLionel Sambuc llvm::SwitchInst *SI = Builder.CreateSwitch(Order, BBs[0]); 1132*f4a2713aSLionel Sambuc 1133*f4a2713aSLionel Sambuc Builder.SetInsertPoint(ContBB); 1134*f4a2713aSLionel Sambuc PHINode *Result = Builder.CreatePHI(Int8Ty, 5, "was_set"); 1135*f4a2713aSLionel Sambuc 1136*f4a2713aSLionel Sambuc for (unsigned i = 0; i < 5; ++i) { 1137*f4a2713aSLionel Sambuc Builder.SetInsertPoint(BBs[i]); 1138*f4a2713aSLionel Sambuc AtomicRMWInst *RMW = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, 1139*f4a2713aSLionel Sambuc Ptr, NewVal, Orders[i]); 1140*f4a2713aSLionel Sambuc RMW->setVolatile(Volatile); 1141*f4a2713aSLionel Sambuc Result->addIncoming(RMW, BBs[i]); 1142*f4a2713aSLionel Sambuc Builder.CreateBr(ContBB); 1143*f4a2713aSLionel Sambuc } 1144*f4a2713aSLionel Sambuc 1145*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(0), BBs[0]); 1146*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(1), BBs[1]); 1147*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(2), BBs[1]); 1148*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(3), BBs[2]); 1149*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(4), BBs[3]); 1150*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(5), BBs[4]); 1151*f4a2713aSLionel Sambuc 1152*f4a2713aSLionel Sambuc Builder.SetInsertPoint(ContBB); 1153*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateIsNotNull(Result, "tobool")); 1154*f4a2713aSLionel Sambuc } 1155*f4a2713aSLionel Sambuc 1156*f4a2713aSLionel Sambuc case Builtin::BI__atomic_clear: { 1157*f4a2713aSLionel Sambuc QualType PtrTy = E->getArg(0)->IgnoreImpCasts()->getType(); 1158*f4a2713aSLionel Sambuc bool Volatile = 1159*f4a2713aSLionel Sambuc PtrTy->castAs<PointerType>()->getPointeeType().isVolatileQualified(); 1160*f4a2713aSLionel Sambuc 1161*f4a2713aSLionel Sambuc Value *Ptr = EmitScalarExpr(E->getArg(0)); 1162*f4a2713aSLionel Sambuc unsigned AddrSpace = Ptr->getType()->getPointerAddressSpace(); 1163*f4a2713aSLionel Sambuc Ptr = Builder.CreateBitCast(Ptr, Int8Ty->getPointerTo(AddrSpace)); 1164*f4a2713aSLionel Sambuc Value *NewVal = Builder.getInt8(0); 1165*f4a2713aSLionel Sambuc Value *Order = EmitScalarExpr(E->getArg(1)); 1166*f4a2713aSLionel Sambuc if (isa<llvm::ConstantInt>(Order)) { 1167*f4a2713aSLionel Sambuc int ord = cast<llvm::ConstantInt>(Order)->getZExtValue(); 1168*f4a2713aSLionel Sambuc StoreInst *Store = Builder.CreateStore(NewVal, Ptr, Volatile); 1169*f4a2713aSLionel Sambuc Store->setAlignment(1); 1170*f4a2713aSLionel Sambuc switch (ord) { 1171*f4a2713aSLionel Sambuc case 0: // memory_order_relaxed 1172*f4a2713aSLionel Sambuc default: // invalid order 1173*f4a2713aSLionel Sambuc Store->setOrdering(llvm::Monotonic); 1174*f4a2713aSLionel Sambuc break; 1175*f4a2713aSLionel Sambuc case 3: // memory_order_release 1176*f4a2713aSLionel Sambuc Store->setOrdering(llvm::Release); 1177*f4a2713aSLionel Sambuc break; 1178*f4a2713aSLionel Sambuc case 5: // memory_order_seq_cst 1179*f4a2713aSLionel Sambuc Store->setOrdering(llvm::SequentiallyConsistent); 1180*f4a2713aSLionel Sambuc break; 1181*f4a2713aSLionel Sambuc } 1182*f4a2713aSLionel Sambuc return RValue::get(0); 1183*f4a2713aSLionel Sambuc } 1184*f4a2713aSLionel Sambuc 1185*f4a2713aSLionel Sambuc llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn); 1186*f4a2713aSLionel Sambuc 1187*f4a2713aSLionel Sambuc llvm::BasicBlock *BBs[3] = { 1188*f4a2713aSLionel Sambuc createBasicBlock("monotonic", CurFn), 1189*f4a2713aSLionel Sambuc createBasicBlock("release", CurFn), 1190*f4a2713aSLionel Sambuc createBasicBlock("seqcst", CurFn) 1191*f4a2713aSLionel Sambuc }; 1192*f4a2713aSLionel Sambuc llvm::AtomicOrdering Orders[3] = { 1193*f4a2713aSLionel Sambuc llvm::Monotonic, llvm::Release, llvm::SequentiallyConsistent 1194*f4a2713aSLionel Sambuc }; 1195*f4a2713aSLionel Sambuc 1196*f4a2713aSLionel Sambuc Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false); 1197*f4a2713aSLionel Sambuc llvm::SwitchInst *SI = Builder.CreateSwitch(Order, BBs[0]); 1198*f4a2713aSLionel Sambuc 1199*f4a2713aSLionel Sambuc for (unsigned i = 0; i < 3; ++i) { 1200*f4a2713aSLionel Sambuc Builder.SetInsertPoint(BBs[i]); 1201*f4a2713aSLionel Sambuc StoreInst *Store = Builder.CreateStore(NewVal, Ptr, Volatile); 1202*f4a2713aSLionel Sambuc Store->setAlignment(1); 1203*f4a2713aSLionel Sambuc Store->setOrdering(Orders[i]); 1204*f4a2713aSLionel Sambuc Builder.CreateBr(ContBB); 1205*f4a2713aSLionel Sambuc } 1206*f4a2713aSLionel Sambuc 1207*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(0), BBs[0]); 1208*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(3), BBs[1]); 1209*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(5), BBs[2]); 1210*f4a2713aSLionel Sambuc 1211*f4a2713aSLionel Sambuc Builder.SetInsertPoint(ContBB); 1212*f4a2713aSLionel Sambuc return RValue::get(0); 1213*f4a2713aSLionel Sambuc } 1214*f4a2713aSLionel Sambuc 1215*f4a2713aSLionel Sambuc case Builtin::BI__atomic_thread_fence: 1216*f4a2713aSLionel Sambuc case Builtin::BI__atomic_signal_fence: 1217*f4a2713aSLionel Sambuc case Builtin::BI__c11_atomic_thread_fence: 1218*f4a2713aSLionel Sambuc case Builtin::BI__c11_atomic_signal_fence: { 1219*f4a2713aSLionel Sambuc llvm::SynchronizationScope Scope; 1220*f4a2713aSLionel Sambuc if (BuiltinID == Builtin::BI__atomic_signal_fence || 1221*f4a2713aSLionel Sambuc BuiltinID == Builtin::BI__c11_atomic_signal_fence) 1222*f4a2713aSLionel Sambuc Scope = llvm::SingleThread; 1223*f4a2713aSLionel Sambuc else 1224*f4a2713aSLionel Sambuc Scope = llvm::CrossThread; 1225*f4a2713aSLionel Sambuc Value *Order = EmitScalarExpr(E->getArg(0)); 1226*f4a2713aSLionel Sambuc if (isa<llvm::ConstantInt>(Order)) { 1227*f4a2713aSLionel Sambuc int ord = cast<llvm::ConstantInt>(Order)->getZExtValue(); 1228*f4a2713aSLionel Sambuc switch (ord) { 1229*f4a2713aSLionel Sambuc case 0: // memory_order_relaxed 1230*f4a2713aSLionel Sambuc default: // invalid order 1231*f4a2713aSLionel Sambuc break; 1232*f4a2713aSLionel Sambuc case 1: // memory_order_consume 1233*f4a2713aSLionel Sambuc case 2: // memory_order_acquire 1234*f4a2713aSLionel Sambuc Builder.CreateFence(llvm::Acquire, Scope); 1235*f4a2713aSLionel Sambuc break; 1236*f4a2713aSLionel Sambuc case 3: // memory_order_release 1237*f4a2713aSLionel Sambuc Builder.CreateFence(llvm::Release, Scope); 1238*f4a2713aSLionel Sambuc break; 1239*f4a2713aSLionel Sambuc case 4: // memory_order_acq_rel 1240*f4a2713aSLionel Sambuc Builder.CreateFence(llvm::AcquireRelease, Scope); 1241*f4a2713aSLionel Sambuc break; 1242*f4a2713aSLionel Sambuc case 5: // memory_order_seq_cst 1243*f4a2713aSLionel Sambuc Builder.CreateFence(llvm::SequentiallyConsistent, Scope); 1244*f4a2713aSLionel Sambuc break; 1245*f4a2713aSLionel Sambuc } 1246*f4a2713aSLionel Sambuc return RValue::get(0); 1247*f4a2713aSLionel Sambuc } 1248*f4a2713aSLionel Sambuc 1249*f4a2713aSLionel Sambuc llvm::BasicBlock *AcquireBB, *ReleaseBB, *AcqRelBB, *SeqCstBB; 1250*f4a2713aSLionel Sambuc AcquireBB = createBasicBlock("acquire", CurFn); 1251*f4a2713aSLionel Sambuc ReleaseBB = createBasicBlock("release", CurFn); 1252*f4a2713aSLionel Sambuc AcqRelBB = createBasicBlock("acqrel", CurFn); 1253*f4a2713aSLionel Sambuc SeqCstBB = createBasicBlock("seqcst", CurFn); 1254*f4a2713aSLionel Sambuc llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn); 1255*f4a2713aSLionel Sambuc 1256*f4a2713aSLionel Sambuc Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false); 1257*f4a2713aSLionel Sambuc llvm::SwitchInst *SI = Builder.CreateSwitch(Order, ContBB); 1258*f4a2713aSLionel Sambuc 1259*f4a2713aSLionel Sambuc Builder.SetInsertPoint(AcquireBB); 1260*f4a2713aSLionel Sambuc Builder.CreateFence(llvm::Acquire, Scope); 1261*f4a2713aSLionel Sambuc Builder.CreateBr(ContBB); 1262*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(1), AcquireBB); 1263*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(2), AcquireBB); 1264*f4a2713aSLionel Sambuc 1265*f4a2713aSLionel Sambuc Builder.SetInsertPoint(ReleaseBB); 1266*f4a2713aSLionel Sambuc Builder.CreateFence(llvm::Release, Scope); 1267*f4a2713aSLionel Sambuc Builder.CreateBr(ContBB); 1268*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(3), ReleaseBB); 1269*f4a2713aSLionel Sambuc 1270*f4a2713aSLionel Sambuc Builder.SetInsertPoint(AcqRelBB); 1271*f4a2713aSLionel Sambuc Builder.CreateFence(llvm::AcquireRelease, Scope); 1272*f4a2713aSLionel Sambuc Builder.CreateBr(ContBB); 1273*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(4), AcqRelBB); 1274*f4a2713aSLionel Sambuc 1275*f4a2713aSLionel Sambuc Builder.SetInsertPoint(SeqCstBB); 1276*f4a2713aSLionel Sambuc Builder.CreateFence(llvm::SequentiallyConsistent, Scope); 1277*f4a2713aSLionel Sambuc Builder.CreateBr(ContBB); 1278*f4a2713aSLionel Sambuc SI->addCase(Builder.getInt32(5), SeqCstBB); 1279*f4a2713aSLionel Sambuc 1280*f4a2713aSLionel Sambuc Builder.SetInsertPoint(ContBB); 1281*f4a2713aSLionel Sambuc return RValue::get(0); 1282*f4a2713aSLionel Sambuc } 1283*f4a2713aSLionel Sambuc 1284*f4a2713aSLionel Sambuc // Library functions with special handling. 1285*f4a2713aSLionel Sambuc case Builtin::BIsqrt: 1286*f4a2713aSLionel Sambuc case Builtin::BIsqrtf: 1287*f4a2713aSLionel Sambuc case Builtin::BIsqrtl: { 1288*f4a2713aSLionel Sambuc // Transform a call to sqrt* into a @llvm.sqrt.* intrinsic call, but only 1289*f4a2713aSLionel Sambuc // in finite- or unsafe-math mode (the intrinsic has different semantics 1290*f4a2713aSLionel Sambuc // for handling negative numbers compared to the library function, so 1291*f4a2713aSLionel Sambuc // -fmath-errno=0 is not enough). 1292*f4a2713aSLionel Sambuc if (!FD->hasAttr<ConstAttr>()) 1293*f4a2713aSLionel Sambuc break; 1294*f4a2713aSLionel Sambuc if (!(CGM.getCodeGenOpts().UnsafeFPMath || 1295*f4a2713aSLionel Sambuc CGM.getCodeGenOpts().NoNaNsFPMath)) 1296*f4a2713aSLionel Sambuc break; 1297*f4a2713aSLionel Sambuc Value *Arg0 = EmitScalarExpr(E->getArg(0)); 1298*f4a2713aSLionel Sambuc llvm::Type *ArgType = Arg0->getType(); 1299*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::sqrt, ArgType); 1300*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall(F, Arg0)); 1301*f4a2713aSLionel Sambuc } 1302*f4a2713aSLionel Sambuc 1303*f4a2713aSLionel Sambuc case Builtin::BIpow: 1304*f4a2713aSLionel Sambuc case Builtin::BIpowf: 1305*f4a2713aSLionel Sambuc case Builtin::BIpowl: { 1306*f4a2713aSLionel Sambuc // Transform a call to pow* into a @llvm.pow.* intrinsic call. 1307*f4a2713aSLionel Sambuc if (!FD->hasAttr<ConstAttr>()) 1308*f4a2713aSLionel Sambuc break; 1309*f4a2713aSLionel Sambuc Value *Base = EmitScalarExpr(E->getArg(0)); 1310*f4a2713aSLionel Sambuc Value *Exponent = EmitScalarExpr(E->getArg(1)); 1311*f4a2713aSLionel Sambuc llvm::Type *ArgType = Base->getType(); 1312*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::pow, ArgType); 1313*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall2(F, Base, Exponent)); 1314*f4a2713aSLionel Sambuc break; 1315*f4a2713aSLionel Sambuc } 1316*f4a2713aSLionel Sambuc 1317*f4a2713aSLionel Sambuc case Builtin::BIfma: 1318*f4a2713aSLionel Sambuc case Builtin::BIfmaf: 1319*f4a2713aSLionel Sambuc case Builtin::BIfmal: 1320*f4a2713aSLionel Sambuc case Builtin::BI__builtin_fma: 1321*f4a2713aSLionel Sambuc case Builtin::BI__builtin_fmaf: 1322*f4a2713aSLionel Sambuc case Builtin::BI__builtin_fmal: { 1323*f4a2713aSLionel Sambuc // Rewrite fma to intrinsic. 1324*f4a2713aSLionel Sambuc Value *FirstArg = EmitScalarExpr(E->getArg(0)); 1325*f4a2713aSLionel Sambuc llvm::Type *ArgType = FirstArg->getType(); 1326*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::fma, ArgType); 1327*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateCall3(F, FirstArg, 1328*f4a2713aSLionel Sambuc EmitScalarExpr(E->getArg(1)), 1329*f4a2713aSLionel Sambuc EmitScalarExpr(E->getArg(2)))); 1330*f4a2713aSLionel Sambuc } 1331*f4a2713aSLionel Sambuc 1332*f4a2713aSLionel Sambuc case Builtin::BI__builtin_signbit: 1333*f4a2713aSLionel Sambuc case Builtin::BI__builtin_signbitf: 1334*f4a2713aSLionel Sambuc case Builtin::BI__builtin_signbitl: { 1335*f4a2713aSLionel Sambuc LLVMContext &C = CGM.getLLVMContext(); 1336*f4a2713aSLionel Sambuc 1337*f4a2713aSLionel Sambuc Value *Arg = EmitScalarExpr(E->getArg(0)); 1338*f4a2713aSLionel Sambuc llvm::Type *ArgTy = Arg->getType(); 1339*f4a2713aSLionel Sambuc if (ArgTy->isPPC_FP128Ty()) 1340*f4a2713aSLionel Sambuc break; // FIXME: I'm not sure what the right implementation is here. 1341*f4a2713aSLionel Sambuc int ArgWidth = ArgTy->getPrimitiveSizeInBits(); 1342*f4a2713aSLionel Sambuc llvm::Type *ArgIntTy = llvm::IntegerType::get(C, ArgWidth); 1343*f4a2713aSLionel Sambuc Value *BCArg = Builder.CreateBitCast(Arg, ArgIntTy); 1344*f4a2713aSLionel Sambuc Value *ZeroCmp = llvm::Constant::getNullValue(ArgIntTy); 1345*f4a2713aSLionel Sambuc Value *Result = Builder.CreateICmpSLT(BCArg, ZeroCmp); 1346*f4a2713aSLionel Sambuc return RValue::get(Builder.CreateZExt(Result, ConvertType(E->getType()))); 1347*f4a2713aSLionel Sambuc } 1348*f4a2713aSLionel Sambuc case Builtin::BI__builtin_annotation: { 1349*f4a2713aSLionel Sambuc llvm::Value *AnnVal = EmitScalarExpr(E->getArg(0)); 1350*f4a2713aSLionel Sambuc llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::annotation, 1351*f4a2713aSLionel Sambuc AnnVal->getType()); 1352*f4a2713aSLionel Sambuc 1353*f4a2713aSLionel Sambuc // Get the annotation string, go through casts. Sema requires this to be a 1354*f4a2713aSLionel Sambuc // non-wide string literal, potentially casted, so the cast<> is safe. 1355*f4a2713aSLionel Sambuc const Expr *AnnotationStrExpr = E->getArg(1)->IgnoreParenCasts(); 1356*f4a2713aSLionel Sambuc StringRef Str = cast<StringLiteral>(AnnotationStrExpr)->getString(); 1357*f4a2713aSLionel Sambuc return RValue::get(EmitAnnotationCall(F, AnnVal, Str, E->getExprLoc())); 1358*f4a2713aSLionel Sambuc } 1359*f4a2713aSLionel Sambuc case Builtin::BI__builtin_addcb: 1360*f4a2713aSLionel Sambuc case Builtin::BI__builtin_addcs: 1361*f4a2713aSLionel Sambuc case Builtin::BI__builtin_addc: 1362*f4a2713aSLionel Sambuc case Builtin::BI__builtin_addcl: 1363*f4a2713aSLionel Sambuc case Builtin::BI__builtin_addcll: 1364*f4a2713aSLionel Sambuc case Builtin::BI__builtin_subcb: 1365*f4a2713aSLionel Sambuc case Builtin::BI__builtin_subcs: 1366*f4a2713aSLionel Sambuc case Builtin::BI__builtin_subc: 1367*f4a2713aSLionel Sambuc case Builtin::BI__builtin_subcl: 1368*f4a2713aSLionel Sambuc case Builtin::BI__builtin_subcll: { 1369*f4a2713aSLionel Sambuc 1370*f4a2713aSLionel Sambuc // We translate all of these builtins from expressions of the form: 1371*f4a2713aSLionel Sambuc // int x = ..., y = ..., carryin = ..., carryout, result; 1372*f4a2713aSLionel Sambuc // result = __builtin_addc(x, y, carryin, &carryout); 1373*f4a2713aSLionel Sambuc // 1374*f4a2713aSLionel Sambuc // to LLVM IR of the form: 1375*f4a2713aSLionel Sambuc // 1376*f4a2713aSLionel Sambuc // %tmp1 = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %x, i32 %y) 1377*f4a2713aSLionel Sambuc // %tmpsum1 = extractvalue {i32, i1} %tmp1, 0 1378*f4a2713aSLionel Sambuc // %carry1 = extractvalue {i32, i1} %tmp1, 1 1379*f4a2713aSLionel Sambuc // %tmp2 = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %tmpsum1, 1380*f4a2713aSLionel Sambuc // i32 %carryin) 1381*f4a2713aSLionel Sambuc // %result = extractvalue {i32, i1} %tmp2, 0 1382*f4a2713aSLionel Sambuc // %carry2 = extractvalue {i32, i1} %tmp2, 1 1383*f4a2713aSLionel Sambuc // %tmp3 = or i1 %carry1, %carry2 1384*f4a2713aSLionel Sambuc // %tmp4 = zext i1 %tmp3 to i32 1385*f4a2713aSLionel Sambuc // store i32 %tmp4, i32* %carryout 1386*f4a2713aSLionel Sambuc 1387*f4a2713aSLionel Sambuc // Scalarize our inputs. 1388*f4a2713aSLionel Sambuc llvm::Value *X = EmitScalarExpr(E->getArg(0)); 1389*f4a2713aSLionel Sambuc llvm::Value *Y = EmitScalarExpr(E->getArg(1)); 1390*f4a2713aSLionel Sambuc llvm::Value *Carryin = EmitScalarExpr(E->getArg(2)); 1391*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> CarryOutPtr = 1392*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(3)); 1393*f4a2713aSLionel Sambuc 1394*f4a2713aSLionel Sambuc // Decide if we are lowering to a uadd.with.overflow or usub.with.overflow. 1395*f4a2713aSLionel Sambuc llvm::Intrinsic::ID IntrinsicId; 1396*f4a2713aSLionel Sambuc switch (BuiltinID) { 1397*f4a2713aSLionel Sambuc default: llvm_unreachable("Unknown multiprecision builtin id."); 1398*f4a2713aSLionel Sambuc case Builtin::BI__builtin_addcb: 1399*f4a2713aSLionel Sambuc case Builtin::BI__builtin_addcs: 1400*f4a2713aSLionel Sambuc case Builtin::BI__builtin_addc: 1401*f4a2713aSLionel Sambuc case Builtin::BI__builtin_addcl: 1402*f4a2713aSLionel Sambuc case Builtin::BI__builtin_addcll: 1403*f4a2713aSLionel Sambuc IntrinsicId = llvm::Intrinsic::uadd_with_overflow; 1404*f4a2713aSLionel Sambuc break; 1405*f4a2713aSLionel Sambuc case Builtin::BI__builtin_subcb: 1406*f4a2713aSLionel Sambuc case Builtin::BI__builtin_subcs: 1407*f4a2713aSLionel Sambuc case Builtin::BI__builtin_subc: 1408*f4a2713aSLionel Sambuc case Builtin::BI__builtin_subcl: 1409*f4a2713aSLionel Sambuc case Builtin::BI__builtin_subcll: 1410*f4a2713aSLionel Sambuc IntrinsicId = llvm::Intrinsic::usub_with_overflow; 1411*f4a2713aSLionel Sambuc break; 1412*f4a2713aSLionel Sambuc } 1413*f4a2713aSLionel Sambuc 1414*f4a2713aSLionel Sambuc // Construct our resulting LLVM IR expression. 1415*f4a2713aSLionel Sambuc llvm::Value *Carry1; 1416*f4a2713aSLionel Sambuc llvm::Value *Sum1 = EmitOverflowIntrinsic(*this, IntrinsicId, 1417*f4a2713aSLionel Sambuc X, Y, Carry1); 1418*f4a2713aSLionel Sambuc llvm::Value *Carry2; 1419*f4a2713aSLionel Sambuc llvm::Value *Sum2 = EmitOverflowIntrinsic(*this, IntrinsicId, 1420*f4a2713aSLionel Sambuc Sum1, Carryin, Carry2); 1421*f4a2713aSLionel Sambuc llvm::Value *CarryOut = Builder.CreateZExt(Builder.CreateOr(Carry1, Carry2), 1422*f4a2713aSLionel Sambuc X->getType()); 1423*f4a2713aSLionel Sambuc llvm::StoreInst *CarryOutStore = Builder.CreateStore(CarryOut, 1424*f4a2713aSLionel Sambuc CarryOutPtr.first); 1425*f4a2713aSLionel Sambuc CarryOutStore->setAlignment(CarryOutPtr.second); 1426*f4a2713aSLionel Sambuc return RValue::get(Sum2); 1427*f4a2713aSLionel Sambuc } 1428*f4a2713aSLionel Sambuc case Builtin::BI__builtin_uadd_overflow: 1429*f4a2713aSLionel Sambuc case Builtin::BI__builtin_uaddl_overflow: 1430*f4a2713aSLionel Sambuc case Builtin::BI__builtin_uaddll_overflow: 1431*f4a2713aSLionel Sambuc case Builtin::BI__builtin_usub_overflow: 1432*f4a2713aSLionel Sambuc case Builtin::BI__builtin_usubl_overflow: 1433*f4a2713aSLionel Sambuc case Builtin::BI__builtin_usubll_overflow: 1434*f4a2713aSLionel Sambuc case Builtin::BI__builtin_umul_overflow: 1435*f4a2713aSLionel Sambuc case Builtin::BI__builtin_umull_overflow: 1436*f4a2713aSLionel Sambuc case Builtin::BI__builtin_umulll_overflow: 1437*f4a2713aSLionel Sambuc case Builtin::BI__builtin_sadd_overflow: 1438*f4a2713aSLionel Sambuc case Builtin::BI__builtin_saddl_overflow: 1439*f4a2713aSLionel Sambuc case Builtin::BI__builtin_saddll_overflow: 1440*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ssub_overflow: 1441*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ssubl_overflow: 1442*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ssubll_overflow: 1443*f4a2713aSLionel Sambuc case Builtin::BI__builtin_smul_overflow: 1444*f4a2713aSLionel Sambuc case Builtin::BI__builtin_smull_overflow: 1445*f4a2713aSLionel Sambuc case Builtin::BI__builtin_smulll_overflow: { 1446*f4a2713aSLionel Sambuc 1447*f4a2713aSLionel Sambuc // We translate all of these builtins directly to the relevant llvm IR node. 1448*f4a2713aSLionel Sambuc 1449*f4a2713aSLionel Sambuc // Scalarize our inputs. 1450*f4a2713aSLionel Sambuc llvm::Value *X = EmitScalarExpr(E->getArg(0)); 1451*f4a2713aSLionel Sambuc llvm::Value *Y = EmitScalarExpr(E->getArg(1)); 1452*f4a2713aSLionel Sambuc std::pair<llvm::Value *, unsigned> SumOutPtr = 1453*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(2)); 1454*f4a2713aSLionel Sambuc 1455*f4a2713aSLionel Sambuc // Decide which of the overflow intrinsics we are lowering to: 1456*f4a2713aSLionel Sambuc llvm::Intrinsic::ID IntrinsicId; 1457*f4a2713aSLionel Sambuc switch (BuiltinID) { 1458*f4a2713aSLionel Sambuc default: llvm_unreachable("Unknown security overflow builtin id."); 1459*f4a2713aSLionel Sambuc case Builtin::BI__builtin_uadd_overflow: 1460*f4a2713aSLionel Sambuc case Builtin::BI__builtin_uaddl_overflow: 1461*f4a2713aSLionel Sambuc case Builtin::BI__builtin_uaddll_overflow: 1462*f4a2713aSLionel Sambuc IntrinsicId = llvm::Intrinsic::uadd_with_overflow; 1463*f4a2713aSLionel Sambuc break; 1464*f4a2713aSLionel Sambuc case Builtin::BI__builtin_usub_overflow: 1465*f4a2713aSLionel Sambuc case Builtin::BI__builtin_usubl_overflow: 1466*f4a2713aSLionel Sambuc case Builtin::BI__builtin_usubll_overflow: 1467*f4a2713aSLionel Sambuc IntrinsicId = llvm::Intrinsic::usub_with_overflow; 1468*f4a2713aSLionel Sambuc break; 1469*f4a2713aSLionel Sambuc case Builtin::BI__builtin_umul_overflow: 1470*f4a2713aSLionel Sambuc case Builtin::BI__builtin_umull_overflow: 1471*f4a2713aSLionel Sambuc case Builtin::BI__builtin_umulll_overflow: 1472*f4a2713aSLionel Sambuc IntrinsicId = llvm::Intrinsic::umul_with_overflow; 1473*f4a2713aSLionel Sambuc break; 1474*f4a2713aSLionel Sambuc case Builtin::BI__builtin_sadd_overflow: 1475*f4a2713aSLionel Sambuc case Builtin::BI__builtin_saddl_overflow: 1476*f4a2713aSLionel Sambuc case Builtin::BI__builtin_saddll_overflow: 1477*f4a2713aSLionel Sambuc IntrinsicId = llvm::Intrinsic::sadd_with_overflow; 1478*f4a2713aSLionel Sambuc break; 1479*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ssub_overflow: 1480*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ssubl_overflow: 1481*f4a2713aSLionel Sambuc case Builtin::BI__builtin_ssubll_overflow: 1482*f4a2713aSLionel Sambuc IntrinsicId = llvm::Intrinsic::ssub_with_overflow; 1483*f4a2713aSLionel Sambuc break; 1484*f4a2713aSLionel Sambuc case Builtin::BI__builtin_smul_overflow: 1485*f4a2713aSLionel Sambuc case Builtin::BI__builtin_smull_overflow: 1486*f4a2713aSLionel Sambuc case Builtin::BI__builtin_smulll_overflow: 1487*f4a2713aSLionel Sambuc IntrinsicId = llvm::Intrinsic::smul_with_overflow; 1488*f4a2713aSLionel Sambuc break; 1489*f4a2713aSLionel Sambuc } 1490*f4a2713aSLionel Sambuc 1491*f4a2713aSLionel Sambuc 1492*f4a2713aSLionel Sambuc llvm::Value *Carry; 1493*f4a2713aSLionel Sambuc llvm::Value *Sum = EmitOverflowIntrinsic(*this, IntrinsicId, X, Y, Carry); 1494*f4a2713aSLionel Sambuc llvm::StoreInst *SumOutStore = Builder.CreateStore(Sum, SumOutPtr.first); 1495*f4a2713aSLionel Sambuc SumOutStore->setAlignment(SumOutPtr.second); 1496*f4a2713aSLionel Sambuc 1497*f4a2713aSLionel Sambuc return RValue::get(Carry); 1498*f4a2713aSLionel Sambuc } 1499*f4a2713aSLionel Sambuc case Builtin::BI__builtin_addressof: 1500*f4a2713aSLionel Sambuc return RValue::get(EmitLValue(E->getArg(0)).getAddress()); 1501*f4a2713aSLionel Sambuc case Builtin::BI__noop: 1502*f4a2713aSLionel Sambuc return RValue::get(0); 1503*f4a2713aSLionel Sambuc } 1504*f4a2713aSLionel Sambuc 1505*f4a2713aSLionel Sambuc // If this is an alias for a lib function (e.g. __builtin_sin), emit 1506*f4a2713aSLionel Sambuc // the call using the normal call path, but using the unmangled 1507*f4a2713aSLionel Sambuc // version of the function name. 1508*f4a2713aSLionel Sambuc if (getContext().BuiltinInfo.isLibFunction(BuiltinID)) 1509*f4a2713aSLionel Sambuc return emitLibraryCall(*this, FD, E, 1510*f4a2713aSLionel Sambuc CGM.getBuiltinLibFunction(FD, BuiltinID)); 1511*f4a2713aSLionel Sambuc 1512*f4a2713aSLionel Sambuc // If this is a predefined lib function (e.g. malloc), emit the call 1513*f4a2713aSLionel Sambuc // using exactly the normal call path. 1514*f4a2713aSLionel Sambuc if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) 1515*f4a2713aSLionel Sambuc return emitLibraryCall(*this, FD, E, EmitScalarExpr(E->getCallee())); 1516*f4a2713aSLionel Sambuc 1517*f4a2713aSLionel Sambuc // See if we have a target specific intrinsic. 1518*f4a2713aSLionel Sambuc const char *Name = getContext().BuiltinInfo.GetName(BuiltinID); 1519*f4a2713aSLionel Sambuc Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic; 1520*f4a2713aSLionel Sambuc if (const char *Prefix = 1521*f4a2713aSLionel Sambuc llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch())) 1522*f4a2713aSLionel Sambuc IntrinsicID = Intrinsic::getIntrinsicForGCCBuiltin(Prefix, Name); 1523*f4a2713aSLionel Sambuc 1524*f4a2713aSLionel Sambuc if (IntrinsicID != Intrinsic::not_intrinsic) { 1525*f4a2713aSLionel Sambuc SmallVector<Value*, 16> Args; 1526*f4a2713aSLionel Sambuc 1527*f4a2713aSLionel Sambuc // Find out if any arguments are required to be integer constant 1528*f4a2713aSLionel Sambuc // expressions. 1529*f4a2713aSLionel Sambuc unsigned ICEArguments = 0; 1530*f4a2713aSLionel Sambuc ASTContext::GetBuiltinTypeError Error; 1531*f4a2713aSLionel Sambuc getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments); 1532*f4a2713aSLionel Sambuc assert(Error == ASTContext::GE_None && "Should not codegen an error"); 1533*f4a2713aSLionel Sambuc 1534*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(IntrinsicID); 1535*f4a2713aSLionel Sambuc llvm::FunctionType *FTy = F->getFunctionType(); 1536*f4a2713aSLionel Sambuc 1537*f4a2713aSLionel Sambuc for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { 1538*f4a2713aSLionel Sambuc Value *ArgValue; 1539*f4a2713aSLionel Sambuc // If this is a normal argument, just emit it as a scalar. 1540*f4a2713aSLionel Sambuc if ((ICEArguments & (1 << i)) == 0) { 1541*f4a2713aSLionel Sambuc ArgValue = EmitScalarExpr(E->getArg(i)); 1542*f4a2713aSLionel Sambuc } else { 1543*f4a2713aSLionel Sambuc // If this is required to be a constant, constant fold it so that we 1544*f4a2713aSLionel Sambuc // know that the generated intrinsic gets a ConstantInt. 1545*f4a2713aSLionel Sambuc llvm::APSInt Result; 1546*f4a2713aSLionel Sambuc bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result,getContext()); 1547*f4a2713aSLionel Sambuc assert(IsConst && "Constant arg isn't actually constant?"); 1548*f4a2713aSLionel Sambuc (void)IsConst; 1549*f4a2713aSLionel Sambuc ArgValue = llvm::ConstantInt::get(getLLVMContext(), Result); 1550*f4a2713aSLionel Sambuc } 1551*f4a2713aSLionel Sambuc 1552*f4a2713aSLionel Sambuc // If the intrinsic arg type is different from the builtin arg type 1553*f4a2713aSLionel Sambuc // we need to do a bit cast. 1554*f4a2713aSLionel Sambuc llvm::Type *PTy = FTy->getParamType(i); 1555*f4a2713aSLionel Sambuc if (PTy != ArgValue->getType()) { 1556*f4a2713aSLionel Sambuc assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) && 1557*f4a2713aSLionel Sambuc "Must be able to losslessly bit cast to param"); 1558*f4a2713aSLionel Sambuc ArgValue = Builder.CreateBitCast(ArgValue, PTy); 1559*f4a2713aSLionel Sambuc } 1560*f4a2713aSLionel Sambuc 1561*f4a2713aSLionel Sambuc Args.push_back(ArgValue); 1562*f4a2713aSLionel Sambuc } 1563*f4a2713aSLionel Sambuc 1564*f4a2713aSLionel Sambuc Value *V = Builder.CreateCall(F, Args); 1565*f4a2713aSLionel Sambuc QualType BuiltinRetType = E->getType(); 1566*f4a2713aSLionel Sambuc 1567*f4a2713aSLionel Sambuc llvm::Type *RetTy = VoidTy; 1568*f4a2713aSLionel Sambuc if (!BuiltinRetType->isVoidType()) 1569*f4a2713aSLionel Sambuc RetTy = ConvertType(BuiltinRetType); 1570*f4a2713aSLionel Sambuc 1571*f4a2713aSLionel Sambuc if (RetTy != V->getType()) { 1572*f4a2713aSLionel Sambuc assert(V->getType()->canLosslesslyBitCastTo(RetTy) && 1573*f4a2713aSLionel Sambuc "Must be able to losslessly bit cast result type"); 1574*f4a2713aSLionel Sambuc V = Builder.CreateBitCast(V, RetTy); 1575*f4a2713aSLionel Sambuc } 1576*f4a2713aSLionel Sambuc 1577*f4a2713aSLionel Sambuc return RValue::get(V); 1578*f4a2713aSLionel Sambuc } 1579*f4a2713aSLionel Sambuc 1580*f4a2713aSLionel Sambuc // See if we have a target specific builtin that needs to be lowered. 1581*f4a2713aSLionel Sambuc if (Value *V = EmitTargetBuiltinExpr(BuiltinID, E)) 1582*f4a2713aSLionel Sambuc return RValue::get(V); 1583*f4a2713aSLionel Sambuc 1584*f4a2713aSLionel Sambuc ErrorUnsupported(E, "builtin function"); 1585*f4a2713aSLionel Sambuc 1586*f4a2713aSLionel Sambuc // Unknown builtin, for now just dump it out and return undef. 1587*f4a2713aSLionel Sambuc return GetUndefRValue(E->getType()); 1588*f4a2713aSLionel Sambuc } 1589*f4a2713aSLionel Sambuc 1590*f4a2713aSLionel Sambuc Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, 1591*f4a2713aSLionel Sambuc const CallExpr *E) { 1592*f4a2713aSLionel Sambuc switch (getTarget().getTriple().getArch()) { 1593*f4a2713aSLionel Sambuc case llvm::Triple::aarch64: 1594*f4a2713aSLionel Sambuc return EmitAArch64BuiltinExpr(BuiltinID, E); 1595*f4a2713aSLionel Sambuc case llvm::Triple::arm: 1596*f4a2713aSLionel Sambuc case llvm::Triple::thumb: 1597*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(BuiltinID, E); 1598*f4a2713aSLionel Sambuc case llvm::Triple::x86: 1599*f4a2713aSLionel Sambuc case llvm::Triple::x86_64: 1600*f4a2713aSLionel Sambuc return EmitX86BuiltinExpr(BuiltinID, E); 1601*f4a2713aSLionel Sambuc case llvm::Triple::ppc: 1602*f4a2713aSLionel Sambuc case llvm::Triple::ppc64: 1603*f4a2713aSLionel Sambuc case llvm::Triple::ppc64le: 1604*f4a2713aSLionel Sambuc return EmitPPCBuiltinExpr(BuiltinID, E); 1605*f4a2713aSLionel Sambuc default: 1606*f4a2713aSLionel Sambuc return 0; 1607*f4a2713aSLionel Sambuc } 1608*f4a2713aSLionel Sambuc } 1609*f4a2713aSLionel Sambuc 1610*f4a2713aSLionel Sambuc static llvm::VectorType *GetNeonType(CodeGenFunction *CGF, 1611*f4a2713aSLionel Sambuc NeonTypeFlags TypeFlags, 1612*f4a2713aSLionel Sambuc bool V1Ty=false) { 1613*f4a2713aSLionel Sambuc int IsQuad = TypeFlags.isQuad(); 1614*f4a2713aSLionel Sambuc switch (TypeFlags.getEltType()) { 1615*f4a2713aSLionel Sambuc case NeonTypeFlags::Int8: 1616*f4a2713aSLionel Sambuc case NeonTypeFlags::Poly8: 1617*f4a2713aSLionel Sambuc return llvm::VectorType::get(CGF->Int8Ty, V1Ty ? 1 : (8 << IsQuad)); 1618*f4a2713aSLionel Sambuc case NeonTypeFlags::Int16: 1619*f4a2713aSLionel Sambuc case NeonTypeFlags::Poly16: 1620*f4a2713aSLionel Sambuc case NeonTypeFlags::Float16: 1621*f4a2713aSLionel Sambuc return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad)); 1622*f4a2713aSLionel Sambuc case NeonTypeFlags::Int32: 1623*f4a2713aSLionel Sambuc return llvm::VectorType::get(CGF->Int32Ty, V1Ty ? 1 : (2 << IsQuad)); 1624*f4a2713aSLionel Sambuc case NeonTypeFlags::Int64: 1625*f4a2713aSLionel Sambuc case NeonTypeFlags::Poly64: 1626*f4a2713aSLionel Sambuc return llvm::VectorType::get(CGF->Int64Ty, V1Ty ? 1 : (1 << IsQuad)); 1627*f4a2713aSLionel Sambuc case NeonTypeFlags::Float32: 1628*f4a2713aSLionel Sambuc return llvm::VectorType::get(CGF->FloatTy, V1Ty ? 1 : (2 << IsQuad)); 1629*f4a2713aSLionel Sambuc case NeonTypeFlags::Float64: 1630*f4a2713aSLionel Sambuc return llvm::VectorType::get(CGF->DoubleTy, V1Ty ? 1 : (1 << IsQuad)); 1631*f4a2713aSLionel Sambuc } 1632*f4a2713aSLionel Sambuc llvm_unreachable("Unknown vector element type!"); 1633*f4a2713aSLionel Sambuc } 1634*f4a2713aSLionel Sambuc 1635*f4a2713aSLionel Sambuc Value *CodeGenFunction::EmitNeonSplat(Value *V, Constant *C) { 1636*f4a2713aSLionel Sambuc unsigned nElts = cast<llvm::VectorType>(V->getType())->getNumElements(); 1637*f4a2713aSLionel Sambuc Value* SV = llvm::ConstantVector::getSplat(nElts, C); 1638*f4a2713aSLionel Sambuc return Builder.CreateShuffleVector(V, V, SV, "lane"); 1639*f4a2713aSLionel Sambuc } 1640*f4a2713aSLionel Sambuc 1641*f4a2713aSLionel Sambuc Value *CodeGenFunction::EmitNeonCall(Function *F, SmallVectorImpl<Value*> &Ops, 1642*f4a2713aSLionel Sambuc const char *name, 1643*f4a2713aSLionel Sambuc unsigned shift, bool rightshift) { 1644*f4a2713aSLionel Sambuc unsigned j = 0; 1645*f4a2713aSLionel Sambuc for (Function::const_arg_iterator ai = F->arg_begin(), ae = F->arg_end(); 1646*f4a2713aSLionel Sambuc ai != ae; ++ai, ++j) 1647*f4a2713aSLionel Sambuc if (shift > 0 && shift == j) 1648*f4a2713aSLionel Sambuc Ops[j] = EmitNeonShiftVector(Ops[j], ai->getType(), rightshift); 1649*f4a2713aSLionel Sambuc else 1650*f4a2713aSLionel Sambuc Ops[j] = Builder.CreateBitCast(Ops[j], ai->getType(), name); 1651*f4a2713aSLionel Sambuc 1652*f4a2713aSLionel Sambuc return Builder.CreateCall(F, Ops, name); 1653*f4a2713aSLionel Sambuc } 1654*f4a2713aSLionel Sambuc 1655*f4a2713aSLionel Sambuc Value *CodeGenFunction::EmitNeonShiftVector(Value *V, llvm::Type *Ty, 1656*f4a2713aSLionel Sambuc bool neg) { 1657*f4a2713aSLionel Sambuc int SV = cast<ConstantInt>(V)->getSExtValue(); 1658*f4a2713aSLionel Sambuc 1659*f4a2713aSLionel Sambuc llvm::VectorType *VTy = cast<llvm::VectorType>(Ty); 1660*f4a2713aSLionel Sambuc llvm::Constant *C = ConstantInt::get(VTy->getElementType(), neg ? -SV : SV); 1661*f4a2713aSLionel Sambuc return llvm::ConstantVector::getSplat(VTy->getNumElements(), C); 1662*f4a2713aSLionel Sambuc } 1663*f4a2713aSLionel Sambuc 1664*f4a2713aSLionel Sambuc // \brief Right-shift a vector by a constant. 1665*f4a2713aSLionel Sambuc Value *CodeGenFunction::EmitNeonRShiftImm(Value *Vec, Value *Shift, 1666*f4a2713aSLionel Sambuc llvm::Type *Ty, bool usgn, 1667*f4a2713aSLionel Sambuc const char *name) { 1668*f4a2713aSLionel Sambuc llvm::VectorType *VTy = cast<llvm::VectorType>(Ty); 1669*f4a2713aSLionel Sambuc 1670*f4a2713aSLionel Sambuc int ShiftAmt = cast<ConstantInt>(Shift)->getSExtValue(); 1671*f4a2713aSLionel Sambuc int EltSize = VTy->getScalarSizeInBits(); 1672*f4a2713aSLionel Sambuc 1673*f4a2713aSLionel Sambuc Vec = Builder.CreateBitCast(Vec, Ty); 1674*f4a2713aSLionel Sambuc 1675*f4a2713aSLionel Sambuc // lshr/ashr are undefined when the shift amount is equal to the vector 1676*f4a2713aSLionel Sambuc // element size. 1677*f4a2713aSLionel Sambuc if (ShiftAmt == EltSize) { 1678*f4a2713aSLionel Sambuc if (usgn) { 1679*f4a2713aSLionel Sambuc // Right-shifting an unsigned value by its size yields 0. 1680*f4a2713aSLionel Sambuc llvm::Constant *Zero = ConstantInt::get(VTy->getElementType(), 0); 1681*f4a2713aSLionel Sambuc return llvm::ConstantVector::getSplat(VTy->getNumElements(), Zero); 1682*f4a2713aSLionel Sambuc } else { 1683*f4a2713aSLionel Sambuc // Right-shifting a signed value by its size is equivalent 1684*f4a2713aSLionel Sambuc // to a shift of size-1. 1685*f4a2713aSLionel Sambuc --ShiftAmt; 1686*f4a2713aSLionel Sambuc Shift = ConstantInt::get(VTy->getElementType(), ShiftAmt); 1687*f4a2713aSLionel Sambuc } 1688*f4a2713aSLionel Sambuc } 1689*f4a2713aSLionel Sambuc 1690*f4a2713aSLionel Sambuc Shift = EmitNeonShiftVector(Shift, Ty, false); 1691*f4a2713aSLionel Sambuc if (usgn) 1692*f4a2713aSLionel Sambuc return Builder.CreateLShr(Vec, Shift, name); 1693*f4a2713aSLionel Sambuc else 1694*f4a2713aSLionel Sambuc return Builder.CreateAShr(Vec, Shift, name); 1695*f4a2713aSLionel Sambuc } 1696*f4a2713aSLionel Sambuc 1697*f4a2713aSLionel Sambuc /// GetPointeeAlignment - Given an expression with a pointer type, find the 1698*f4a2713aSLionel Sambuc /// alignment of the type referenced by the pointer. Skip over implicit 1699*f4a2713aSLionel Sambuc /// casts. 1700*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> 1701*f4a2713aSLionel Sambuc CodeGenFunction::EmitPointerWithAlignment(const Expr *Addr) { 1702*f4a2713aSLionel Sambuc assert(Addr->getType()->isPointerType()); 1703*f4a2713aSLionel Sambuc Addr = Addr->IgnoreParens(); 1704*f4a2713aSLionel Sambuc if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Addr)) { 1705*f4a2713aSLionel Sambuc if ((ICE->getCastKind() == CK_BitCast || ICE->getCastKind() == CK_NoOp) && 1706*f4a2713aSLionel Sambuc ICE->getSubExpr()->getType()->isPointerType()) { 1707*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Ptr = 1708*f4a2713aSLionel Sambuc EmitPointerWithAlignment(ICE->getSubExpr()); 1709*f4a2713aSLionel Sambuc Ptr.first = Builder.CreateBitCast(Ptr.first, 1710*f4a2713aSLionel Sambuc ConvertType(Addr->getType())); 1711*f4a2713aSLionel Sambuc return Ptr; 1712*f4a2713aSLionel Sambuc } else if (ICE->getCastKind() == CK_ArrayToPointerDecay) { 1713*f4a2713aSLionel Sambuc LValue LV = EmitLValue(ICE->getSubExpr()); 1714*f4a2713aSLionel Sambuc unsigned Align = LV.getAlignment().getQuantity(); 1715*f4a2713aSLionel Sambuc if (!Align) { 1716*f4a2713aSLionel Sambuc // FIXME: Once LValues are fixed to always set alignment, 1717*f4a2713aSLionel Sambuc // zap this code. 1718*f4a2713aSLionel Sambuc QualType PtTy = ICE->getSubExpr()->getType(); 1719*f4a2713aSLionel Sambuc if (!PtTy->isIncompleteType()) 1720*f4a2713aSLionel Sambuc Align = getContext().getTypeAlignInChars(PtTy).getQuantity(); 1721*f4a2713aSLionel Sambuc else 1722*f4a2713aSLionel Sambuc Align = 1; 1723*f4a2713aSLionel Sambuc } 1724*f4a2713aSLionel Sambuc return std::make_pair(LV.getAddress(), Align); 1725*f4a2713aSLionel Sambuc } 1726*f4a2713aSLionel Sambuc } 1727*f4a2713aSLionel Sambuc if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Addr)) { 1728*f4a2713aSLionel Sambuc if (UO->getOpcode() == UO_AddrOf) { 1729*f4a2713aSLionel Sambuc LValue LV = EmitLValue(UO->getSubExpr()); 1730*f4a2713aSLionel Sambuc unsigned Align = LV.getAlignment().getQuantity(); 1731*f4a2713aSLionel Sambuc if (!Align) { 1732*f4a2713aSLionel Sambuc // FIXME: Once LValues are fixed to always set alignment, 1733*f4a2713aSLionel Sambuc // zap this code. 1734*f4a2713aSLionel Sambuc QualType PtTy = UO->getSubExpr()->getType(); 1735*f4a2713aSLionel Sambuc if (!PtTy->isIncompleteType()) 1736*f4a2713aSLionel Sambuc Align = getContext().getTypeAlignInChars(PtTy).getQuantity(); 1737*f4a2713aSLionel Sambuc else 1738*f4a2713aSLionel Sambuc Align = 1; 1739*f4a2713aSLionel Sambuc } 1740*f4a2713aSLionel Sambuc return std::make_pair(LV.getAddress(), Align); 1741*f4a2713aSLionel Sambuc } 1742*f4a2713aSLionel Sambuc } 1743*f4a2713aSLionel Sambuc 1744*f4a2713aSLionel Sambuc unsigned Align = 1; 1745*f4a2713aSLionel Sambuc QualType PtTy = Addr->getType()->getPointeeType(); 1746*f4a2713aSLionel Sambuc if (!PtTy->isIncompleteType()) 1747*f4a2713aSLionel Sambuc Align = getContext().getTypeAlignInChars(PtTy).getQuantity(); 1748*f4a2713aSLionel Sambuc 1749*f4a2713aSLionel Sambuc return std::make_pair(EmitScalarExpr(Addr), Align); 1750*f4a2713aSLionel Sambuc } 1751*f4a2713aSLionel Sambuc 1752*f4a2713aSLionel Sambuc static Value *EmitAArch64ScalarBuiltinExpr(CodeGenFunction &CGF, 1753*f4a2713aSLionel Sambuc unsigned BuiltinID, 1754*f4a2713aSLionel Sambuc const CallExpr *E) { 1755*f4a2713aSLionel Sambuc unsigned int Int = 0; 1756*f4a2713aSLionel Sambuc // Scalar result generated across vectors 1757*f4a2713aSLionel Sambuc bool AcrossVec = false; 1758*f4a2713aSLionel Sambuc // Extend element of one-element vector 1759*f4a2713aSLionel Sambuc bool ExtendEle = false; 1760*f4a2713aSLionel Sambuc bool OverloadInt = false; 1761*f4a2713aSLionel Sambuc bool OverloadCmpInt = false; 1762*f4a2713aSLionel Sambuc bool OverloadWideInt = false; 1763*f4a2713aSLionel Sambuc bool OverloadNarrowInt = false; 1764*f4a2713aSLionel Sambuc const char *s = NULL; 1765*f4a2713aSLionel Sambuc 1766*f4a2713aSLionel Sambuc SmallVector<Value *, 4> Ops; 1767*f4a2713aSLionel Sambuc for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) { 1768*f4a2713aSLionel Sambuc Ops.push_back(CGF.EmitScalarExpr(E->getArg(i))); 1769*f4a2713aSLionel Sambuc } 1770*f4a2713aSLionel Sambuc 1771*f4a2713aSLionel Sambuc // AArch64 scalar builtins are not overloaded, they do not have an extra 1772*f4a2713aSLionel Sambuc // argument that specifies the vector type, need to handle each case. 1773*f4a2713aSLionel Sambuc switch (BuiltinID) { 1774*f4a2713aSLionel Sambuc default: break; 1775*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vdups_lane_f32: 1776*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vdupd_lane_f64: 1777*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vdups_laneq_f32: 1778*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vdupd_laneq_f64: { 1779*f4a2713aSLionel Sambuc return CGF.Builder.CreateExtractElement(Ops[0], Ops[1], "vdup_lane"); 1780*f4a2713aSLionel Sambuc } 1781*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vdupb_lane_i8: 1782*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vduph_lane_i16: 1783*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vdups_lane_i32: 1784*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vdupd_lane_i64: 1785*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vdupb_laneq_i8: 1786*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vduph_laneq_i16: 1787*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vdups_laneq_i32: 1788*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vdupd_laneq_i64: { 1789*f4a2713aSLionel Sambuc // The backend treats Neon scalar types as v1ix types 1790*f4a2713aSLionel Sambuc // So we want to dup lane from any vector to v1ix vector 1791*f4a2713aSLionel Sambuc // with shufflevector 1792*f4a2713aSLionel Sambuc s = "vdup_lane"; 1793*f4a2713aSLionel Sambuc Value* SV = llvm::ConstantVector::getSplat(1, cast<ConstantInt>(Ops[1])); 1794*f4a2713aSLionel Sambuc Value *Result = CGF.Builder.CreateShuffleVector(Ops[0], Ops[0], SV, s); 1795*f4a2713aSLionel Sambuc llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType()); 1796*f4a2713aSLionel Sambuc // AArch64 intrinsic one-element vector type cast to 1797*f4a2713aSLionel Sambuc // scalar type expected by the builtin 1798*f4a2713aSLionel Sambuc return CGF.Builder.CreateBitCast(Result, Ty, s); 1799*f4a2713aSLionel Sambuc } 1800*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlalh_lane_s16 : 1801*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlalh_laneq_s16 : 1802*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlals_lane_s32 : 1803*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlals_laneq_s32 : 1804*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlslh_lane_s16 : 1805*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlslh_laneq_s16 : 1806*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlsls_lane_s32 : 1807*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlsls_laneq_s32 : { 1808*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqadds; 1809*f4a2713aSLionel Sambuc if (BuiltinID == AArch64::BI__builtin_neon_vqdmlslh_lane_s16 || 1810*f4a2713aSLionel Sambuc BuiltinID == AArch64::BI__builtin_neon_vqdmlslh_laneq_s16 || 1811*f4a2713aSLionel Sambuc BuiltinID == AArch64::BI__builtin_neon_vqdmlsls_lane_s32 || 1812*f4a2713aSLionel Sambuc BuiltinID == AArch64::BI__builtin_neon_vqdmlsls_laneq_s32) { 1813*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqsubs; 1814*f4a2713aSLionel Sambuc } 1815*f4a2713aSLionel Sambuc // create vqdmull call with b * c[i] 1816*f4a2713aSLionel Sambuc llvm::Type *Ty = CGF.ConvertType(E->getArg(1)->getType()); 1817*f4a2713aSLionel Sambuc llvm::VectorType *OpVTy = llvm::VectorType::get(Ty, 1); 1818*f4a2713aSLionel Sambuc Ty = CGF.ConvertType(E->getArg(0)->getType()); 1819*f4a2713aSLionel Sambuc llvm::VectorType *ResVTy = llvm::VectorType::get(Ty, 1); 1820*f4a2713aSLionel Sambuc Value *F = CGF.CGM.getIntrinsic(Intrinsic::arm_neon_vqdmull, ResVTy); 1821*f4a2713aSLionel Sambuc Value *V = UndefValue::get(OpVTy); 1822*f4a2713aSLionel Sambuc llvm::Constant *CI = ConstantInt::get(CGF.Int32Ty, 0); 1823*f4a2713aSLionel Sambuc SmallVector<Value *, 2> MulOps; 1824*f4a2713aSLionel Sambuc MulOps.push_back(Ops[1]); 1825*f4a2713aSLionel Sambuc MulOps.push_back(Ops[2]); 1826*f4a2713aSLionel Sambuc MulOps[0] = CGF.Builder.CreateInsertElement(V, MulOps[0], CI); 1827*f4a2713aSLionel Sambuc MulOps[1] = CGF.Builder.CreateExtractElement(MulOps[1], Ops[3], "extract"); 1828*f4a2713aSLionel Sambuc MulOps[1] = CGF.Builder.CreateInsertElement(V, MulOps[1], CI); 1829*f4a2713aSLionel Sambuc Value *MulRes = CGF.Builder.CreateCall2(F, MulOps[0], MulOps[1]); 1830*f4a2713aSLionel Sambuc // create vqadds call with a +/- vqdmull result 1831*f4a2713aSLionel Sambuc F = CGF.CGM.getIntrinsic(Int, ResVTy); 1832*f4a2713aSLionel Sambuc SmallVector<Value *, 2> AddOps; 1833*f4a2713aSLionel Sambuc AddOps.push_back(Ops[0]); 1834*f4a2713aSLionel Sambuc AddOps.push_back(MulRes); 1835*f4a2713aSLionel Sambuc V = UndefValue::get(ResVTy); 1836*f4a2713aSLionel Sambuc AddOps[0] = CGF.Builder.CreateInsertElement(V, AddOps[0], CI); 1837*f4a2713aSLionel Sambuc Value *AddRes = CGF.Builder.CreateCall2(F, AddOps[0], AddOps[1]); 1838*f4a2713aSLionel Sambuc return CGF.Builder.CreateBitCast(AddRes, Ty); 1839*f4a2713aSLionel Sambuc } 1840*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfmas_lane_f32: 1841*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfmas_laneq_f32: 1842*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfmad_lane_f64: 1843*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfmad_laneq_f64: { 1844*f4a2713aSLionel Sambuc llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType()); 1845*f4a2713aSLionel Sambuc Value *F = CGF.CGM.getIntrinsic(Intrinsic::fma, Ty); 1846*f4a2713aSLionel Sambuc Ops[2] = CGF.Builder.CreateExtractElement(Ops[2], Ops[3], "extract"); 1847*f4a2713aSLionel Sambuc return CGF.Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]); 1848*f4a2713aSLionel Sambuc } 1849*f4a2713aSLionel Sambuc // Scalar Floating-point Multiply Extended 1850*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmulxs_f32: 1851*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmulxd_f64: { 1852*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vmulx; 1853*f4a2713aSLionel Sambuc llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType()); 1854*f4a2713aSLionel Sambuc return CGF.EmitNeonCall(CGF.CGM.getIntrinsic(Int, Ty), Ops, "vmulx"); 1855*f4a2713aSLionel Sambuc } 1856*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmul_n_f64: { 1857*f4a2713aSLionel Sambuc // v1f64 vmul_n_f64 should be mapped to Neon scalar mul lane 1858*f4a2713aSLionel Sambuc llvm::Type *VTy = GetNeonType(&CGF, 1859*f4a2713aSLionel Sambuc NeonTypeFlags(NeonTypeFlags::Float64, false, false)); 1860*f4a2713aSLionel Sambuc Ops[0] = CGF.Builder.CreateBitCast(Ops[0], VTy); 1861*f4a2713aSLionel Sambuc llvm::Value *Idx = llvm::ConstantInt::get(CGF.Int32Ty, 0); 1862*f4a2713aSLionel Sambuc Ops[0] = CGF.Builder.CreateExtractElement(Ops[0], Idx, "extract"); 1863*f4a2713aSLionel Sambuc Value *Result = CGF.Builder.CreateFMul(Ops[0], Ops[1]); 1864*f4a2713aSLionel Sambuc return CGF.Builder.CreateBitCast(Result, VTy); 1865*f4a2713aSLionel Sambuc } 1866*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vget_lane_i8: 1867*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vget_lane_i16: 1868*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vget_lane_i32: 1869*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vget_lane_i64: 1870*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vget_lane_f32: 1871*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vget_lane_f64: 1872*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vgetq_lane_i8: 1873*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vgetq_lane_i16: 1874*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vgetq_lane_i32: 1875*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vgetq_lane_i64: 1876*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vgetq_lane_f32: 1877*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vgetq_lane_f64: 1878*f4a2713aSLionel Sambuc return CGF.EmitARMBuiltinExpr(ARM::BI__builtin_neon_vget_lane_i8, E); 1879*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vset_lane_i8: 1880*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vset_lane_i16: 1881*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vset_lane_i32: 1882*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vset_lane_i64: 1883*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vset_lane_f32: 1884*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vset_lane_f64: 1885*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsetq_lane_i8: 1886*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsetq_lane_i16: 1887*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsetq_lane_i32: 1888*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsetq_lane_i64: 1889*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsetq_lane_f32: 1890*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsetq_lane_f64: 1891*f4a2713aSLionel Sambuc return CGF.EmitARMBuiltinExpr(ARM::BI__builtin_neon_vset_lane_i8, E); 1892*f4a2713aSLionel Sambuc // Crypto 1893*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsha1h_u32: 1894*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_sha1h; 1895*f4a2713aSLionel Sambuc s = "sha1h"; OverloadInt = true; break; 1896*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsha1cq_u32: 1897*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_sha1c; 1898*f4a2713aSLionel Sambuc s = "sha1c"; break; 1899*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsha1pq_u32: 1900*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_sha1p; 1901*f4a2713aSLionel Sambuc s = "sha1p"; break; 1902*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsha1mq_u32: 1903*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_sha1m; 1904*f4a2713aSLionel Sambuc s = "sha1m"; break; 1905*f4a2713aSLionel Sambuc // Scalar Add 1906*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddd_s64: 1907*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vaddds; 1908*f4a2713aSLionel Sambuc s = "vaddds"; break; 1909*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddd_u64: 1910*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vadddu; 1911*f4a2713aSLionel Sambuc s = "vadddu"; break; 1912*f4a2713aSLionel Sambuc // Scalar Sub 1913*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsubd_s64: 1914*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsubds; 1915*f4a2713aSLionel Sambuc s = "vsubds"; break; 1916*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsubd_u64: 1917*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsubdu; 1918*f4a2713aSLionel Sambuc s = "vsubdu"; break; 1919*f4a2713aSLionel Sambuc // Scalar Saturating Add 1920*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqaddb_s8: 1921*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqaddh_s16: 1922*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqadds_s32: 1923*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqaddd_s64: 1924*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqadds; 1925*f4a2713aSLionel Sambuc s = "vqadds"; OverloadInt = true; break; 1926*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqaddb_u8: 1927*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqaddh_u16: 1928*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqadds_u32: 1929*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqaddd_u64: 1930*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqaddu; 1931*f4a2713aSLionel Sambuc s = "vqaddu"; OverloadInt = true; break; 1932*f4a2713aSLionel Sambuc // Scalar Saturating Sub 1933*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqsubb_s8: 1934*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqsubh_s16: 1935*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqsubs_s32: 1936*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqsubd_s64: 1937*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqsubs; 1938*f4a2713aSLionel Sambuc s = "vqsubs"; OverloadInt = true; break; 1939*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqsubb_u8: 1940*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqsubh_u16: 1941*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqsubs_u32: 1942*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqsubd_u64: 1943*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqsubu; 1944*f4a2713aSLionel Sambuc s = "vqsubu"; OverloadInt = true; break; 1945*f4a2713aSLionel Sambuc // Scalar Shift Left 1946*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshld_s64: 1947*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vshlds; 1948*f4a2713aSLionel Sambuc s = "vshlds"; break; 1949*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshld_u64: 1950*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vshldu; 1951*f4a2713aSLionel Sambuc s = "vshldu"; break; 1952*f4a2713aSLionel Sambuc // Scalar Saturating Shift Left 1953*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlb_s8: 1954*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlh_s16: 1955*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshls_s32: 1956*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshld_s64: 1957*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vqshls; 1958*f4a2713aSLionel Sambuc s = "vqshls"; OverloadInt = true; break; 1959*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlb_u8: 1960*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlh_u16: 1961*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshls_u32: 1962*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshld_u64: 1963*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vqshlu; 1964*f4a2713aSLionel Sambuc s = "vqshlu"; OverloadInt = true; break; 1965*f4a2713aSLionel Sambuc // Scalar Rouding Shift Left 1966*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrshld_s64: 1967*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vrshlds; 1968*f4a2713aSLionel Sambuc s = "vrshlds"; break; 1969*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrshld_u64: 1970*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vrshldu; 1971*f4a2713aSLionel Sambuc s = "vrshldu"; break; 1972*f4a2713aSLionel Sambuc // Scalar Saturating Rouding Shift Left 1973*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshlb_s8: 1974*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshlh_s16: 1975*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshls_s32: 1976*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshld_s64: 1977*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vqrshls; 1978*f4a2713aSLionel Sambuc s = "vqrshls"; OverloadInt = true; break; 1979*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshlb_u8: 1980*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshlh_u16: 1981*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshls_u32: 1982*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshld_u64: 1983*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vqrshlu; 1984*f4a2713aSLionel Sambuc s = "vqrshlu"; OverloadInt = true; break; 1985*f4a2713aSLionel Sambuc // Scalar Reduce Pairwise Add 1986*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpaddd_s64: 1987*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpadd; s = "vpadd"; 1988*f4a2713aSLionel Sambuc break; 1989*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpadds_f32: 1990*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpfadd; s = "vpfadd"; 1991*f4a2713aSLionel Sambuc break; 1992*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpaddd_f64: 1993*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpfaddq; s = "vpfaddq"; 1994*f4a2713aSLionel Sambuc break; 1995*f4a2713aSLionel Sambuc // Scalar Reduce Pairwise Floating Point Max 1996*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpmaxs_f32: 1997*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpmax; s = "vpmax"; 1998*f4a2713aSLionel Sambuc break; 1999*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpmaxqd_f64: 2000*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpmaxq; s = "vpmaxq"; 2001*f4a2713aSLionel Sambuc break; 2002*f4a2713aSLionel Sambuc // Scalar Reduce Pairwise Floating Point Min 2003*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpmins_f32: 2004*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpmin; s = "vpmin"; 2005*f4a2713aSLionel Sambuc break; 2006*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpminqd_f64: 2007*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpminq; s = "vpminq"; 2008*f4a2713aSLionel Sambuc break; 2009*f4a2713aSLionel Sambuc // Scalar Reduce Pairwise Floating Point Maxnm 2010*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpmaxnms_f32: 2011*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpfmaxnm; s = "vpfmaxnm"; 2012*f4a2713aSLionel Sambuc break; 2013*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpmaxnmqd_f64: 2014*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpfmaxnmq; s = "vpfmaxnmq"; 2015*f4a2713aSLionel Sambuc break; 2016*f4a2713aSLionel Sambuc // Scalar Reduce Pairwise Floating Point Minnm 2017*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpminnms_f32: 2018*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpfminnm; s = "vpfminnm"; 2019*f4a2713aSLionel Sambuc break; 2020*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpminnmqd_f64: 2021*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpfminnmq; s = "vpfminnmq"; 2022*f4a2713aSLionel Sambuc break; 2023*f4a2713aSLionel Sambuc // The followings are intrinsics with scalar results generated AcrossVec vectors 2024*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddlv_s8: 2025*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddlv_s16: 2026*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddlvq_s8: 2027*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddlvq_s16: 2028*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddlvq_s32: 2029*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_saddlv; 2030*f4a2713aSLionel Sambuc AcrossVec = true; ExtendEle = true; s = "saddlv"; break; 2031*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddlv_u8: 2032*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddlv_u16: 2033*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddlvq_u8: 2034*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddlvq_u16: 2035*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddlvq_u32: 2036*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_uaddlv; 2037*f4a2713aSLionel Sambuc AcrossVec = true; ExtendEle = true; s = "uaddlv"; break; 2038*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxv_s8: 2039*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxv_s16: 2040*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxvq_s8: 2041*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxvq_s16: 2042*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxvq_s32: 2043*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_smaxv; 2044*f4a2713aSLionel Sambuc AcrossVec = true; ExtendEle = false; s = "smaxv"; break; 2045*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxv_u8: 2046*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxv_u16: 2047*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxvq_u8: 2048*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxvq_u16: 2049*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxvq_u32: 2050*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_umaxv; 2051*f4a2713aSLionel Sambuc AcrossVec = true; ExtendEle = false; s = "umaxv"; break; 2052*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminv_s8: 2053*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminv_s16: 2054*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminvq_s8: 2055*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminvq_s16: 2056*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminvq_s32: 2057*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_sminv; 2058*f4a2713aSLionel Sambuc AcrossVec = true; ExtendEle = false; s = "sminv"; break; 2059*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminv_u8: 2060*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminv_u16: 2061*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminvq_u8: 2062*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminvq_u16: 2063*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminvq_u32: 2064*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_uminv; 2065*f4a2713aSLionel Sambuc AcrossVec = true; ExtendEle = false; s = "uminv"; break; 2066*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddv_s8: 2067*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddv_s16: 2068*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddvq_s8: 2069*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddvq_s16: 2070*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddvq_s32: 2071*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddv_u8: 2072*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddv_u16: 2073*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddvq_u8: 2074*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddvq_u16: 2075*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddvq_u32: 2076*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vaddv; 2077*f4a2713aSLionel Sambuc AcrossVec = true; ExtendEle = false; s = "vaddv"; break; 2078*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxvq_f32: 2079*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vmaxv; 2080*f4a2713aSLionel Sambuc AcrossVec = true; ExtendEle = false; s = "vmaxv"; break; 2081*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminvq_f32: 2082*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vminv; 2083*f4a2713aSLionel Sambuc AcrossVec = true; ExtendEle = false; s = "vminv"; break; 2084*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxnmvq_f32: 2085*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vmaxnmv; 2086*f4a2713aSLionel Sambuc AcrossVec = true; ExtendEle = false; s = "vmaxnmv"; break; 2087*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminnmvq_f32: 2088*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vminnmv; 2089*f4a2713aSLionel Sambuc AcrossVec = true; ExtendEle = false; s = "vminnmv"; break; 2090*f4a2713aSLionel Sambuc // Scalar Integer Saturating Doubling Multiply Half High 2091*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmulhh_s16: 2092*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmulhs_s32: 2093*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqdmulh; 2094*f4a2713aSLionel Sambuc s = "vqdmulh"; OverloadInt = true; break; 2095*f4a2713aSLionel Sambuc // Scalar Integer Saturating Rounding Doubling Multiply Half High 2096*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrdmulhh_s16: 2097*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrdmulhs_s32: 2098*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqrdmulh; 2099*f4a2713aSLionel Sambuc s = "vqrdmulh"; OverloadInt = true; break; 2100*f4a2713aSLionel Sambuc // Scalar Floating-point Reciprocal Step and 2101*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrecpss_f32: 2102*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrecpsd_f64: 2103*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vrecps; 2104*f4a2713aSLionel Sambuc s = "vrecps"; OverloadInt = true; break; 2105*f4a2713aSLionel Sambuc // Scalar Floating-point Reciprocal Square Root Step 2106*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsqrtss_f32: 2107*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsqrtsd_f64: 2108*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vrsqrts; 2109*f4a2713aSLionel Sambuc s = "vrsqrts"; OverloadInt = true; break; 2110*f4a2713aSLionel Sambuc // Scalar Signed Integer Convert To Floating-point 2111*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvts_f32_s32: 2112*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvtf32_s32, 2113*f4a2713aSLionel Sambuc s = "vcvtf"; OverloadInt = false; break; 2114*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtd_f64_s64: 2115*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvtf64_s64, 2116*f4a2713aSLionel Sambuc s = "vcvtf"; OverloadInt = false; break; 2117*f4a2713aSLionel Sambuc // Scalar Unsigned Integer Convert To Floating-point 2118*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvts_f32_u32: 2119*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvtf32_u32, 2120*f4a2713aSLionel Sambuc s = "vcvtf"; OverloadInt = false; break; 2121*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtd_f64_u64: 2122*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvtf64_u64, 2123*f4a2713aSLionel Sambuc s = "vcvtf"; OverloadInt = false; break; 2124*f4a2713aSLionel Sambuc // Scalar Floating-point Reciprocal Estimate 2125*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrecpes_f32: 2126*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrecped_f64: 2127*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vrecpe; 2128*f4a2713aSLionel Sambuc s = "vrecpe"; OverloadInt = true; break; 2129*f4a2713aSLionel Sambuc // Scalar Floating-point Reciprocal Exponent 2130*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrecpxs_f32: 2131*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrecpxd_f64: 2132*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vrecpx; 2133*f4a2713aSLionel Sambuc s = "vrecpx"; OverloadInt = true; break; 2134*f4a2713aSLionel Sambuc // Scalar Floating-point Reciprocal Square Root Estimate 2135*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsqrtes_f32: 2136*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsqrted_f64: 2137*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vrsqrte; 2138*f4a2713aSLionel Sambuc s = "vrsqrte"; OverloadInt = true; break; 2139*f4a2713aSLionel Sambuc // Scalar Compare Equal 2140*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vceqd_s64: 2141*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vceqd_u64: 2142*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vceq; s = "vceq"; 2143*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2144*f4a2713aSLionel Sambuc // Scalar Compare Equal To Zero 2145*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vceqzd_s64: 2146*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vceqzd_u64: 2147*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vceq; s = "vceq"; 2148*f4a2713aSLionel Sambuc // Add implicit zero operand. 2149*f4a2713aSLionel Sambuc Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType())); 2150*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2151*f4a2713aSLionel Sambuc // Scalar Compare Greater Than or Equal 2152*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcged_s64: 2153*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcge; s = "vcge"; 2154*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2155*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcged_u64: 2156*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vchs; s = "vcge"; 2157*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2158*f4a2713aSLionel Sambuc // Scalar Compare Greater Than or Equal To Zero 2159*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgezd_s64: 2160*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcge; s = "vcge"; 2161*f4a2713aSLionel Sambuc // Add implicit zero operand. 2162*f4a2713aSLionel Sambuc Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType())); 2163*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2164*f4a2713aSLionel Sambuc // Scalar Compare Greater Than 2165*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgtd_s64: 2166*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt"; 2167*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2168*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgtd_u64: 2169*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vchi; s = "vcgt"; 2170*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2171*f4a2713aSLionel Sambuc // Scalar Compare Greater Than Zero 2172*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgtzd_s64: 2173*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt"; 2174*f4a2713aSLionel Sambuc // Add implicit zero operand. 2175*f4a2713aSLionel Sambuc Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType())); 2176*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2177*f4a2713aSLionel Sambuc // Scalar Compare Less Than or Equal 2178*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcled_s64: 2179*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcge; s = "vcge"; 2180*f4a2713aSLionel Sambuc OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break; 2181*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcled_u64: 2182*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vchs; s = "vchs"; 2183*f4a2713aSLionel Sambuc OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break; 2184*f4a2713aSLionel Sambuc // Scalar Compare Less Than or Equal To Zero 2185*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vclezd_s64: 2186*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vclez; s = "vcle"; 2187*f4a2713aSLionel Sambuc // Add implicit zero operand. 2188*f4a2713aSLionel Sambuc Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType())); 2189*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2190*f4a2713aSLionel Sambuc // Scalar Compare Less Than 2191*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcltd_s64: 2192*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt"; 2193*f4a2713aSLionel Sambuc OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break; 2194*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcltd_u64: 2195*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vchi; s = "vchi"; 2196*f4a2713aSLionel Sambuc OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break; 2197*f4a2713aSLionel Sambuc // Scalar Compare Less Than Zero 2198*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcltzd_s64: 2199*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcltz; s = "vclt"; 2200*f4a2713aSLionel Sambuc // Add implicit zero operand. 2201*f4a2713aSLionel Sambuc Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType())); 2202*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2203*f4a2713aSLionel Sambuc // Scalar Floating-point Compare Equal 2204*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vceqs_f32: 2205*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vceqd_f64: 2206*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vceq; s = "vceq"; 2207*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2208*f4a2713aSLionel Sambuc // Scalar Floating-point Compare Equal To Zero 2209*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vceqzs_f32: 2210*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vceqzd_f64: 2211*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vceq; s = "vceq"; 2212*f4a2713aSLionel Sambuc // Add implicit zero operand. 2213*f4a2713aSLionel Sambuc Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType())); 2214*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2215*f4a2713aSLionel Sambuc // Scalar Floating-point Compare Greater Than Or Equal 2216*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcges_f32: 2217*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcged_f64: 2218*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcge; s = "vcge"; 2219*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2220*f4a2713aSLionel Sambuc // Scalar Floating-point Compare Greater Than Or Equal To Zero 2221*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgezs_f32: 2222*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgezd_f64: 2223*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcge; s = "vcge"; 2224*f4a2713aSLionel Sambuc // Add implicit zero operand. 2225*f4a2713aSLionel Sambuc Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType())); 2226*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2227*f4a2713aSLionel Sambuc // Scalar Floating-point Compare Greather Than 2228*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgts_f32: 2229*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgtd_f64: 2230*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt"; 2231*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2232*f4a2713aSLionel Sambuc // Scalar Floating-point Compare Greather Than Zero 2233*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgtzs_f32: 2234*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgtzd_f64: 2235*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt"; 2236*f4a2713aSLionel Sambuc // Add implicit zero operand. 2237*f4a2713aSLionel Sambuc Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType())); 2238*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2239*f4a2713aSLionel Sambuc // Scalar Floating-point Compare Less Than or Equal 2240*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcles_f32: 2241*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcled_f64: 2242*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcge; s = "vcge"; 2243*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2244*f4a2713aSLionel Sambuc // Scalar Floating-point Compare Less Than Or Equal To Zero 2245*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vclezs_f32: 2246*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vclezd_f64: 2247*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vclez; s = "vcle"; 2248*f4a2713aSLionel Sambuc // Add implicit zero operand. 2249*f4a2713aSLionel Sambuc Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType())); 2250*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2251*f4a2713aSLionel Sambuc // Scalar Floating-point Compare Less Than Zero 2252*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vclts_f32: 2253*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcltd_f64: 2254*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt"; 2255*f4a2713aSLionel Sambuc OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break; 2256*f4a2713aSLionel Sambuc // Scalar Floating-point Compare Less Than Zero 2257*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcltzs_f32: 2258*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcltzd_f64: 2259*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcltz; s = "vclt"; 2260*f4a2713aSLionel Sambuc // Add implicit zero operand. 2261*f4a2713aSLionel Sambuc Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType())); 2262*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2263*f4a2713aSLionel Sambuc // Scalar Floating-point Absolute Compare Greater Than Or Equal 2264*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcages_f32: 2265*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcaged_f64: 2266*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcage; s = "vcage"; 2267*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2268*f4a2713aSLionel Sambuc // Scalar Floating-point Absolute Compare Greater Than 2269*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcagts_f32: 2270*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcagtd_f64: 2271*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcagt; s = "vcagt"; 2272*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2273*f4a2713aSLionel Sambuc // Scalar Floating-point Absolute Compare Less Than Or Equal 2274*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcales_f32: 2275*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcaled_f64: 2276*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcage; s = "vcage"; 2277*f4a2713aSLionel Sambuc OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break; 2278*f4a2713aSLionel Sambuc // Scalar Floating-point Absolute Compare Less Than 2279*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcalts_f32: 2280*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcaltd_f64: 2281*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcagt; s = "vcalt"; 2282*f4a2713aSLionel Sambuc OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break; 2283*f4a2713aSLionel Sambuc // Scalar Compare Bitwise Test Bits 2284*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtstd_s64: 2285*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtstd_u64: 2286*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vtstd; s = "vtst"; 2287*f4a2713aSLionel Sambuc OverloadCmpInt = true; break; 2288*f4a2713aSLionel Sambuc // Scalar Absolute Value 2289*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vabsd_s64: 2290*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vabs; 2291*f4a2713aSLionel Sambuc s = "vabs"; OverloadInt = false; break; 2292*f4a2713aSLionel Sambuc // Scalar Signed Saturating Absolute Value 2293*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqabsb_s8: 2294*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqabsh_s16: 2295*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqabss_s32: 2296*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqabsd_s64: 2297*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqabs; 2298*f4a2713aSLionel Sambuc s = "vqabs"; OverloadInt = true; break; 2299*f4a2713aSLionel Sambuc // Scalar Negate 2300*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vnegd_s64: 2301*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vneg; 2302*f4a2713aSLionel Sambuc s = "vneg"; OverloadInt = false; break; 2303*f4a2713aSLionel Sambuc // Scalar Signed Saturating Negate 2304*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqnegb_s8: 2305*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqnegh_s16: 2306*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqnegs_s32: 2307*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqnegd_s64: 2308*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqneg; 2309*f4a2713aSLionel Sambuc s = "vqneg"; OverloadInt = true; break; 2310*f4a2713aSLionel Sambuc // Scalar Signed Saturating Accumulated of Unsigned Value 2311*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vuqaddb_s8: 2312*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vuqaddh_s16: 2313*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vuqadds_s32: 2314*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vuqaddd_s64: 2315*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vuqadd; 2316*f4a2713aSLionel Sambuc s = "vuqadd"; OverloadInt = true; break; 2317*f4a2713aSLionel Sambuc // Scalar Unsigned Saturating Accumulated of Signed Value 2318*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsqaddb_u8: 2319*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsqaddh_u16: 2320*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsqadds_u32: 2321*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsqaddd_u64: 2322*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsqadd; 2323*f4a2713aSLionel Sambuc s = "vsqadd"; OverloadInt = true; break; 2324*f4a2713aSLionel Sambuc // Signed Saturating Doubling Multiply-Add Long 2325*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlalh_s16: 2326*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlals_s32: 2327*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vqdmlal; 2328*f4a2713aSLionel Sambuc s = "vqdmlal"; OverloadWideInt = true; break; 2329*f4a2713aSLionel Sambuc // Signed Saturating Doubling Multiply-Subtract Long 2330*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlslh_s16: 2331*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlsls_s32: 2332*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vqdmlsl; 2333*f4a2713aSLionel Sambuc s = "vqdmlsl"; OverloadWideInt = true; break; 2334*f4a2713aSLionel Sambuc // Signed Saturating Doubling Multiply Long 2335*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmullh_s16: 2336*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmulls_s32: 2337*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqdmull; 2338*f4a2713aSLionel Sambuc s = "vqdmull"; OverloadWideInt = true; break; 2339*f4a2713aSLionel Sambuc // Scalar Signed Saturating Extract Unsigned Narrow 2340*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqmovunh_s16: 2341*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqmovuns_s32: 2342*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqmovund_s64: 2343*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqmovnsu; 2344*f4a2713aSLionel Sambuc s = "vqmovun"; OverloadNarrowInt = true; break; 2345*f4a2713aSLionel Sambuc // Scalar Signed Saturating Extract Narrow 2346*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqmovnh_s16: 2347*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqmovns_s32: 2348*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqmovnd_s64: 2349*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqmovns; 2350*f4a2713aSLionel Sambuc s = "vqmovn"; OverloadNarrowInt = true; break; 2351*f4a2713aSLionel Sambuc // Scalar Unsigned Saturating Extract Narrow 2352*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqmovnh_u16: 2353*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqmovns_u32: 2354*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqmovnd_u64: 2355*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vqmovnu; 2356*f4a2713aSLionel Sambuc s = "vqmovn"; OverloadNarrowInt = true; break; 2357*f4a2713aSLionel Sambuc // Scalar Signed Shift Right (Immediate) 2358*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshrd_n_s64: 2359*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vshrds_n; 2360*f4a2713aSLionel Sambuc s = "vsshr"; OverloadInt = false; break; 2361*f4a2713aSLionel Sambuc // Scalar Unsigned Shift Right (Immediate) 2362*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshrd_n_u64: 2363*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vshrdu_n; 2364*f4a2713aSLionel Sambuc s = "vushr"; OverloadInt = false; break; 2365*f4a2713aSLionel Sambuc // Scalar Signed Rounding Shift Right (Immediate) 2366*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrshrd_n_s64: 2367*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsrshr; 2368*f4a2713aSLionel Sambuc s = "vsrshr"; OverloadInt = true; break; 2369*f4a2713aSLionel Sambuc // Scalar Unsigned Rounding Shift Right (Immediate) 2370*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrshrd_n_u64: 2371*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vurshr; 2372*f4a2713aSLionel Sambuc s = "vurshr"; OverloadInt = true; break; 2373*f4a2713aSLionel Sambuc // Scalar Signed Shift Right and Accumulate (Immediate) 2374*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsrad_n_s64: 2375*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsrads_n; 2376*f4a2713aSLionel Sambuc s = "vssra"; OverloadInt = false; break; 2377*f4a2713aSLionel Sambuc // Scalar Unsigned Shift Right and Accumulate (Immediate) 2378*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsrad_n_u64: 2379*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsradu_n; 2380*f4a2713aSLionel Sambuc s = "vusra"; OverloadInt = false; break; 2381*f4a2713aSLionel Sambuc // Scalar Signed Rounding Shift Right and Accumulate (Immediate) 2382*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsrad_n_s64: 2383*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vrsrads_n; 2384*f4a2713aSLionel Sambuc s = "vsrsra"; OverloadInt = false; break; 2385*f4a2713aSLionel Sambuc // Scalar Unsigned Rounding Shift Right and Accumulate (Immediate) 2386*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsrad_n_u64: 2387*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vrsradu_n; 2388*f4a2713aSLionel Sambuc s = "vursra"; OverloadInt = false; break; 2389*f4a2713aSLionel Sambuc // Scalar Signed/Unsigned Shift Left (Immediate) 2390*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshld_n_s64: 2391*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshld_n_u64: 2392*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vshld_n; 2393*f4a2713aSLionel Sambuc s = "vshl"; OverloadInt = false; break; 2394*f4a2713aSLionel Sambuc // Signed Saturating Shift Left (Immediate) 2395*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlb_n_s8: 2396*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlh_n_s16: 2397*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshls_n_s32: 2398*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshld_n_s64: 2399*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vqshls_n; 2400*f4a2713aSLionel Sambuc s = "vsqshl"; OverloadInt = true; break; 2401*f4a2713aSLionel Sambuc // Unsigned Saturating Shift Left (Immediate) 2402*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlb_n_u8: 2403*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlh_n_u16: 2404*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshls_n_u32: 2405*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshld_n_u64: 2406*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vqshlu_n; 2407*f4a2713aSLionel Sambuc s = "vuqshl"; OverloadInt = true; break; 2408*f4a2713aSLionel Sambuc // Signed Saturating Shift Left Unsigned (Immediate) 2409*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlub_n_s8: 2410*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshluh_n_s16: 2411*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlus_n_s32: 2412*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlud_n_s64: 2413*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsqshlu; 2414*f4a2713aSLionel Sambuc s = "vsqshlu"; OverloadInt = true; break; 2415*f4a2713aSLionel Sambuc // Shift Right And Insert (Immediate) 2416*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsrid_n_s64: 2417*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsrid_n_u64: 2418*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsri; 2419*f4a2713aSLionel Sambuc s = "vsri"; OverloadInt = true; break; 2420*f4a2713aSLionel Sambuc // Shift Left And Insert (Immediate) 2421*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vslid_n_s64: 2422*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vslid_n_u64: 2423*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsli; 2424*f4a2713aSLionel Sambuc s = "vsli"; OverloadInt = true; break; 2425*f4a2713aSLionel Sambuc // Signed Saturating Shift Right Narrow (Immediate) 2426*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshrnh_n_s16: 2427*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshrns_n_s32: 2428*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshrnd_n_s64: 2429*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsqshrn; 2430*f4a2713aSLionel Sambuc s = "vsqshrn"; OverloadInt = true; break; 2431*f4a2713aSLionel Sambuc // Unsigned Saturating Shift Right Narrow (Immediate) 2432*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshrnh_n_u16: 2433*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshrns_n_u32: 2434*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshrnd_n_u64: 2435*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vuqshrn; 2436*f4a2713aSLionel Sambuc s = "vuqshrn"; OverloadInt = true; break; 2437*f4a2713aSLionel Sambuc // Signed Saturating Rounded Shift Right Narrow (Immediate) 2438*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshrnh_n_s16: 2439*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshrns_n_s32: 2440*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshrnd_n_s64: 2441*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsqrshrn; 2442*f4a2713aSLionel Sambuc s = "vsqrshrn"; OverloadInt = true; break; 2443*f4a2713aSLionel Sambuc // Unsigned Saturating Rounded Shift Right Narrow (Immediate) 2444*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshrnh_n_u16: 2445*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshrns_n_u32: 2446*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshrnd_n_u64: 2447*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vuqrshrn; 2448*f4a2713aSLionel Sambuc s = "vuqrshrn"; OverloadInt = true; break; 2449*f4a2713aSLionel Sambuc // Signed Saturating Shift Right Unsigned Narrow (Immediate) 2450*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshrunh_n_s16: 2451*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshruns_n_s32: 2452*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshrund_n_s64: 2453*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsqshrun; 2454*f4a2713aSLionel Sambuc s = "vsqshrun"; OverloadInt = true; break; 2455*f4a2713aSLionel Sambuc // Signed Saturating Rounded Shift Right Unsigned Narrow (Immediate) 2456*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshrunh_n_s16: 2457*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshruns_n_s32: 2458*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshrund_n_s64: 2459*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsqrshrun; 2460*f4a2713aSLionel Sambuc s = "vsqrshrun"; OverloadInt = true; break; 2461*f4a2713aSLionel Sambuc // Scalar Signed Fixed-point Convert To Floating-Point (Immediate) 2462*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvts_n_f32_s32: 2463*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvtf32_n_s32; 2464*f4a2713aSLionel Sambuc s = "vcvtf"; OverloadInt = false; break; 2465*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtd_n_f64_s64: 2466*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvtf64_n_s64; 2467*f4a2713aSLionel Sambuc s = "vcvtf"; OverloadInt = false; break; 2468*f4a2713aSLionel Sambuc // Scalar Unsigned Fixed-point Convert To Floating-Point (Immediate) 2469*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvts_n_f32_u32: 2470*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvtf32_n_u32; 2471*f4a2713aSLionel Sambuc s = "vcvtf"; OverloadInt = false; break; 2472*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtd_n_f64_u64: 2473*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvtf64_n_u64; 2474*f4a2713aSLionel Sambuc s = "vcvtf"; OverloadInt = false; break; 2475*f4a2713aSLionel Sambuc // Scalar Floating-point Convert To Signed Fixed-point (Immediate) 2476*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvts_n_s32_f32: 2477*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvts_n_s32_f32; 2478*f4a2713aSLionel Sambuc s = "fcvtzs"; OverloadInt = false; break; 2479*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtd_n_s64_f64: 2480*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvtd_n_s64_f64; 2481*f4a2713aSLionel Sambuc s = "fcvtzs"; OverloadInt = false; break; 2482*f4a2713aSLionel Sambuc // Scalar Floating-point Convert To Unsigned Fixed-point (Immediate) 2483*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvts_n_u32_f32: 2484*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvts_n_u32_f32; 2485*f4a2713aSLionel Sambuc s = "fcvtzu"; OverloadInt = false; break; 2486*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtd_n_u64_f64: 2487*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vcvtd_n_u64_f64; 2488*f4a2713aSLionel Sambuc s = "fcvtzu"; OverloadInt = false; break; 2489*f4a2713aSLionel Sambuc } 2490*f4a2713aSLionel Sambuc 2491*f4a2713aSLionel Sambuc if (!Int) 2492*f4a2713aSLionel Sambuc return 0; 2493*f4a2713aSLionel Sambuc 2494*f4a2713aSLionel Sambuc // AArch64 scalar builtin that returns scalar type 2495*f4a2713aSLionel Sambuc // and should be mapped to AArch64 intrinsic that returns 2496*f4a2713aSLionel Sambuc // one-element vector type. 2497*f4a2713aSLionel Sambuc Function *F = 0; 2498*f4a2713aSLionel Sambuc if (AcrossVec) { 2499*f4a2713aSLionel Sambuc // Gen arg type 2500*f4a2713aSLionel Sambuc const Expr *Arg = E->getArg(E->getNumArgs()-1); 2501*f4a2713aSLionel Sambuc llvm::Type *Ty = CGF.ConvertType(Arg->getType()); 2502*f4a2713aSLionel Sambuc llvm::VectorType *VTy = cast<llvm::VectorType>(Ty); 2503*f4a2713aSLionel Sambuc llvm::Type *ETy = VTy->getElementType(); 2504*f4a2713aSLionel Sambuc llvm::VectorType *RTy = llvm::VectorType::get(ETy, 1); 2505*f4a2713aSLionel Sambuc 2506*f4a2713aSLionel Sambuc if (ExtendEle) { 2507*f4a2713aSLionel Sambuc assert(!ETy->isFloatingPointTy()); 2508*f4a2713aSLionel Sambuc RTy = llvm::VectorType::getExtendedElementVectorType(RTy); 2509*f4a2713aSLionel Sambuc } 2510*f4a2713aSLionel Sambuc 2511*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = {RTy, VTy}; 2512*f4a2713aSLionel Sambuc F = CGF.CGM.getIntrinsic(Int, Tys); 2513*f4a2713aSLionel Sambuc assert(E->getNumArgs() == 1); 2514*f4a2713aSLionel Sambuc } else if (OverloadInt) { 2515*f4a2713aSLionel Sambuc // Determine the type of this overloaded AArch64 intrinsic 2516*f4a2713aSLionel Sambuc llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType()); 2517*f4a2713aSLionel Sambuc llvm::VectorType *VTy = llvm::VectorType::get(Ty, 1); 2518*f4a2713aSLionel Sambuc assert(VTy); 2519*f4a2713aSLionel Sambuc 2520*f4a2713aSLionel Sambuc F = CGF.CGM.getIntrinsic(Int, VTy); 2521*f4a2713aSLionel Sambuc } else if (OverloadWideInt || OverloadNarrowInt) { 2522*f4a2713aSLionel Sambuc // Determine the type of this overloaded AArch64 intrinsic 2523*f4a2713aSLionel Sambuc const Expr *Arg = E->getArg(E->getNumArgs()-1); 2524*f4a2713aSLionel Sambuc llvm::Type *Ty = CGF.ConvertType(Arg->getType()); 2525*f4a2713aSLionel Sambuc llvm::VectorType *VTy = llvm::VectorType::get(Ty, 1); 2526*f4a2713aSLionel Sambuc llvm::VectorType *RTy = OverloadWideInt ? 2527*f4a2713aSLionel Sambuc llvm::VectorType::getExtendedElementVectorType(VTy) : 2528*f4a2713aSLionel Sambuc llvm::VectorType::getTruncatedElementVectorType(VTy); 2529*f4a2713aSLionel Sambuc F = CGF.CGM.getIntrinsic(Int, RTy); 2530*f4a2713aSLionel Sambuc } else if (OverloadCmpInt) { 2531*f4a2713aSLionel Sambuc // Determine the types of this overloaded AArch64 intrinsic 2532*f4a2713aSLionel Sambuc SmallVector<llvm::Type *, 3> Tys; 2533*f4a2713aSLionel Sambuc const Expr *Arg = E->getArg(E->getNumArgs()-1); 2534*f4a2713aSLionel Sambuc llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType()); 2535*f4a2713aSLionel Sambuc llvm::VectorType *VTy = llvm::VectorType::get(Ty, 1); 2536*f4a2713aSLionel Sambuc Tys.push_back(VTy); 2537*f4a2713aSLionel Sambuc Ty = CGF.ConvertType(Arg->getType()); 2538*f4a2713aSLionel Sambuc VTy = llvm::VectorType::get(Ty, 1); 2539*f4a2713aSLionel Sambuc Tys.push_back(VTy); 2540*f4a2713aSLionel Sambuc Tys.push_back(VTy); 2541*f4a2713aSLionel Sambuc 2542*f4a2713aSLionel Sambuc F = CGF.CGM.getIntrinsic(Int, Tys); 2543*f4a2713aSLionel Sambuc } else 2544*f4a2713aSLionel Sambuc F = CGF.CGM.getIntrinsic(Int); 2545*f4a2713aSLionel Sambuc 2546*f4a2713aSLionel Sambuc Value *Result = CGF.EmitNeonCall(F, Ops, s); 2547*f4a2713aSLionel Sambuc llvm::Type *ResultType = CGF.ConvertType(E->getType()); 2548*f4a2713aSLionel Sambuc // AArch64 intrinsic one-element vector type cast to 2549*f4a2713aSLionel Sambuc // scalar type expected by the builtin 2550*f4a2713aSLionel Sambuc return CGF.Builder.CreateBitCast(Result, ResultType, s); 2551*f4a2713aSLionel Sambuc } 2552*f4a2713aSLionel Sambuc 2553*f4a2713aSLionel Sambuc Value *CodeGenFunction::EmitAArch64CompareBuiltinExpr( 2554*f4a2713aSLionel Sambuc Value *Op, llvm::Type *Ty, const CmpInst::Predicate Fp, 2555*f4a2713aSLionel Sambuc const CmpInst::Predicate Ip, const Twine &Name) { 2556*f4a2713aSLionel Sambuc llvm::Type *OTy = ((llvm::User *)Op)->getOperand(0)->getType(); 2557*f4a2713aSLionel Sambuc if (OTy->isPointerTy()) 2558*f4a2713aSLionel Sambuc OTy = Ty; 2559*f4a2713aSLionel Sambuc Op = Builder.CreateBitCast(Op, OTy); 2560*f4a2713aSLionel Sambuc if (((llvm::VectorType *)OTy)->getElementType()->isFloatingPointTy()) { 2561*f4a2713aSLionel Sambuc Op = Builder.CreateFCmp(Fp, Op, ConstantAggregateZero::get(OTy)); 2562*f4a2713aSLionel Sambuc } else { 2563*f4a2713aSLionel Sambuc Op = Builder.CreateICmp(Ip, Op, ConstantAggregateZero::get(OTy)); 2564*f4a2713aSLionel Sambuc } 2565*f4a2713aSLionel Sambuc return Builder.CreateZExt(Op, Ty, Name); 2566*f4a2713aSLionel Sambuc } 2567*f4a2713aSLionel Sambuc 2568*f4a2713aSLionel Sambuc static Value *packTBLDVectorList(CodeGenFunction &CGF, ArrayRef<Value *> Ops, 2569*f4a2713aSLionel Sambuc Value *ExtOp, Value *IndexOp, 2570*f4a2713aSLionel Sambuc llvm::Type *ResTy, unsigned IntID, 2571*f4a2713aSLionel Sambuc const char *Name) { 2572*f4a2713aSLionel Sambuc SmallVector<Value *, 2> TblOps; 2573*f4a2713aSLionel Sambuc if (ExtOp) 2574*f4a2713aSLionel Sambuc TblOps.push_back(ExtOp); 2575*f4a2713aSLionel Sambuc 2576*f4a2713aSLionel Sambuc // Build a vector containing sequential number like (0, 1, 2, ..., 15) 2577*f4a2713aSLionel Sambuc SmallVector<Constant*, 16> Indices; 2578*f4a2713aSLionel Sambuc llvm::VectorType *TblTy = cast<llvm::VectorType>(Ops[0]->getType()); 2579*f4a2713aSLionel Sambuc for (unsigned i = 0, e = TblTy->getNumElements(); i != e; ++i) { 2580*f4a2713aSLionel Sambuc Indices.push_back(ConstantInt::get(CGF.Int32Ty, 2*i)); 2581*f4a2713aSLionel Sambuc Indices.push_back(ConstantInt::get(CGF.Int32Ty, 2*i+1)); 2582*f4a2713aSLionel Sambuc } 2583*f4a2713aSLionel Sambuc Value *SV = llvm::ConstantVector::get(Indices); 2584*f4a2713aSLionel Sambuc 2585*f4a2713aSLionel Sambuc int PairPos = 0, End = Ops.size() - 1; 2586*f4a2713aSLionel Sambuc while (PairPos < End) { 2587*f4a2713aSLionel Sambuc TblOps.push_back(CGF.Builder.CreateShuffleVector(Ops[PairPos], 2588*f4a2713aSLionel Sambuc Ops[PairPos+1], SV, Name)); 2589*f4a2713aSLionel Sambuc PairPos += 2; 2590*f4a2713aSLionel Sambuc } 2591*f4a2713aSLionel Sambuc 2592*f4a2713aSLionel Sambuc // If there's an odd number of 64-bit lookup table, fill the high 64-bit 2593*f4a2713aSLionel Sambuc // of the 128-bit lookup table with zero. 2594*f4a2713aSLionel Sambuc if (PairPos == End) { 2595*f4a2713aSLionel Sambuc Value *ZeroTbl = ConstantAggregateZero::get(TblTy); 2596*f4a2713aSLionel Sambuc TblOps.push_back(CGF.Builder.CreateShuffleVector(Ops[PairPos], 2597*f4a2713aSLionel Sambuc ZeroTbl, SV, Name)); 2598*f4a2713aSLionel Sambuc } 2599*f4a2713aSLionel Sambuc 2600*f4a2713aSLionel Sambuc TblTy = llvm::VectorType::get(TblTy->getElementType(), 2601*f4a2713aSLionel Sambuc 2*TblTy->getNumElements()); 2602*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { ResTy, TblTy }; 2603*f4a2713aSLionel Sambuc 2604*f4a2713aSLionel Sambuc Function *TblF; 2605*f4a2713aSLionel Sambuc TblOps.push_back(IndexOp); 2606*f4a2713aSLionel Sambuc TblF = CGF.CGM.getIntrinsic(IntID, Tys); 2607*f4a2713aSLionel Sambuc 2608*f4a2713aSLionel Sambuc return CGF.EmitNeonCall(TblF, TblOps, Name); 2609*f4a2713aSLionel Sambuc } 2610*f4a2713aSLionel Sambuc 2611*f4a2713aSLionel Sambuc static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, 2612*f4a2713aSLionel Sambuc unsigned BuiltinID, 2613*f4a2713aSLionel Sambuc const CallExpr *E) { 2614*f4a2713aSLionel Sambuc unsigned int Int = 0; 2615*f4a2713aSLionel Sambuc const char *s = NULL; 2616*f4a2713aSLionel Sambuc 2617*f4a2713aSLionel Sambuc unsigned TblPos; 2618*f4a2713aSLionel Sambuc switch (BuiltinID) { 2619*f4a2713aSLionel Sambuc default: 2620*f4a2713aSLionel Sambuc return 0; 2621*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbl1_v: 2622*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl1_v: 2623*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl1q_v: 2624*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbl2_v: 2625*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl2_v: 2626*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl2q_v: 2627*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbl3_v: 2628*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl3_v: 2629*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl3q_v: 2630*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbl4_v: 2631*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl4_v: 2632*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl4q_v: 2633*f4a2713aSLionel Sambuc TblPos = 0; 2634*f4a2713aSLionel Sambuc break; 2635*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbx1_v: 2636*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx1_v: 2637*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx1q_v: 2638*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbx2_v: 2639*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx2_v: 2640*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx2q_v: 2641*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbx3_v: 2642*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx3_v: 2643*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx3q_v: 2644*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbx4_v: 2645*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx4_v: 2646*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx4q_v: 2647*f4a2713aSLionel Sambuc TblPos = 1; 2648*f4a2713aSLionel Sambuc break; 2649*f4a2713aSLionel Sambuc } 2650*f4a2713aSLionel Sambuc 2651*f4a2713aSLionel Sambuc assert(E->getNumArgs() >= 3); 2652*f4a2713aSLionel Sambuc 2653*f4a2713aSLionel Sambuc // Get the last argument, which specifies the vector type. 2654*f4a2713aSLionel Sambuc llvm::APSInt Result; 2655*f4a2713aSLionel Sambuc const Expr *Arg = E->getArg(E->getNumArgs() - 1); 2656*f4a2713aSLionel Sambuc if (!Arg->isIntegerConstantExpr(Result, CGF.getContext())) 2657*f4a2713aSLionel Sambuc return 0; 2658*f4a2713aSLionel Sambuc 2659*f4a2713aSLionel Sambuc // Determine the type of this overloaded NEON intrinsic. 2660*f4a2713aSLionel Sambuc NeonTypeFlags Type(Result.getZExtValue()); 2661*f4a2713aSLionel Sambuc llvm::VectorType *VTy = GetNeonType(&CGF, Type); 2662*f4a2713aSLionel Sambuc llvm::Type *Ty = VTy; 2663*f4a2713aSLionel Sambuc if (!Ty) 2664*f4a2713aSLionel Sambuc return 0; 2665*f4a2713aSLionel Sambuc 2666*f4a2713aSLionel Sambuc SmallVector<Value *, 4> Ops; 2667*f4a2713aSLionel Sambuc for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) { 2668*f4a2713aSLionel Sambuc Ops.push_back(CGF.EmitScalarExpr(E->getArg(i))); 2669*f4a2713aSLionel Sambuc } 2670*f4a2713aSLionel Sambuc 2671*f4a2713aSLionel Sambuc Arg = E->getArg(TblPos); 2672*f4a2713aSLionel Sambuc llvm::Type *TblTy = CGF.ConvertType(Arg->getType()); 2673*f4a2713aSLionel Sambuc llvm::VectorType *VTblTy = cast<llvm::VectorType>(TblTy); 2674*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, VTblTy }; 2675*f4a2713aSLionel Sambuc unsigned nElts = VTy->getNumElements(); 2676*f4a2713aSLionel Sambuc 2677*f4a2713aSLionel Sambuc // AArch64 scalar builtins are not overloaded, they do not have an extra 2678*f4a2713aSLionel Sambuc // argument that specifies the vector type, need to handle each case. 2679*f4a2713aSLionel Sambuc SmallVector<Value *, 2> TblOps; 2680*f4a2713aSLionel Sambuc switch (BuiltinID) { 2681*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbl1_v: { 2682*f4a2713aSLionel Sambuc TblOps.push_back(Ops[0]); 2683*f4a2713aSLionel Sambuc return packTBLDVectorList(CGF, TblOps, 0, Ops[1], Ty, 2684*f4a2713aSLionel Sambuc Intrinsic::aarch64_neon_vtbl1, "vtbl1"); 2685*f4a2713aSLionel Sambuc } 2686*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbl2_v: { 2687*f4a2713aSLionel Sambuc TblOps.push_back(Ops[0]); 2688*f4a2713aSLionel Sambuc TblOps.push_back(Ops[1]); 2689*f4a2713aSLionel Sambuc return packTBLDVectorList(CGF, TblOps, 0, Ops[2], Ty, 2690*f4a2713aSLionel Sambuc Intrinsic::aarch64_neon_vtbl1, "vtbl1"); 2691*f4a2713aSLionel Sambuc } 2692*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbl3_v: { 2693*f4a2713aSLionel Sambuc TblOps.push_back(Ops[0]); 2694*f4a2713aSLionel Sambuc TblOps.push_back(Ops[1]); 2695*f4a2713aSLionel Sambuc TblOps.push_back(Ops[2]); 2696*f4a2713aSLionel Sambuc return packTBLDVectorList(CGF, TblOps, 0, Ops[3], Ty, 2697*f4a2713aSLionel Sambuc Intrinsic::aarch64_neon_vtbl2, "vtbl2"); 2698*f4a2713aSLionel Sambuc } 2699*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbl4_v: { 2700*f4a2713aSLionel Sambuc TblOps.push_back(Ops[0]); 2701*f4a2713aSLionel Sambuc TblOps.push_back(Ops[1]); 2702*f4a2713aSLionel Sambuc TblOps.push_back(Ops[2]); 2703*f4a2713aSLionel Sambuc TblOps.push_back(Ops[3]); 2704*f4a2713aSLionel Sambuc return packTBLDVectorList(CGF, TblOps, 0, Ops[4], Ty, 2705*f4a2713aSLionel Sambuc Intrinsic::aarch64_neon_vtbl2, "vtbl2"); 2706*f4a2713aSLionel Sambuc } 2707*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbx1_v: { 2708*f4a2713aSLionel Sambuc TblOps.push_back(Ops[1]); 2709*f4a2713aSLionel Sambuc Value *TblRes = packTBLDVectorList(CGF, TblOps, 0, Ops[2], Ty, 2710*f4a2713aSLionel Sambuc Intrinsic::aarch64_neon_vtbl1, "vtbl1"); 2711*f4a2713aSLionel Sambuc 2712*f4a2713aSLionel Sambuc llvm::Constant *Eight = ConstantInt::get(VTy->getElementType(), 8); 2713*f4a2713aSLionel Sambuc Value* EightV = llvm::ConstantVector::getSplat(nElts, Eight); 2714*f4a2713aSLionel Sambuc Value *CmpRes = CGF.Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[2], EightV); 2715*f4a2713aSLionel Sambuc CmpRes = CGF.Builder.CreateSExt(CmpRes, Ty); 2716*f4a2713aSLionel Sambuc 2717*f4a2713aSLionel Sambuc SmallVector<Value *, 4> BslOps; 2718*f4a2713aSLionel Sambuc BslOps.push_back(CmpRes); 2719*f4a2713aSLionel Sambuc BslOps.push_back(Ops[0]); 2720*f4a2713aSLionel Sambuc BslOps.push_back(TblRes); 2721*f4a2713aSLionel Sambuc Function *BslF = CGF.CGM.getIntrinsic(Intrinsic::arm_neon_vbsl, Ty); 2722*f4a2713aSLionel Sambuc return CGF.EmitNeonCall(BslF, BslOps, "vbsl"); 2723*f4a2713aSLionel Sambuc } 2724*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbx2_v: { 2725*f4a2713aSLionel Sambuc TblOps.push_back(Ops[1]); 2726*f4a2713aSLionel Sambuc TblOps.push_back(Ops[2]); 2727*f4a2713aSLionel Sambuc return packTBLDVectorList(CGF, TblOps, Ops[0], Ops[3], Ty, 2728*f4a2713aSLionel Sambuc Intrinsic::aarch64_neon_vtbx1, "vtbx1"); 2729*f4a2713aSLionel Sambuc } 2730*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbx3_v: { 2731*f4a2713aSLionel Sambuc TblOps.push_back(Ops[1]); 2732*f4a2713aSLionel Sambuc TblOps.push_back(Ops[2]); 2733*f4a2713aSLionel Sambuc TblOps.push_back(Ops[3]); 2734*f4a2713aSLionel Sambuc Value *TblRes = packTBLDVectorList(CGF, TblOps, 0, Ops[4], Ty, 2735*f4a2713aSLionel Sambuc Intrinsic::aarch64_neon_vtbl2, "vtbl2"); 2736*f4a2713aSLionel Sambuc 2737*f4a2713aSLionel Sambuc llvm::Constant *TwentyFour = ConstantInt::get(VTy->getElementType(), 24); 2738*f4a2713aSLionel Sambuc Value* TwentyFourV = llvm::ConstantVector::getSplat(nElts, TwentyFour); 2739*f4a2713aSLionel Sambuc Value *CmpRes = CGF.Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[4], 2740*f4a2713aSLionel Sambuc TwentyFourV); 2741*f4a2713aSLionel Sambuc CmpRes = CGF.Builder.CreateSExt(CmpRes, Ty); 2742*f4a2713aSLionel Sambuc 2743*f4a2713aSLionel Sambuc SmallVector<Value *, 4> BslOps; 2744*f4a2713aSLionel Sambuc BslOps.push_back(CmpRes); 2745*f4a2713aSLionel Sambuc BslOps.push_back(Ops[0]); 2746*f4a2713aSLionel Sambuc BslOps.push_back(TblRes); 2747*f4a2713aSLionel Sambuc Function *BslF = CGF.CGM.getIntrinsic(Intrinsic::arm_neon_vbsl, Ty); 2748*f4a2713aSLionel Sambuc return CGF.EmitNeonCall(BslF, BslOps, "vbsl"); 2749*f4a2713aSLionel Sambuc } 2750*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtbx4_v: { 2751*f4a2713aSLionel Sambuc TblOps.push_back(Ops[1]); 2752*f4a2713aSLionel Sambuc TblOps.push_back(Ops[2]); 2753*f4a2713aSLionel Sambuc TblOps.push_back(Ops[3]); 2754*f4a2713aSLionel Sambuc TblOps.push_back(Ops[4]); 2755*f4a2713aSLionel Sambuc return packTBLDVectorList(CGF, TblOps, Ops[0], Ops[5], Ty, 2756*f4a2713aSLionel Sambuc Intrinsic::aarch64_neon_vtbx2, "vtbx2"); 2757*f4a2713aSLionel Sambuc } 2758*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl1_v: 2759*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl1q_v: 2760*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vtbl1; s = "vtbl1"; break; 2761*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl2_v: 2762*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl2q_v: { 2763*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vtbl2; s = "vtbl2"; break; 2764*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl3_v: 2765*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl3q_v: 2766*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vtbl3; s = "vtbl3"; break; 2767*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl4_v: 2768*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbl4q_v: 2769*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vtbl4; s = "vtbl4"; break; 2770*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx1_v: 2771*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx1q_v: 2772*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vtbx1; s = "vtbx1"; break; 2773*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx2_v: 2774*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx2q_v: 2775*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vtbx2; s = "vtbx2"; break; 2776*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx3_v: 2777*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx3q_v: 2778*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vtbx3; s = "vtbx3"; break; 2779*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx4_v: 2780*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqtbx4q_v: 2781*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vtbx4; s = "vtbx4"; break; 2782*f4a2713aSLionel Sambuc } 2783*f4a2713aSLionel Sambuc } 2784*f4a2713aSLionel Sambuc 2785*f4a2713aSLionel Sambuc if (!Int) 2786*f4a2713aSLionel Sambuc return 0; 2787*f4a2713aSLionel Sambuc 2788*f4a2713aSLionel Sambuc Function *F = CGF.CGM.getIntrinsic(Int, Tys); 2789*f4a2713aSLionel Sambuc return CGF.EmitNeonCall(F, Ops, s); 2790*f4a2713aSLionel Sambuc } 2791*f4a2713aSLionel Sambuc 2792*f4a2713aSLionel Sambuc Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, 2793*f4a2713aSLionel Sambuc const CallExpr *E) { 2794*f4a2713aSLionel Sambuc // Process AArch64 scalar builtins 2795*f4a2713aSLionel Sambuc if (Value *Result = EmitAArch64ScalarBuiltinExpr(*this, BuiltinID, E)) 2796*f4a2713aSLionel Sambuc return Result; 2797*f4a2713aSLionel Sambuc 2798*f4a2713aSLionel Sambuc // Process AArch64 table lookup builtins 2799*f4a2713aSLionel Sambuc if (Value *Result = EmitAArch64TblBuiltinExpr(*this, BuiltinID, E)) 2800*f4a2713aSLionel Sambuc return Result; 2801*f4a2713aSLionel Sambuc 2802*f4a2713aSLionel Sambuc if (BuiltinID == AArch64::BI__clear_cache) { 2803*f4a2713aSLionel Sambuc assert(E->getNumArgs() == 2 && 2804*f4a2713aSLionel Sambuc "Variadic __clear_cache slipped through on AArch64"); 2805*f4a2713aSLionel Sambuc 2806*f4a2713aSLionel Sambuc const FunctionDecl *FD = E->getDirectCallee(); 2807*f4a2713aSLionel Sambuc SmallVector<Value *, 2> Ops; 2808*f4a2713aSLionel Sambuc for (unsigned i = 0; i < E->getNumArgs(); i++) 2809*f4a2713aSLionel Sambuc Ops.push_back(EmitScalarExpr(E->getArg(i))); 2810*f4a2713aSLionel Sambuc llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType()); 2811*f4a2713aSLionel Sambuc llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty); 2812*f4a2713aSLionel Sambuc StringRef Name = FD->getName(); 2813*f4a2713aSLionel Sambuc return EmitNounwindRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Ops); 2814*f4a2713aSLionel Sambuc } 2815*f4a2713aSLionel Sambuc 2816*f4a2713aSLionel Sambuc SmallVector<Value *, 4> Ops; 2817*f4a2713aSLionel Sambuc llvm::Value *Align = 0; // Alignment for load/store 2818*f4a2713aSLionel Sambuc for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) { 2819*f4a2713aSLionel Sambuc if (i == 0) { 2820*f4a2713aSLionel Sambuc switch (BuiltinID) { 2821*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_x2_v: 2822*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_x2_v: 2823*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_x3_v: 2824*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_x3_v: 2825*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_x4_v: 2826*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_x4_v: 2827*f4a2713aSLionel Sambuc // Handle ld1/st1 lane in this function a little different from ARM. 2828*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_lane_v: 2829*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_lane_v: 2830*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_lane_v: 2831*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_lane_v: 2832*f4a2713aSLionel Sambuc // Get the alignment for the argument in addition to the value; 2833*f4a2713aSLionel Sambuc // we'll use it later. 2834*f4a2713aSLionel Sambuc std::pair<llvm::Value *, unsigned> Src = 2835*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(0)); 2836*f4a2713aSLionel Sambuc Ops.push_back(Src.first); 2837*f4a2713aSLionel Sambuc Align = Builder.getInt32(Src.second); 2838*f4a2713aSLionel Sambuc continue; 2839*f4a2713aSLionel Sambuc } 2840*f4a2713aSLionel Sambuc } 2841*f4a2713aSLionel Sambuc if (i == 1) { 2842*f4a2713aSLionel Sambuc switch (BuiltinID) { 2843*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_x2_v: 2844*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_x2_v: 2845*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_x3_v: 2846*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_x3_v: 2847*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_x4_v: 2848*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_x4_v: 2849*f4a2713aSLionel Sambuc // Handle ld1/st1 dup lane in this function a little different from ARM. 2850*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2_dup_v: 2851*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2q_dup_v: 2852*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld3_dup_v: 2853*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld3q_dup_v: 2854*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld4_dup_v: 2855*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld4q_dup_v: 2856*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2_lane_v: 2857*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2q_lane_v: 2858*f4a2713aSLionel Sambuc // Get the alignment for the argument in addition to the value; 2859*f4a2713aSLionel Sambuc // we'll use it later. 2860*f4a2713aSLionel Sambuc std::pair<llvm::Value *, unsigned> Src = 2861*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(1)); 2862*f4a2713aSLionel Sambuc Ops.push_back(Src.first); 2863*f4a2713aSLionel Sambuc Align = Builder.getInt32(Src.second); 2864*f4a2713aSLionel Sambuc continue; 2865*f4a2713aSLionel Sambuc } 2866*f4a2713aSLionel Sambuc } 2867*f4a2713aSLionel Sambuc Ops.push_back(EmitScalarExpr(E->getArg(i))); 2868*f4a2713aSLionel Sambuc } 2869*f4a2713aSLionel Sambuc 2870*f4a2713aSLionel Sambuc // Get the last argument, which specifies the vector type. 2871*f4a2713aSLionel Sambuc llvm::APSInt Result; 2872*f4a2713aSLionel Sambuc const Expr *Arg = E->getArg(E->getNumArgs() - 1); 2873*f4a2713aSLionel Sambuc if (!Arg->isIntegerConstantExpr(Result, getContext())) 2874*f4a2713aSLionel Sambuc return 0; 2875*f4a2713aSLionel Sambuc 2876*f4a2713aSLionel Sambuc // Determine the type of this overloaded NEON intrinsic. 2877*f4a2713aSLionel Sambuc NeonTypeFlags Type(Result.getZExtValue()); 2878*f4a2713aSLionel Sambuc bool usgn = Type.isUnsigned(); 2879*f4a2713aSLionel Sambuc 2880*f4a2713aSLionel Sambuc llvm::VectorType *VTy = GetNeonType(this, Type); 2881*f4a2713aSLionel Sambuc llvm::Type *Ty = VTy; 2882*f4a2713aSLionel Sambuc if (!Ty) 2883*f4a2713aSLionel Sambuc return 0; 2884*f4a2713aSLionel Sambuc 2885*f4a2713aSLionel Sambuc unsigned Int; 2886*f4a2713aSLionel Sambuc switch (BuiltinID) { 2887*f4a2713aSLionel Sambuc default: 2888*f4a2713aSLionel Sambuc return 0; 2889*f4a2713aSLionel Sambuc 2890*f4a2713aSLionel Sambuc // AArch64 builtins mapping to legacy ARM v7 builtins. 2891*f4a2713aSLionel Sambuc // FIXME: the mapped builtins listed correspond to what has been tested 2892*f4a2713aSLionel Sambuc // in aarch64-neon-intrinsics.c so far. 2893*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vuzp_v: 2894*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vuzp_v, E); 2895*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vuzpq_v: 2896*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vuzpq_v, E); 2897*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vzip_v: 2898*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vzip_v, E); 2899*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vzipq_v: 2900*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vzipq_v, E); 2901*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtrn_v: 2902*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vtrn_v, E); 2903*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtrnq_v: 2904*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vtrnq_v, E); 2905*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vext_v: 2906*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vext_v, E); 2907*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vextq_v: 2908*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vextq_v, E); 2909*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmul_v: 2910*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmul_v, E); 2911*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmulq_v: 2912*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmulq_v, E); 2913*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vabd_v: 2914*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vabd_v, E); 2915*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vabdq_v: 2916*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vabdq_v, E); 2917*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfma_v: 2918*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vfma_v, E); 2919*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfmaq_v: 2920*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vfmaq_v, E); 2921*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vbsl_v: 2922*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vbsl_v, E); 2923*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vbslq_v: 2924*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vbslq_v, E); 2925*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsqrts_v: 2926*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrsqrts_v, E); 2927*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsqrtsq_v: 2928*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrsqrtsq_v, E); 2929*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrecps_v: 2930*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrecps_v, E); 2931*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrecpsq_v: 2932*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrecpsq_v, E); 2933*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcage_v: 2934*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcage_v, E); 2935*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcale_v: 2936*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcale_v, E); 2937*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcaleq_v: 2938*f4a2713aSLionel Sambuc std::swap(Ops[0], Ops[1]); 2939*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcageq_v: { 2940*f4a2713aSLionel Sambuc Function *F; 2941*f4a2713aSLionel Sambuc if (VTy->getElementType()->isIntegerTy(64)) 2942*f4a2713aSLionel Sambuc F = CGM.getIntrinsic(Intrinsic::aarch64_neon_vacgeq); 2943*f4a2713aSLionel Sambuc else 2944*f4a2713aSLionel Sambuc F = CGM.getIntrinsic(Intrinsic::arm_neon_vacgeq); 2945*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcage"); 2946*f4a2713aSLionel Sambuc } 2947*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcalt_v: 2948*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcalt_v, E); 2949*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcagt_v: 2950*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcagt_v, E); 2951*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcaltq_v: 2952*f4a2713aSLionel Sambuc std::swap(Ops[0], Ops[1]); 2953*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcagtq_v: { 2954*f4a2713aSLionel Sambuc Function *F; 2955*f4a2713aSLionel Sambuc if (VTy->getElementType()->isIntegerTy(64)) 2956*f4a2713aSLionel Sambuc F = CGM.getIntrinsic(Intrinsic::aarch64_neon_vacgtq); 2957*f4a2713aSLionel Sambuc else 2958*f4a2713aSLionel Sambuc F = CGM.getIntrinsic(Intrinsic::arm_neon_vacgtq); 2959*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcagt"); 2960*f4a2713aSLionel Sambuc } 2961*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtst_v: 2962*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vtst_v, E); 2963*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vtstq_v: 2964*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vtstq_v, E); 2965*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vhadd_v: 2966*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vhadd_v, E); 2967*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vhaddq_v: 2968*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vhaddq_v, E); 2969*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vhsub_v: 2970*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vhsub_v, E); 2971*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vhsubq_v: 2972*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vhsubq_v, E); 2973*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrhadd_v: 2974*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrhadd_v, E); 2975*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrhaddq_v: 2976*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrhaddq_v, E); 2977*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqadd_v: 2978*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqadd_v, E); 2979*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqaddq_v: 2980*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqaddq_v, E); 2981*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqsub_v: 2982*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqsub_v, E); 2983*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqsubq_v: 2984*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqsubq_v, E); 2985*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshl_v: 2986*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshl_v, E); 2987*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshlq_v: 2988*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshlq_v, E); 2989*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshl_v: 2990*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqshl_v, E); 2991*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlq_v: 2992*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqshlq_v, E); 2993*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrshl_v: 2994*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrshl_v, E); 2995*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrshlq_v: 2996*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrshlq_v, E); 2997*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshl_v: 2998*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqrshl_v, E); 2999*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshlq_v: 3000*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqrshlq_v, E); 3001*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaddhn_v: 3002*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vaddhn_v, E); 3003*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vraddhn_v: 3004*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vraddhn_v, E); 3005*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsubhn_v: 3006*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vsubhn_v, E); 3007*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsubhn_v: 3008*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrsubhn_v, E); 3009*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmull_v: 3010*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmull_v, E); 3011*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmull_v: 3012*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqdmull_v, E); 3013*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlal_v: 3014*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqdmlal_v, E); 3015*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmlsl_v: 3016*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqdmlsl_v, E); 3017*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmax_v: 3018*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmax_v, E); 3019*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxq_v: 3020*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmaxq_v, E); 3021*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmin_v: 3022*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmin_v, E); 3023*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminq_v: 3024*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vminq_v, E); 3025*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpmax_v: 3026*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vpmax_v, E); 3027*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpmin_v: 3028*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vpmin_v, E); 3029*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpadd_v: 3030*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vpadd_v, E); 3031*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmulh_v: 3032*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqdmulh_v, E); 3033*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqdmulhq_v: 3034*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqdmulhq_v, E); 3035*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrdmulh_v: 3036*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqrdmulh_v, E); 3037*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrdmulhq_v: 3038*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqrdmulhq_v, E); 3039*f4a2713aSLionel Sambuc 3040*f4a2713aSLionel Sambuc // Shift by immediate 3041*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshr_n_v: 3042*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshr_n_v, E); 3043*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshrq_n_v: 3044*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshrq_n_v, E); 3045*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrshr_n_v: 3046*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrshrq_n_v: 3047*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::aarch64_neon_vurshr 3048*f4a2713aSLionel Sambuc : Intrinsic::aarch64_neon_vsrshr; 3049*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshr_n"); 3050*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsra_n_v: 3051*f4a2713aSLionel Sambuc if (VTy->getElementType()->isIntegerTy(64)) { 3052*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::aarch64_neon_vsradu_n 3053*f4a2713aSLionel Sambuc : Intrinsic::aarch64_neon_vsrads_n; 3054*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int), Ops, "vsra_n"); 3055*f4a2713aSLionel Sambuc } 3056*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vsra_n_v, E); 3057*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsraq_n_v: 3058*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vsraq_n_v, E); 3059*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsra_n_v: 3060*f4a2713aSLionel Sambuc if (VTy->getElementType()->isIntegerTy(64)) { 3061*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::aarch64_neon_vrsradu_n 3062*f4a2713aSLionel Sambuc : Intrinsic::aarch64_neon_vrsrads_n; 3063*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int), Ops, "vrsra_n"); 3064*f4a2713aSLionel Sambuc } 3065*f4a2713aSLionel Sambuc // fall through 3066*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsraq_n_v: { 3067*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3068*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 3069*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::aarch64_neon_vurshr 3070*f4a2713aSLionel Sambuc : Intrinsic::aarch64_neon_vsrshr; 3071*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall2(CGM.getIntrinsic(Int, Ty), Ops[1], Ops[2]); 3072*f4a2713aSLionel Sambuc return Builder.CreateAdd(Ops[0], Ops[1], "vrsra_n"); 3073*f4a2713aSLionel Sambuc } 3074*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshl_n_v: 3075*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshl_n_v, E); 3076*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshlq_n_v: 3077*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshlq_n_v, E); 3078*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshl_n_v: 3079*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqshl_n_v, E); 3080*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlq_n_v: 3081*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqshlq_n_v, E); 3082*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshlu_n_v: 3083*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshluq_n_v: 3084*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsqshlu; 3085*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshlu_n"); 3086*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsri_n_v: 3087*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsriq_n_v: 3088*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsri; 3089*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsri_n"); 3090*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsli_n_v: 3091*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsliq_n_v: 3092*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsli; 3093*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsli_n"); 3094*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshll_n_v: { 3095*f4a2713aSLionel Sambuc llvm::Type *SrcTy = llvm::VectorType::getTruncatedElementVectorType(VTy); 3096*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy); 3097*f4a2713aSLionel Sambuc if (usgn) 3098*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateZExt(Ops[0], VTy); 3099*f4a2713aSLionel Sambuc else 3100*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateSExt(Ops[0], VTy); 3101*f4a2713aSLionel Sambuc Ops[1] = EmitNeonShiftVector(Ops[1], VTy, false); 3102*f4a2713aSLionel Sambuc return Builder.CreateShl(Ops[0], Ops[1], "vshll_n"); 3103*f4a2713aSLionel Sambuc } 3104*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vshrn_n_v: { 3105*f4a2713aSLionel Sambuc llvm::Type *SrcTy = llvm::VectorType::getExtendedElementVectorType(VTy); 3106*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy); 3107*f4a2713aSLionel Sambuc Ops[1] = EmitNeonShiftVector(Ops[1], SrcTy, false); 3108*f4a2713aSLionel Sambuc if (usgn) 3109*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateLShr(Ops[0], Ops[1]); 3110*f4a2713aSLionel Sambuc else 3111*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateAShr(Ops[0], Ops[1]); 3112*f4a2713aSLionel Sambuc return Builder.CreateTrunc(Ops[0], Ty, "vshrn_n"); 3113*f4a2713aSLionel Sambuc } 3114*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshrun_n_v: 3115*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsqshrun; 3116*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrun_n"); 3117*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrshrn_n_v: 3118*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vrshrn; 3119*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshrn_n"); 3120*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshrun_n_v: 3121*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vsqrshrun; 3122*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrun_n"); 3123*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqshrn_n_v: 3124*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::aarch64_neon_vuqshrn 3125*f4a2713aSLionel Sambuc : Intrinsic::aarch64_neon_vsqshrn; 3126*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrn_n"); 3127*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqrshrn_n_v: 3128*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::aarch64_neon_vuqrshrn 3129*f4a2713aSLionel Sambuc : Intrinsic::aarch64_neon_vsqrshrn; 3130*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrn_n"); 3131*f4a2713aSLionel Sambuc 3132*f4a2713aSLionel Sambuc // Convert 3133*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmovl_v: 3134*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmovl_v, E); 3135*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvt_n_f32_v: 3136*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_n_f32_v, E); 3137*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_n_f32_v: 3138*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvtq_n_f32_v, E); 3139*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_n_f64_v: { 3140*f4a2713aSLionel Sambuc llvm::Type *FloatTy = 3141*f4a2713aSLionel Sambuc GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, true)); 3142*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { FloatTy, Ty }; 3143*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vcvtfxu2fp 3144*f4a2713aSLionel Sambuc : Intrinsic::arm_neon_vcvtfxs2fp; 3145*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Int, Tys); 3146*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcvt_n"); 3147*f4a2713aSLionel Sambuc } 3148*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvt_n_s32_v: 3149*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_n_s32_v, E); 3150*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_n_s32_v: 3151*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvtq_n_s32_v, E); 3152*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvt_n_u32_v: 3153*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_n_u32_v, E); 3154*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_n_u32_v: 3155*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvtq_n_u32_v, E); 3156*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_n_s64_v: 3157*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_n_u64_v: { 3158*f4a2713aSLionel Sambuc llvm::Type *FloatTy = 3159*f4a2713aSLionel Sambuc GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, true)); 3160*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, FloatTy }; 3161*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vcvtfp2fxu 3162*f4a2713aSLionel Sambuc : Intrinsic::arm_neon_vcvtfp2fxs; 3163*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Int, Tys); 3164*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcvt_n"); 3165*f4a2713aSLionel Sambuc } 3166*f4a2713aSLionel Sambuc 3167*f4a2713aSLionel Sambuc // Load/Store 3168*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_v: 3169*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld1_v, E); 3170*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_v: 3171*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld1q_v, E); 3172*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2_v: 3173*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld2_v, E); 3174*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2q_v: 3175*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld2q_v, E); 3176*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld3_v: 3177*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld3_v, E); 3178*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld3q_v: 3179*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld3q_v, E); 3180*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld4_v: 3181*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld4_v, E); 3182*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld4q_v: 3183*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld4q_v, E); 3184*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_v: 3185*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst1_v, E); 3186*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_v: 3187*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst1q_v, E); 3188*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst2_v: 3189*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst2_v, E); 3190*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst2q_v: 3191*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst2q_v, E); 3192*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst3_v: 3193*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst3_v, E); 3194*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst3q_v: 3195*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst3q_v, E); 3196*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst4_v: 3197*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst4_v, E); 3198*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst4q_v: 3199*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst4q_v, E); 3200*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_x2_v: 3201*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_x2_v: 3202*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_x3_v: 3203*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_x3_v: 3204*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_x4_v: 3205*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_x4_v: { 3206*f4a2713aSLionel Sambuc unsigned Int; 3207*f4a2713aSLionel Sambuc switch (BuiltinID) { 3208*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_x2_v: 3209*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_x2_v: 3210*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vld1x2; 3211*f4a2713aSLionel Sambuc break; 3212*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_x3_v: 3213*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_x3_v: 3214*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vld1x3; 3215*f4a2713aSLionel Sambuc break; 3216*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_x4_v: 3217*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_x4_v: 3218*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vld1x4; 3219*f4a2713aSLionel Sambuc break; 3220*f4a2713aSLionel Sambuc } 3221*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Int, Ty); 3222*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld1xN"); 3223*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 3224*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3225*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 3226*f4a2713aSLionel Sambuc } 3227*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_x2_v: 3228*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_x2_v: 3229*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_x3_v: 3230*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_x3_v: 3231*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_x4_v: 3232*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_x4_v: { 3233*f4a2713aSLionel Sambuc Ops.push_back(Align); 3234*f4a2713aSLionel Sambuc unsigned Int; 3235*f4a2713aSLionel Sambuc switch (BuiltinID) { 3236*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_x2_v: 3237*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_x2_v: 3238*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vst1x2; 3239*f4a2713aSLionel Sambuc break; 3240*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_x3_v: 3241*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_x3_v: 3242*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vst1x3; 3243*f4a2713aSLionel Sambuc break; 3244*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_x4_v: 3245*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_x4_v: 3246*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vst1x4; 3247*f4a2713aSLionel Sambuc break; 3248*f4a2713aSLionel Sambuc } 3249*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, ""); 3250*f4a2713aSLionel Sambuc } 3251*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_lane_v: 3252*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_lane_v: { 3253*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 3254*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(VTy->getElementType()); 3255*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3256*f4a2713aSLionel Sambuc LoadInst *Ld = Builder.CreateLoad(Ops[0]); 3257*f4a2713aSLionel Sambuc Ld->setAlignment(cast<ConstantInt>(Align)->getZExtValue()); 3258*f4a2713aSLionel Sambuc return Builder.CreateInsertElement(Ops[1], Ld, Ops[2], "vld1_lane"); 3259*f4a2713aSLionel Sambuc } 3260*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2_lane_v: 3261*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld2q_lane_v, E); 3262*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2q_lane_v: 3263*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld2q_lane_v, E); 3264*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld3_lane_v: 3265*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld3_lane_v, E); 3266*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld3q_lane_v: 3267*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld3q_lane_v, E); 3268*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld4_lane_v: 3269*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld4_lane_v, E); 3270*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld4q_lane_v: 3271*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld4q_lane_v, E); 3272*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1_lane_v: 3273*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst1q_lane_v: { 3274*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 3275*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]); 3276*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 3277*f4a2713aSLionel Sambuc StoreInst *St = 3278*f4a2713aSLionel Sambuc Builder.CreateStore(Ops[1], Builder.CreateBitCast(Ops[0], Ty)); 3279*f4a2713aSLionel Sambuc St->setAlignment(cast<ConstantInt>(Align)->getZExtValue()); 3280*f4a2713aSLionel Sambuc return St; 3281*f4a2713aSLionel Sambuc } 3282*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst2_lane_v: 3283*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst2_lane_v, E); 3284*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst2q_lane_v: 3285*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst2q_lane_v, E); 3286*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst3_lane_v: 3287*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst3_lane_v, E); 3288*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst3q_lane_v: 3289*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst3q_lane_v, E); 3290*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst4_lane_v: 3291*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst4_lane_v, E); 3292*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vst4q_lane_v: 3293*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst4q_lane_v, E); 3294*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1_dup_v: 3295*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld1_dup_v, E); 3296*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld1q_dup_v: 3297*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld1q_dup_v, E); 3298*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2_dup_v: 3299*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2q_dup_v: 3300*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld3_dup_v: 3301*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld3q_dup_v: 3302*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld4_dup_v: 3303*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld4q_dup_v: { 3304*f4a2713aSLionel Sambuc // Handle 64-bit x 1 elements as a special-case. There is no "dup" needed. 3305*f4a2713aSLionel Sambuc if (VTy->getElementType()->getPrimitiveSizeInBits() == 64 && 3306*f4a2713aSLionel Sambuc VTy->getNumElements() == 1) { 3307*f4a2713aSLionel Sambuc switch (BuiltinID) { 3308*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2_dup_v: 3309*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld2; 3310*f4a2713aSLionel Sambuc break; 3311*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld3_dup_v: 3312*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld3; 3313*f4a2713aSLionel Sambuc break; 3314*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld4_dup_v: 3315*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld4; 3316*f4a2713aSLionel Sambuc break; 3317*f4a2713aSLionel Sambuc default: 3318*f4a2713aSLionel Sambuc llvm_unreachable("unknown vld_dup intrinsic?"); 3319*f4a2713aSLionel Sambuc } 3320*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Int, Ty); 3321*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld_dup"); 3322*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 3323*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3324*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 3325*f4a2713aSLionel Sambuc } 3326*f4a2713aSLionel Sambuc switch (BuiltinID) { 3327*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2_dup_v: 3328*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld2q_dup_v: 3329*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld2lane; 3330*f4a2713aSLionel Sambuc break; 3331*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld3_dup_v: 3332*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld3q_dup_v: 3333*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld3lane; 3334*f4a2713aSLionel Sambuc break; 3335*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld4_dup_v: 3336*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vld4q_dup_v: 3337*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld4lane; 3338*f4a2713aSLionel Sambuc break; 3339*f4a2713aSLionel Sambuc } 3340*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Int, Ty); 3341*f4a2713aSLionel Sambuc llvm::StructType *STy = cast<llvm::StructType>(F->getReturnType()); 3342*f4a2713aSLionel Sambuc 3343*f4a2713aSLionel Sambuc SmallVector<Value *, 6> Args; 3344*f4a2713aSLionel Sambuc Args.push_back(Ops[1]); 3345*f4a2713aSLionel Sambuc Args.append(STy->getNumElements(), UndefValue::get(Ty)); 3346*f4a2713aSLionel Sambuc 3347*f4a2713aSLionel Sambuc llvm::Constant *CI = ConstantInt::get(Int32Ty, 0); 3348*f4a2713aSLionel Sambuc Args.push_back(CI); 3349*f4a2713aSLionel Sambuc Args.push_back(Align); 3350*f4a2713aSLionel Sambuc 3351*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall(F, Args, "vld_dup"); 3352*f4a2713aSLionel Sambuc // splat lane 0 to all elts in each vector of the result. 3353*f4a2713aSLionel Sambuc for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { 3354*f4a2713aSLionel Sambuc Value *Val = Builder.CreateExtractValue(Ops[1], i); 3355*f4a2713aSLionel Sambuc Value *Elt = Builder.CreateBitCast(Val, Ty); 3356*f4a2713aSLionel Sambuc Elt = EmitNeonSplat(Elt, CI); 3357*f4a2713aSLionel Sambuc Elt = Builder.CreateBitCast(Elt, Val->getType()); 3358*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateInsertValue(Ops[1], Elt, i); 3359*f4a2713aSLionel Sambuc } 3360*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 3361*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3362*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 3363*f4a2713aSLionel Sambuc } 3364*f4a2713aSLionel Sambuc 3365*f4a2713aSLionel Sambuc // Crypto 3366*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaeseq_v: 3367*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_aese, Ty), 3368*f4a2713aSLionel Sambuc Ops, "aese"); 3369*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaesdq_v: 3370*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_aesd, Ty), 3371*f4a2713aSLionel Sambuc Ops, "aesd"); 3372*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaesmcq_v: 3373*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_aesmc, Ty), 3374*f4a2713aSLionel Sambuc Ops, "aesmc"); 3375*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vaesimcq_v: 3376*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_aesimc, Ty), 3377*f4a2713aSLionel Sambuc Ops, "aesimc"); 3378*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsha1su1q_v: 3379*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1su1, Ty), 3380*f4a2713aSLionel Sambuc Ops, "sha1su1"); 3381*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsha256su0q_v: 3382*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha256su0, Ty), 3383*f4a2713aSLionel Sambuc Ops, "sha256su0"); 3384*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsha1su0q_v: 3385*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1su0, Ty), 3386*f4a2713aSLionel Sambuc Ops, "sha1su0"); 3387*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsha256hq_v: 3388*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha256h, Ty), 3389*f4a2713aSLionel Sambuc Ops, "sha256h"); 3390*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsha256h2q_v: 3391*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha256h2, Ty), 3392*f4a2713aSLionel Sambuc Ops, "sha256h2"); 3393*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsha256su1q_v: 3394*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha256su1, Ty), 3395*f4a2713aSLionel Sambuc Ops, "sha256su1"); 3396*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmul_lane_v: 3397*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmul_laneq_v: { 3398*f4a2713aSLionel Sambuc // v1f64 vmul_lane should be mapped to Neon scalar mul lane 3399*f4a2713aSLionel Sambuc bool Quad = false; 3400*f4a2713aSLionel Sambuc if (BuiltinID == AArch64::BI__builtin_neon_vmul_laneq_v) 3401*f4a2713aSLionel Sambuc Quad = true; 3402*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy); 3403*f4a2713aSLionel Sambuc llvm::Type *VTy = GetNeonType(this, 3404*f4a2713aSLionel Sambuc NeonTypeFlags(NeonTypeFlags::Float64, false, Quad ? true : false)); 3405*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], VTy); 3406*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract"); 3407*f4a2713aSLionel Sambuc Value *Result = Builder.CreateFMul(Ops[0], Ops[1]); 3408*f4a2713aSLionel Sambuc return Builder.CreateBitCast(Result, Ty); 3409*f4a2713aSLionel Sambuc } 3410*f4a2713aSLionel Sambuc 3411*f4a2713aSLionel Sambuc // AArch64-only builtins 3412*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfmaq_laneq_v: { 3413*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty); 3414*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3415*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 3416*f4a2713aSLionel Sambuc 3417*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], Ty); 3418*f4a2713aSLionel Sambuc Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3])); 3419*f4a2713aSLionel Sambuc return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]); 3420*f4a2713aSLionel Sambuc } 3421*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfmaq_lane_v: { 3422*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty); 3423*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3424*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 3425*f4a2713aSLionel Sambuc 3426*f4a2713aSLionel Sambuc llvm::VectorType *VTy = cast<llvm::VectorType>(Ty); 3427*f4a2713aSLionel Sambuc llvm::Type *STy = llvm::VectorType::get(VTy->getElementType(), 3428*f4a2713aSLionel Sambuc VTy->getNumElements() / 2); 3429*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], STy); 3430*f4a2713aSLionel Sambuc Value* SV = llvm::ConstantVector::getSplat(VTy->getNumElements(), 3431*f4a2713aSLionel Sambuc cast<ConstantInt>(Ops[3])); 3432*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateShuffleVector(Ops[2], Ops[2], SV, "lane"); 3433*f4a2713aSLionel Sambuc 3434*f4a2713aSLionel Sambuc return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]); 3435*f4a2713aSLionel Sambuc } 3436*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfma_lane_v: { 3437*f4a2713aSLionel Sambuc llvm::VectorType *VTy = cast<llvm::VectorType>(Ty); 3438*f4a2713aSLionel Sambuc // v1f64 fma should be mapped to Neon scalar f64 fma 3439*f4a2713aSLionel Sambuc if (VTy && VTy->getElementType() == DoubleTy) { 3440*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy); 3441*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy); 3442*f4a2713aSLionel Sambuc llvm::Type *VTy = GetNeonType(this, 3443*f4a2713aSLionel Sambuc NeonTypeFlags(NeonTypeFlags::Float64, false, false)); 3444*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], VTy); 3445*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract"); 3446*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy); 3447*f4a2713aSLionel Sambuc Value *Result = Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]); 3448*f4a2713aSLionel Sambuc return Builder.CreateBitCast(Result, Ty); 3449*f4a2713aSLionel Sambuc } 3450*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty); 3451*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3452*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 3453*f4a2713aSLionel Sambuc 3454*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], Ty); 3455*f4a2713aSLionel Sambuc Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3])); 3456*f4a2713aSLionel Sambuc return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]); 3457*f4a2713aSLionel Sambuc } 3458*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfma_laneq_v: { 3459*f4a2713aSLionel Sambuc llvm::VectorType *VTy = cast<llvm::VectorType>(Ty); 3460*f4a2713aSLionel Sambuc // v1f64 fma should be mapped to Neon scalar f64 fma 3461*f4a2713aSLionel Sambuc if (VTy && VTy->getElementType() == DoubleTy) { 3462*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy); 3463*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy); 3464*f4a2713aSLionel Sambuc llvm::Type *VTy = GetNeonType(this, 3465*f4a2713aSLionel Sambuc NeonTypeFlags(NeonTypeFlags::Float64, false, true)); 3466*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], VTy); 3467*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract"); 3468*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy); 3469*f4a2713aSLionel Sambuc Value *Result = Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]); 3470*f4a2713aSLionel Sambuc return Builder.CreateBitCast(Result, Ty); 3471*f4a2713aSLionel Sambuc } 3472*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty); 3473*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3474*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 3475*f4a2713aSLionel Sambuc 3476*f4a2713aSLionel Sambuc llvm::Type *STy = llvm::VectorType::get(VTy->getElementType(), 3477*f4a2713aSLionel Sambuc VTy->getNumElements() * 2); 3478*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], STy); 3479*f4a2713aSLionel Sambuc Value* SV = llvm::ConstantVector::getSplat(VTy->getNumElements(), 3480*f4a2713aSLionel Sambuc cast<ConstantInt>(Ops[3])); 3481*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateShuffleVector(Ops[2], Ops[2], SV, "lane"); 3482*f4a2713aSLionel Sambuc 3483*f4a2713aSLionel Sambuc return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]); 3484*f4a2713aSLionel Sambuc } 3485*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfms_v: 3486*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vfmsq_v: { 3487*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty); 3488*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3489*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 3490*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateFNeg(Ops[1]); 3491*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], Ty); 3492*f4a2713aSLionel Sambuc 3493*f4a2713aSLionel Sambuc // LLVM's fma intrinsic puts the accumulator in the last position, but the 3494*f4a2713aSLionel Sambuc // AArch64 intrinsic has it first. 3495*f4a2713aSLionel Sambuc return Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]); 3496*f4a2713aSLionel Sambuc } 3497*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxnm_v: 3498*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmaxnmq_v: { 3499*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vmaxnm; 3500*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmaxnm"); 3501*f4a2713aSLionel Sambuc } 3502*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminnm_v: 3503*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vminnmq_v: { 3504*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vminnm; 3505*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vminnm"); 3506*f4a2713aSLionel Sambuc } 3507*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpmaxnm_v: 3508*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpmaxnmq_v: { 3509*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpmaxnm; 3510*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmaxnm"); 3511*f4a2713aSLionel Sambuc } 3512*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpminnm_v: 3513*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpminnmq_v: { 3514*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vpminnm; 3515*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpminnm"); 3516*f4a2713aSLionel Sambuc } 3517*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpmaxq_v: { 3518*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vpmaxu : Intrinsic::arm_neon_vpmaxs; 3519*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmax"); 3520*f4a2713aSLionel Sambuc } 3521*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpminq_v: { 3522*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vpminu : Intrinsic::arm_neon_vpmins; 3523*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmin"); 3524*f4a2713aSLionel Sambuc } 3525*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpaddq_v: { 3526*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vpadd; 3527*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpadd"); 3528*f4a2713aSLionel Sambuc } 3529*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmulx_v: 3530*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmulxq_v: { 3531*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_vmulx; 3532*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmulx"); 3533*f4a2713aSLionel Sambuc } 3534*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpaddl_v: 3535*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpaddlq_v: 3536*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vpaddl_v, E); 3537*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpadal_v: 3538*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vpadalq_v: 3539*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vpadal_v, E); 3540*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqabs_v: 3541*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqabsq_v: 3542*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqabs_v, E); 3543*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqneg_v: 3544*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqnegq_v: 3545*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqneg_v, E); 3546*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vabs_v: 3547*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vabsq_v: { 3548*f4a2713aSLionel Sambuc if (VTy->getElementType()->isFloatingPointTy()) { 3549*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::fabs, Ty), Ops, "vabs"); 3550*f4a2713aSLionel Sambuc } 3551*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vabs_v, E); 3552*f4a2713aSLionel Sambuc } 3553*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsqadd_v: 3554*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsqaddq_v: { 3555*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_usqadd; 3556*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsqadd"); 3557*f4a2713aSLionel Sambuc } 3558*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vuqadd_v: 3559*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vuqaddq_v: { 3560*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_suqadd; 3561*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vuqadd"); 3562*f4a2713aSLionel Sambuc } 3563*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcls_v: 3564*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vclsq_v: 3565*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcls_v, E); 3566*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vclz_v: 3567*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vclzq_v: 3568*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vclz_v, E); 3569*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcnt_v: 3570*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcntq_v: 3571*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcnt_v, E); 3572*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrbit_v: 3573*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrbitq_v: 3574*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_rbit; 3575*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrbit"); 3576*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vmovn_v: 3577*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmovn_v, E); 3578*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqmovun_v: 3579*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqmovun_v, E); 3580*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vqmovn_v: 3581*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqmovn_v, E); 3582*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvt_f16_v: 3583*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_f16_v, E); 3584*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvt_f32_f16: 3585*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_f32_f16, E); 3586*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvt_f32_f64: { 3587*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3588*f4a2713aSLionel Sambuc Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, false)); 3589*f4a2713aSLionel Sambuc return Builder.CreateFPTrunc(Ops[0], Ty, "vcvt"); 3590*f4a2713aSLionel Sambuc } 3591*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtx_f32_v: { 3592*f4a2713aSLionel Sambuc llvm::Type *EltTy = FloatTy; 3593*f4a2713aSLionel Sambuc llvm::Type *ResTy = llvm::VectorType::get(EltTy, 2); 3594*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { ResTy, Ty }; 3595*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtxn; 3596*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtx_f32_f64"); 3597*f4a2713aSLionel Sambuc } 3598*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvt_f64_v: { 3599*f4a2713aSLionel Sambuc llvm::Type *OpTy = 3600*f4a2713aSLionel Sambuc GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, false)); 3601*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], OpTy); 3602*f4a2713aSLionel Sambuc return Builder.CreateFPExt(Ops[0], Ty, "vcvt"); 3603*f4a2713aSLionel Sambuc } 3604*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_f64_v: { 3605*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 3606*f4a2713aSLionel Sambuc Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, true)); 3607*f4a2713aSLionel Sambuc return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt") 3608*f4a2713aSLionel Sambuc : Builder.CreateSIToFP(Ops[0], Ty, "vcvt"); 3609*f4a2713aSLionel Sambuc } 3610*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqmovun_v, E); 3611*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndn_v: 3612*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndnq_v: { 3613*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_frintn; 3614*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndn"); 3615*f4a2713aSLionel Sambuc } 3616*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrnda_v: 3617*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndaq_v: { 3618*f4a2713aSLionel Sambuc Int = Intrinsic::round; 3619*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnda"); 3620*f4a2713aSLionel Sambuc } 3621*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndp_v: 3622*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndpq_v: { 3623*f4a2713aSLionel Sambuc Int = Intrinsic::ceil; 3624*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndp"); 3625*f4a2713aSLionel Sambuc } 3626*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndm_v: 3627*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndmq_v: { 3628*f4a2713aSLionel Sambuc Int = Intrinsic::floor; 3629*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndm"); 3630*f4a2713aSLionel Sambuc } 3631*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndx_v: 3632*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndxq_v: { 3633*f4a2713aSLionel Sambuc Int = Intrinsic::rint; 3634*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndx"); 3635*f4a2713aSLionel Sambuc } 3636*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrnd_v: 3637*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndq_v: { 3638*f4a2713aSLionel Sambuc Int = Intrinsic::trunc; 3639*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnd"); 3640*f4a2713aSLionel Sambuc } 3641*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndi_v: 3642*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrndiq_v: { 3643*f4a2713aSLionel Sambuc Int = Intrinsic::nearbyint; 3644*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndi"); 3645*f4a2713aSLionel Sambuc } 3646*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvt_s32_v: 3647*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvt_u32_v: 3648*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_s32_v: 3649*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_u32_v: 3650*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvtq_u32_v, E); 3651*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_s64_v: 3652*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_u64_v: { 3653*f4a2713aSLionel Sambuc llvm::Type *DoubleTy = 3654*f4a2713aSLionel Sambuc GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, true)); 3655*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy); 3656*f4a2713aSLionel Sambuc return usgn ? Builder.CreateFPToUI(Ops[0], Ty, "vcvt") 3657*f4a2713aSLionel Sambuc : Builder.CreateFPToSI(Ops[0], Ty, "vcvt"); 3658*f4a2713aSLionel Sambuc } 3659*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtn_s32_v: 3660*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtnq_s32_v: { 3661*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements()); 3662*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3663*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtns; 3664*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtns_f32"); 3665*f4a2713aSLionel Sambuc } 3666*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtnq_s64_v: { 3667*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements()); 3668*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3669*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtns; 3670*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtns_f64"); 3671*f4a2713aSLionel Sambuc } 3672*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtn_u32_v: 3673*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtnq_u32_v: { 3674*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements()); 3675*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3676*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtnu; 3677*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtnu_f32"); 3678*f4a2713aSLionel Sambuc } 3679*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtnq_u64_v: { 3680*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements()); 3681*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3682*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtnu; 3683*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtnu_f64"); 3684*f4a2713aSLionel Sambuc } 3685*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtp_s32_v: 3686*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtpq_s32_v: { 3687*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements()); 3688*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3689*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtps; 3690*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtps_f32"); 3691*f4a2713aSLionel Sambuc } 3692*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtpq_s64_v: { 3693*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements()); 3694*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3695*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtps; 3696*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtps_f64"); 3697*f4a2713aSLionel Sambuc } 3698*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtp_u32_v: 3699*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtpq_u32_v: { 3700*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements()); 3701*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3702*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtpu; 3703*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtpu_f32"); 3704*f4a2713aSLionel Sambuc } 3705*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtpq_u64_v: { 3706*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements()); 3707*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3708*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtpu; 3709*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtpu_f64"); 3710*f4a2713aSLionel Sambuc } 3711*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtm_s32_v: 3712*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtmq_s32_v: { 3713*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements()); 3714*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3715*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtms; 3716*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtms_f32"); 3717*f4a2713aSLionel Sambuc } 3718*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtmq_s64_v: { 3719*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements()); 3720*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3721*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtms; 3722*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtms_f64"); 3723*f4a2713aSLionel Sambuc } 3724*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtm_u32_v: 3725*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtmq_u32_v: { 3726*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements()); 3727*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3728*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtmu; 3729*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtmu_f32"); 3730*f4a2713aSLionel Sambuc } 3731*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtmq_u64_v: { 3732*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements()); 3733*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3734*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtmu; 3735*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtmu_f64"); 3736*f4a2713aSLionel Sambuc } 3737*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvta_s32_v: 3738*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtaq_s32_v: { 3739*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements()); 3740*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3741*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtas; 3742*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtas_f32"); 3743*f4a2713aSLionel Sambuc } 3744*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtaq_s64_v: { 3745*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements()); 3746*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3747*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtas; 3748*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtas_f64"); 3749*f4a2713aSLionel Sambuc } 3750*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvta_u32_v: 3751*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtaq_u32_v: { 3752*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements()); 3753*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3754*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtau; 3755*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtau_f32"); 3756*f4a2713aSLionel Sambuc } 3757*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtaq_u64_v: { 3758*f4a2713aSLionel Sambuc llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements()); 3759*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, OpTy }; 3760*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fcvtau; 3761*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtau_f64"); 3762*f4a2713aSLionel Sambuc } 3763*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrecpe_v: 3764*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrecpeq_v: 3765*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrecpe_v, E); 3766*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsqrte_v: 3767*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vrsqrteq_v: 3768*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrsqrte_v, E); 3769*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsqrt_v: 3770*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vsqrtq_v: { 3771*f4a2713aSLionel Sambuc Int = Intrinsic::aarch64_neon_fsqrt; 3772*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsqrt"); 3773*f4a2713aSLionel Sambuc } 3774*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvt_f32_v: 3775*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcvtq_f32_v: 3776*f4a2713aSLionel Sambuc return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_f32_v, E); 3777*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vceqz_v: 3778*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vceqzq_v: 3779*f4a2713aSLionel Sambuc return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OEQ, 3780*f4a2713aSLionel Sambuc ICmpInst::ICMP_EQ, "vceqz"); 3781*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgez_v: 3782*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgezq_v: 3783*f4a2713aSLionel Sambuc return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGE, 3784*f4a2713aSLionel Sambuc ICmpInst::ICMP_SGE, "vcgez"); 3785*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vclez_v: 3786*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vclezq_v: 3787*f4a2713aSLionel Sambuc return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLE, 3788*f4a2713aSLionel Sambuc ICmpInst::ICMP_SLE, "vclez"); 3789*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgtz_v: 3790*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcgtzq_v: 3791*f4a2713aSLionel Sambuc return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGT, 3792*f4a2713aSLionel Sambuc ICmpInst::ICMP_SGT, "vcgtz"); 3793*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcltz_v: 3794*f4a2713aSLionel Sambuc case AArch64::BI__builtin_neon_vcltzq_v: 3795*f4a2713aSLionel Sambuc return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLT, 3796*f4a2713aSLionel Sambuc ICmpInst::ICMP_SLT, "vcltz"); 3797*f4a2713aSLionel Sambuc } 3798*f4a2713aSLionel Sambuc } 3799*f4a2713aSLionel Sambuc 3800*f4a2713aSLionel Sambuc Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, 3801*f4a2713aSLionel Sambuc const CallExpr *E) { 3802*f4a2713aSLionel Sambuc if (BuiltinID == ARM::BI__clear_cache) { 3803*f4a2713aSLionel Sambuc assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments"); 3804*f4a2713aSLionel Sambuc const FunctionDecl *FD = E->getDirectCallee(); 3805*f4a2713aSLionel Sambuc SmallVector<Value*, 2> Ops; 3806*f4a2713aSLionel Sambuc for (unsigned i = 0; i < 2; i++) 3807*f4a2713aSLionel Sambuc Ops.push_back(EmitScalarExpr(E->getArg(i))); 3808*f4a2713aSLionel Sambuc llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType()); 3809*f4a2713aSLionel Sambuc llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty); 3810*f4a2713aSLionel Sambuc StringRef Name = FD->getName(); 3811*f4a2713aSLionel Sambuc return EmitNounwindRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Ops); 3812*f4a2713aSLionel Sambuc } 3813*f4a2713aSLionel Sambuc 3814*f4a2713aSLionel Sambuc if (BuiltinID == ARM::BI__builtin_arm_ldrexd || 3815*f4a2713aSLionel Sambuc (BuiltinID == ARM::BI__builtin_arm_ldrex && 3816*f4a2713aSLionel Sambuc getContext().getTypeSize(E->getType()) == 64)) { 3817*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_ldrexd); 3818*f4a2713aSLionel Sambuc 3819*f4a2713aSLionel Sambuc Value *LdPtr = EmitScalarExpr(E->getArg(0)); 3820*f4a2713aSLionel Sambuc Value *Val = Builder.CreateCall(F, Builder.CreateBitCast(LdPtr, Int8PtrTy), 3821*f4a2713aSLionel Sambuc "ldrexd"); 3822*f4a2713aSLionel Sambuc 3823*f4a2713aSLionel Sambuc Value *Val0 = Builder.CreateExtractValue(Val, 1); 3824*f4a2713aSLionel Sambuc Value *Val1 = Builder.CreateExtractValue(Val, 0); 3825*f4a2713aSLionel Sambuc Val0 = Builder.CreateZExt(Val0, Int64Ty); 3826*f4a2713aSLionel Sambuc Val1 = Builder.CreateZExt(Val1, Int64Ty); 3827*f4a2713aSLionel Sambuc 3828*f4a2713aSLionel Sambuc Value *ShiftCst = llvm::ConstantInt::get(Int64Ty, 32); 3829*f4a2713aSLionel Sambuc Val = Builder.CreateShl(Val0, ShiftCst, "shl", true /* nuw */); 3830*f4a2713aSLionel Sambuc Val = Builder.CreateOr(Val, Val1); 3831*f4a2713aSLionel Sambuc return Builder.CreateBitCast(Val, ConvertType(E->getType())); 3832*f4a2713aSLionel Sambuc } 3833*f4a2713aSLionel Sambuc 3834*f4a2713aSLionel Sambuc if (BuiltinID == ARM::BI__builtin_arm_ldrex) { 3835*f4a2713aSLionel Sambuc Value *LoadAddr = EmitScalarExpr(E->getArg(0)); 3836*f4a2713aSLionel Sambuc 3837*f4a2713aSLionel Sambuc QualType Ty = E->getType(); 3838*f4a2713aSLionel Sambuc llvm::Type *RealResTy = ConvertType(Ty); 3839*f4a2713aSLionel Sambuc llvm::Type *IntResTy = llvm::IntegerType::get(getLLVMContext(), 3840*f4a2713aSLionel Sambuc getContext().getTypeSize(Ty)); 3841*f4a2713aSLionel Sambuc LoadAddr = Builder.CreateBitCast(LoadAddr, IntResTy->getPointerTo()); 3842*f4a2713aSLionel Sambuc 3843*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_ldrex, LoadAddr->getType()); 3844*f4a2713aSLionel Sambuc Value *Val = Builder.CreateCall(F, LoadAddr, "ldrex"); 3845*f4a2713aSLionel Sambuc 3846*f4a2713aSLionel Sambuc if (RealResTy->isPointerTy()) 3847*f4a2713aSLionel Sambuc return Builder.CreateIntToPtr(Val, RealResTy); 3848*f4a2713aSLionel Sambuc else { 3849*f4a2713aSLionel Sambuc Val = Builder.CreateTruncOrBitCast(Val, IntResTy); 3850*f4a2713aSLionel Sambuc return Builder.CreateBitCast(Val, RealResTy); 3851*f4a2713aSLionel Sambuc } 3852*f4a2713aSLionel Sambuc } 3853*f4a2713aSLionel Sambuc 3854*f4a2713aSLionel Sambuc if (BuiltinID == ARM::BI__builtin_arm_strexd || 3855*f4a2713aSLionel Sambuc (BuiltinID == ARM::BI__builtin_arm_strex && 3856*f4a2713aSLionel Sambuc getContext().getTypeSize(E->getArg(0)->getType()) == 64)) { 3857*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_strexd); 3858*f4a2713aSLionel Sambuc llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, NULL); 3859*f4a2713aSLionel Sambuc 3860*f4a2713aSLionel Sambuc Value *Tmp = CreateMemTemp(E->getArg(0)->getType()); 3861*f4a2713aSLionel Sambuc Value *Val = EmitScalarExpr(E->getArg(0)); 3862*f4a2713aSLionel Sambuc Builder.CreateStore(Val, Tmp); 3863*f4a2713aSLionel Sambuc 3864*f4a2713aSLionel Sambuc Value *LdPtr = Builder.CreateBitCast(Tmp,llvm::PointerType::getUnqual(STy)); 3865*f4a2713aSLionel Sambuc Val = Builder.CreateLoad(LdPtr); 3866*f4a2713aSLionel Sambuc 3867*f4a2713aSLionel Sambuc Value *Arg0 = Builder.CreateExtractValue(Val, 0); 3868*f4a2713aSLionel Sambuc Value *Arg1 = Builder.CreateExtractValue(Val, 1); 3869*f4a2713aSLionel Sambuc Value *StPtr = Builder.CreateBitCast(EmitScalarExpr(E->getArg(1)), Int8PtrTy); 3870*f4a2713aSLionel Sambuc return Builder.CreateCall3(F, Arg0, Arg1, StPtr, "strexd"); 3871*f4a2713aSLionel Sambuc } 3872*f4a2713aSLionel Sambuc 3873*f4a2713aSLionel Sambuc if (BuiltinID == ARM::BI__builtin_arm_strex) { 3874*f4a2713aSLionel Sambuc Value *StoreVal = EmitScalarExpr(E->getArg(0)); 3875*f4a2713aSLionel Sambuc Value *StoreAddr = EmitScalarExpr(E->getArg(1)); 3876*f4a2713aSLionel Sambuc 3877*f4a2713aSLionel Sambuc QualType Ty = E->getArg(0)->getType(); 3878*f4a2713aSLionel Sambuc llvm::Type *StoreTy = llvm::IntegerType::get(getLLVMContext(), 3879*f4a2713aSLionel Sambuc getContext().getTypeSize(Ty)); 3880*f4a2713aSLionel Sambuc StoreAddr = Builder.CreateBitCast(StoreAddr, StoreTy->getPointerTo()); 3881*f4a2713aSLionel Sambuc 3882*f4a2713aSLionel Sambuc if (StoreVal->getType()->isPointerTy()) 3883*f4a2713aSLionel Sambuc StoreVal = Builder.CreatePtrToInt(StoreVal, Int32Ty); 3884*f4a2713aSLionel Sambuc else { 3885*f4a2713aSLionel Sambuc StoreVal = Builder.CreateBitCast(StoreVal, StoreTy); 3886*f4a2713aSLionel Sambuc StoreVal = Builder.CreateZExtOrBitCast(StoreVal, Int32Ty); 3887*f4a2713aSLionel Sambuc } 3888*f4a2713aSLionel Sambuc 3889*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_strex, StoreAddr->getType()); 3890*f4a2713aSLionel Sambuc return Builder.CreateCall2(F, StoreVal, StoreAddr, "strex"); 3891*f4a2713aSLionel Sambuc } 3892*f4a2713aSLionel Sambuc 3893*f4a2713aSLionel Sambuc if (BuiltinID == ARM::BI__builtin_arm_clrex) { 3894*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_clrex); 3895*f4a2713aSLionel Sambuc return Builder.CreateCall(F); 3896*f4a2713aSLionel Sambuc } 3897*f4a2713aSLionel Sambuc 3898*f4a2713aSLionel Sambuc if (BuiltinID == ARM::BI__builtin_arm_sevl) { 3899*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_sevl); 3900*f4a2713aSLionel Sambuc return Builder.CreateCall(F); 3901*f4a2713aSLionel Sambuc } 3902*f4a2713aSLionel Sambuc 3903*f4a2713aSLionel Sambuc // CRC32 3904*f4a2713aSLionel Sambuc Intrinsic::ID CRCIntrinsicID = Intrinsic::not_intrinsic; 3905*f4a2713aSLionel Sambuc switch (BuiltinID) { 3906*f4a2713aSLionel Sambuc case ARM::BI__builtin_arm_crc32b: 3907*f4a2713aSLionel Sambuc CRCIntrinsicID = Intrinsic::arm_crc32b; break; 3908*f4a2713aSLionel Sambuc case ARM::BI__builtin_arm_crc32cb: 3909*f4a2713aSLionel Sambuc CRCIntrinsicID = Intrinsic::arm_crc32cb; break; 3910*f4a2713aSLionel Sambuc case ARM::BI__builtin_arm_crc32h: 3911*f4a2713aSLionel Sambuc CRCIntrinsicID = Intrinsic::arm_crc32h; break; 3912*f4a2713aSLionel Sambuc case ARM::BI__builtin_arm_crc32ch: 3913*f4a2713aSLionel Sambuc CRCIntrinsicID = Intrinsic::arm_crc32ch; break; 3914*f4a2713aSLionel Sambuc case ARM::BI__builtin_arm_crc32w: 3915*f4a2713aSLionel Sambuc case ARM::BI__builtin_arm_crc32d: 3916*f4a2713aSLionel Sambuc CRCIntrinsicID = Intrinsic::arm_crc32w; break; 3917*f4a2713aSLionel Sambuc case ARM::BI__builtin_arm_crc32cw: 3918*f4a2713aSLionel Sambuc case ARM::BI__builtin_arm_crc32cd: 3919*f4a2713aSLionel Sambuc CRCIntrinsicID = Intrinsic::arm_crc32cw; break; 3920*f4a2713aSLionel Sambuc } 3921*f4a2713aSLionel Sambuc 3922*f4a2713aSLionel Sambuc if (CRCIntrinsicID != Intrinsic::not_intrinsic) { 3923*f4a2713aSLionel Sambuc Value *Arg0 = EmitScalarExpr(E->getArg(0)); 3924*f4a2713aSLionel Sambuc Value *Arg1 = EmitScalarExpr(E->getArg(1)); 3925*f4a2713aSLionel Sambuc 3926*f4a2713aSLionel Sambuc // crc32{c,}d intrinsics are implemnted as two calls to crc32{c,}w 3927*f4a2713aSLionel Sambuc // intrinsics, hence we need different codegen for these cases. 3928*f4a2713aSLionel Sambuc if (BuiltinID == ARM::BI__builtin_arm_crc32d || 3929*f4a2713aSLionel Sambuc BuiltinID == ARM::BI__builtin_arm_crc32cd) { 3930*f4a2713aSLionel Sambuc Value *C1 = llvm::ConstantInt::get(Int64Ty, 32); 3931*f4a2713aSLionel Sambuc Value *Arg1a = Builder.CreateTruncOrBitCast(Arg1, Int32Ty); 3932*f4a2713aSLionel Sambuc Value *Arg1b = Builder.CreateLShr(Arg1, C1); 3933*f4a2713aSLionel Sambuc Arg1b = Builder.CreateTruncOrBitCast(Arg1b, Int32Ty); 3934*f4a2713aSLionel Sambuc 3935*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(CRCIntrinsicID); 3936*f4a2713aSLionel Sambuc Value *Res = Builder.CreateCall2(F, Arg0, Arg1a); 3937*f4a2713aSLionel Sambuc return Builder.CreateCall2(F, Res, Arg1b); 3938*f4a2713aSLionel Sambuc } else { 3939*f4a2713aSLionel Sambuc Arg1 = Builder.CreateZExtOrBitCast(Arg1, Int32Ty); 3940*f4a2713aSLionel Sambuc 3941*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(CRCIntrinsicID); 3942*f4a2713aSLionel Sambuc return Builder.CreateCall2(F, Arg0, Arg1); 3943*f4a2713aSLionel Sambuc } 3944*f4a2713aSLionel Sambuc } 3945*f4a2713aSLionel Sambuc 3946*f4a2713aSLionel Sambuc SmallVector<Value*, 4> Ops; 3947*f4a2713aSLionel Sambuc llvm::Value *Align = 0; 3948*f4a2713aSLionel Sambuc for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) { 3949*f4a2713aSLionel Sambuc if (i == 0) { 3950*f4a2713aSLionel Sambuc switch (BuiltinID) { 3951*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1_v: 3952*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1q_v: 3953*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1q_lane_v: 3954*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1_lane_v: 3955*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1_dup_v: 3956*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1q_dup_v: 3957*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst1_v: 3958*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst1q_v: 3959*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst1q_lane_v: 3960*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst1_lane_v: 3961*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst2_v: 3962*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst2q_v: 3963*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst2_lane_v: 3964*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst2q_lane_v: 3965*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst3_v: 3966*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst3q_v: 3967*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst3_lane_v: 3968*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst3q_lane_v: 3969*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst4_v: 3970*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst4q_v: 3971*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst4_lane_v: 3972*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst4q_lane_v: 3973*f4a2713aSLionel Sambuc // Get the alignment for the argument in addition to the value; 3974*f4a2713aSLionel Sambuc // we'll use it later. 3975*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Src = 3976*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(0)); 3977*f4a2713aSLionel Sambuc Ops.push_back(Src.first); 3978*f4a2713aSLionel Sambuc Align = Builder.getInt32(Src.second); 3979*f4a2713aSLionel Sambuc continue; 3980*f4a2713aSLionel Sambuc } 3981*f4a2713aSLionel Sambuc } 3982*f4a2713aSLionel Sambuc if (i == 1) { 3983*f4a2713aSLionel Sambuc switch (BuiltinID) { 3984*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2_v: 3985*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2q_v: 3986*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3_v: 3987*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3q_v: 3988*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4_v: 3989*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4q_v: 3990*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2_lane_v: 3991*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2q_lane_v: 3992*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3_lane_v: 3993*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3q_lane_v: 3994*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4_lane_v: 3995*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4q_lane_v: 3996*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2_dup_v: 3997*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3_dup_v: 3998*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4_dup_v: 3999*f4a2713aSLionel Sambuc // Get the alignment for the argument in addition to the value; 4000*f4a2713aSLionel Sambuc // we'll use it later. 4001*f4a2713aSLionel Sambuc std::pair<llvm::Value*, unsigned> Src = 4002*f4a2713aSLionel Sambuc EmitPointerWithAlignment(E->getArg(1)); 4003*f4a2713aSLionel Sambuc Ops.push_back(Src.first); 4004*f4a2713aSLionel Sambuc Align = Builder.getInt32(Src.second); 4005*f4a2713aSLionel Sambuc continue; 4006*f4a2713aSLionel Sambuc } 4007*f4a2713aSLionel Sambuc } 4008*f4a2713aSLionel Sambuc Ops.push_back(EmitScalarExpr(E->getArg(i))); 4009*f4a2713aSLionel Sambuc } 4010*f4a2713aSLionel Sambuc 4011*f4a2713aSLionel Sambuc // vget_lane and vset_lane are not overloaded and do not have an extra 4012*f4a2713aSLionel Sambuc // argument that specifies the vector type. 4013*f4a2713aSLionel Sambuc switch (BuiltinID) { 4014*f4a2713aSLionel Sambuc default: break; 4015*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vget_lane_i8: 4016*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vget_lane_i16: 4017*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vget_lane_i32: 4018*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vget_lane_i64: 4019*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vget_lane_f32: 4020*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vgetq_lane_i8: 4021*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vgetq_lane_i16: 4022*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vgetq_lane_i32: 4023*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vgetq_lane_i64: 4024*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vgetq_lane_f32: 4025*f4a2713aSLionel Sambuc return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), 4026*f4a2713aSLionel Sambuc "vget_lane"); 4027*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vset_lane_i8: 4028*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vset_lane_i16: 4029*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vset_lane_i32: 4030*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vset_lane_i64: 4031*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vset_lane_f32: 4032*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsetq_lane_i8: 4033*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsetq_lane_i16: 4034*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsetq_lane_i32: 4035*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsetq_lane_i64: 4036*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsetq_lane_f32: 4037*f4a2713aSLionel Sambuc Ops.push_back(EmitScalarExpr(E->getArg(2))); 4038*f4a2713aSLionel Sambuc return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane"); 4039*f4a2713aSLionel Sambuc } 4040*f4a2713aSLionel Sambuc 4041*f4a2713aSLionel Sambuc // Get the last argument, which specifies the vector type. 4042*f4a2713aSLionel Sambuc llvm::APSInt Result; 4043*f4a2713aSLionel Sambuc const Expr *Arg = E->getArg(E->getNumArgs()-1); 4044*f4a2713aSLionel Sambuc if (!Arg->isIntegerConstantExpr(Result, getContext())) 4045*f4a2713aSLionel Sambuc return 0; 4046*f4a2713aSLionel Sambuc 4047*f4a2713aSLionel Sambuc if (BuiltinID == ARM::BI__builtin_arm_vcvtr_f || 4048*f4a2713aSLionel Sambuc BuiltinID == ARM::BI__builtin_arm_vcvtr_d) { 4049*f4a2713aSLionel Sambuc // Determine the overloaded type of this builtin. 4050*f4a2713aSLionel Sambuc llvm::Type *Ty; 4051*f4a2713aSLionel Sambuc if (BuiltinID == ARM::BI__builtin_arm_vcvtr_f) 4052*f4a2713aSLionel Sambuc Ty = FloatTy; 4053*f4a2713aSLionel Sambuc else 4054*f4a2713aSLionel Sambuc Ty = DoubleTy; 4055*f4a2713aSLionel Sambuc 4056*f4a2713aSLionel Sambuc // Determine whether this is an unsigned conversion or not. 4057*f4a2713aSLionel Sambuc bool usgn = Result.getZExtValue() == 1; 4058*f4a2713aSLionel Sambuc unsigned Int = usgn ? Intrinsic::arm_vcvtru : Intrinsic::arm_vcvtr; 4059*f4a2713aSLionel Sambuc 4060*f4a2713aSLionel Sambuc // Call the appropriate intrinsic. 4061*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Int, Ty); 4062*f4a2713aSLionel Sambuc return Builder.CreateCall(F, Ops, "vcvtr"); 4063*f4a2713aSLionel Sambuc } 4064*f4a2713aSLionel Sambuc 4065*f4a2713aSLionel Sambuc // Determine the type of this overloaded NEON intrinsic. 4066*f4a2713aSLionel Sambuc NeonTypeFlags Type(Result.getZExtValue()); 4067*f4a2713aSLionel Sambuc bool usgn = Type.isUnsigned(); 4068*f4a2713aSLionel Sambuc bool quad = Type.isQuad(); 4069*f4a2713aSLionel Sambuc bool rightShift = false; 4070*f4a2713aSLionel Sambuc 4071*f4a2713aSLionel Sambuc llvm::VectorType *VTy = GetNeonType(this, Type); 4072*f4a2713aSLionel Sambuc llvm::Type *Ty = VTy; 4073*f4a2713aSLionel Sambuc if (!Ty) 4074*f4a2713aSLionel Sambuc return 0; 4075*f4a2713aSLionel Sambuc 4076*f4a2713aSLionel Sambuc unsigned Int; 4077*f4a2713aSLionel Sambuc switch (BuiltinID) { 4078*f4a2713aSLionel Sambuc default: return 0; 4079*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vbsl_v: 4080*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vbslq_v: 4081*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vbsl, Ty), 4082*f4a2713aSLionel Sambuc Ops, "vbsl"); 4083*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vabd_v: 4084*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vabdq_v: 4085*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vabdu : Intrinsic::arm_neon_vabds; 4086*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vabd"); 4087*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vabs_v: 4088*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vabsq_v: 4089*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vabs, Ty), 4090*f4a2713aSLionel Sambuc Ops, "vabs"); 4091*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vaddhn_v: { 4092*f4a2713aSLionel Sambuc llvm::VectorType *SrcTy = 4093*f4a2713aSLionel Sambuc llvm::VectorType::getExtendedElementVectorType(VTy); 4094*f4a2713aSLionel Sambuc 4095*f4a2713aSLionel Sambuc // %sum = add <4 x i32> %lhs, %rhs 4096*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy); 4097*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], SrcTy); 4098*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateAdd(Ops[0], Ops[1], "vaddhn"); 4099*f4a2713aSLionel Sambuc 4100*f4a2713aSLionel Sambuc // %high = lshr <4 x i32> %sum, <i32 16, i32 16, i32 16, i32 16> 4101*f4a2713aSLionel Sambuc Constant *ShiftAmt = ConstantInt::get(SrcTy->getElementType(), 4102*f4a2713aSLionel Sambuc SrcTy->getScalarSizeInBits() / 2); 4103*f4a2713aSLionel Sambuc ShiftAmt = ConstantVector::getSplat(VTy->getNumElements(), ShiftAmt); 4104*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateLShr(Ops[0], ShiftAmt, "vaddhn"); 4105*f4a2713aSLionel Sambuc 4106*f4a2713aSLionel Sambuc // %res = trunc <4 x i32> %high to <4 x i16> 4107*f4a2713aSLionel Sambuc return Builder.CreateTrunc(Ops[0], VTy, "vaddhn"); 4108*f4a2713aSLionel Sambuc } 4109*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcale_v: 4110*f4a2713aSLionel Sambuc std::swap(Ops[0], Ops[1]); 4111*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcage_v: { 4112*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vacged); 4113*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcage"); 4114*f4a2713aSLionel Sambuc } 4115*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcaleq_v: 4116*f4a2713aSLionel Sambuc std::swap(Ops[0], Ops[1]); 4117*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcageq_v: { 4118*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vacgeq); 4119*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcage"); 4120*f4a2713aSLionel Sambuc } 4121*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcalt_v: 4122*f4a2713aSLionel Sambuc std::swap(Ops[0], Ops[1]); 4123*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcagt_v: { 4124*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vacgtd); 4125*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcagt"); 4126*f4a2713aSLionel Sambuc } 4127*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcaltq_v: 4128*f4a2713aSLionel Sambuc std::swap(Ops[0], Ops[1]); 4129*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcagtq_v: { 4130*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vacgtq); 4131*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcagt"); 4132*f4a2713aSLionel Sambuc } 4133*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcls_v: 4134*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vclsq_v: { 4135*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vcls, Ty); 4136*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcls"); 4137*f4a2713aSLionel Sambuc } 4138*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vclz_v: 4139*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vclzq_v: { 4140*f4a2713aSLionel Sambuc // Generate target-independent intrinsic; also need to add second argument 4141*f4a2713aSLionel Sambuc // for whether or not clz of zero is undefined; on ARM it isn't. 4142*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::ctlz, Ty); 4143*f4a2713aSLionel Sambuc Ops.push_back(Builder.getInt1(getTarget().isCLZForZeroUndef())); 4144*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vclz"); 4145*f4a2713aSLionel Sambuc } 4146*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcnt_v: 4147*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcntq_v: { 4148*f4a2713aSLionel Sambuc // generate target-independent intrinsic 4149*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::ctpop, Ty); 4150*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vctpop"); 4151*f4a2713aSLionel Sambuc } 4152*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvt_f16_v: { 4153*f4a2713aSLionel Sambuc assert(Type.getEltType() == NeonTypeFlags::Float16 && !quad && 4154*f4a2713aSLionel Sambuc "unexpected vcvt_f16_v builtin"); 4155*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vcvtfp2hf); 4156*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcvt"); 4157*f4a2713aSLionel Sambuc } 4158*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvt_f32_f16: { 4159*f4a2713aSLionel Sambuc assert(Type.getEltType() == NeonTypeFlags::Float16 && !quad && 4160*f4a2713aSLionel Sambuc "unexpected vcvt_f32_f16 builtin"); 4161*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vcvthf2fp); 4162*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcvt"); 4163*f4a2713aSLionel Sambuc } 4164*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvt_f32_v: 4165*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvtq_f32_v: 4166*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4167*f4a2713aSLionel Sambuc Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, quad)); 4168*f4a2713aSLionel Sambuc return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt") 4169*f4a2713aSLionel Sambuc : Builder.CreateSIToFP(Ops[0], Ty, "vcvt"); 4170*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvt_s32_v: 4171*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvt_u32_v: 4172*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvtq_s32_v: 4173*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvtq_u32_v: { 4174*f4a2713aSLionel Sambuc llvm::Type *FloatTy = 4175*f4a2713aSLionel Sambuc GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, quad)); 4176*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], FloatTy); 4177*f4a2713aSLionel Sambuc return usgn ? Builder.CreateFPToUI(Ops[0], Ty, "vcvt") 4178*f4a2713aSLionel Sambuc : Builder.CreateFPToSI(Ops[0], Ty, "vcvt"); 4179*f4a2713aSLionel Sambuc } 4180*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvt_n_f32_v: 4181*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvtq_n_f32_v: { 4182*f4a2713aSLionel Sambuc llvm::Type *FloatTy = 4183*f4a2713aSLionel Sambuc GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, quad)); 4184*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { FloatTy, Ty }; 4185*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vcvtfxu2fp 4186*f4a2713aSLionel Sambuc : Intrinsic::arm_neon_vcvtfxs2fp; 4187*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Int, Tys); 4188*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcvt_n"); 4189*f4a2713aSLionel Sambuc } 4190*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvt_n_s32_v: 4191*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvt_n_u32_v: 4192*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvtq_n_s32_v: 4193*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vcvtq_n_u32_v: { 4194*f4a2713aSLionel Sambuc llvm::Type *FloatTy = 4195*f4a2713aSLionel Sambuc GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, quad)); 4196*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, FloatTy }; 4197*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vcvtfp2fxu 4198*f4a2713aSLionel Sambuc : Intrinsic::arm_neon_vcvtfp2fxs; 4199*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Int, Tys); 4200*f4a2713aSLionel Sambuc return EmitNeonCall(F, Ops, "vcvt_n"); 4201*f4a2713aSLionel Sambuc } 4202*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vext_v: 4203*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vextq_v: { 4204*f4a2713aSLionel Sambuc int CV = cast<ConstantInt>(Ops[2])->getSExtValue(); 4205*f4a2713aSLionel Sambuc SmallVector<Constant*, 16> Indices; 4206*f4a2713aSLionel Sambuc for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) 4207*f4a2713aSLionel Sambuc Indices.push_back(ConstantInt::get(Int32Ty, i+CV)); 4208*f4a2713aSLionel Sambuc 4209*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4210*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 4211*f4a2713aSLionel Sambuc Value *SV = llvm::ConstantVector::get(Indices); 4212*f4a2713aSLionel Sambuc return Builder.CreateShuffleVector(Ops[0], Ops[1], SV, "vext"); 4213*f4a2713aSLionel Sambuc } 4214*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vhadd_v: 4215*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vhaddq_v: 4216*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vhaddu : Intrinsic::arm_neon_vhadds; 4217*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vhadd"); 4218*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vhsub_v: 4219*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vhsubq_v: 4220*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vhsubu : Intrinsic::arm_neon_vhsubs; 4221*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vhsub"); 4222*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1_v: 4223*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1q_v: 4224*f4a2713aSLionel Sambuc Ops.push_back(Align); 4225*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vld1, Ty), 4226*f4a2713aSLionel Sambuc Ops, "vld1"); 4227*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1q_lane_v: 4228*f4a2713aSLionel Sambuc // Handle 64-bit integer elements as a special case. Use shuffles of 4229*f4a2713aSLionel Sambuc // one-element vectors to avoid poor code for i64 in the backend. 4230*f4a2713aSLionel Sambuc if (VTy->getElementType()->isIntegerTy(64)) { 4231*f4a2713aSLionel Sambuc // Extract the other lane. 4232*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 4233*f4a2713aSLionel Sambuc int Lane = cast<ConstantInt>(Ops[2])->getZExtValue(); 4234*f4a2713aSLionel Sambuc Value *SV = llvm::ConstantVector::get(ConstantInt::get(Int32Ty, 1-Lane)); 4235*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateShuffleVector(Ops[1], Ops[1], SV); 4236*f4a2713aSLionel Sambuc // Load the value as a one-element vector. 4237*f4a2713aSLionel Sambuc Ty = llvm::VectorType::get(VTy->getElementType(), 1); 4238*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld1, Ty); 4239*f4a2713aSLionel Sambuc Value *Ld = Builder.CreateCall2(F, Ops[0], Align); 4240*f4a2713aSLionel Sambuc // Combine them. 4241*f4a2713aSLionel Sambuc SmallVector<Constant*, 2> Indices; 4242*f4a2713aSLionel Sambuc Indices.push_back(ConstantInt::get(Int32Ty, 1-Lane)); 4243*f4a2713aSLionel Sambuc Indices.push_back(ConstantInt::get(Int32Ty, Lane)); 4244*f4a2713aSLionel Sambuc SV = llvm::ConstantVector::get(Indices); 4245*f4a2713aSLionel Sambuc return Builder.CreateShuffleVector(Ops[1], Ld, SV, "vld1q_lane"); 4246*f4a2713aSLionel Sambuc } 4247*f4a2713aSLionel Sambuc // fall through 4248*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1_lane_v: { 4249*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 4250*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(VTy->getElementType()); 4251*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4252*f4a2713aSLionel Sambuc LoadInst *Ld = Builder.CreateLoad(Ops[0]); 4253*f4a2713aSLionel Sambuc Ld->setAlignment(cast<ConstantInt>(Align)->getZExtValue()); 4254*f4a2713aSLionel Sambuc return Builder.CreateInsertElement(Ops[1], Ld, Ops[2], "vld1_lane"); 4255*f4a2713aSLionel Sambuc } 4256*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1_dup_v: 4257*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld1q_dup_v: { 4258*f4a2713aSLionel Sambuc Value *V = UndefValue::get(Ty); 4259*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(VTy->getElementType()); 4260*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4261*f4a2713aSLionel Sambuc LoadInst *Ld = Builder.CreateLoad(Ops[0]); 4262*f4a2713aSLionel Sambuc Ld->setAlignment(cast<ConstantInt>(Align)->getZExtValue()); 4263*f4a2713aSLionel Sambuc llvm::Constant *CI = ConstantInt::get(Int32Ty, 0); 4264*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateInsertElement(V, Ld, CI); 4265*f4a2713aSLionel Sambuc return EmitNeonSplat(Ops[0], CI); 4266*f4a2713aSLionel Sambuc } 4267*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2_v: 4268*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2q_v: { 4269*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld2, Ty); 4270*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld2"); 4271*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 4272*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4273*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 4274*f4a2713aSLionel Sambuc } 4275*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3_v: 4276*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3q_v: { 4277*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld3, Ty); 4278*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld3"); 4279*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 4280*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4281*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 4282*f4a2713aSLionel Sambuc } 4283*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4_v: 4284*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4q_v: { 4285*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld4, Ty); 4286*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld4"); 4287*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 4288*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4289*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 4290*f4a2713aSLionel Sambuc } 4291*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2_lane_v: 4292*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2q_lane_v: { 4293*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld2lane, Ty); 4294*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], Ty); 4295*f4a2713aSLionel Sambuc Ops[3] = Builder.CreateBitCast(Ops[3], Ty); 4296*f4a2713aSLionel Sambuc Ops.push_back(Align); 4297*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall(F, makeArrayRef(Ops).slice(1), "vld2_lane"); 4298*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 4299*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4300*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 4301*f4a2713aSLionel Sambuc } 4302*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3_lane_v: 4303*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3q_lane_v: { 4304*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld3lane, Ty); 4305*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], Ty); 4306*f4a2713aSLionel Sambuc Ops[3] = Builder.CreateBitCast(Ops[3], Ty); 4307*f4a2713aSLionel Sambuc Ops[4] = Builder.CreateBitCast(Ops[4], Ty); 4308*f4a2713aSLionel Sambuc Ops.push_back(Align); 4309*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall(F, makeArrayRef(Ops).slice(1), "vld3_lane"); 4310*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 4311*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4312*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 4313*f4a2713aSLionel Sambuc } 4314*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4_lane_v: 4315*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4q_lane_v: { 4316*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld4lane, Ty); 4317*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], Ty); 4318*f4a2713aSLionel Sambuc Ops[3] = Builder.CreateBitCast(Ops[3], Ty); 4319*f4a2713aSLionel Sambuc Ops[4] = Builder.CreateBitCast(Ops[4], Ty); 4320*f4a2713aSLionel Sambuc Ops[5] = Builder.CreateBitCast(Ops[5], Ty); 4321*f4a2713aSLionel Sambuc Ops.push_back(Align); 4322*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall(F, makeArrayRef(Ops).slice(1), "vld3_lane"); 4323*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 4324*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4325*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 4326*f4a2713aSLionel Sambuc } 4327*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2_dup_v: 4328*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3_dup_v: 4329*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4_dup_v: { 4330*f4a2713aSLionel Sambuc // Handle 64-bit elements as a special-case. There is no "dup" needed. 4331*f4a2713aSLionel Sambuc if (VTy->getElementType()->getPrimitiveSizeInBits() == 64) { 4332*f4a2713aSLionel Sambuc switch (BuiltinID) { 4333*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2_dup_v: 4334*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld2; 4335*f4a2713aSLionel Sambuc break; 4336*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3_dup_v: 4337*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld3; 4338*f4a2713aSLionel Sambuc break; 4339*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4_dup_v: 4340*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld4; 4341*f4a2713aSLionel Sambuc break; 4342*f4a2713aSLionel Sambuc default: llvm_unreachable("unknown vld_dup intrinsic?"); 4343*f4a2713aSLionel Sambuc } 4344*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Int, Ty); 4345*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld_dup"); 4346*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 4347*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4348*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 4349*f4a2713aSLionel Sambuc } 4350*f4a2713aSLionel Sambuc switch (BuiltinID) { 4351*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld2_dup_v: 4352*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld2lane; 4353*f4a2713aSLionel Sambuc break; 4354*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld3_dup_v: 4355*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld3lane; 4356*f4a2713aSLionel Sambuc break; 4357*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vld4_dup_v: 4358*f4a2713aSLionel Sambuc Int = Intrinsic::arm_neon_vld4lane; 4359*f4a2713aSLionel Sambuc break; 4360*f4a2713aSLionel Sambuc default: llvm_unreachable("unknown vld_dup intrinsic?"); 4361*f4a2713aSLionel Sambuc } 4362*f4a2713aSLionel Sambuc Function *F = CGM.getIntrinsic(Int, Ty); 4363*f4a2713aSLionel Sambuc llvm::StructType *STy = cast<llvm::StructType>(F->getReturnType()); 4364*f4a2713aSLionel Sambuc 4365*f4a2713aSLionel Sambuc SmallVector<Value*, 6> Args; 4366*f4a2713aSLionel Sambuc Args.push_back(Ops[1]); 4367*f4a2713aSLionel Sambuc Args.append(STy->getNumElements(), UndefValue::get(Ty)); 4368*f4a2713aSLionel Sambuc 4369*f4a2713aSLionel Sambuc llvm::Constant *CI = ConstantInt::get(Int32Ty, 0); 4370*f4a2713aSLionel Sambuc Args.push_back(CI); 4371*f4a2713aSLionel Sambuc Args.push_back(Align); 4372*f4a2713aSLionel Sambuc 4373*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall(F, Args, "vld_dup"); 4374*f4a2713aSLionel Sambuc // splat lane 0 to all elts in each vector of the result. 4375*f4a2713aSLionel Sambuc for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { 4376*f4a2713aSLionel Sambuc Value *Val = Builder.CreateExtractValue(Ops[1], i); 4377*f4a2713aSLionel Sambuc Value *Elt = Builder.CreateBitCast(Val, Ty); 4378*f4a2713aSLionel Sambuc Elt = EmitNeonSplat(Elt, CI); 4379*f4a2713aSLionel Sambuc Elt = Builder.CreateBitCast(Elt, Val->getType()); 4380*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateInsertValue(Ops[1], Elt, i); 4381*f4a2713aSLionel Sambuc } 4382*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 4383*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4384*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 4385*f4a2713aSLionel Sambuc } 4386*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vmax_v: 4387*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vmaxq_v: 4388*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vmaxu : Intrinsic::arm_neon_vmaxs; 4389*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmax"); 4390*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vmin_v: 4391*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vminq_v: 4392*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vminu : Intrinsic::arm_neon_vmins; 4393*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmin"); 4394*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vmovl_v: { 4395*f4a2713aSLionel Sambuc llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy); 4396*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], DTy); 4397*f4a2713aSLionel Sambuc if (usgn) 4398*f4a2713aSLionel Sambuc return Builder.CreateZExt(Ops[0], Ty, "vmovl"); 4399*f4a2713aSLionel Sambuc return Builder.CreateSExt(Ops[0], Ty, "vmovl"); 4400*f4a2713aSLionel Sambuc } 4401*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vmovn_v: { 4402*f4a2713aSLionel Sambuc llvm::Type *QTy = llvm::VectorType::getExtendedElementVectorType(VTy); 4403*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], QTy); 4404*f4a2713aSLionel Sambuc return Builder.CreateTrunc(Ops[0], Ty, "vmovn"); 4405*f4a2713aSLionel Sambuc } 4406*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vmul_v: 4407*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vmulq_v: 4408*f4a2713aSLionel Sambuc assert(Type.isPoly() && "vmul builtin only supported for polynomial types"); 4409*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vmulp, Ty), 4410*f4a2713aSLionel Sambuc Ops, "vmul"); 4411*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vmull_v: 4412*f4a2713aSLionel Sambuc // FIXME: the integer vmull operations could be emitted in terms of pure 4413*f4a2713aSLionel Sambuc // LLVM IR (2 exts followed by a mul). Unfortunately LLVM has a habit of 4414*f4a2713aSLionel Sambuc // hoisting the exts outside loops. Until global ISel comes along that can 4415*f4a2713aSLionel Sambuc // see through such movement this leads to bad CodeGen. So we need an 4416*f4a2713aSLionel Sambuc // intrinsic for now. 4417*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vmullu : Intrinsic::arm_neon_vmulls; 4418*f4a2713aSLionel Sambuc Int = Type.isPoly() ? (unsigned)Intrinsic::arm_neon_vmullp : Int; 4419*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmull"); 4420*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vfma_v: 4421*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vfmaq_v: { 4422*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty); 4423*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4424*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 4425*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], Ty); 4426*f4a2713aSLionel Sambuc 4427*f4a2713aSLionel Sambuc // NEON intrinsic puts accumulator first, unlike the LLVM fma. 4428*f4a2713aSLionel Sambuc return Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]); 4429*f4a2713aSLionel Sambuc } 4430*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vpadal_v: 4431*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vpadalq_v: { 4432*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vpadalu : Intrinsic::arm_neon_vpadals; 4433*f4a2713aSLionel Sambuc // The source operand type has twice as many elements of half the size. 4434*f4a2713aSLionel Sambuc unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); 4435*f4a2713aSLionel Sambuc llvm::Type *EltTy = 4436*f4a2713aSLionel Sambuc llvm::IntegerType::get(getLLVMContext(), EltBits / 2); 4437*f4a2713aSLionel Sambuc llvm::Type *NarrowTy = 4438*f4a2713aSLionel Sambuc llvm::VectorType::get(EltTy, VTy->getNumElements() * 2); 4439*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, NarrowTy }; 4440*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vpadal"); 4441*f4a2713aSLionel Sambuc } 4442*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vpadd_v: 4443*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vpadd, Ty), 4444*f4a2713aSLionel Sambuc Ops, "vpadd"); 4445*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vpaddl_v: 4446*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vpaddlq_v: { 4447*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vpaddlu : Intrinsic::arm_neon_vpaddls; 4448*f4a2713aSLionel Sambuc // The source operand type has twice as many elements of half the size. 4449*f4a2713aSLionel Sambuc unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); 4450*f4a2713aSLionel Sambuc llvm::Type *EltTy = llvm::IntegerType::get(getLLVMContext(), EltBits / 2); 4451*f4a2713aSLionel Sambuc llvm::Type *NarrowTy = 4452*f4a2713aSLionel Sambuc llvm::VectorType::get(EltTy, VTy->getNumElements() * 2); 4453*f4a2713aSLionel Sambuc llvm::Type *Tys[2] = { Ty, NarrowTy }; 4454*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vpaddl"); 4455*f4a2713aSLionel Sambuc } 4456*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vpmax_v: 4457*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vpmaxu : Intrinsic::arm_neon_vpmaxs; 4458*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmax"); 4459*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vpmin_v: 4460*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vpminu : Intrinsic::arm_neon_vpmins; 4461*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmin"); 4462*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqabs_v: 4463*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqabsq_v: 4464*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqabs, Ty), 4465*f4a2713aSLionel Sambuc Ops, "vqabs"); 4466*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqadd_v: 4467*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqaddq_v: 4468*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vqaddu : Intrinsic::arm_neon_vqadds; 4469*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqadd"); 4470*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqdmlal_v: { 4471*f4a2713aSLionel Sambuc SmallVector<Value *, 2> MulOps(Ops.begin() + 1, Ops.end()); 4472*f4a2713aSLionel Sambuc Value *Mul = EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmull, Ty), 4473*f4a2713aSLionel Sambuc MulOps, "vqdmlal"); 4474*f4a2713aSLionel Sambuc 4475*f4a2713aSLionel Sambuc SmallVector<Value *, 2> AddOps; 4476*f4a2713aSLionel Sambuc AddOps.push_back(Ops[0]); 4477*f4a2713aSLionel Sambuc AddOps.push_back(Mul); 4478*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqadds, Ty), 4479*f4a2713aSLionel Sambuc AddOps, "vqdmlal"); 4480*f4a2713aSLionel Sambuc } 4481*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqdmlsl_v: { 4482*f4a2713aSLionel Sambuc SmallVector<Value *, 2> MulOps(Ops.begin() + 1, Ops.end()); 4483*f4a2713aSLionel Sambuc Value *Mul = EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmull, Ty), 4484*f4a2713aSLionel Sambuc MulOps, "vqdmlsl"); 4485*f4a2713aSLionel Sambuc 4486*f4a2713aSLionel Sambuc SmallVector<Value *, 2> SubOps; 4487*f4a2713aSLionel Sambuc SubOps.push_back(Ops[0]); 4488*f4a2713aSLionel Sambuc SubOps.push_back(Mul); 4489*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqsubs, Ty), 4490*f4a2713aSLionel Sambuc SubOps, "vqdmlsl"); 4491*f4a2713aSLionel Sambuc } 4492*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqdmulh_v: 4493*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqdmulhq_v: 4494*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmulh, Ty), 4495*f4a2713aSLionel Sambuc Ops, "vqdmulh"); 4496*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqdmull_v: 4497*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmull, Ty), 4498*f4a2713aSLionel Sambuc Ops, "vqdmull"); 4499*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqmovn_v: 4500*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vqmovnu : Intrinsic::arm_neon_vqmovns; 4501*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqmovn"); 4502*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqmovun_v: 4503*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqmovnsu, Ty), 4504*f4a2713aSLionel Sambuc Ops, "vqdmull"); 4505*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqneg_v: 4506*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqnegq_v: 4507*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqneg, Ty), 4508*f4a2713aSLionel Sambuc Ops, "vqneg"); 4509*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqrdmulh_v: 4510*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqrdmulhq_v: 4511*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqrdmulh, Ty), 4512*f4a2713aSLionel Sambuc Ops, "vqrdmulh"); 4513*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqrshl_v: 4514*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqrshlq_v: 4515*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vqrshiftu : Intrinsic::arm_neon_vqrshifts; 4516*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshl"); 4517*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqrshrn_n_v: 4518*f4a2713aSLionel Sambuc Int = 4519*f4a2713aSLionel Sambuc usgn ? Intrinsic::arm_neon_vqrshiftnu : Intrinsic::arm_neon_vqrshiftns; 4520*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrn_n", 4521*f4a2713aSLionel Sambuc 1, true); 4522*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqrshrun_n_v: 4523*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqrshiftnsu, Ty), 4524*f4a2713aSLionel Sambuc Ops, "vqrshrun_n", 1, true); 4525*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqshl_v: 4526*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqshlq_v: 4527*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vqshiftu : Intrinsic::arm_neon_vqshifts; 4528*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshl"); 4529*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqshl_n_v: 4530*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqshlq_n_v: 4531*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vqshiftu : Intrinsic::arm_neon_vqshifts; 4532*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshl_n", 4533*f4a2713aSLionel Sambuc 1, false); 4534*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqshlu_n_v: 4535*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqshluq_n_v: 4536*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqshiftsu, Ty), 4537*f4a2713aSLionel Sambuc Ops, "vqshlu", 1, false); 4538*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqshrn_n_v: 4539*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vqshiftnu : Intrinsic::arm_neon_vqshiftns; 4540*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrn_n", 4541*f4a2713aSLionel Sambuc 1, true); 4542*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqshrun_n_v: 4543*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqshiftnsu, Ty), 4544*f4a2713aSLionel Sambuc Ops, "vqshrun_n", 1, true); 4545*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqsub_v: 4546*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vqsubq_v: 4547*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vqsubu : Intrinsic::arm_neon_vqsubs; 4548*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqsub"); 4549*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vraddhn_v: 4550*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vraddhn, Ty), 4551*f4a2713aSLionel Sambuc Ops, "vraddhn"); 4552*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrecpe_v: 4553*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrecpeq_v: 4554*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrecpe, Ty), 4555*f4a2713aSLionel Sambuc Ops, "vrecpe"); 4556*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrecps_v: 4557*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrecpsq_v: 4558*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrecps, Ty), 4559*f4a2713aSLionel Sambuc Ops, "vrecps"); 4560*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrhadd_v: 4561*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrhaddq_v: 4562*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vrhaddu : Intrinsic::arm_neon_vrhadds; 4563*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrhadd"); 4564*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrshl_v: 4565*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrshlq_v: 4566*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vrshiftu : Intrinsic::arm_neon_vrshifts; 4567*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshl"); 4568*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrshrn_n_v: 4569*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrshiftn, Ty), 4570*f4a2713aSLionel Sambuc Ops, "vrshrn_n", 1, true); 4571*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrshr_n_v: 4572*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrshrq_n_v: 4573*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vrshiftu : Intrinsic::arm_neon_vrshifts; 4574*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshr_n", 1, true); 4575*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrsqrte_v: 4576*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrsqrteq_v: 4577*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrsqrte, Ty), 4578*f4a2713aSLionel Sambuc Ops, "vrsqrte"); 4579*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrsqrts_v: 4580*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrsqrtsq_v: 4581*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrsqrts, Ty), 4582*f4a2713aSLionel Sambuc Ops, "vrsqrts"); 4583*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrsra_n_v: 4584*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrsraq_n_v: 4585*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4586*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 4587*f4a2713aSLionel Sambuc Ops[2] = EmitNeonShiftVector(Ops[2], Ty, true); 4588*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vrshiftu : Intrinsic::arm_neon_vrshifts; 4589*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateCall2(CGM.getIntrinsic(Int, Ty), Ops[1], Ops[2]); 4590*f4a2713aSLionel Sambuc return Builder.CreateAdd(Ops[0], Ops[1], "vrsra_n"); 4591*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vrsubhn_v: 4592*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrsubhn, Ty), 4593*f4a2713aSLionel Sambuc Ops, "vrsubhn"); 4594*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vshl_v: 4595*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vshlq_v: 4596*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vshiftu : Intrinsic::arm_neon_vshifts; 4597*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vshl"); 4598*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vshll_n_v: 4599*f4a2713aSLionel Sambuc Int = usgn ? Intrinsic::arm_neon_vshiftlu : Intrinsic::arm_neon_vshiftls; 4600*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vshll", 1); 4601*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vshl_n_v: 4602*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vshlq_n_v: 4603*f4a2713aSLionel Sambuc Ops[1] = EmitNeonShiftVector(Ops[1], Ty, false); 4604*f4a2713aSLionel Sambuc return Builder.CreateShl(Builder.CreateBitCast(Ops[0],Ty), Ops[1], 4605*f4a2713aSLionel Sambuc "vshl_n"); 4606*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vshrn_n_v: 4607*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vshiftn, Ty), 4608*f4a2713aSLionel Sambuc Ops, "vshrn_n", 1, true); 4609*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vshr_n_v: 4610*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vshrq_n_v: 4611*f4a2713aSLionel Sambuc return EmitNeonRShiftImm(Ops[0], Ops[1], Ty, usgn, "vshr_n"); 4612*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsri_n_v: 4613*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsriq_n_v: 4614*f4a2713aSLionel Sambuc rightShift = true; 4615*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsli_n_v: 4616*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsliq_n_v: 4617*f4a2713aSLionel Sambuc Ops[2] = EmitNeonShiftVector(Ops[2], Ty, rightShift); 4618*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vshiftins, Ty), 4619*f4a2713aSLionel Sambuc Ops, "vsli_n"); 4620*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsra_n_v: 4621*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsraq_n_v: 4622*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4623*f4a2713aSLionel Sambuc Ops[1] = EmitNeonRShiftImm(Ops[1], Ops[2], Ty, usgn, "vsra_n"); 4624*f4a2713aSLionel Sambuc return Builder.CreateAdd(Ops[0], Ops[1]); 4625*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst1_v: 4626*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst1q_v: 4627*f4a2713aSLionel Sambuc Ops.push_back(Align); 4628*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst1, Ty), 4629*f4a2713aSLionel Sambuc Ops, ""); 4630*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst1q_lane_v: 4631*f4a2713aSLionel Sambuc // Handle 64-bit integer elements as a special case. Use a shuffle to get 4632*f4a2713aSLionel Sambuc // a one-element vector and avoid poor code for i64 in the backend. 4633*f4a2713aSLionel Sambuc if (VTy->getElementType()->isIntegerTy(64)) { 4634*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 4635*f4a2713aSLionel Sambuc Value *SV = llvm::ConstantVector::get(cast<llvm::Constant>(Ops[2])); 4636*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateShuffleVector(Ops[1], Ops[1], SV); 4637*f4a2713aSLionel Sambuc Ops[2] = Align; 4638*f4a2713aSLionel Sambuc return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst1, 4639*f4a2713aSLionel Sambuc Ops[1]->getType()), Ops); 4640*f4a2713aSLionel Sambuc } 4641*f4a2713aSLionel Sambuc // fall through 4642*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst1_lane_v: { 4643*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 4644*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]); 4645*f4a2713aSLionel Sambuc Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); 4646*f4a2713aSLionel Sambuc StoreInst *St = Builder.CreateStore(Ops[1], 4647*f4a2713aSLionel Sambuc Builder.CreateBitCast(Ops[0], Ty)); 4648*f4a2713aSLionel Sambuc St->setAlignment(cast<ConstantInt>(Align)->getZExtValue()); 4649*f4a2713aSLionel Sambuc return St; 4650*f4a2713aSLionel Sambuc } 4651*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst2_v: 4652*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst2q_v: 4653*f4a2713aSLionel Sambuc Ops.push_back(Align); 4654*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst2, Ty), 4655*f4a2713aSLionel Sambuc Ops, ""); 4656*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst2_lane_v: 4657*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst2q_lane_v: 4658*f4a2713aSLionel Sambuc Ops.push_back(Align); 4659*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst2lane, Ty), 4660*f4a2713aSLionel Sambuc Ops, ""); 4661*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst3_v: 4662*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst3q_v: 4663*f4a2713aSLionel Sambuc Ops.push_back(Align); 4664*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst3, Ty), 4665*f4a2713aSLionel Sambuc Ops, ""); 4666*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst3_lane_v: 4667*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst3q_lane_v: 4668*f4a2713aSLionel Sambuc Ops.push_back(Align); 4669*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst3lane, Ty), 4670*f4a2713aSLionel Sambuc Ops, ""); 4671*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst4_v: 4672*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst4q_v: 4673*f4a2713aSLionel Sambuc Ops.push_back(Align); 4674*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst4, Ty), 4675*f4a2713aSLionel Sambuc Ops, ""); 4676*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst4_lane_v: 4677*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vst4q_lane_v: 4678*f4a2713aSLionel Sambuc Ops.push_back(Align); 4679*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst4lane, Ty), 4680*f4a2713aSLionel Sambuc Ops, ""); 4681*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vsubhn_v: { 4682*f4a2713aSLionel Sambuc llvm::VectorType *SrcTy = 4683*f4a2713aSLionel Sambuc llvm::VectorType::getExtendedElementVectorType(VTy); 4684*f4a2713aSLionel Sambuc 4685*f4a2713aSLionel Sambuc // %sum = add <4 x i32> %lhs, %rhs 4686*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy); 4687*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], SrcTy); 4688*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateSub(Ops[0], Ops[1], "vsubhn"); 4689*f4a2713aSLionel Sambuc 4690*f4a2713aSLionel Sambuc // %high = lshr <4 x i32> %sum, <i32 16, i32 16, i32 16, i32 16> 4691*f4a2713aSLionel Sambuc Constant *ShiftAmt = ConstantInt::get(SrcTy->getElementType(), 4692*f4a2713aSLionel Sambuc SrcTy->getScalarSizeInBits() / 2); 4693*f4a2713aSLionel Sambuc ShiftAmt = ConstantVector::getSplat(VTy->getNumElements(), ShiftAmt); 4694*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateLShr(Ops[0], ShiftAmt, "vsubhn"); 4695*f4a2713aSLionel Sambuc 4696*f4a2713aSLionel Sambuc // %res = trunc <4 x i32> %high to <4 x i16> 4697*f4a2713aSLionel Sambuc return Builder.CreateTrunc(Ops[0], VTy, "vsubhn"); 4698*f4a2713aSLionel Sambuc } 4699*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtbl1_v: 4700*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl1), 4701*f4a2713aSLionel Sambuc Ops, "vtbl1"); 4702*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtbl2_v: 4703*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl2), 4704*f4a2713aSLionel Sambuc Ops, "vtbl2"); 4705*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtbl3_v: 4706*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl3), 4707*f4a2713aSLionel Sambuc Ops, "vtbl3"); 4708*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtbl4_v: 4709*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl4), 4710*f4a2713aSLionel Sambuc Ops, "vtbl4"); 4711*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtbx1_v: 4712*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx1), 4713*f4a2713aSLionel Sambuc Ops, "vtbx1"); 4714*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtbx2_v: 4715*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx2), 4716*f4a2713aSLionel Sambuc Ops, "vtbx2"); 4717*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtbx3_v: 4718*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx3), 4719*f4a2713aSLionel Sambuc Ops, "vtbx3"); 4720*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtbx4_v: 4721*f4a2713aSLionel Sambuc return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx4), 4722*f4a2713aSLionel Sambuc Ops, "vtbx4"); 4723*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtst_v: 4724*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtstq_v: { 4725*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], Ty); 4726*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 4727*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateAnd(Ops[0], Ops[1]); 4728*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateICmp(ICmpInst::ICMP_NE, Ops[0], 4729*f4a2713aSLionel Sambuc ConstantAggregateZero::get(Ty)); 4730*f4a2713aSLionel Sambuc return Builder.CreateSExt(Ops[0], Ty, "vtst"); 4731*f4a2713aSLionel Sambuc } 4732*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtrn_v: 4733*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vtrnq_v: { 4734*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty)); 4735*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 4736*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], Ty); 4737*f4a2713aSLionel Sambuc Value *SV = 0; 4738*f4a2713aSLionel Sambuc 4739*f4a2713aSLionel Sambuc for (unsigned vi = 0; vi != 2; ++vi) { 4740*f4a2713aSLionel Sambuc SmallVector<Constant*, 16> Indices; 4741*f4a2713aSLionel Sambuc for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) { 4742*f4a2713aSLionel Sambuc Indices.push_back(Builder.getInt32(i+vi)); 4743*f4a2713aSLionel Sambuc Indices.push_back(Builder.getInt32(i+e+vi)); 4744*f4a2713aSLionel Sambuc } 4745*f4a2713aSLionel Sambuc Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi); 4746*f4a2713aSLionel Sambuc SV = llvm::ConstantVector::get(Indices); 4747*f4a2713aSLionel Sambuc SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vtrn"); 4748*f4a2713aSLionel Sambuc SV = Builder.CreateStore(SV, Addr); 4749*f4a2713aSLionel Sambuc } 4750*f4a2713aSLionel Sambuc return SV; 4751*f4a2713aSLionel Sambuc } 4752*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vuzp_v: 4753*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vuzpq_v: { 4754*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty)); 4755*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 4756*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], Ty); 4757*f4a2713aSLionel Sambuc Value *SV = 0; 4758*f4a2713aSLionel Sambuc 4759*f4a2713aSLionel Sambuc for (unsigned vi = 0; vi != 2; ++vi) { 4760*f4a2713aSLionel Sambuc SmallVector<Constant*, 16> Indices; 4761*f4a2713aSLionel Sambuc for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) 4762*f4a2713aSLionel Sambuc Indices.push_back(ConstantInt::get(Int32Ty, 2*i+vi)); 4763*f4a2713aSLionel Sambuc 4764*f4a2713aSLionel Sambuc Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi); 4765*f4a2713aSLionel Sambuc SV = llvm::ConstantVector::get(Indices); 4766*f4a2713aSLionel Sambuc SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vuzp"); 4767*f4a2713aSLionel Sambuc SV = Builder.CreateStore(SV, Addr); 4768*f4a2713aSLionel Sambuc } 4769*f4a2713aSLionel Sambuc return SV; 4770*f4a2713aSLionel Sambuc } 4771*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vzip_v: 4772*f4a2713aSLionel Sambuc case ARM::BI__builtin_neon_vzipq_v: { 4773*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty)); 4774*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Ty); 4775*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], Ty); 4776*f4a2713aSLionel Sambuc Value *SV = 0; 4777*f4a2713aSLionel Sambuc 4778*f4a2713aSLionel Sambuc for (unsigned vi = 0; vi != 2; ++vi) { 4779*f4a2713aSLionel Sambuc SmallVector<Constant*, 16> Indices; 4780*f4a2713aSLionel Sambuc for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) { 4781*f4a2713aSLionel Sambuc Indices.push_back(ConstantInt::get(Int32Ty, (i + vi*e) >> 1)); 4782*f4a2713aSLionel Sambuc Indices.push_back(ConstantInt::get(Int32Ty, ((i + vi*e) >> 1)+e)); 4783*f4a2713aSLionel Sambuc } 4784*f4a2713aSLionel Sambuc Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi); 4785*f4a2713aSLionel Sambuc SV = llvm::ConstantVector::get(Indices); 4786*f4a2713aSLionel Sambuc SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vzip"); 4787*f4a2713aSLionel Sambuc SV = Builder.CreateStore(SV, Addr); 4788*f4a2713aSLionel Sambuc } 4789*f4a2713aSLionel Sambuc return SV; 4790*f4a2713aSLionel Sambuc } 4791*f4a2713aSLionel Sambuc } 4792*f4a2713aSLionel Sambuc } 4793*f4a2713aSLionel Sambuc 4794*f4a2713aSLionel Sambuc llvm::Value *CodeGenFunction:: 4795*f4a2713aSLionel Sambuc BuildVector(ArrayRef<llvm::Value*> Ops) { 4796*f4a2713aSLionel Sambuc assert((Ops.size() & (Ops.size() - 1)) == 0 && 4797*f4a2713aSLionel Sambuc "Not a power-of-two sized vector!"); 4798*f4a2713aSLionel Sambuc bool AllConstants = true; 4799*f4a2713aSLionel Sambuc for (unsigned i = 0, e = Ops.size(); i != e && AllConstants; ++i) 4800*f4a2713aSLionel Sambuc AllConstants &= isa<Constant>(Ops[i]); 4801*f4a2713aSLionel Sambuc 4802*f4a2713aSLionel Sambuc // If this is a constant vector, create a ConstantVector. 4803*f4a2713aSLionel Sambuc if (AllConstants) { 4804*f4a2713aSLionel Sambuc SmallVector<llvm::Constant*, 16> CstOps; 4805*f4a2713aSLionel Sambuc for (unsigned i = 0, e = Ops.size(); i != e; ++i) 4806*f4a2713aSLionel Sambuc CstOps.push_back(cast<Constant>(Ops[i])); 4807*f4a2713aSLionel Sambuc return llvm::ConstantVector::get(CstOps); 4808*f4a2713aSLionel Sambuc } 4809*f4a2713aSLionel Sambuc 4810*f4a2713aSLionel Sambuc // Otherwise, insertelement the values to build the vector. 4811*f4a2713aSLionel Sambuc Value *Result = 4812*f4a2713aSLionel Sambuc llvm::UndefValue::get(llvm::VectorType::get(Ops[0]->getType(), Ops.size())); 4813*f4a2713aSLionel Sambuc 4814*f4a2713aSLionel Sambuc for (unsigned i = 0, e = Ops.size(); i != e; ++i) 4815*f4a2713aSLionel Sambuc Result = Builder.CreateInsertElement(Result, Ops[i], Builder.getInt32(i)); 4816*f4a2713aSLionel Sambuc 4817*f4a2713aSLionel Sambuc return Result; 4818*f4a2713aSLionel Sambuc } 4819*f4a2713aSLionel Sambuc 4820*f4a2713aSLionel Sambuc Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, 4821*f4a2713aSLionel Sambuc const CallExpr *E) { 4822*f4a2713aSLionel Sambuc SmallVector<Value*, 4> Ops; 4823*f4a2713aSLionel Sambuc 4824*f4a2713aSLionel Sambuc // Find out if any arguments are required to be integer constant expressions. 4825*f4a2713aSLionel Sambuc unsigned ICEArguments = 0; 4826*f4a2713aSLionel Sambuc ASTContext::GetBuiltinTypeError Error; 4827*f4a2713aSLionel Sambuc getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments); 4828*f4a2713aSLionel Sambuc assert(Error == ASTContext::GE_None && "Should not codegen an error"); 4829*f4a2713aSLionel Sambuc 4830*f4a2713aSLionel Sambuc for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) { 4831*f4a2713aSLionel Sambuc // If this is a normal argument, just emit it as a scalar. 4832*f4a2713aSLionel Sambuc if ((ICEArguments & (1 << i)) == 0) { 4833*f4a2713aSLionel Sambuc Ops.push_back(EmitScalarExpr(E->getArg(i))); 4834*f4a2713aSLionel Sambuc continue; 4835*f4a2713aSLionel Sambuc } 4836*f4a2713aSLionel Sambuc 4837*f4a2713aSLionel Sambuc // If this is required to be a constant, constant fold it so that we know 4838*f4a2713aSLionel Sambuc // that the generated intrinsic gets a ConstantInt. 4839*f4a2713aSLionel Sambuc llvm::APSInt Result; 4840*f4a2713aSLionel Sambuc bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); 4841*f4a2713aSLionel Sambuc assert(IsConst && "Constant arg isn't actually constant?"); (void)IsConst; 4842*f4a2713aSLionel Sambuc Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); 4843*f4a2713aSLionel Sambuc } 4844*f4a2713aSLionel Sambuc 4845*f4a2713aSLionel Sambuc switch (BuiltinID) { 4846*f4a2713aSLionel Sambuc default: return 0; 4847*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_vec_init_v8qi: 4848*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_vec_init_v4hi: 4849*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_vec_init_v2si: 4850*f4a2713aSLionel Sambuc return Builder.CreateBitCast(BuildVector(Ops), 4851*f4a2713aSLionel Sambuc llvm::Type::getX86_MMXTy(getLLVMContext())); 4852*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_vec_ext_v2si: 4853*f4a2713aSLionel Sambuc return Builder.CreateExtractElement(Ops[0], 4854*f4a2713aSLionel Sambuc llvm::ConstantInt::get(Ops[1]->getType(), 0)); 4855*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_ldmxcsr: { 4856*f4a2713aSLionel Sambuc Value *Tmp = CreateMemTemp(E->getArg(0)->getType()); 4857*f4a2713aSLionel Sambuc Builder.CreateStore(Ops[0], Tmp); 4858*f4a2713aSLionel Sambuc return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr), 4859*f4a2713aSLionel Sambuc Builder.CreateBitCast(Tmp, Int8PtrTy)); 4860*f4a2713aSLionel Sambuc } 4861*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_stmxcsr: { 4862*f4a2713aSLionel Sambuc Value *Tmp = CreateMemTemp(E->getType()); 4863*f4a2713aSLionel Sambuc Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr), 4864*f4a2713aSLionel Sambuc Builder.CreateBitCast(Tmp, Int8PtrTy)); 4865*f4a2713aSLionel Sambuc return Builder.CreateLoad(Tmp, "stmxcsr"); 4866*f4a2713aSLionel Sambuc } 4867*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_storehps: 4868*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_storelps: { 4869*f4a2713aSLionel Sambuc llvm::Type *PtrTy = llvm::PointerType::getUnqual(Int64Ty); 4870*f4a2713aSLionel Sambuc llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 2); 4871*f4a2713aSLionel Sambuc 4872*f4a2713aSLionel Sambuc // cast val v2i64 4873*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], VecTy, "cast"); 4874*f4a2713aSLionel Sambuc 4875*f4a2713aSLionel Sambuc // extract (0, 1) 4876*f4a2713aSLionel Sambuc unsigned Index = BuiltinID == X86::BI__builtin_ia32_storelps ? 0 : 1; 4877*f4a2713aSLionel Sambuc llvm::Value *Idx = llvm::ConstantInt::get(Int32Ty, Index); 4878*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateExtractElement(Ops[1], Idx, "extract"); 4879*f4a2713aSLionel Sambuc 4880*f4a2713aSLionel Sambuc // cast pointer to i64 & store 4881*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy); 4882*f4a2713aSLionel Sambuc return Builder.CreateStore(Ops[1], Ops[0]); 4883*f4a2713aSLionel Sambuc } 4884*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_palignr: { 4885*f4a2713aSLionel Sambuc unsigned shiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue(); 4886*f4a2713aSLionel Sambuc 4887*f4a2713aSLionel Sambuc // If palignr is shifting the pair of input vectors less than 9 bytes, 4888*f4a2713aSLionel Sambuc // emit a shuffle instruction. 4889*f4a2713aSLionel Sambuc if (shiftVal <= 8) { 4890*f4a2713aSLionel Sambuc SmallVector<llvm::Constant*, 8> Indices; 4891*f4a2713aSLionel Sambuc for (unsigned i = 0; i != 8; ++i) 4892*f4a2713aSLionel Sambuc Indices.push_back(llvm::ConstantInt::get(Int32Ty, shiftVal + i)); 4893*f4a2713aSLionel Sambuc 4894*f4a2713aSLionel Sambuc Value* SV = llvm::ConstantVector::get(Indices); 4895*f4a2713aSLionel Sambuc return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr"); 4896*f4a2713aSLionel Sambuc } 4897*f4a2713aSLionel Sambuc 4898*f4a2713aSLionel Sambuc // If palignr is shifting the pair of input vectors more than 8 but less 4899*f4a2713aSLionel Sambuc // than 16 bytes, emit a logical right shift of the destination. 4900*f4a2713aSLionel Sambuc if (shiftVal < 16) { 4901*f4a2713aSLionel Sambuc // MMX has these as 1 x i64 vectors for some odd optimization reasons. 4902*f4a2713aSLionel Sambuc llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 1); 4903*f4a2713aSLionel Sambuc 4904*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast"); 4905*f4a2713aSLionel Sambuc Ops[1] = llvm::ConstantInt::get(VecTy, (shiftVal-8) * 8); 4906*f4a2713aSLionel Sambuc 4907*f4a2713aSLionel Sambuc // create i32 constant 4908*f4a2713aSLionel Sambuc llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_mmx_psrl_q); 4909*f4a2713aSLionel Sambuc return Builder.CreateCall(F, makeArrayRef(&Ops[0], 2), "palignr"); 4910*f4a2713aSLionel Sambuc } 4911*f4a2713aSLionel Sambuc 4912*f4a2713aSLionel Sambuc // If palignr is shifting the pair of vectors more than 16 bytes, emit zero. 4913*f4a2713aSLionel Sambuc return llvm::Constant::getNullValue(ConvertType(E->getType())); 4914*f4a2713aSLionel Sambuc } 4915*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_palignr128: { 4916*f4a2713aSLionel Sambuc unsigned shiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue(); 4917*f4a2713aSLionel Sambuc 4918*f4a2713aSLionel Sambuc // If palignr is shifting the pair of input vectors less than 17 bytes, 4919*f4a2713aSLionel Sambuc // emit a shuffle instruction. 4920*f4a2713aSLionel Sambuc if (shiftVal <= 16) { 4921*f4a2713aSLionel Sambuc SmallVector<llvm::Constant*, 16> Indices; 4922*f4a2713aSLionel Sambuc for (unsigned i = 0; i != 16; ++i) 4923*f4a2713aSLionel Sambuc Indices.push_back(llvm::ConstantInt::get(Int32Ty, shiftVal + i)); 4924*f4a2713aSLionel Sambuc 4925*f4a2713aSLionel Sambuc Value* SV = llvm::ConstantVector::get(Indices); 4926*f4a2713aSLionel Sambuc return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr"); 4927*f4a2713aSLionel Sambuc } 4928*f4a2713aSLionel Sambuc 4929*f4a2713aSLionel Sambuc // If palignr is shifting the pair of input vectors more than 16 but less 4930*f4a2713aSLionel Sambuc // than 32 bytes, emit a logical right shift of the destination. 4931*f4a2713aSLionel Sambuc if (shiftVal < 32) { 4932*f4a2713aSLionel Sambuc llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 2); 4933*f4a2713aSLionel Sambuc 4934*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast"); 4935*f4a2713aSLionel Sambuc Ops[1] = llvm::ConstantInt::get(Int32Ty, (shiftVal-16) * 8); 4936*f4a2713aSLionel Sambuc 4937*f4a2713aSLionel Sambuc // create i32 constant 4938*f4a2713aSLionel Sambuc llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse2_psrl_dq); 4939*f4a2713aSLionel Sambuc return Builder.CreateCall(F, makeArrayRef(&Ops[0], 2), "palignr"); 4940*f4a2713aSLionel Sambuc } 4941*f4a2713aSLionel Sambuc 4942*f4a2713aSLionel Sambuc // If palignr is shifting the pair of vectors more than 32 bytes, emit zero. 4943*f4a2713aSLionel Sambuc return llvm::Constant::getNullValue(ConvertType(E->getType())); 4944*f4a2713aSLionel Sambuc } 4945*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_palignr256: { 4946*f4a2713aSLionel Sambuc unsigned shiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue(); 4947*f4a2713aSLionel Sambuc 4948*f4a2713aSLionel Sambuc // If palignr is shifting the pair of input vectors less than 17 bytes, 4949*f4a2713aSLionel Sambuc // emit a shuffle instruction. 4950*f4a2713aSLionel Sambuc if (shiftVal <= 16) { 4951*f4a2713aSLionel Sambuc SmallVector<llvm::Constant*, 32> Indices; 4952*f4a2713aSLionel Sambuc // 256-bit palignr operates on 128-bit lanes so we need to handle that 4953*f4a2713aSLionel Sambuc for (unsigned l = 0; l != 2; ++l) { 4954*f4a2713aSLionel Sambuc unsigned LaneStart = l * 16; 4955*f4a2713aSLionel Sambuc unsigned LaneEnd = (l+1) * 16; 4956*f4a2713aSLionel Sambuc for (unsigned i = 0; i != 16; ++i) { 4957*f4a2713aSLionel Sambuc unsigned Idx = shiftVal + i + LaneStart; 4958*f4a2713aSLionel Sambuc if (Idx >= LaneEnd) Idx += 16; // end of lane, switch operand 4959*f4a2713aSLionel Sambuc Indices.push_back(llvm::ConstantInt::get(Int32Ty, Idx)); 4960*f4a2713aSLionel Sambuc } 4961*f4a2713aSLionel Sambuc } 4962*f4a2713aSLionel Sambuc 4963*f4a2713aSLionel Sambuc Value* SV = llvm::ConstantVector::get(Indices); 4964*f4a2713aSLionel Sambuc return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr"); 4965*f4a2713aSLionel Sambuc } 4966*f4a2713aSLionel Sambuc 4967*f4a2713aSLionel Sambuc // If palignr is shifting the pair of input vectors more than 16 but less 4968*f4a2713aSLionel Sambuc // than 32 bytes, emit a logical right shift of the destination. 4969*f4a2713aSLionel Sambuc if (shiftVal < 32) { 4970*f4a2713aSLionel Sambuc llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 4); 4971*f4a2713aSLionel Sambuc 4972*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast"); 4973*f4a2713aSLionel Sambuc Ops[1] = llvm::ConstantInt::get(Int32Ty, (shiftVal-16) * 8); 4974*f4a2713aSLionel Sambuc 4975*f4a2713aSLionel Sambuc // create i32 constant 4976*f4a2713aSLionel Sambuc llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_avx2_psrl_dq); 4977*f4a2713aSLionel Sambuc return Builder.CreateCall(F, makeArrayRef(&Ops[0], 2), "palignr"); 4978*f4a2713aSLionel Sambuc } 4979*f4a2713aSLionel Sambuc 4980*f4a2713aSLionel Sambuc // If palignr is shifting the pair of vectors more than 32 bytes, emit zero. 4981*f4a2713aSLionel Sambuc return llvm::Constant::getNullValue(ConvertType(E->getType())); 4982*f4a2713aSLionel Sambuc } 4983*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_movntps: 4984*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_movntps256: 4985*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_movntpd: 4986*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_movntpd256: 4987*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_movntdq: 4988*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_movntdq256: 4989*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_movnti: 4990*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_movnti64: { 4991*f4a2713aSLionel Sambuc llvm::MDNode *Node = llvm::MDNode::get(getLLVMContext(), 4992*f4a2713aSLionel Sambuc Builder.getInt32(1)); 4993*f4a2713aSLionel Sambuc 4994*f4a2713aSLionel Sambuc // Convert the type of the pointer to a pointer to the stored type. 4995*f4a2713aSLionel Sambuc Value *BC = Builder.CreateBitCast(Ops[0], 4996*f4a2713aSLionel Sambuc llvm::PointerType::getUnqual(Ops[1]->getType()), 4997*f4a2713aSLionel Sambuc "cast"); 4998*f4a2713aSLionel Sambuc StoreInst *SI = Builder.CreateStore(Ops[1], BC); 4999*f4a2713aSLionel Sambuc SI->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node); 5000*f4a2713aSLionel Sambuc 5001*f4a2713aSLionel Sambuc // If the operand is an integer, we can't assume alignment. Otherwise, 5002*f4a2713aSLionel Sambuc // assume natural alignment. 5003*f4a2713aSLionel Sambuc QualType ArgTy = E->getArg(1)->getType(); 5004*f4a2713aSLionel Sambuc unsigned Align; 5005*f4a2713aSLionel Sambuc if (ArgTy->isIntegerType()) 5006*f4a2713aSLionel Sambuc Align = 1; 5007*f4a2713aSLionel Sambuc else 5008*f4a2713aSLionel Sambuc Align = getContext().getTypeSizeInChars(ArgTy).getQuantity(); 5009*f4a2713aSLionel Sambuc SI->setAlignment(Align); 5010*f4a2713aSLionel Sambuc return SI; 5011*f4a2713aSLionel Sambuc } 5012*f4a2713aSLionel Sambuc // 3DNow! 5013*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_pswapdsf: 5014*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_pswapdsi: { 5015*f4a2713aSLionel Sambuc const char *name = 0; 5016*f4a2713aSLionel Sambuc Intrinsic::ID ID = Intrinsic::not_intrinsic; 5017*f4a2713aSLionel Sambuc switch(BuiltinID) { 5018*f4a2713aSLionel Sambuc default: llvm_unreachable("Unsupported intrinsic!"); 5019*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_pswapdsf: 5020*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_pswapdsi: 5021*f4a2713aSLionel Sambuc name = "pswapd"; 5022*f4a2713aSLionel Sambuc ID = Intrinsic::x86_3dnowa_pswapd; 5023*f4a2713aSLionel Sambuc break; 5024*f4a2713aSLionel Sambuc } 5025*f4a2713aSLionel Sambuc llvm::Type *MMXTy = llvm::Type::getX86_MMXTy(getLLVMContext()); 5026*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateBitCast(Ops[0], MMXTy, "cast"); 5027*f4a2713aSLionel Sambuc llvm::Function *F = CGM.getIntrinsic(ID); 5028*f4a2713aSLionel Sambuc return Builder.CreateCall(F, Ops, name); 5029*f4a2713aSLionel Sambuc } 5030*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdrand16_step: 5031*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdrand32_step: 5032*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdrand64_step: 5033*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdseed16_step: 5034*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdseed32_step: 5035*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdseed64_step: { 5036*f4a2713aSLionel Sambuc Intrinsic::ID ID; 5037*f4a2713aSLionel Sambuc switch (BuiltinID) { 5038*f4a2713aSLionel Sambuc default: llvm_unreachable("Unsupported intrinsic!"); 5039*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdrand16_step: 5040*f4a2713aSLionel Sambuc ID = Intrinsic::x86_rdrand_16; 5041*f4a2713aSLionel Sambuc break; 5042*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdrand32_step: 5043*f4a2713aSLionel Sambuc ID = Intrinsic::x86_rdrand_32; 5044*f4a2713aSLionel Sambuc break; 5045*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdrand64_step: 5046*f4a2713aSLionel Sambuc ID = Intrinsic::x86_rdrand_64; 5047*f4a2713aSLionel Sambuc break; 5048*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdseed16_step: 5049*f4a2713aSLionel Sambuc ID = Intrinsic::x86_rdseed_16; 5050*f4a2713aSLionel Sambuc break; 5051*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdseed32_step: 5052*f4a2713aSLionel Sambuc ID = Intrinsic::x86_rdseed_32; 5053*f4a2713aSLionel Sambuc break; 5054*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_rdseed64_step: 5055*f4a2713aSLionel Sambuc ID = Intrinsic::x86_rdseed_64; 5056*f4a2713aSLionel Sambuc break; 5057*f4a2713aSLionel Sambuc } 5058*f4a2713aSLionel Sambuc 5059*f4a2713aSLionel Sambuc Value *Call = Builder.CreateCall(CGM.getIntrinsic(ID)); 5060*f4a2713aSLionel Sambuc Builder.CreateStore(Builder.CreateExtractValue(Call, 0), Ops[0]); 5061*f4a2713aSLionel Sambuc return Builder.CreateExtractValue(Call, 1); 5062*f4a2713aSLionel Sambuc } 5063*f4a2713aSLionel Sambuc // AVX2 broadcast 5064*f4a2713aSLionel Sambuc case X86::BI__builtin_ia32_vbroadcastsi256: { 5065*f4a2713aSLionel Sambuc Value *VecTmp = CreateMemTemp(E->getArg(0)->getType()); 5066*f4a2713aSLionel Sambuc Builder.CreateStore(Ops[0], VecTmp); 5067*f4a2713aSLionel Sambuc Value *F = CGM.getIntrinsic(Intrinsic::x86_avx2_vbroadcasti128); 5068*f4a2713aSLionel Sambuc return Builder.CreateCall(F, Builder.CreateBitCast(VecTmp, Int8PtrTy)); 5069*f4a2713aSLionel Sambuc } 5070*f4a2713aSLionel Sambuc } 5071*f4a2713aSLionel Sambuc } 5072*f4a2713aSLionel Sambuc 5073*f4a2713aSLionel Sambuc 5074*f4a2713aSLionel Sambuc Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, 5075*f4a2713aSLionel Sambuc const CallExpr *E) { 5076*f4a2713aSLionel Sambuc SmallVector<Value*, 4> Ops; 5077*f4a2713aSLionel Sambuc 5078*f4a2713aSLionel Sambuc for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) 5079*f4a2713aSLionel Sambuc Ops.push_back(EmitScalarExpr(E->getArg(i))); 5080*f4a2713aSLionel Sambuc 5081*f4a2713aSLionel Sambuc Intrinsic::ID ID = Intrinsic::not_intrinsic; 5082*f4a2713aSLionel Sambuc 5083*f4a2713aSLionel Sambuc switch (BuiltinID) { 5084*f4a2713aSLionel Sambuc default: return 0; 5085*f4a2713aSLionel Sambuc 5086*f4a2713aSLionel Sambuc // vec_ld, vec_lvsl, vec_lvsr 5087*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvx: 5088*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvxl: 5089*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvebx: 5090*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvehx: 5091*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvewx: 5092*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvsl: 5093*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvsr: 5094*f4a2713aSLionel Sambuc { 5095*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy); 5096*f4a2713aSLionel Sambuc 5097*f4a2713aSLionel Sambuc Ops[0] = Builder.CreateGEP(Ops[1], Ops[0]); 5098*f4a2713aSLionel Sambuc Ops.pop_back(); 5099*f4a2713aSLionel Sambuc 5100*f4a2713aSLionel Sambuc switch (BuiltinID) { 5101*f4a2713aSLionel Sambuc default: llvm_unreachable("Unsupported ld/lvsl/lvsr intrinsic!"); 5102*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvx: 5103*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_lvx; 5104*f4a2713aSLionel Sambuc break; 5105*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvxl: 5106*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_lvxl; 5107*f4a2713aSLionel Sambuc break; 5108*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvebx: 5109*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_lvebx; 5110*f4a2713aSLionel Sambuc break; 5111*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvehx: 5112*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_lvehx; 5113*f4a2713aSLionel Sambuc break; 5114*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvewx: 5115*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_lvewx; 5116*f4a2713aSLionel Sambuc break; 5117*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvsl: 5118*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_lvsl; 5119*f4a2713aSLionel Sambuc break; 5120*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_lvsr: 5121*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_lvsr; 5122*f4a2713aSLionel Sambuc break; 5123*f4a2713aSLionel Sambuc } 5124*f4a2713aSLionel Sambuc llvm::Function *F = CGM.getIntrinsic(ID); 5125*f4a2713aSLionel Sambuc return Builder.CreateCall(F, Ops, ""); 5126*f4a2713aSLionel Sambuc } 5127*f4a2713aSLionel Sambuc 5128*f4a2713aSLionel Sambuc // vec_st 5129*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_stvx: 5130*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_stvxl: 5131*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_stvebx: 5132*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_stvehx: 5133*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_stvewx: 5134*f4a2713aSLionel Sambuc { 5135*f4a2713aSLionel Sambuc Ops[2] = Builder.CreateBitCast(Ops[2], Int8PtrTy); 5136*f4a2713aSLionel Sambuc Ops[1] = Builder.CreateGEP(Ops[2], Ops[1]); 5137*f4a2713aSLionel Sambuc Ops.pop_back(); 5138*f4a2713aSLionel Sambuc 5139*f4a2713aSLionel Sambuc switch (BuiltinID) { 5140*f4a2713aSLionel Sambuc default: llvm_unreachable("Unsupported st intrinsic!"); 5141*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_stvx: 5142*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_stvx; 5143*f4a2713aSLionel Sambuc break; 5144*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_stvxl: 5145*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_stvxl; 5146*f4a2713aSLionel Sambuc break; 5147*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_stvebx: 5148*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_stvebx; 5149*f4a2713aSLionel Sambuc break; 5150*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_stvehx: 5151*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_stvehx; 5152*f4a2713aSLionel Sambuc break; 5153*f4a2713aSLionel Sambuc case PPC::BI__builtin_altivec_stvewx: 5154*f4a2713aSLionel Sambuc ID = Intrinsic::ppc_altivec_stvewx; 5155*f4a2713aSLionel Sambuc break; 5156*f4a2713aSLionel Sambuc } 5157*f4a2713aSLionel Sambuc llvm::Function *F = CGM.getIntrinsic(ID); 5158*f4a2713aSLionel Sambuc return Builder.CreateCall(F, Ops, ""); 5159*f4a2713aSLionel Sambuc } 5160*f4a2713aSLionel Sambuc } 5161*f4a2713aSLionel Sambuc } 5162