xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/TargetBuiltins/PPC.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===---------- PPC.cpp - Emit LLVM Code for builtins ---------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This contains code to emit Builtin calls as LLVM code.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "CGBuiltin.h"
14*700637cbSDimitry Andric #include "clang/Basic/TargetBuiltins.h"
15*700637cbSDimitry Andric #include "llvm/IR/InlineAsm.h"
16*700637cbSDimitry Andric #include "llvm/IR/IntrinsicsPowerPC.h"
17*700637cbSDimitry Andric #include "llvm/Support/ScopedPrinter.h"
18*700637cbSDimitry Andric 
19*700637cbSDimitry Andric using namespace clang;
20*700637cbSDimitry Andric using namespace CodeGen;
21*700637cbSDimitry Andric using namespace llvm;
22*700637cbSDimitry Andric 
emitPPCLoadReserveIntrinsic(CodeGenFunction & CGF,unsigned BuiltinID,const CallExpr * E)23*700637cbSDimitry Andric static llvm::Value *emitPPCLoadReserveIntrinsic(CodeGenFunction &CGF,
24*700637cbSDimitry Andric                                                 unsigned BuiltinID,
25*700637cbSDimitry Andric                                                 const CallExpr *E) {
26*700637cbSDimitry Andric   Value *Addr = CGF.EmitScalarExpr(E->getArg(0));
27*700637cbSDimitry Andric 
28*700637cbSDimitry Andric   SmallString<64> Asm;
29*700637cbSDimitry Andric   raw_svector_ostream AsmOS(Asm);
30*700637cbSDimitry Andric   llvm::IntegerType *RetType = CGF.Int32Ty;
31*700637cbSDimitry Andric 
32*700637cbSDimitry Andric   switch (BuiltinID) {
33*700637cbSDimitry Andric   case clang::PPC::BI__builtin_ppc_ldarx:
34*700637cbSDimitry Andric     AsmOS << "ldarx ";
35*700637cbSDimitry Andric     RetType = CGF.Int64Ty;
36*700637cbSDimitry Andric     break;
37*700637cbSDimitry Andric   case clang::PPC::BI__builtin_ppc_lwarx:
38*700637cbSDimitry Andric     AsmOS << "lwarx ";
39*700637cbSDimitry Andric     RetType = CGF.Int32Ty;
40*700637cbSDimitry Andric     break;
41*700637cbSDimitry Andric   case clang::PPC::BI__builtin_ppc_lharx:
42*700637cbSDimitry Andric     AsmOS << "lharx ";
43*700637cbSDimitry Andric     RetType = CGF.Int16Ty;
44*700637cbSDimitry Andric     break;
45*700637cbSDimitry Andric   case clang::PPC::BI__builtin_ppc_lbarx:
46*700637cbSDimitry Andric     AsmOS << "lbarx ";
47*700637cbSDimitry Andric     RetType = CGF.Int8Ty;
48*700637cbSDimitry Andric     break;
49*700637cbSDimitry Andric   default:
50*700637cbSDimitry Andric     llvm_unreachable("Expected only PowerPC load reserve intrinsics");
51*700637cbSDimitry Andric   }
52*700637cbSDimitry Andric 
53*700637cbSDimitry Andric   AsmOS << "$0, ${1:y}";
54*700637cbSDimitry Andric 
55*700637cbSDimitry Andric   std::string Constraints = "=r,*Z,~{memory}";
56*700637cbSDimitry Andric   std::string_view MachineClobbers = CGF.getTarget().getClobbers();
57*700637cbSDimitry Andric   if (!MachineClobbers.empty()) {
58*700637cbSDimitry Andric     Constraints += ',';
59*700637cbSDimitry Andric     Constraints += MachineClobbers;
60*700637cbSDimitry Andric   }
61*700637cbSDimitry Andric 
62*700637cbSDimitry Andric   llvm::Type *PtrType = CGF.UnqualPtrTy;
63*700637cbSDimitry Andric   llvm::FunctionType *FTy = llvm::FunctionType::get(RetType, {PtrType}, false);
64*700637cbSDimitry Andric 
65*700637cbSDimitry Andric   llvm::InlineAsm *IA =
66*700637cbSDimitry Andric       llvm::InlineAsm::get(FTy, Asm, Constraints, /*hasSideEffects=*/true);
67*700637cbSDimitry Andric   llvm::CallInst *CI = CGF.Builder.CreateCall(IA, {Addr});
68*700637cbSDimitry Andric   CI->addParamAttr(
69*700637cbSDimitry Andric       0, Attribute::get(CGF.getLLVMContext(), Attribute::ElementType, RetType));
70*700637cbSDimitry Andric   return CI;
71*700637cbSDimitry Andric }
72*700637cbSDimitry Andric 
EmitPPCBuiltinExpr(unsigned BuiltinID,const CallExpr * E)73*700637cbSDimitry Andric Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
74*700637cbSDimitry Andric                                            const CallExpr *E) {
75*700637cbSDimitry Andric   // Do not emit the builtin arguments in the arguments of a function call,
76*700637cbSDimitry Andric   // because the evaluation order of function arguments is not specified in C++.
77*700637cbSDimitry Andric   // This is important when testing to ensure the arguments are emitted in the
78*700637cbSDimitry Andric   // same order every time. Eg:
79*700637cbSDimitry Andric   // Instead of:
80*700637cbSDimitry Andric   //   return Builder.CreateFDiv(EmitScalarExpr(E->getArg(0)),
81*700637cbSDimitry Andric   //                             EmitScalarExpr(E->getArg(1)), "swdiv");
82*700637cbSDimitry Andric   // Use:
83*700637cbSDimitry Andric   //   Value *Op0 = EmitScalarExpr(E->getArg(0));
84*700637cbSDimitry Andric   //   Value *Op1 = EmitScalarExpr(E->getArg(1));
85*700637cbSDimitry Andric   //   return Builder.CreateFDiv(Op0, Op1, "swdiv")
86*700637cbSDimitry Andric 
87*700637cbSDimitry Andric   Intrinsic::ID ID = Intrinsic::not_intrinsic;
88*700637cbSDimitry Andric 
89*700637cbSDimitry Andric #include "llvm/TargetParser/PPCTargetParser.def"
90*700637cbSDimitry Andric   auto GenAIXPPCBuiltinCpuExpr = [&](unsigned SupportMethod, unsigned FieldIdx,
91*700637cbSDimitry Andric                                      unsigned Mask, CmpInst::Predicate CompOp,
92*700637cbSDimitry Andric                                      unsigned OpValue) -> Value * {
93*700637cbSDimitry Andric     if (SupportMethod == BUILTIN_PPC_FALSE)
94*700637cbSDimitry Andric       return llvm::ConstantInt::getFalse(ConvertType(E->getType()));
95*700637cbSDimitry Andric 
96*700637cbSDimitry Andric     if (SupportMethod == BUILTIN_PPC_TRUE)
97*700637cbSDimitry Andric       return llvm::ConstantInt::getTrue(ConvertType(E->getType()));
98*700637cbSDimitry Andric 
99*700637cbSDimitry Andric     assert(SupportMethod <= SYS_CALL && "Invalid value for SupportMethod.");
100*700637cbSDimitry Andric 
101*700637cbSDimitry Andric     llvm::Value *FieldValue = nullptr;
102*700637cbSDimitry Andric     if (SupportMethod == USE_SYS_CONF) {
103*700637cbSDimitry Andric       llvm::Type *STy = llvm::StructType::get(PPC_SYSTEMCONFIG_TYPE);
104*700637cbSDimitry Andric       llvm::Constant *SysConf =
105*700637cbSDimitry Andric           CGM.CreateRuntimeVariable(STy, "_system_configuration");
106*700637cbSDimitry Andric 
107*700637cbSDimitry Andric       // Grab the appropriate field from _system_configuration.
108*700637cbSDimitry Andric       llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0),
109*700637cbSDimitry Andric                              ConstantInt::get(Int32Ty, FieldIdx)};
110*700637cbSDimitry Andric 
111*700637cbSDimitry Andric       FieldValue = Builder.CreateInBoundsGEP(STy, SysConf, Idxs);
112*700637cbSDimitry Andric       FieldValue = Builder.CreateAlignedLoad(Int32Ty, FieldValue,
113*700637cbSDimitry Andric                                              CharUnits::fromQuantity(4));
114*700637cbSDimitry Andric     } else if (SupportMethod == SYS_CALL) {
115*700637cbSDimitry Andric       llvm::FunctionType *FTy =
116*700637cbSDimitry Andric           llvm::FunctionType::get(Int64Ty, Int32Ty, false);
117*700637cbSDimitry Andric       llvm::FunctionCallee Func =
118*700637cbSDimitry Andric           CGM.CreateRuntimeFunction(FTy, "getsystemcfg");
119*700637cbSDimitry Andric 
120*700637cbSDimitry Andric       FieldValue =
121*700637cbSDimitry Andric           Builder.CreateCall(Func, {ConstantInt::get(Int32Ty, FieldIdx)});
122*700637cbSDimitry Andric     }
123*700637cbSDimitry Andric     assert(FieldValue &&
124*700637cbSDimitry Andric            "SupportMethod value is not defined in PPCTargetParser.def.");
125*700637cbSDimitry Andric 
126*700637cbSDimitry Andric     if (Mask)
127*700637cbSDimitry Andric       FieldValue = Builder.CreateAnd(FieldValue, Mask);
128*700637cbSDimitry Andric 
129*700637cbSDimitry Andric     llvm::Type *ValueType = FieldValue->getType();
130*700637cbSDimitry Andric     bool IsValueType64Bit = ValueType->isIntegerTy(64);
131*700637cbSDimitry Andric     assert(
132*700637cbSDimitry Andric         (IsValueType64Bit || ValueType->isIntegerTy(32)) &&
133*700637cbSDimitry Andric         "Only 32/64-bit integers are supported in GenAIXPPCBuiltinCpuExpr().");
134*700637cbSDimitry Andric 
135*700637cbSDimitry Andric     return Builder.CreateICmp(
136*700637cbSDimitry Andric         CompOp, FieldValue,
137*700637cbSDimitry Andric         ConstantInt::get(IsValueType64Bit ? Int64Ty : Int32Ty, OpValue));
138*700637cbSDimitry Andric   };
139*700637cbSDimitry Andric 
140*700637cbSDimitry Andric   switch (BuiltinID) {
141*700637cbSDimitry Andric   default: return nullptr;
142*700637cbSDimitry Andric 
143*700637cbSDimitry Andric   case Builtin::BI__builtin_cpu_is: {
144*700637cbSDimitry Andric     const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();
145*700637cbSDimitry Andric     StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();
146*700637cbSDimitry Andric     llvm::Triple Triple = getTarget().getTriple();
147*700637cbSDimitry Andric 
148*700637cbSDimitry Andric     typedef std::tuple<unsigned, unsigned, unsigned, unsigned> CPUInfo;
149*700637cbSDimitry Andric 
150*700637cbSDimitry Andric     auto [LinuxSupportMethod, LinuxIDValue, AIXSupportMethod, AIXIDValue] =
151*700637cbSDimitry Andric         static_cast<CPUInfo>(StringSwitch<CPUInfo>(CPUStr)
152*700637cbSDimitry Andric #define PPC_CPU(NAME, Linux_SUPPORT_METHOD, LinuxID, AIX_SUPPORT_METHOD,       \
153*700637cbSDimitry Andric                 AIXID)                                                         \
154*700637cbSDimitry Andric   .Case(NAME, {Linux_SUPPORT_METHOD, LinuxID, AIX_SUPPORT_METHOD, AIXID})
155*700637cbSDimitry Andric #include "llvm/TargetParser/PPCTargetParser.def"
156*700637cbSDimitry Andric                                  .Default({BUILTIN_PPC_UNSUPPORTED, 0,
157*700637cbSDimitry Andric                                            BUILTIN_PPC_UNSUPPORTED, 0}));
158*700637cbSDimitry Andric 
159*700637cbSDimitry Andric     if (Triple.isOSAIX()) {
160*700637cbSDimitry Andric       assert((AIXSupportMethod != BUILTIN_PPC_UNSUPPORTED) &&
161*700637cbSDimitry Andric              "Invalid CPU name. Missed by SemaChecking?");
162*700637cbSDimitry Andric       return GenAIXPPCBuiltinCpuExpr(AIXSupportMethod, AIX_SYSCON_IMPL_IDX, 0,
163*700637cbSDimitry Andric                                      ICmpInst::ICMP_EQ, AIXIDValue);
164*700637cbSDimitry Andric     }
165*700637cbSDimitry Andric 
166*700637cbSDimitry Andric     assert(Triple.isOSLinux() &&
167*700637cbSDimitry Andric            "__builtin_cpu_is() is only supported for AIX and Linux.");
168*700637cbSDimitry Andric 
169*700637cbSDimitry Andric     assert((LinuxSupportMethod != BUILTIN_PPC_UNSUPPORTED) &&
170*700637cbSDimitry Andric            "Invalid CPU name. Missed by SemaChecking?");
171*700637cbSDimitry Andric 
172*700637cbSDimitry Andric     if (LinuxSupportMethod == BUILTIN_PPC_FALSE)
173*700637cbSDimitry Andric       return llvm::ConstantInt::getFalse(ConvertType(E->getType()));
174*700637cbSDimitry Andric 
175*700637cbSDimitry Andric     Value *Op0 = llvm::ConstantInt::get(Int32Ty, PPC_FAWORD_CPUID);
176*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_fixed_addr_ld);
177*700637cbSDimitry Andric     Value *TheCall = Builder.CreateCall(F, {Op0}, "cpu_is");
178*700637cbSDimitry Andric     return Builder.CreateICmpEQ(TheCall,
179*700637cbSDimitry Andric                                 llvm::ConstantInt::get(Int32Ty, LinuxIDValue));
180*700637cbSDimitry Andric   }
181*700637cbSDimitry Andric   case Builtin::BI__builtin_cpu_supports: {
182*700637cbSDimitry Andric     llvm::Triple Triple = getTarget().getTriple();
183*700637cbSDimitry Andric     const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();
184*700637cbSDimitry Andric     StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();
185*700637cbSDimitry Andric     if (Triple.isOSAIX()) {
186*700637cbSDimitry Andric       typedef std::tuple<unsigned, unsigned, unsigned, CmpInst::Predicate,
187*700637cbSDimitry Andric                          unsigned>
188*700637cbSDimitry Andric           CPUSupportType;
189*700637cbSDimitry Andric       auto [SupportMethod, FieldIdx, Mask, CompOp, Value] =
190*700637cbSDimitry Andric           static_cast<CPUSupportType>(StringSwitch<CPUSupportType>(CPUStr)
191*700637cbSDimitry Andric #define PPC_AIX_FEATURE(NAME, DESC, SUPPORT_METHOD, INDEX, MASK, COMP_OP,      \
192*700637cbSDimitry Andric                         VALUE)                                                 \
193*700637cbSDimitry Andric   .Case(NAME, {SUPPORT_METHOD, INDEX, MASK, COMP_OP, VALUE})
194*700637cbSDimitry Andric #include "llvm/TargetParser/PPCTargetParser.def"
195*700637cbSDimitry Andric                                           .Default({BUILTIN_PPC_FALSE, 0, 0,
196*700637cbSDimitry Andric                                                     CmpInst::Predicate(), 0}));
197*700637cbSDimitry Andric       return GenAIXPPCBuiltinCpuExpr(SupportMethod, FieldIdx, Mask, CompOp,
198*700637cbSDimitry Andric                                      Value);
199*700637cbSDimitry Andric     }
200*700637cbSDimitry Andric 
201*700637cbSDimitry Andric     assert(Triple.isOSLinux() &&
202*700637cbSDimitry Andric            "__builtin_cpu_supports() is only supported for AIX and Linux.");
203*700637cbSDimitry Andric     auto [FeatureWord, BitMask] =
204*700637cbSDimitry Andric         StringSwitch<std::pair<unsigned, unsigned>>(CPUStr)
205*700637cbSDimitry Andric #define PPC_LNX_FEATURE(Name, Description, EnumName, Bitmask, FA_WORD)         \
206*700637cbSDimitry Andric   .Case(Name, {FA_WORD, Bitmask})
207*700637cbSDimitry Andric #include "llvm/TargetParser/PPCTargetParser.def"
208*700637cbSDimitry Andric             .Default({0, 0});
209*700637cbSDimitry Andric     if (!BitMask)
210*700637cbSDimitry Andric       return Builder.getFalse();
211*700637cbSDimitry Andric     Value *Op0 = llvm::ConstantInt::get(Int32Ty, FeatureWord);
212*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_fixed_addr_ld);
213*700637cbSDimitry Andric     Value *TheCall = Builder.CreateCall(F, {Op0}, "cpu_supports");
214*700637cbSDimitry Andric     Value *Mask =
215*700637cbSDimitry Andric         Builder.CreateAnd(TheCall, llvm::ConstantInt::get(Int32Ty, BitMask));
216*700637cbSDimitry Andric     return Builder.CreateICmpNE(Mask, llvm::Constant::getNullValue(Int32Ty));
217*700637cbSDimitry Andric #undef PPC_FAWORD_HWCAP
218*700637cbSDimitry Andric #undef PPC_FAWORD_HWCAP2
219*700637cbSDimitry Andric #undef PPC_FAWORD_CPUID
220*700637cbSDimitry Andric   }
221*700637cbSDimitry Andric 
222*700637cbSDimitry Andric   // __builtin_ppc_get_timebase is GCC 4.8+'s PowerPC-specific name for what we
223*700637cbSDimitry Andric   // call __builtin_readcyclecounter.
224*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_get_timebase:
225*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::readcyclecounter));
226*700637cbSDimitry Andric 
227*700637cbSDimitry Andric   // vec_ld, vec_xl_be, vec_lvsl, vec_lvsr
228*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_lvx:
229*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_lvxl:
230*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_lvebx:
231*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_lvehx:
232*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_lvewx:
233*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_lvsl:
234*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_lvsr:
235*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_lxvd2x:
236*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_lxvw4x:
237*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_lxvd2x_be:
238*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_lxvw4x_be:
239*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_lxvl:
240*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_lxvll:
241*700637cbSDimitry Andric   {
242*700637cbSDimitry Andric     SmallVector<Value *, 2> Ops;
243*700637cbSDimitry Andric     Ops.push_back(EmitScalarExpr(E->getArg(0)));
244*700637cbSDimitry Andric     Ops.push_back(EmitScalarExpr(E->getArg(1)));
245*700637cbSDimitry Andric     if (!(BuiltinID == PPC::BI__builtin_vsx_lxvl ||
246*700637cbSDimitry Andric           BuiltinID == PPC::BI__builtin_vsx_lxvll)) {
247*700637cbSDimitry Andric       Ops[0] = Builder.CreateGEP(Int8Ty, Ops[1], Ops[0]);
248*700637cbSDimitry Andric       Ops.pop_back();
249*700637cbSDimitry Andric     }
250*700637cbSDimitry Andric 
251*700637cbSDimitry Andric     switch (BuiltinID) {
252*700637cbSDimitry Andric     default: llvm_unreachable("Unsupported ld/lvsl/lvsr intrinsic!");
253*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_lvx:
254*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_lvx;
255*700637cbSDimitry Andric       break;
256*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_lvxl:
257*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_lvxl;
258*700637cbSDimitry Andric       break;
259*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_lvebx:
260*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_lvebx;
261*700637cbSDimitry Andric       break;
262*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_lvehx:
263*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_lvehx;
264*700637cbSDimitry Andric       break;
265*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_lvewx:
266*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_lvewx;
267*700637cbSDimitry Andric       break;
268*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_lvsl:
269*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_lvsl;
270*700637cbSDimitry Andric       break;
271*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_lvsr:
272*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_lvsr;
273*700637cbSDimitry Andric       break;
274*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_lxvd2x:
275*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_lxvd2x;
276*700637cbSDimitry Andric       break;
277*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_lxvw4x:
278*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_lxvw4x;
279*700637cbSDimitry Andric       break;
280*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_lxvd2x_be:
281*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_lxvd2x_be;
282*700637cbSDimitry Andric       break;
283*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_lxvw4x_be:
284*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_lxvw4x_be;
285*700637cbSDimitry Andric       break;
286*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_lxvl:
287*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_lxvl;
288*700637cbSDimitry Andric       break;
289*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_lxvll:
290*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_lxvll;
291*700637cbSDimitry Andric       break;
292*700637cbSDimitry Andric     }
293*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(ID);
294*700637cbSDimitry Andric     return Builder.CreateCall(F, Ops, "");
295*700637cbSDimitry Andric   }
296*700637cbSDimitry Andric 
297*700637cbSDimitry Andric   // vec_st, vec_xst_be
298*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_stvx:
299*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_stvxl:
300*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_stvebx:
301*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_stvehx:
302*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_stvewx:
303*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_stxvd2x:
304*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_stxvw4x:
305*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_stxvd2x_be:
306*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_stxvw4x_be:
307*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_stxvl:
308*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_stxvll:
309*700637cbSDimitry Andric   {
310*700637cbSDimitry Andric     SmallVector<Value *, 3> Ops;
311*700637cbSDimitry Andric     Ops.push_back(EmitScalarExpr(E->getArg(0)));
312*700637cbSDimitry Andric     Ops.push_back(EmitScalarExpr(E->getArg(1)));
313*700637cbSDimitry Andric     Ops.push_back(EmitScalarExpr(E->getArg(2)));
314*700637cbSDimitry Andric     if (!(BuiltinID == PPC::BI__builtin_vsx_stxvl ||
315*700637cbSDimitry Andric           BuiltinID == PPC::BI__builtin_vsx_stxvll)) {
316*700637cbSDimitry Andric       Ops[1] = Builder.CreateGEP(Int8Ty, Ops[2], Ops[1]);
317*700637cbSDimitry Andric       Ops.pop_back();
318*700637cbSDimitry Andric     }
319*700637cbSDimitry Andric 
320*700637cbSDimitry Andric     switch (BuiltinID) {
321*700637cbSDimitry Andric     default: llvm_unreachable("Unsupported st intrinsic!");
322*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_stvx:
323*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_stvx;
324*700637cbSDimitry Andric       break;
325*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_stvxl:
326*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_stvxl;
327*700637cbSDimitry Andric       break;
328*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_stvebx:
329*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_stvebx;
330*700637cbSDimitry Andric       break;
331*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_stvehx:
332*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_stvehx;
333*700637cbSDimitry Andric       break;
334*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_stvewx:
335*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_stvewx;
336*700637cbSDimitry Andric       break;
337*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_stxvd2x:
338*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_stxvd2x;
339*700637cbSDimitry Andric       break;
340*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_stxvw4x:
341*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_stxvw4x;
342*700637cbSDimitry Andric       break;
343*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_stxvd2x_be:
344*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_stxvd2x_be;
345*700637cbSDimitry Andric       break;
346*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_stxvw4x_be:
347*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_stxvw4x_be;
348*700637cbSDimitry Andric       break;
349*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_stxvl:
350*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_stxvl;
351*700637cbSDimitry Andric       break;
352*700637cbSDimitry Andric     case PPC::BI__builtin_vsx_stxvll:
353*700637cbSDimitry Andric       ID = Intrinsic::ppc_vsx_stxvll;
354*700637cbSDimitry Andric       break;
355*700637cbSDimitry Andric     }
356*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(ID);
357*700637cbSDimitry Andric     return Builder.CreateCall(F, Ops, "");
358*700637cbSDimitry Andric   }
359*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_ldrmb: {
360*700637cbSDimitry Andric     // Essentially boils down to performing an unaligned VMX load sequence so
361*700637cbSDimitry Andric     // as to avoid crossing a page boundary and then shuffling the elements
362*700637cbSDimitry Andric     // into the right side of the vector register.
363*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
364*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
365*700637cbSDimitry Andric     int64_t NumBytes = cast<ConstantInt>(Op1)->getZExtValue();
366*700637cbSDimitry Andric     llvm::Type *ResTy = ConvertType(E->getType());
367*700637cbSDimitry Andric     bool IsLE = getTarget().isLittleEndian();
368*700637cbSDimitry Andric 
369*700637cbSDimitry Andric     // If the user wants the entire vector, just load the entire vector.
370*700637cbSDimitry Andric     if (NumBytes == 16) {
371*700637cbSDimitry Andric       Value *LD =
372*700637cbSDimitry Andric           Builder.CreateLoad(Address(Op0, ResTy, CharUnits::fromQuantity(1)));
373*700637cbSDimitry Andric       if (!IsLE)
374*700637cbSDimitry Andric         return LD;
375*700637cbSDimitry Andric 
376*700637cbSDimitry Andric       // Reverse the bytes on LE.
377*700637cbSDimitry Andric       SmallVector<int, 16> RevMask;
378*700637cbSDimitry Andric       for (int Idx = 0; Idx < 16; Idx++)
379*700637cbSDimitry Andric         RevMask.push_back(15 - Idx);
380*700637cbSDimitry Andric       return Builder.CreateShuffleVector(LD, LD, RevMask);
381*700637cbSDimitry Andric     }
382*700637cbSDimitry Andric 
383*700637cbSDimitry Andric     llvm::Function *Lvx = CGM.getIntrinsic(Intrinsic::ppc_altivec_lvx);
384*700637cbSDimitry Andric     llvm::Function *Lvs = CGM.getIntrinsic(IsLE ? Intrinsic::ppc_altivec_lvsr
385*700637cbSDimitry Andric                                                 : Intrinsic::ppc_altivec_lvsl);
386*700637cbSDimitry Andric     llvm::Function *Vperm = CGM.getIntrinsic(Intrinsic::ppc_altivec_vperm);
387*700637cbSDimitry Andric     Value *HiMem = Builder.CreateGEP(
388*700637cbSDimitry Andric         Int8Ty, Op0, ConstantInt::get(Op1->getType(), NumBytes - 1));
389*700637cbSDimitry Andric     Value *LoLd = Builder.CreateCall(Lvx, Op0, "ld.lo");
390*700637cbSDimitry Andric     Value *HiLd = Builder.CreateCall(Lvx, HiMem, "ld.hi");
391*700637cbSDimitry Andric     Value *Mask1 = Builder.CreateCall(Lvs, Op0, "mask1");
392*700637cbSDimitry Andric 
393*700637cbSDimitry Andric     Op0 = IsLE ? HiLd : LoLd;
394*700637cbSDimitry Andric     Op1 = IsLE ? LoLd : HiLd;
395*700637cbSDimitry Andric     Value *AllElts = Builder.CreateCall(Vperm, {Op0, Op1, Mask1}, "shuffle1");
396*700637cbSDimitry Andric     Constant *Zero = llvm::Constant::getNullValue(IsLE ? ResTy : AllElts->getType());
397*700637cbSDimitry Andric 
398*700637cbSDimitry Andric     if (IsLE) {
399*700637cbSDimitry Andric       SmallVector<int, 16> Consts;
400*700637cbSDimitry Andric       for (int Idx = 0; Idx < 16; Idx++) {
401*700637cbSDimitry Andric         int Val = (NumBytes - Idx - 1 >= 0) ? (NumBytes - Idx - 1)
402*700637cbSDimitry Andric                                             : 16 - (NumBytes - Idx);
403*700637cbSDimitry Andric         Consts.push_back(Val);
404*700637cbSDimitry Andric       }
405*700637cbSDimitry Andric       return Builder.CreateShuffleVector(Builder.CreateBitCast(AllElts, ResTy),
406*700637cbSDimitry Andric                                          Zero, Consts);
407*700637cbSDimitry Andric     }
408*700637cbSDimitry Andric     SmallVector<Constant *, 16> Consts;
409*700637cbSDimitry Andric     for (int Idx = 0; Idx < 16; Idx++)
410*700637cbSDimitry Andric       Consts.push_back(Builder.getInt8(NumBytes + Idx));
411*700637cbSDimitry Andric     Value *Mask2 = ConstantVector::get(Consts);
412*700637cbSDimitry Andric     return Builder.CreateBitCast(
413*700637cbSDimitry Andric         Builder.CreateCall(Vperm, {Zero, AllElts, Mask2}, "shuffle2"), ResTy);
414*700637cbSDimitry Andric   }
415*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_strmb: {
416*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
417*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
418*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
419*700637cbSDimitry Andric     int64_t NumBytes = cast<ConstantInt>(Op1)->getZExtValue();
420*700637cbSDimitry Andric     bool IsLE = getTarget().isLittleEndian();
421*700637cbSDimitry Andric     auto StoreSubVec = [&](unsigned Width, unsigned Offset, unsigned EltNo) {
422*700637cbSDimitry Andric       // Storing the whole vector, simply store it on BE and reverse bytes and
423*700637cbSDimitry Andric       // store on LE.
424*700637cbSDimitry Andric       if (Width == 16) {
425*700637cbSDimitry Andric         Value *StVec = Op2;
426*700637cbSDimitry Andric         if (IsLE) {
427*700637cbSDimitry Andric           SmallVector<int, 16> RevMask;
428*700637cbSDimitry Andric           for (int Idx = 0; Idx < 16; Idx++)
429*700637cbSDimitry Andric             RevMask.push_back(15 - Idx);
430*700637cbSDimitry Andric           StVec = Builder.CreateShuffleVector(Op2, Op2, RevMask);
431*700637cbSDimitry Andric         }
432*700637cbSDimitry Andric         return Builder.CreateStore(
433*700637cbSDimitry Andric             StVec, Address(Op0, Op2->getType(), CharUnits::fromQuantity(1)));
434*700637cbSDimitry Andric       }
435*700637cbSDimitry Andric       auto *ConvTy = Int64Ty;
436*700637cbSDimitry Andric       unsigned NumElts = 0;
437*700637cbSDimitry Andric       switch (Width) {
438*700637cbSDimitry Andric       default:
439*700637cbSDimitry Andric         llvm_unreachable("width for stores must be a power of 2");
440*700637cbSDimitry Andric       case 8:
441*700637cbSDimitry Andric         ConvTy = Int64Ty;
442*700637cbSDimitry Andric         NumElts = 2;
443*700637cbSDimitry Andric         break;
444*700637cbSDimitry Andric       case 4:
445*700637cbSDimitry Andric         ConvTy = Int32Ty;
446*700637cbSDimitry Andric         NumElts = 4;
447*700637cbSDimitry Andric         break;
448*700637cbSDimitry Andric       case 2:
449*700637cbSDimitry Andric         ConvTy = Int16Ty;
450*700637cbSDimitry Andric         NumElts = 8;
451*700637cbSDimitry Andric         break;
452*700637cbSDimitry Andric       case 1:
453*700637cbSDimitry Andric         ConvTy = Int8Ty;
454*700637cbSDimitry Andric         NumElts = 16;
455*700637cbSDimitry Andric         break;
456*700637cbSDimitry Andric       }
457*700637cbSDimitry Andric       Value *Vec = Builder.CreateBitCast(
458*700637cbSDimitry Andric           Op2, llvm::FixedVectorType::get(ConvTy, NumElts));
459*700637cbSDimitry Andric       Value *Ptr =
460*700637cbSDimitry Andric           Builder.CreateGEP(Int8Ty, Op0, ConstantInt::get(Int64Ty, Offset));
461*700637cbSDimitry Andric       Value *Elt = Builder.CreateExtractElement(Vec, EltNo);
462*700637cbSDimitry Andric       if (IsLE && Width > 1) {
463*700637cbSDimitry Andric         Function *F = CGM.getIntrinsic(Intrinsic::bswap, ConvTy);
464*700637cbSDimitry Andric         Elt = Builder.CreateCall(F, Elt);
465*700637cbSDimitry Andric       }
466*700637cbSDimitry Andric       return Builder.CreateStore(
467*700637cbSDimitry Andric           Elt, Address(Ptr, ConvTy, CharUnits::fromQuantity(1)));
468*700637cbSDimitry Andric     };
469*700637cbSDimitry Andric     unsigned Stored = 0;
470*700637cbSDimitry Andric     unsigned RemainingBytes = NumBytes;
471*700637cbSDimitry Andric     Value *Result;
472*700637cbSDimitry Andric     if (NumBytes == 16)
473*700637cbSDimitry Andric       return StoreSubVec(16, 0, 0);
474*700637cbSDimitry Andric     if (NumBytes >= 8) {
475*700637cbSDimitry Andric       Result = StoreSubVec(8, NumBytes - 8, IsLE ? 0 : 1);
476*700637cbSDimitry Andric       RemainingBytes -= 8;
477*700637cbSDimitry Andric       Stored += 8;
478*700637cbSDimitry Andric     }
479*700637cbSDimitry Andric     if (RemainingBytes >= 4) {
480*700637cbSDimitry Andric       Result = StoreSubVec(4, NumBytes - Stored - 4,
481*700637cbSDimitry Andric                            IsLE ? (Stored >> 2) : 3 - (Stored >> 2));
482*700637cbSDimitry Andric       RemainingBytes -= 4;
483*700637cbSDimitry Andric       Stored += 4;
484*700637cbSDimitry Andric     }
485*700637cbSDimitry Andric     if (RemainingBytes >= 2) {
486*700637cbSDimitry Andric       Result = StoreSubVec(2, NumBytes - Stored - 2,
487*700637cbSDimitry Andric                            IsLE ? (Stored >> 1) : 7 - (Stored >> 1));
488*700637cbSDimitry Andric       RemainingBytes -= 2;
489*700637cbSDimitry Andric       Stored += 2;
490*700637cbSDimitry Andric     }
491*700637cbSDimitry Andric     if (RemainingBytes)
492*700637cbSDimitry Andric       Result =
493*700637cbSDimitry Andric           StoreSubVec(1, NumBytes - Stored - 1, IsLE ? Stored : 15 - Stored);
494*700637cbSDimitry Andric     return Result;
495*700637cbSDimitry Andric   }
496*700637cbSDimitry Andric   // Square root
497*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvsqrtsp:
498*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvsqrtdp: {
499*700637cbSDimitry Andric     llvm::Type *ResultType = ConvertType(E->getType());
500*700637cbSDimitry Andric     Value *X = EmitScalarExpr(E->getArg(0));
501*700637cbSDimitry Andric     if (Builder.getIsFPConstrained()) {
502*700637cbSDimitry Andric       llvm::Function *F = CGM.getIntrinsic(
503*700637cbSDimitry Andric           Intrinsic::experimental_constrained_sqrt, ResultType);
504*700637cbSDimitry Andric       return Builder.CreateConstrainedFPCall(F, X);
505*700637cbSDimitry Andric     } else {
506*700637cbSDimitry Andric       llvm::Function *F = CGM.getIntrinsic(Intrinsic::sqrt, ResultType);
507*700637cbSDimitry Andric       return Builder.CreateCall(F, X);
508*700637cbSDimitry Andric     }
509*700637cbSDimitry Andric   }
510*700637cbSDimitry Andric   // Count leading zeros
511*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vclzb:
512*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vclzh:
513*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vclzw:
514*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vclzd: {
515*700637cbSDimitry Andric     llvm::Type *ResultType = ConvertType(E->getType());
516*700637cbSDimitry Andric     Value *X = EmitScalarExpr(E->getArg(0));
517*700637cbSDimitry Andric     Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);
518*700637cbSDimitry Andric     Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ResultType);
519*700637cbSDimitry Andric     return Builder.CreateCall(F, {X, Undef});
520*700637cbSDimitry Andric   }
521*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vctzb:
522*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vctzh:
523*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vctzw:
524*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vctzd: {
525*700637cbSDimitry Andric     llvm::Type *ResultType = ConvertType(E->getType());
526*700637cbSDimitry Andric     Value *X = EmitScalarExpr(E->getArg(0));
527*700637cbSDimitry Andric     Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);
528*700637cbSDimitry Andric     Function *F = CGM.getIntrinsic(Intrinsic::cttz, ResultType);
529*700637cbSDimitry Andric     return Builder.CreateCall(F, {X, Undef});
530*700637cbSDimitry Andric   }
531*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vinsd:
532*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vinsw:
533*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vinsd_elt:
534*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vinsw_elt: {
535*700637cbSDimitry Andric     llvm::Type *ResultType = ConvertType(E->getType());
536*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
537*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
538*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
539*700637cbSDimitry Andric 
540*700637cbSDimitry Andric     bool IsUnaligned = (BuiltinID == PPC::BI__builtin_altivec_vinsw ||
541*700637cbSDimitry Andric                         BuiltinID == PPC::BI__builtin_altivec_vinsd);
542*700637cbSDimitry Andric 
543*700637cbSDimitry Andric     bool Is32bit = (BuiltinID == PPC::BI__builtin_altivec_vinsw ||
544*700637cbSDimitry Andric                     BuiltinID == PPC::BI__builtin_altivec_vinsw_elt);
545*700637cbSDimitry Andric 
546*700637cbSDimitry Andric     // The third argument must be a compile time constant.
547*700637cbSDimitry Andric     ConstantInt *ArgCI = dyn_cast<ConstantInt>(Op2);
548*700637cbSDimitry Andric     assert(ArgCI &&
549*700637cbSDimitry Andric            "Third Arg to vinsw/vinsd intrinsic must be a constant integer!");
550*700637cbSDimitry Andric 
551*700637cbSDimitry Andric     // Valid value for the third argument is dependent on the input type and
552*700637cbSDimitry Andric     // builtin called.
553*700637cbSDimitry Andric     int ValidMaxValue = 0;
554*700637cbSDimitry Andric     if (IsUnaligned)
555*700637cbSDimitry Andric       ValidMaxValue = (Is32bit) ? 12 : 8;
556*700637cbSDimitry Andric     else
557*700637cbSDimitry Andric       ValidMaxValue = (Is32bit) ? 3 : 1;
558*700637cbSDimitry Andric 
559*700637cbSDimitry Andric     // Get value of third argument.
560*700637cbSDimitry Andric     int64_t ConstArg = ArgCI->getSExtValue();
561*700637cbSDimitry Andric 
562*700637cbSDimitry Andric     // Compose range checking error message.
563*700637cbSDimitry Andric     std::string RangeErrMsg = IsUnaligned ? "byte" : "element";
564*700637cbSDimitry Andric     RangeErrMsg += " number " + llvm::to_string(ConstArg);
565*700637cbSDimitry Andric     RangeErrMsg += " is outside of the valid range [0, ";
566*700637cbSDimitry Andric     RangeErrMsg += llvm::to_string(ValidMaxValue) + "]";
567*700637cbSDimitry Andric 
568*700637cbSDimitry Andric     // Issue error if third argument is not within the valid range.
569*700637cbSDimitry Andric     if (ConstArg < 0 || ConstArg > ValidMaxValue)
570*700637cbSDimitry Andric       CGM.Error(E->getExprLoc(), RangeErrMsg);
571*700637cbSDimitry Andric 
572*700637cbSDimitry Andric     // Input to vec_replace_elt is an element index, convert to byte index.
573*700637cbSDimitry Andric     if (!IsUnaligned) {
574*700637cbSDimitry Andric       ConstArg *= Is32bit ? 4 : 8;
575*700637cbSDimitry Andric       // Fix the constant according to endianess.
576*700637cbSDimitry Andric       if (getTarget().isLittleEndian())
577*700637cbSDimitry Andric         ConstArg = (Is32bit ? 12 : 8) - ConstArg;
578*700637cbSDimitry Andric     }
579*700637cbSDimitry Andric 
580*700637cbSDimitry Andric     ID = Is32bit ? Intrinsic::ppc_altivec_vinsw : Intrinsic::ppc_altivec_vinsd;
581*700637cbSDimitry Andric     Op2 = ConstantInt::getSigned(Int32Ty, ConstArg);
582*700637cbSDimitry Andric     // Casting input to vector int as per intrinsic definition.
583*700637cbSDimitry Andric     Op0 =
584*700637cbSDimitry Andric         Is32bit
585*700637cbSDimitry Andric             ? Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int32Ty, 4))
586*700637cbSDimitry Andric             : Builder.CreateBitCast(Op0,
587*700637cbSDimitry Andric                                     llvm::FixedVectorType::get(Int64Ty, 2));
588*700637cbSDimitry Andric     return Builder.CreateBitCast(
589*700637cbSDimitry Andric         Builder.CreateCall(CGM.getIntrinsic(ID), {Op0, Op1, Op2}), ResultType);
590*700637cbSDimitry Andric   }
591*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vadduqm:
592*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vsubuqm: {
593*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
594*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
595*700637cbSDimitry Andric     llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128);
596*700637cbSDimitry Andric     Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int128Ty, 1));
597*700637cbSDimitry Andric     Op1 = Builder.CreateBitCast(Op1, llvm::FixedVectorType::get(Int128Ty, 1));
598*700637cbSDimitry Andric     if (BuiltinID == PPC::BI__builtin_altivec_vadduqm)
599*700637cbSDimitry Andric       return Builder.CreateAdd(Op0, Op1, "vadduqm");
600*700637cbSDimitry Andric     else
601*700637cbSDimitry Andric       return Builder.CreateSub(Op0, Op1, "vsubuqm");
602*700637cbSDimitry Andric   }
603*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vaddcuq_c:
604*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vsubcuq_c: {
605*700637cbSDimitry Andric     SmallVector<Value *, 2> Ops;
606*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
607*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
608*700637cbSDimitry Andric     llvm::Type *V1I128Ty = llvm::FixedVectorType::get(
609*700637cbSDimitry Andric         llvm::IntegerType::get(getLLVMContext(), 128), 1);
610*700637cbSDimitry Andric     Ops.push_back(Builder.CreateBitCast(Op0, V1I128Ty));
611*700637cbSDimitry Andric     Ops.push_back(Builder.CreateBitCast(Op1, V1I128Ty));
612*700637cbSDimitry Andric     ID = (BuiltinID == PPC::BI__builtin_altivec_vaddcuq_c)
613*700637cbSDimitry Andric              ? Intrinsic::ppc_altivec_vaddcuq
614*700637cbSDimitry Andric              : Intrinsic::ppc_altivec_vsubcuq;
615*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
616*700637cbSDimitry Andric   }
617*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vaddeuqm_c:
618*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vaddecuq_c:
619*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vsubeuqm_c:
620*700637cbSDimitry Andric   case PPC::BI__builtin_altivec_vsubecuq_c: {
621*700637cbSDimitry Andric     SmallVector<Value *, 3> Ops;
622*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
623*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
624*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
625*700637cbSDimitry Andric     llvm::Type *V1I128Ty = llvm::FixedVectorType::get(
626*700637cbSDimitry Andric         llvm::IntegerType::get(getLLVMContext(), 128), 1);
627*700637cbSDimitry Andric     Ops.push_back(Builder.CreateBitCast(Op0, V1I128Ty));
628*700637cbSDimitry Andric     Ops.push_back(Builder.CreateBitCast(Op1, V1I128Ty));
629*700637cbSDimitry Andric     Ops.push_back(Builder.CreateBitCast(Op2, V1I128Ty));
630*700637cbSDimitry Andric     switch (BuiltinID) {
631*700637cbSDimitry Andric     default:
632*700637cbSDimitry Andric       llvm_unreachable("Unsupported intrinsic!");
633*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_vaddeuqm_c:
634*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_vaddeuqm;
635*700637cbSDimitry Andric       break;
636*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_vaddecuq_c:
637*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_vaddecuq;
638*700637cbSDimitry Andric       break;
639*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_vsubeuqm_c:
640*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_vsubeuqm;
641*700637cbSDimitry Andric       break;
642*700637cbSDimitry Andric     case PPC::BI__builtin_altivec_vsubecuq_c:
643*700637cbSDimitry Andric       ID = Intrinsic::ppc_altivec_vsubecuq;
644*700637cbSDimitry Andric       break;
645*700637cbSDimitry Andric     }
646*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
647*700637cbSDimitry Andric   }
648*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_rldimi:
649*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_rlwimi: {
650*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
651*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
652*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
653*700637cbSDimitry Andric     Value *Op3 = EmitScalarExpr(E->getArg(3));
654*700637cbSDimitry Andric     // rldimi is 64-bit instruction, expand the intrinsic before isel to
655*700637cbSDimitry Andric     // leverage peephole and avoid legalization efforts.
656*700637cbSDimitry Andric     if (BuiltinID == PPC::BI__builtin_ppc_rldimi &&
657*700637cbSDimitry Andric         !getTarget().getTriple().isPPC64()) {
658*700637cbSDimitry Andric       Function *F = CGM.getIntrinsic(Intrinsic::fshl, Op0->getType());
659*700637cbSDimitry Andric       Op2 = Builder.CreateZExt(Op2, Int64Ty);
660*700637cbSDimitry Andric       Value *Shift = Builder.CreateCall(F, {Op0, Op0, Op2});
661*700637cbSDimitry Andric       return Builder.CreateOr(Builder.CreateAnd(Shift, Op3),
662*700637cbSDimitry Andric                               Builder.CreateAnd(Op1, Builder.CreateNot(Op3)));
663*700637cbSDimitry Andric     }
664*700637cbSDimitry Andric     return Builder.CreateCall(
665*700637cbSDimitry Andric         CGM.getIntrinsic(BuiltinID == PPC::BI__builtin_ppc_rldimi
666*700637cbSDimitry Andric                              ? Intrinsic::ppc_rldimi
667*700637cbSDimitry Andric                              : Intrinsic::ppc_rlwimi),
668*700637cbSDimitry Andric         {Op0, Op1, Op2, Op3});
669*700637cbSDimitry Andric   }
670*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_rlwnm: {
671*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
672*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
673*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
674*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_rlwnm),
675*700637cbSDimitry Andric                               {Op0, Op1, Op2});
676*700637cbSDimitry Andric   }
677*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_poppar4:
678*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_poppar8: {
679*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
680*700637cbSDimitry Andric     llvm::Type *ArgType = Op0->getType();
681*700637cbSDimitry Andric     Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
682*700637cbSDimitry Andric     Value *Tmp = Builder.CreateCall(F, Op0);
683*700637cbSDimitry Andric 
684*700637cbSDimitry Andric     llvm::Type *ResultType = ConvertType(E->getType());
685*700637cbSDimitry Andric     Value *Result = Builder.CreateAnd(Tmp, llvm::ConstantInt::get(ArgType, 1));
686*700637cbSDimitry Andric     if (Result->getType() != ResultType)
687*700637cbSDimitry Andric       Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
688*700637cbSDimitry Andric                                      "cast");
689*700637cbSDimitry Andric     return Result;
690*700637cbSDimitry Andric   }
691*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_cmpb: {
692*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
693*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
694*700637cbSDimitry Andric     if (getTarget().getTriple().isPPC64()) {
695*700637cbSDimitry Andric       Function *F =
696*700637cbSDimitry Andric           CGM.getIntrinsic(Intrinsic::ppc_cmpb, {Int64Ty, Int64Ty, Int64Ty});
697*700637cbSDimitry Andric       return Builder.CreateCall(F, {Op0, Op1}, "cmpb");
698*700637cbSDimitry Andric     }
699*700637cbSDimitry Andric     // For 32 bit, emit the code as below:
700*700637cbSDimitry Andric     // %conv = trunc i64 %a to i32
701*700637cbSDimitry Andric     // %conv1 = trunc i64 %b to i32
702*700637cbSDimitry Andric     // %shr = lshr i64 %a, 32
703*700637cbSDimitry Andric     // %conv2 = trunc i64 %shr to i32
704*700637cbSDimitry Andric     // %shr3 = lshr i64 %b, 32
705*700637cbSDimitry Andric     // %conv4 = trunc i64 %shr3 to i32
706*700637cbSDimitry Andric     // %0 = tail call i32 @llvm.ppc.cmpb32(i32 %conv, i32 %conv1)
707*700637cbSDimitry Andric     // %conv5 = zext i32 %0 to i64
708*700637cbSDimitry Andric     // %1 = tail call i32 @llvm.ppc.cmpb32(i32 %conv2, i32 %conv4)
709*700637cbSDimitry Andric     // %conv614 = zext i32 %1 to i64
710*700637cbSDimitry Andric     // %shl = shl nuw i64 %conv614, 32
711*700637cbSDimitry Andric     // %or = or i64 %shl, %conv5
712*700637cbSDimitry Andric     // ret i64 %or
713*700637cbSDimitry Andric     Function *F =
714*700637cbSDimitry Andric         CGM.getIntrinsic(Intrinsic::ppc_cmpb, {Int32Ty, Int32Ty, Int32Ty});
715*700637cbSDimitry Andric     Value *ArgOneLo = Builder.CreateTrunc(Op0, Int32Ty);
716*700637cbSDimitry Andric     Value *ArgTwoLo = Builder.CreateTrunc(Op1, Int32Ty);
717*700637cbSDimitry Andric     Constant *ShiftAmt = ConstantInt::get(Int64Ty, 32);
718*700637cbSDimitry Andric     Value *ArgOneHi =
719*700637cbSDimitry Andric         Builder.CreateTrunc(Builder.CreateLShr(Op0, ShiftAmt), Int32Ty);
720*700637cbSDimitry Andric     Value *ArgTwoHi =
721*700637cbSDimitry Andric         Builder.CreateTrunc(Builder.CreateLShr(Op1, ShiftAmt), Int32Ty);
722*700637cbSDimitry Andric     Value *ResLo = Builder.CreateZExt(
723*700637cbSDimitry Andric         Builder.CreateCall(F, {ArgOneLo, ArgTwoLo}, "cmpb"), Int64Ty);
724*700637cbSDimitry Andric     Value *ResHiShift = Builder.CreateZExt(
725*700637cbSDimitry Andric         Builder.CreateCall(F, {ArgOneHi, ArgTwoHi}, "cmpb"), Int64Ty);
726*700637cbSDimitry Andric     Value *ResHi = Builder.CreateShl(ResHiShift, ShiftAmt);
727*700637cbSDimitry Andric     return Builder.CreateOr(ResLo, ResHi);
728*700637cbSDimitry Andric   }
729*700637cbSDimitry Andric   // Copy sign
730*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvcpsgnsp:
731*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvcpsgndp: {
732*700637cbSDimitry Andric     llvm::Type *ResultType = ConvertType(E->getType());
733*700637cbSDimitry Andric     Value *X = EmitScalarExpr(E->getArg(0));
734*700637cbSDimitry Andric     Value *Y = EmitScalarExpr(E->getArg(1));
735*700637cbSDimitry Andric     ID = Intrinsic::copysign;
736*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(ID, ResultType);
737*700637cbSDimitry Andric     return Builder.CreateCall(F, {X, Y});
738*700637cbSDimitry Andric   }
739*700637cbSDimitry Andric   // Rounding/truncation
740*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvrspip:
741*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvrdpip:
742*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvrdpim:
743*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvrspim:
744*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvrdpi:
745*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvrspi:
746*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvrdpic:
747*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvrspic:
748*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvrdpiz:
749*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvrspiz: {
750*700637cbSDimitry Andric     llvm::Type *ResultType = ConvertType(E->getType());
751*700637cbSDimitry Andric     Value *X = EmitScalarExpr(E->getArg(0));
752*700637cbSDimitry Andric     if (BuiltinID == PPC::BI__builtin_vsx_xvrdpim ||
753*700637cbSDimitry Andric         BuiltinID == PPC::BI__builtin_vsx_xvrspim)
754*700637cbSDimitry Andric       ID = Builder.getIsFPConstrained()
755*700637cbSDimitry Andric                ? Intrinsic::experimental_constrained_floor
756*700637cbSDimitry Andric                : Intrinsic::floor;
757*700637cbSDimitry Andric     else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpi ||
758*700637cbSDimitry Andric              BuiltinID == PPC::BI__builtin_vsx_xvrspi)
759*700637cbSDimitry Andric       ID = Builder.getIsFPConstrained()
760*700637cbSDimitry Andric                ? Intrinsic::experimental_constrained_round
761*700637cbSDimitry Andric                : Intrinsic::round;
762*700637cbSDimitry Andric     else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpic ||
763*700637cbSDimitry Andric              BuiltinID == PPC::BI__builtin_vsx_xvrspic)
764*700637cbSDimitry Andric       ID = Builder.getIsFPConstrained()
765*700637cbSDimitry Andric                ? Intrinsic::experimental_constrained_rint
766*700637cbSDimitry Andric                : Intrinsic::rint;
767*700637cbSDimitry Andric     else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpip ||
768*700637cbSDimitry Andric              BuiltinID == PPC::BI__builtin_vsx_xvrspip)
769*700637cbSDimitry Andric       ID = Builder.getIsFPConstrained()
770*700637cbSDimitry Andric                ? Intrinsic::experimental_constrained_ceil
771*700637cbSDimitry Andric                : Intrinsic::ceil;
772*700637cbSDimitry Andric     else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpiz ||
773*700637cbSDimitry Andric              BuiltinID == PPC::BI__builtin_vsx_xvrspiz)
774*700637cbSDimitry Andric       ID = Builder.getIsFPConstrained()
775*700637cbSDimitry Andric                ? Intrinsic::experimental_constrained_trunc
776*700637cbSDimitry Andric                : Intrinsic::trunc;
777*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(ID, ResultType);
778*700637cbSDimitry Andric     return Builder.getIsFPConstrained() ? Builder.CreateConstrainedFPCall(F, X)
779*700637cbSDimitry Andric                                         : Builder.CreateCall(F, X);
780*700637cbSDimitry Andric   }
781*700637cbSDimitry Andric 
782*700637cbSDimitry Andric   // Absolute value
783*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvabsdp:
784*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvabssp: {
785*700637cbSDimitry Andric     llvm::Type *ResultType = ConvertType(E->getType());
786*700637cbSDimitry Andric     Value *X = EmitScalarExpr(E->getArg(0));
787*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType);
788*700637cbSDimitry Andric     return Builder.CreateCall(F, X);
789*700637cbSDimitry Andric   }
790*700637cbSDimitry Andric 
791*700637cbSDimitry Andric   // Fastmath by default
792*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_recipdivf:
793*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_recipdivd:
794*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_rsqrtf:
795*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_rsqrtd: {
796*700637cbSDimitry Andric     FastMathFlags FMF = Builder.getFastMathFlags();
797*700637cbSDimitry Andric     Builder.getFastMathFlags().setFast();
798*700637cbSDimitry Andric     llvm::Type *ResultType = ConvertType(E->getType());
799*700637cbSDimitry Andric     Value *X = EmitScalarExpr(E->getArg(0));
800*700637cbSDimitry Andric 
801*700637cbSDimitry Andric     if (BuiltinID == PPC::BI__builtin_ppc_recipdivf ||
802*700637cbSDimitry Andric         BuiltinID == PPC::BI__builtin_ppc_recipdivd) {
803*700637cbSDimitry Andric       Value *Y = EmitScalarExpr(E->getArg(1));
804*700637cbSDimitry Andric       Value *FDiv = Builder.CreateFDiv(X, Y, "recipdiv");
805*700637cbSDimitry Andric       Builder.getFastMathFlags() &= (FMF);
806*700637cbSDimitry Andric       return FDiv;
807*700637cbSDimitry Andric     }
808*700637cbSDimitry Andric     auto *One = ConstantFP::get(ResultType, 1.0);
809*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(Intrinsic::sqrt, ResultType);
810*700637cbSDimitry Andric     Value *FDiv = Builder.CreateFDiv(One, Builder.CreateCall(F, X), "rsqrt");
811*700637cbSDimitry Andric     Builder.getFastMathFlags() &= (FMF);
812*700637cbSDimitry Andric     return FDiv;
813*700637cbSDimitry Andric   }
814*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_alignx: {
815*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
816*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
817*700637cbSDimitry Andric     ConstantInt *AlignmentCI = cast<ConstantInt>(Op0);
818*700637cbSDimitry Andric     if (AlignmentCI->getValue().ugt(llvm::Value::MaximumAlignment))
819*700637cbSDimitry Andric       AlignmentCI = ConstantInt::get(AlignmentCI->getIntegerType(),
820*700637cbSDimitry Andric                                      llvm::Value::MaximumAlignment);
821*700637cbSDimitry Andric 
822*700637cbSDimitry Andric     emitAlignmentAssumption(Op1, E->getArg(1),
823*700637cbSDimitry Andric                             /*The expr loc is sufficient.*/ SourceLocation(),
824*700637cbSDimitry Andric                             AlignmentCI, nullptr);
825*700637cbSDimitry Andric     return Op1;
826*700637cbSDimitry Andric   }
827*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_rdlam: {
828*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
829*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
830*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
831*700637cbSDimitry Andric     llvm::Type *Ty = Op0->getType();
832*700637cbSDimitry Andric     Value *ShiftAmt = Builder.CreateIntCast(Op1, Ty, false);
833*700637cbSDimitry Andric     Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty);
834*700637cbSDimitry Andric     Value *Rotate = Builder.CreateCall(F, {Op0, Op0, ShiftAmt});
835*700637cbSDimitry Andric     return Builder.CreateAnd(Rotate, Op2);
836*700637cbSDimitry Andric   }
837*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_load2r: {
838*700637cbSDimitry Andric     Function *F = CGM.getIntrinsic(Intrinsic::ppc_load2r);
839*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
840*700637cbSDimitry Andric     Value *LoadIntrinsic = Builder.CreateCall(F, {Op0});
841*700637cbSDimitry Andric     return Builder.CreateTrunc(LoadIntrinsic, Int16Ty);
842*700637cbSDimitry Andric   }
843*700637cbSDimitry Andric   // FMA variations
844*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fnmsub:
845*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fnmsubs:
846*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvmaddadp:
847*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvmaddasp:
848*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvnmaddadp:
849*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvnmaddasp:
850*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvmsubadp:
851*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvmsubasp:
852*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvnmsubadp:
853*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xvnmsubasp: {
854*700637cbSDimitry Andric     llvm::Type *ResultType = ConvertType(E->getType());
855*700637cbSDimitry Andric     Value *X = EmitScalarExpr(E->getArg(0));
856*700637cbSDimitry Andric     Value *Y = EmitScalarExpr(E->getArg(1));
857*700637cbSDimitry Andric     Value *Z = EmitScalarExpr(E->getArg(2));
858*700637cbSDimitry Andric     llvm::Function *F;
859*700637cbSDimitry Andric     if (Builder.getIsFPConstrained())
860*700637cbSDimitry Andric       F = CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, ResultType);
861*700637cbSDimitry Andric     else
862*700637cbSDimitry Andric       F = CGM.getIntrinsic(Intrinsic::fma, ResultType);
863*700637cbSDimitry Andric     switch (BuiltinID) {
864*700637cbSDimitry Andric       case PPC::BI__builtin_vsx_xvmaddadp:
865*700637cbSDimitry Andric       case PPC::BI__builtin_vsx_xvmaddasp:
866*700637cbSDimitry Andric         if (Builder.getIsFPConstrained())
867*700637cbSDimitry Andric           return Builder.CreateConstrainedFPCall(F, {X, Y, Z});
868*700637cbSDimitry Andric         else
869*700637cbSDimitry Andric           return Builder.CreateCall(F, {X, Y, Z});
870*700637cbSDimitry Andric       case PPC::BI__builtin_vsx_xvnmaddadp:
871*700637cbSDimitry Andric       case PPC::BI__builtin_vsx_xvnmaddasp:
872*700637cbSDimitry Andric         if (Builder.getIsFPConstrained())
873*700637cbSDimitry Andric           return Builder.CreateFNeg(
874*700637cbSDimitry Andric               Builder.CreateConstrainedFPCall(F, {X, Y, Z}), "neg");
875*700637cbSDimitry Andric         else
876*700637cbSDimitry Andric           return Builder.CreateFNeg(Builder.CreateCall(F, {X, Y, Z}), "neg");
877*700637cbSDimitry Andric       case PPC::BI__builtin_vsx_xvmsubadp:
878*700637cbSDimitry Andric       case PPC::BI__builtin_vsx_xvmsubasp:
879*700637cbSDimitry Andric         if (Builder.getIsFPConstrained())
880*700637cbSDimitry Andric           return Builder.CreateConstrainedFPCall(
881*700637cbSDimitry Andric               F, {X, Y, Builder.CreateFNeg(Z, "neg")});
882*700637cbSDimitry Andric         else
883*700637cbSDimitry Andric           return Builder.CreateCall(F, {X, Y, Builder.CreateFNeg(Z, "neg")});
884*700637cbSDimitry Andric       case PPC::BI__builtin_ppc_fnmsub:
885*700637cbSDimitry Andric       case PPC::BI__builtin_ppc_fnmsubs:
886*700637cbSDimitry Andric       case PPC::BI__builtin_vsx_xvnmsubadp:
887*700637cbSDimitry Andric       case PPC::BI__builtin_vsx_xvnmsubasp:
888*700637cbSDimitry Andric         if (Builder.getIsFPConstrained())
889*700637cbSDimitry Andric           return Builder.CreateFNeg(
890*700637cbSDimitry Andric               Builder.CreateConstrainedFPCall(
891*700637cbSDimitry Andric                   F, {X, Y, Builder.CreateFNeg(Z, "neg")}),
892*700637cbSDimitry Andric               "neg");
893*700637cbSDimitry Andric         else
894*700637cbSDimitry Andric           return Builder.CreateCall(
895*700637cbSDimitry Andric               CGM.getIntrinsic(Intrinsic::ppc_fnmsub, ResultType), {X, Y, Z});
896*700637cbSDimitry Andric       }
897*700637cbSDimitry Andric     llvm_unreachable("Unknown FMA operation");
898*700637cbSDimitry Andric     return nullptr; // Suppress no-return warning
899*700637cbSDimitry Andric   }
900*700637cbSDimitry Andric 
901*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_insertword: {
902*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
903*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
904*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
905*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_vsx_xxinsertw);
906*700637cbSDimitry Andric 
907*700637cbSDimitry Andric     // Third argument is a compile time constant int. It must be clamped to
908*700637cbSDimitry Andric     // to the range [0, 12].
909*700637cbSDimitry Andric     ConstantInt *ArgCI = dyn_cast<ConstantInt>(Op2);
910*700637cbSDimitry Andric     assert(ArgCI &&
911*700637cbSDimitry Andric            "Third arg to xxinsertw intrinsic must be constant integer");
912*700637cbSDimitry Andric     const int64_t MaxIndex = 12;
913*700637cbSDimitry Andric     int64_t Index = std::clamp(ArgCI->getSExtValue(), (int64_t)0, MaxIndex);
914*700637cbSDimitry Andric 
915*700637cbSDimitry Andric     // The builtin semantics don't exactly match the xxinsertw instructions
916*700637cbSDimitry Andric     // semantics (which ppc_vsx_xxinsertw follows). The builtin extracts the
917*700637cbSDimitry Andric     // word from the first argument, and inserts it in the second argument. The
918*700637cbSDimitry Andric     // instruction extracts the word from its second input register and inserts
919*700637cbSDimitry Andric     // it into its first input register, so swap the first and second arguments.
920*700637cbSDimitry Andric     std::swap(Op0, Op1);
921*700637cbSDimitry Andric 
922*700637cbSDimitry Andric     // Need to cast the second argument from a vector of unsigned int to a
923*700637cbSDimitry Andric     // vector of long long.
924*700637cbSDimitry Andric     Op1 = Builder.CreateBitCast(Op1, llvm::FixedVectorType::get(Int64Ty, 2));
925*700637cbSDimitry Andric 
926*700637cbSDimitry Andric     if (getTarget().isLittleEndian()) {
927*700637cbSDimitry Andric       // Reverse the double words in the vector we will extract from.
928*700637cbSDimitry Andric       Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int64Ty, 2));
929*700637cbSDimitry Andric       Op0 = Builder.CreateShuffleVector(Op0, Op0, {1, 0});
930*700637cbSDimitry Andric 
931*700637cbSDimitry Andric       // Reverse the index.
932*700637cbSDimitry Andric       Index = MaxIndex - Index;
933*700637cbSDimitry Andric     }
934*700637cbSDimitry Andric 
935*700637cbSDimitry Andric     // Intrinsic expects the first arg to be a vector of int.
936*700637cbSDimitry Andric     Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int32Ty, 4));
937*700637cbSDimitry Andric     Op2 = ConstantInt::getSigned(Int32Ty, Index);
938*700637cbSDimitry Andric     return Builder.CreateCall(F, {Op0, Op1, Op2});
939*700637cbSDimitry Andric   }
940*700637cbSDimitry Andric 
941*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_extractuword: {
942*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
943*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
944*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_vsx_xxextractuw);
945*700637cbSDimitry Andric 
946*700637cbSDimitry Andric     // Intrinsic expects the first argument to be a vector of doublewords.
947*700637cbSDimitry Andric     Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int64Ty, 2));
948*700637cbSDimitry Andric 
949*700637cbSDimitry Andric     // The second argument is a compile time constant int that needs to
950*700637cbSDimitry Andric     // be clamped to the range [0, 12].
951*700637cbSDimitry Andric     ConstantInt *ArgCI = dyn_cast<ConstantInt>(Op1);
952*700637cbSDimitry Andric     assert(ArgCI &&
953*700637cbSDimitry Andric            "Second Arg to xxextractuw intrinsic must be a constant integer!");
954*700637cbSDimitry Andric     const int64_t MaxIndex = 12;
955*700637cbSDimitry Andric     int64_t Index = std::clamp(ArgCI->getSExtValue(), (int64_t)0, MaxIndex);
956*700637cbSDimitry Andric 
957*700637cbSDimitry Andric     if (getTarget().isLittleEndian()) {
958*700637cbSDimitry Andric       // Reverse the index.
959*700637cbSDimitry Andric       Index = MaxIndex - Index;
960*700637cbSDimitry Andric       Op1 = ConstantInt::getSigned(Int32Ty, Index);
961*700637cbSDimitry Andric 
962*700637cbSDimitry Andric       // Emit the call, then reverse the double words of the results vector.
963*700637cbSDimitry Andric       Value *Call = Builder.CreateCall(F, {Op0, Op1});
964*700637cbSDimitry Andric 
965*700637cbSDimitry Andric       Value *ShuffleCall =
966*700637cbSDimitry Andric           Builder.CreateShuffleVector(Call, Call, {1, 0});
967*700637cbSDimitry Andric       return ShuffleCall;
968*700637cbSDimitry Andric     } else {
969*700637cbSDimitry Andric       Op1 = ConstantInt::getSigned(Int32Ty, Index);
970*700637cbSDimitry Andric       return Builder.CreateCall(F, {Op0, Op1});
971*700637cbSDimitry Andric     }
972*700637cbSDimitry Andric   }
973*700637cbSDimitry Andric 
974*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xxpermdi: {
975*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
976*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
977*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
978*700637cbSDimitry Andric     ConstantInt *ArgCI = dyn_cast<ConstantInt>(Op2);
979*700637cbSDimitry Andric     assert(ArgCI && "Third arg must be constant integer!");
980*700637cbSDimitry Andric 
981*700637cbSDimitry Andric     unsigned Index = ArgCI->getZExtValue();
982*700637cbSDimitry Andric     Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int64Ty, 2));
983*700637cbSDimitry Andric     Op1 = Builder.CreateBitCast(Op1, llvm::FixedVectorType::get(Int64Ty, 2));
984*700637cbSDimitry Andric 
985*700637cbSDimitry Andric     // Account for endianness by treating this as just a shuffle. So we use the
986*700637cbSDimitry Andric     // same indices for both LE and BE in order to produce expected results in
987*700637cbSDimitry Andric     // both cases.
988*700637cbSDimitry Andric     int ElemIdx0 = (Index & 2) >> 1;
989*700637cbSDimitry Andric     int ElemIdx1 = 2 + (Index & 1);
990*700637cbSDimitry Andric 
991*700637cbSDimitry Andric     int ShuffleElts[2] = {ElemIdx0, ElemIdx1};
992*700637cbSDimitry Andric     Value *ShuffleCall = Builder.CreateShuffleVector(Op0, Op1, ShuffleElts);
993*700637cbSDimitry Andric     QualType BIRetType = E->getType();
994*700637cbSDimitry Andric     auto RetTy = ConvertType(BIRetType);
995*700637cbSDimitry Andric     return Builder.CreateBitCast(ShuffleCall, RetTy);
996*700637cbSDimitry Andric   }
997*700637cbSDimitry Andric 
998*700637cbSDimitry Andric   case PPC::BI__builtin_vsx_xxsldwi: {
999*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1000*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1001*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
1002*700637cbSDimitry Andric     ConstantInt *ArgCI = dyn_cast<ConstantInt>(Op2);
1003*700637cbSDimitry Andric     assert(ArgCI && "Third argument must be a compile time constant");
1004*700637cbSDimitry Andric     unsigned Index = ArgCI->getZExtValue() & 0x3;
1005*700637cbSDimitry Andric     Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int32Ty, 4));
1006*700637cbSDimitry Andric     Op1 = Builder.CreateBitCast(Op1, llvm::FixedVectorType::get(Int32Ty, 4));
1007*700637cbSDimitry Andric 
1008*700637cbSDimitry Andric     // Create a shuffle mask
1009*700637cbSDimitry Andric     int ElemIdx0;
1010*700637cbSDimitry Andric     int ElemIdx1;
1011*700637cbSDimitry Andric     int ElemIdx2;
1012*700637cbSDimitry Andric     int ElemIdx3;
1013*700637cbSDimitry Andric     if (getTarget().isLittleEndian()) {
1014*700637cbSDimitry Andric       // Little endian element N comes from element 8+N-Index of the
1015*700637cbSDimitry Andric       // concatenated wide vector (of course, using modulo arithmetic on
1016*700637cbSDimitry Andric       // the total number of elements).
1017*700637cbSDimitry Andric       ElemIdx0 = (8 - Index) % 8;
1018*700637cbSDimitry Andric       ElemIdx1 = (9 - Index) % 8;
1019*700637cbSDimitry Andric       ElemIdx2 = (10 - Index) % 8;
1020*700637cbSDimitry Andric       ElemIdx3 = (11 - Index) % 8;
1021*700637cbSDimitry Andric     } else {
1022*700637cbSDimitry Andric       // Big endian ElemIdx<N> = Index + N
1023*700637cbSDimitry Andric       ElemIdx0 = Index;
1024*700637cbSDimitry Andric       ElemIdx1 = Index + 1;
1025*700637cbSDimitry Andric       ElemIdx2 = Index + 2;
1026*700637cbSDimitry Andric       ElemIdx3 = Index + 3;
1027*700637cbSDimitry Andric     }
1028*700637cbSDimitry Andric 
1029*700637cbSDimitry Andric     int ShuffleElts[4] = {ElemIdx0, ElemIdx1, ElemIdx2, ElemIdx3};
1030*700637cbSDimitry Andric     Value *ShuffleCall = Builder.CreateShuffleVector(Op0, Op1, ShuffleElts);
1031*700637cbSDimitry Andric     QualType BIRetType = E->getType();
1032*700637cbSDimitry Andric     auto RetTy = ConvertType(BIRetType);
1033*700637cbSDimitry Andric     return Builder.CreateBitCast(ShuffleCall, RetTy);
1034*700637cbSDimitry Andric   }
1035*700637cbSDimitry Andric 
1036*700637cbSDimitry Andric   case PPC::BI__builtin_pack_vector_int128: {
1037*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1038*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1039*700637cbSDimitry Andric     bool isLittleEndian = getTarget().isLittleEndian();
1040*700637cbSDimitry Andric     Value *PoisonValue =
1041*700637cbSDimitry Andric         llvm::PoisonValue::get(llvm::FixedVectorType::get(Op0->getType(), 2));
1042*700637cbSDimitry Andric     Value *Res = Builder.CreateInsertElement(
1043*700637cbSDimitry Andric         PoisonValue, Op0, (uint64_t)(isLittleEndian ? 1 : 0));
1044*700637cbSDimitry Andric     Res = Builder.CreateInsertElement(Res, Op1,
1045*700637cbSDimitry Andric                                       (uint64_t)(isLittleEndian ? 0 : 1));
1046*700637cbSDimitry Andric     return Builder.CreateBitCast(Res, ConvertType(E->getType()));
1047*700637cbSDimitry Andric   }
1048*700637cbSDimitry Andric 
1049*700637cbSDimitry Andric   case PPC::BI__builtin_unpack_vector_int128: {
1050*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1051*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1052*700637cbSDimitry Andric     ConstantInt *Index = cast<ConstantInt>(Op1);
1053*700637cbSDimitry Andric     Value *Unpacked = Builder.CreateBitCast(
1054*700637cbSDimitry Andric         Op0, llvm::FixedVectorType::get(ConvertType(E->getType()), 2));
1055*700637cbSDimitry Andric 
1056*700637cbSDimitry Andric     if (getTarget().isLittleEndian())
1057*700637cbSDimitry Andric       Index =
1058*700637cbSDimitry Andric           ConstantInt::get(Index->getIntegerType(), 1 - Index->getZExtValue());
1059*700637cbSDimitry Andric 
1060*700637cbSDimitry Andric     return Builder.CreateExtractElement(Unpacked, Index);
1061*700637cbSDimitry Andric   }
1062*700637cbSDimitry Andric 
1063*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_sthcx: {
1064*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_sthcx);
1065*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1066*700637cbSDimitry Andric     Value *Op1 = Builder.CreateSExt(EmitScalarExpr(E->getArg(1)), Int32Ty);
1067*700637cbSDimitry Andric     return Builder.CreateCall(F, {Op0, Op1});
1068*700637cbSDimitry Andric   }
1069*700637cbSDimitry Andric 
1070*700637cbSDimitry Andric   // The PPC MMA builtins take a pointer to a __vector_quad as an argument.
1071*700637cbSDimitry Andric   // Some of the MMA instructions accumulate their result into an existing
1072*700637cbSDimitry Andric   // accumulator whereas the others generate a new accumulator. So we need to
1073*700637cbSDimitry Andric   // use custom code generation to expand a builtin call with a pointer to a
1074*700637cbSDimitry Andric   // load (if the corresponding instruction accumulates its result) followed by
1075*700637cbSDimitry Andric   // the call to the intrinsic and a store of the result.
1076*700637cbSDimitry Andric #define CUSTOM_BUILTIN(Name, Intr, Types, Accumulate, Feature) \
1077*700637cbSDimitry Andric   case PPC::BI__builtin_##Name:
1078*700637cbSDimitry Andric #include "clang/Basic/BuiltinsPPC.def"
1079*700637cbSDimitry Andric   {
1080*700637cbSDimitry Andric     SmallVector<Value *, 4> Ops;
1081*700637cbSDimitry Andric     for (unsigned i = 0, e = E->getNumArgs(); i != e; i++)
1082*700637cbSDimitry Andric       if (E->getArg(i)->getType()->isArrayType())
1083*700637cbSDimitry Andric         Ops.push_back(
1084*700637cbSDimitry Andric             EmitArrayToPointerDecay(E->getArg(i)).emitRawPointer(*this));
1085*700637cbSDimitry Andric       else
1086*700637cbSDimitry Andric         Ops.push_back(EmitScalarExpr(E->getArg(i)));
1087*700637cbSDimitry Andric     // The first argument of these two builtins is a pointer used to store their
1088*700637cbSDimitry Andric     // result. However, the llvm intrinsics return their result in multiple
1089*700637cbSDimitry Andric     // return values. So, here we emit code extracting these values from the
1090*700637cbSDimitry Andric     // intrinsic results and storing them using that pointer.
1091*700637cbSDimitry Andric     if (BuiltinID == PPC::BI__builtin_mma_disassemble_acc ||
1092*700637cbSDimitry Andric         BuiltinID == PPC::BI__builtin_vsx_disassemble_pair ||
1093*700637cbSDimitry Andric         BuiltinID == PPC::BI__builtin_mma_disassemble_pair) {
1094*700637cbSDimitry Andric       unsigned NumVecs = 2;
1095*700637cbSDimitry Andric       auto Intrinsic = Intrinsic::ppc_vsx_disassemble_pair;
1096*700637cbSDimitry Andric       if (BuiltinID == PPC::BI__builtin_mma_disassemble_acc) {
1097*700637cbSDimitry Andric         NumVecs = 4;
1098*700637cbSDimitry Andric         Intrinsic = Intrinsic::ppc_mma_disassemble_acc;
1099*700637cbSDimitry Andric       }
1100*700637cbSDimitry Andric       llvm::Function *F = CGM.getIntrinsic(Intrinsic);
1101*700637cbSDimitry Andric       Address Addr = EmitPointerWithAlignment(E->getArg(1));
1102*700637cbSDimitry Andric       Value *Vec = Builder.CreateLoad(Addr);
1103*700637cbSDimitry Andric       Value *Call = Builder.CreateCall(F, {Vec});
1104*700637cbSDimitry Andric       llvm::Type *VTy = llvm::FixedVectorType::get(Int8Ty, 16);
1105*700637cbSDimitry Andric       Value *Ptr = Ops[0];
1106*700637cbSDimitry Andric       for (unsigned i=0; i<NumVecs; i++) {
1107*700637cbSDimitry Andric         Value *Vec = Builder.CreateExtractValue(Call, i);
1108*700637cbSDimitry Andric         llvm::ConstantInt* Index = llvm::ConstantInt::get(IntTy, i);
1109*700637cbSDimitry Andric         Value *GEP = Builder.CreateInBoundsGEP(VTy, Ptr, Index);
1110*700637cbSDimitry Andric         Builder.CreateAlignedStore(Vec, GEP, MaybeAlign(16));
1111*700637cbSDimitry Andric       }
1112*700637cbSDimitry Andric       return Call;
1113*700637cbSDimitry Andric     }
1114*700637cbSDimitry Andric     if (BuiltinID == PPC::BI__builtin_vsx_build_pair ||
1115*700637cbSDimitry Andric         BuiltinID == PPC::BI__builtin_mma_build_acc) {
1116*700637cbSDimitry Andric       // Reverse the order of the operands for LE, so the
1117*700637cbSDimitry Andric       // same builtin call can be used on both LE and BE
1118*700637cbSDimitry Andric       // without the need for the programmer to swap operands.
1119*700637cbSDimitry Andric       // The operands are reversed starting from the second argument,
1120*700637cbSDimitry Andric       // the first operand is the pointer to the pair/accumulator
1121*700637cbSDimitry Andric       // that is being built.
1122*700637cbSDimitry Andric       if (getTarget().isLittleEndian())
1123*700637cbSDimitry Andric         std::reverse(Ops.begin() + 1, Ops.end());
1124*700637cbSDimitry Andric     }
1125*700637cbSDimitry Andric     bool Accumulate;
1126*700637cbSDimitry Andric     switch (BuiltinID) {
1127*700637cbSDimitry Andric   #define CUSTOM_BUILTIN(Name, Intr, Types, Acc, Feature) \
1128*700637cbSDimitry Andric     case PPC::BI__builtin_##Name: \
1129*700637cbSDimitry Andric       ID = Intrinsic::ppc_##Intr; \
1130*700637cbSDimitry Andric       Accumulate = Acc; \
1131*700637cbSDimitry Andric       break;
1132*700637cbSDimitry Andric   #include "clang/Basic/BuiltinsPPC.def"
1133*700637cbSDimitry Andric     }
1134*700637cbSDimitry Andric     if (BuiltinID == PPC::BI__builtin_vsx_lxvp ||
1135*700637cbSDimitry Andric         BuiltinID == PPC::BI__builtin_vsx_stxvp ||
1136*700637cbSDimitry Andric         BuiltinID == PPC::BI__builtin_mma_lxvp ||
1137*700637cbSDimitry Andric         BuiltinID == PPC::BI__builtin_mma_stxvp) {
1138*700637cbSDimitry Andric       if (BuiltinID == PPC::BI__builtin_vsx_lxvp ||
1139*700637cbSDimitry Andric           BuiltinID == PPC::BI__builtin_mma_lxvp) {
1140*700637cbSDimitry Andric         Ops[0] = Builder.CreateGEP(Int8Ty, Ops[1], Ops[0]);
1141*700637cbSDimitry Andric       } else {
1142*700637cbSDimitry Andric         Ops[1] = Builder.CreateGEP(Int8Ty, Ops[2], Ops[1]);
1143*700637cbSDimitry Andric       }
1144*700637cbSDimitry Andric       Ops.pop_back();
1145*700637cbSDimitry Andric       llvm::Function *F = CGM.getIntrinsic(ID);
1146*700637cbSDimitry Andric       return Builder.CreateCall(F, Ops, "");
1147*700637cbSDimitry Andric     }
1148*700637cbSDimitry Andric     SmallVector<Value*, 4> CallOps;
1149*700637cbSDimitry Andric     if (Accumulate) {
1150*700637cbSDimitry Andric       Address Addr = EmitPointerWithAlignment(E->getArg(0));
1151*700637cbSDimitry Andric       Value *Acc = Builder.CreateLoad(Addr);
1152*700637cbSDimitry Andric       CallOps.push_back(Acc);
1153*700637cbSDimitry Andric     }
1154*700637cbSDimitry Andric     for (unsigned i=1; i<Ops.size(); i++)
1155*700637cbSDimitry Andric       CallOps.push_back(Ops[i]);
1156*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(ID);
1157*700637cbSDimitry Andric     Value *Call = Builder.CreateCall(F, CallOps);
1158*700637cbSDimitry Andric     return Builder.CreateAlignedStore(Call, Ops[0], MaybeAlign());
1159*700637cbSDimitry Andric   }
1160*700637cbSDimitry Andric 
1161*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_compare_and_swap:
1162*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_compare_and_swaplp: {
1163*700637cbSDimitry Andric     Address Addr = EmitPointerWithAlignment(E->getArg(0));
1164*700637cbSDimitry Andric     Address OldValAddr = EmitPointerWithAlignment(E->getArg(1));
1165*700637cbSDimitry Andric     Value *OldVal = Builder.CreateLoad(OldValAddr);
1166*700637cbSDimitry Andric     QualType AtomicTy = E->getArg(0)->getType()->getPointeeType();
1167*700637cbSDimitry Andric     LValue LV = MakeAddrLValue(Addr, AtomicTy);
1168*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
1169*700637cbSDimitry Andric     auto Pair = EmitAtomicCompareExchange(
1170*700637cbSDimitry Andric         LV, RValue::get(OldVal), RValue::get(Op2), E->getExprLoc(),
1171*700637cbSDimitry Andric         llvm::AtomicOrdering::Monotonic, llvm::AtomicOrdering::Monotonic, true);
1172*700637cbSDimitry Andric     // Unlike c11's atomic_compare_exchange, according to
1173*700637cbSDimitry Andric     // https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=functions-compare-swap-compare-swaplp
1174*700637cbSDimitry Andric     // > In either case, the contents of the memory location specified by addr
1175*700637cbSDimitry Andric     // > are copied into the memory location specified by old_val_addr.
1176*700637cbSDimitry Andric     // But it hasn't specified storing to OldValAddr is atomic or not and
1177*700637cbSDimitry Andric     // which order to use. Now following XL's codegen, treat it as a normal
1178*700637cbSDimitry Andric     // store.
1179*700637cbSDimitry Andric     Value *LoadedVal = Pair.first.getScalarVal();
1180*700637cbSDimitry Andric     Builder.CreateStore(LoadedVal, OldValAddr);
1181*700637cbSDimitry Andric     return Builder.CreateZExt(Pair.second, Builder.getInt32Ty());
1182*700637cbSDimitry Andric   }
1183*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_add:
1184*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_addlp: {
1185*700637cbSDimitry Andric     return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E,
1186*700637cbSDimitry Andric                                  llvm::AtomicOrdering::Monotonic);
1187*700637cbSDimitry Andric   }
1188*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_and:
1189*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_andlp: {
1190*700637cbSDimitry Andric     return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E,
1191*700637cbSDimitry Andric                                  llvm::AtomicOrdering::Monotonic);
1192*700637cbSDimitry Andric   }
1193*700637cbSDimitry Andric 
1194*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_or:
1195*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_orlp: {
1196*700637cbSDimitry Andric     return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E,
1197*700637cbSDimitry Andric                                  llvm::AtomicOrdering::Monotonic);
1198*700637cbSDimitry Andric   }
1199*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_swap:
1200*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_swaplp: {
1201*700637cbSDimitry Andric     return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E,
1202*700637cbSDimitry Andric                                  llvm::AtomicOrdering::Monotonic);
1203*700637cbSDimitry Andric   }
1204*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_ldarx:
1205*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_lwarx:
1206*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_lharx:
1207*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_lbarx:
1208*700637cbSDimitry Andric     return emitPPCLoadReserveIntrinsic(*this, BuiltinID, E);
1209*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_mfspr: {
1210*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1211*700637cbSDimitry Andric     llvm::Type *RetType = CGM.getDataLayout().getTypeSizeInBits(VoidPtrTy) == 32
1212*700637cbSDimitry Andric                               ? Int32Ty
1213*700637cbSDimitry Andric                               : Int64Ty;
1214*700637cbSDimitry Andric     Function *F = CGM.getIntrinsic(Intrinsic::ppc_mfspr, RetType);
1215*700637cbSDimitry Andric     return Builder.CreateCall(F, {Op0});
1216*700637cbSDimitry Andric   }
1217*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_mtspr: {
1218*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1219*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1220*700637cbSDimitry Andric     llvm::Type *RetType = CGM.getDataLayout().getTypeSizeInBits(VoidPtrTy) == 32
1221*700637cbSDimitry Andric                               ? Int32Ty
1222*700637cbSDimitry Andric                               : Int64Ty;
1223*700637cbSDimitry Andric     Function *F = CGM.getIntrinsic(Intrinsic::ppc_mtspr, RetType);
1224*700637cbSDimitry Andric     return Builder.CreateCall(F, {Op0, Op1});
1225*700637cbSDimitry Andric   }
1226*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_popcntb: {
1227*700637cbSDimitry Andric     Value *ArgValue = EmitScalarExpr(E->getArg(0));
1228*700637cbSDimitry Andric     llvm::Type *ArgType = ArgValue->getType();
1229*700637cbSDimitry Andric     Function *F = CGM.getIntrinsic(Intrinsic::ppc_popcntb, {ArgType, ArgType});
1230*700637cbSDimitry Andric     return Builder.CreateCall(F, {ArgValue}, "popcntb");
1231*700637cbSDimitry Andric   }
1232*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_mtfsf: {
1233*700637cbSDimitry Andric     // The builtin takes a uint32 that needs to be cast to an
1234*700637cbSDimitry Andric     // f64 to be passed to the intrinsic.
1235*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1236*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1237*700637cbSDimitry Andric     Value *Cast = Builder.CreateUIToFP(Op1, DoubleTy);
1238*700637cbSDimitry Andric     llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_mtfsf);
1239*700637cbSDimitry Andric     return Builder.CreateCall(F, {Op0, Cast}, "");
1240*700637cbSDimitry Andric   }
1241*700637cbSDimitry Andric 
1242*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_swdiv_nochk:
1243*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_swdivs_nochk: {
1244*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1245*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1246*700637cbSDimitry Andric     FastMathFlags FMF = Builder.getFastMathFlags();
1247*700637cbSDimitry Andric     Builder.getFastMathFlags().setFast();
1248*700637cbSDimitry Andric     Value *FDiv = Builder.CreateFDiv(Op0, Op1, "swdiv_nochk");
1249*700637cbSDimitry Andric     Builder.getFastMathFlags() &= (FMF);
1250*700637cbSDimitry Andric     return FDiv;
1251*700637cbSDimitry Andric   }
1252*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fric:
1253*700637cbSDimitry Andric     return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
1254*700637cbSDimitry Andric                            *this, E, Intrinsic::rint,
1255*700637cbSDimitry Andric                            Intrinsic::experimental_constrained_rint))
1256*700637cbSDimitry Andric         .getScalarVal();
1257*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_frim:
1258*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_frims:
1259*700637cbSDimitry Andric     return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
1260*700637cbSDimitry Andric                            *this, E, Intrinsic::floor,
1261*700637cbSDimitry Andric                            Intrinsic::experimental_constrained_floor))
1262*700637cbSDimitry Andric         .getScalarVal();
1263*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_frin:
1264*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_frins:
1265*700637cbSDimitry Andric     return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
1266*700637cbSDimitry Andric                            *this, E, Intrinsic::round,
1267*700637cbSDimitry Andric                            Intrinsic::experimental_constrained_round))
1268*700637cbSDimitry Andric         .getScalarVal();
1269*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_frip:
1270*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_frips:
1271*700637cbSDimitry Andric     return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
1272*700637cbSDimitry Andric                            *this, E, Intrinsic::ceil,
1273*700637cbSDimitry Andric                            Intrinsic::experimental_constrained_ceil))
1274*700637cbSDimitry Andric         .getScalarVal();
1275*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_friz:
1276*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_frizs:
1277*700637cbSDimitry Andric     return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
1278*700637cbSDimitry Andric                            *this, E, Intrinsic::trunc,
1279*700637cbSDimitry Andric                            Intrinsic::experimental_constrained_trunc))
1280*700637cbSDimitry Andric         .getScalarVal();
1281*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fsqrt:
1282*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_fsqrts:
1283*700637cbSDimitry Andric     return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
1284*700637cbSDimitry Andric                            *this, E, Intrinsic::sqrt,
1285*700637cbSDimitry Andric                            Intrinsic::experimental_constrained_sqrt))
1286*700637cbSDimitry Andric         .getScalarVal();
1287*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_test_data_class: {
1288*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1289*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1290*700637cbSDimitry Andric     return Builder.CreateCall(
1291*700637cbSDimitry Andric         CGM.getIntrinsic(Intrinsic::ppc_test_data_class, Op0->getType()),
1292*700637cbSDimitry Andric         {Op0, Op1}, "test_data_class");
1293*700637cbSDimitry Andric   }
1294*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_maxfe: {
1295*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1296*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1297*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
1298*700637cbSDimitry Andric     Value *Op3 = EmitScalarExpr(E->getArg(3));
1299*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_maxfe),
1300*700637cbSDimitry Andric                               {Op0, Op1, Op2, Op3});
1301*700637cbSDimitry Andric   }
1302*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_maxfl: {
1303*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1304*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1305*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
1306*700637cbSDimitry Andric     Value *Op3 = EmitScalarExpr(E->getArg(3));
1307*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_maxfl),
1308*700637cbSDimitry Andric                               {Op0, Op1, Op2, Op3});
1309*700637cbSDimitry Andric   }
1310*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_maxfs: {
1311*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1312*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1313*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
1314*700637cbSDimitry Andric     Value *Op3 = EmitScalarExpr(E->getArg(3));
1315*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_maxfs),
1316*700637cbSDimitry Andric                               {Op0, Op1, Op2, Op3});
1317*700637cbSDimitry Andric   }
1318*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_minfe: {
1319*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1320*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1321*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
1322*700637cbSDimitry Andric     Value *Op3 = EmitScalarExpr(E->getArg(3));
1323*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_minfe),
1324*700637cbSDimitry Andric                               {Op0, Op1, Op2, Op3});
1325*700637cbSDimitry Andric   }
1326*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_minfl: {
1327*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1328*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1329*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
1330*700637cbSDimitry Andric     Value *Op3 = EmitScalarExpr(E->getArg(3));
1331*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_minfl),
1332*700637cbSDimitry Andric                               {Op0, Op1, Op2, Op3});
1333*700637cbSDimitry Andric   }
1334*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_minfs: {
1335*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1336*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1337*700637cbSDimitry Andric     Value *Op2 = EmitScalarExpr(E->getArg(2));
1338*700637cbSDimitry Andric     Value *Op3 = EmitScalarExpr(E->getArg(3));
1339*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_minfs),
1340*700637cbSDimitry Andric                               {Op0, Op1, Op2, Op3});
1341*700637cbSDimitry Andric   }
1342*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_swdiv:
1343*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_swdivs: {
1344*700637cbSDimitry Andric     Value *Op0 = EmitScalarExpr(E->getArg(0));
1345*700637cbSDimitry Andric     Value *Op1 = EmitScalarExpr(E->getArg(1));
1346*700637cbSDimitry Andric     return Builder.CreateFDiv(Op0, Op1, "swdiv");
1347*700637cbSDimitry Andric   }
1348*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_set_fpscr_rn:
1349*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_setrnd),
1350*700637cbSDimitry Andric                               {EmitScalarExpr(E->getArg(0))});
1351*700637cbSDimitry Andric   case PPC::BI__builtin_ppc_mffs:
1352*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_readflm));
1353*700637cbSDimitry Andric   }
1354*700637cbSDimitry Andric }
1355