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