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