clang: lib/CodeGen/TargetBuiltins/PPC.cpp Source File (original) (raw)

24 unsigned BuiltinID,

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 ";

36 break;

37 case clang::PPC::BI__builtin_ppc_lwarx:

38 AsmOS << "lwarx ";

40 break;

41 case clang::PPC::BI__builtin_ppc_lharx:

42 AsmOS << "lharx ";

44 break;

45 case clang::PPC::BI__builtin_ppc_lbarx:

46 AsmOS << "lbarx ";

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}";

57 if (!MachineClobbers.empty()) {

58 Constraints += ',';

59 Constraints += MachineClobbers;

60 }

61

63 llvm::FunctionType *FTy = llvm::FunctionType::get(RetType, {PtrType}, false);

64

65 llvm::InlineAsm *IA =

66 llvm::InlineAsm::get(FTy, Asm, Constraints, 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}

75

76

77

78

79

80

81

82

83

84

85

86

87 Intrinsic::ID ID = Intrinsic::not_intrinsic;

88

89#include "llvm/TargetParser/PPCTargetParser.def"

90 auto GenAIXPPCBuiltinCpuExpr = [&](unsigned SupportMethod, unsigned FieldIdx,

91 unsigned Mask, CmpInst::Predicate CompOp,

92 unsigned OpValue) -> Value * {

93 if (SupportMethod == BUILTIN_PPC_FALSE)

95

96 if (SupportMethod == BUILTIN_PPC_TRUE)

98

99 assert(SupportMethod <= SYS_CALL && "Invalid value for SupportMethod.");

100

101 llvm::Value *FieldValue = nullptr;

102 if (SupportMethod == USE_SYS_CONF) {

103 llvm::Type *STy = llvm::StructType::get(PPC_SYSTEMCONFIG_TYPE);

104 llvm::Constant *SysConf =

105 CGM.CreateRuntimeVariable(STy, "_system_configuration");

106

107

108 llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0),

109 ConstantInt::get(Int32Ty, FieldIdx)};

110

111 FieldValue = Builder.CreateInBoundsGEP(STy, SysConf, Idxs);

112 FieldValue = Builder.CreateAlignedLoad(Int32Ty, FieldValue,

114 } else if (SupportMethod == SYS_CALL) {

115 llvm::FunctionType *FTy =

117 llvm::FunctionCallee Func =

118 CGM.CreateRuntimeFunction(FTy, "getsystemcfg");

119

120 FieldValue =

122 }

123 assert(FieldValue &&

124 "SupportMethod value is not defined in PPCTargetParser.def.");

125

126 if (Mask)

127 FieldValue = Builder.CreateAnd(FieldValue, Mask);

128

129 llvm::Type *ValueType = FieldValue->getType();

130 bool IsValueType64Bit = ValueType->isIntegerTy(64);

131 assert(

132 (IsValueType64Bit || ValueType->isIntegerTy(32)) &&

133 "Only 32/64-bit integers are supported in GenAIXPPCBuiltinCpuExpr().");

134

135 return Builder.CreateICmp(

136 CompOp, FieldValue,

137 ConstantInt::get(IsValueType64Bit ? Int64Ty : Int32Ty, OpValue));

138 };

139

140 switch (BuiltinID) {

141 default: return nullptr;

142

143 case Builtin::BI__builtin_cpu_is: {

147

148 typedef std::tuple<unsigned, unsigned, unsigned, unsigned> CPUInfo;

149

150 auto [LinuxSupportMethod, LinuxIDValue, AIXSupportMethod, AIXIDValue] =

151 static_cast<CPUInfo>(StringSwitch(CPUStr)

152#define PPC_CPU(NAME, Linux_SUPPORT_METHOD, LinuxID, AIX_SUPPORT_METHOD, \

153 AIXID) \

154 .Case(NAME, {Linux_SUPPORT_METHOD, LinuxID, AIX_SUPPORT_METHOD, AIXID})

155#include "llvm/TargetParser/PPCTargetParser.def"

156 .Default({BUILTIN_PPC_UNSUPPORTED, 0,

157 BUILTIN_PPC_UNSUPPORTED, 0}));

158

159 if (Triple.isOSAIX()) {

160 assert((AIXSupportMethod != BUILTIN_PPC_UNSUPPORTED) &&

161 "Invalid CPU name. Missed by SemaChecking?");

162 return GenAIXPPCBuiltinCpuExpr(AIXSupportMethod, AIX_SYSCON_IMPL_IDX, 0,

163 ICmpInst::ICMP_EQ, AIXIDValue);

164 }

165

166 assert(Triple.isOSLinux() &&

167 "__builtin_cpu_is() is only supported for AIX and Linux.");

168

169 assert((LinuxSupportMethod != BUILTIN_PPC_UNSUPPORTED) &&

170 "Invalid CPU name. Missed by SemaChecking?");

171

172 if (LinuxSupportMethod == BUILTIN_PPC_FALSE)

174

175 Value *Op0 = llvm::ConstantInt::get(Int32Ty, PPC_FAWORD_CPUID);

176 llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_fixed_addr_ld);

177 Value *TheCall = Builder.CreateCall(F, {Op0}, "cpu_is");

178 return Builder.CreateICmpEQ(TheCall,

179 llvm::ConstantInt::get(Int32Ty, LinuxIDValue));

180 }

181 case Builtin::BI__builtin_cpu_supports: {

185 if (Triple.isOSAIX()) {

187 unsigned>

188 CPUSupportType;

189 auto [SupportMethod, FieldIdx, Mask, CompOp, Value] =

190 static_cast<CPUSupportType>(StringSwitch(CPUStr)

191#define PPC_AIX_FEATURE(NAME, DESC, SUPPORT_METHOD, INDEX, MASK, COMP_OP, \

192 VALUE) \

193 .Case(NAME, {SUPPORT_METHOD, INDEX, MASK, COMP_OP, VALUE})

194#include "llvm/TargetParser/PPCTargetParser.def"

195 .Default({BUILTIN_PPC_FALSE, 0, 0,

196 CmpInst::Predicate(), 0}));

197 return GenAIXPPCBuiltinCpuExpr(SupportMethod, FieldIdx, Mask, CompOp,

199 }

200

201 assert(Triple.isOSLinux() &&

202 "__builtin_cpu_supports() is only supported for AIX and Linux.");

203 auto [FeatureWord, BitMask] =

204 StringSwitch<std::pair<unsigned, unsigned>>(CPUStr)

205#define PPC_LNX_FEATURE(Name, Description, EnumName, Bitmask, FA_WORD) \

206 .Case(Name, {FA_WORD, Bitmask})

207#include "llvm/TargetParser/PPCTargetParser.def"

209 if (!BitMask)

210 return Builder.getFalse();

211 Value *Op0 = llvm::ConstantInt::get(Int32Ty, FeatureWord);

212 llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_fixed_addr_ld);

213 Value *TheCall = Builder.CreateCall(F, {Op0}, "cpu_supports");

215 Builder.CreateAnd(TheCall, llvm::ConstantInt::get(Int32Ty, BitMask));

216 return Builder.CreateICmpNE(Mask, llvm::Constant::getNullValue(Int32Ty));

217#undef PPC_FAWORD_HWCAP

218#undef PPC_FAWORD_HWCAP2

219#undef PPC_FAWORD_CPUID

220 }

221

222

223

224 case PPC::BI__builtin_ppc_get_timebase:

225 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::readcyclecounter));

226

227

228 case PPC::BI__builtin_altivec_lvx:

229 case PPC::BI__builtin_altivec_lvxl:

230 case PPC::BI__builtin_altivec_lvebx:

231 case PPC::BI__builtin_altivec_lvehx:

232 case PPC::BI__builtin_altivec_lvewx:

233 case PPC::BI__builtin_altivec_lvsl:

234 case PPC::BI__builtin_altivec_lvsr:

235 case PPC::BI__builtin_vsx_lxvd2x:

236 case PPC::BI__builtin_vsx_lxvw4x:

237 case PPC::BI__builtin_vsx_lxvd2x_be:

238 case PPC::BI__builtin_vsx_lxvw4x_be:

239 case PPC::BI__builtin_vsx_lxvl:

240 case PPC::BI__builtin_vsx_lxvll:

241 {

245 if (!(BuiltinID == PPC::BI__builtin_vsx_lxvl ||

246 BuiltinID == PPC::BI__builtin_vsx_lxvll)) {

247 Ops[0] = Builder.CreateGEP(Int8Ty, Ops[1], Ops[0]);

248 Ops.pop_back();

249 }

250

251 switch (BuiltinID) {

252 default: llvm_unreachable("Unsupported ld/lvsl/lvsr intrinsic!");

253 case PPC::BI__builtin_altivec_lvx:

254 ID = Intrinsic::ppc_altivec_lvx;

255 break;

256 case PPC::BI__builtin_altivec_lvxl:

257 ID = Intrinsic::ppc_altivec_lvxl;

258 break;

259 case PPC::BI__builtin_altivec_lvebx:

260 ID = Intrinsic::ppc_altivec_lvebx;

261 break;

262 case PPC::BI__builtin_altivec_lvehx:

263 ID = Intrinsic::ppc_altivec_lvehx;

264 break;

265 case PPC::BI__builtin_altivec_lvewx:

266 ID = Intrinsic::ppc_altivec_lvewx;

267 break;

268 case PPC::BI__builtin_altivec_lvsl:

269 ID = Intrinsic::ppc_altivec_lvsl;

270 break;

271 case PPC::BI__builtin_altivec_lvsr:

272 ID = Intrinsic::ppc_altivec_lvsr;

273 break;

274 case PPC::BI__builtin_vsx_lxvd2x:

275 ID = Intrinsic::ppc_vsx_lxvd2x;

276 break;

277 case PPC::BI__builtin_vsx_lxvw4x:

278 ID = Intrinsic::ppc_vsx_lxvw4x;

279 break;

280 case PPC::BI__builtin_vsx_lxvd2x_be:

281 ID = Intrinsic::ppc_vsx_lxvd2x_be;

282 break;

283 case PPC::BI__builtin_vsx_lxvw4x_be:

284 ID = Intrinsic::ppc_vsx_lxvw4x_be;

285 break;

286 case PPC::BI__builtin_vsx_lxvl:

287 ID = Intrinsic::ppc_vsx_lxvl;

288 break;

289 case PPC::BI__builtin_vsx_lxvll:

290 ID = Intrinsic::ppc_vsx_lxvll;

291 break;

292 }

293 llvm::Function *F = CGM.getIntrinsic(ID);

294 return Builder.CreateCall(F, Ops, "");

295 }

296

297

298 case PPC::BI__builtin_altivec_stvx:

299 case PPC::BI__builtin_altivec_stvxl:

300 case PPC::BI__builtin_altivec_stvebx:

301 case PPC::BI__builtin_altivec_stvehx:

302 case PPC::BI__builtin_altivec_stvewx:

303 case PPC::BI__builtin_vsx_stxvd2x:

304 case PPC::BI__builtin_vsx_stxvw4x:

305 case PPC::BI__builtin_vsx_stxvd2x_be:

306 case PPC::BI__builtin_vsx_stxvw4x_be:

307 case PPC::BI__builtin_vsx_stxvl:

308 case PPC::BI__builtin_vsx_stxvll:

309 {

314 if (!(BuiltinID == PPC::BI__builtin_vsx_stxvl ||

315 BuiltinID == PPC::BI__builtin_vsx_stxvll)) {

316 Ops[1] = Builder.CreateGEP(Int8Ty, Ops[2], Ops[1]);

317 Ops.pop_back();

318 }

319

320 switch (BuiltinID) {

321 default: llvm_unreachable("Unsupported st intrinsic!");

322 case PPC::BI__builtin_altivec_stvx:

323 ID = Intrinsic::ppc_altivec_stvx;

324 break;

325 case PPC::BI__builtin_altivec_stvxl:

326 ID = Intrinsic::ppc_altivec_stvxl;

327 break;

328 case PPC::BI__builtin_altivec_stvebx:

329 ID = Intrinsic::ppc_altivec_stvebx;

330 break;

331 case PPC::BI__builtin_altivec_stvehx:

332 ID = Intrinsic::ppc_altivec_stvehx;

333 break;

334 case PPC::BI__builtin_altivec_stvewx:

335 ID = Intrinsic::ppc_altivec_stvewx;

336 break;

337 case PPC::BI__builtin_vsx_stxvd2x:

338 ID = Intrinsic::ppc_vsx_stxvd2x;

339 break;

340 case PPC::BI__builtin_vsx_stxvw4x:

341 ID = Intrinsic::ppc_vsx_stxvw4x;

342 break;

343 case PPC::BI__builtin_vsx_stxvd2x_be:

344 ID = Intrinsic::ppc_vsx_stxvd2x_be;

345 break;

346 case PPC::BI__builtin_vsx_stxvw4x_be:

347 ID = Intrinsic::ppc_vsx_stxvw4x_be;

348 break;

349 case PPC::BI__builtin_vsx_stxvl:

350 ID = Intrinsic::ppc_vsx_stxvl;

351 break;

352 case PPC::BI__builtin_vsx_stxvll:

353 ID = Intrinsic::ppc_vsx_stxvll;

354 break;

355 }

356 llvm::Function *F = CGM.getIntrinsic(ID);

357 return Builder.CreateCall(F, Ops, "");

358 }

359 case PPC::BI__builtin_vsx_ldrmb: {

360

361

362

368

369

370 if (NumBytes == 16) {

373 if (!IsLE)

374 return LD;

375

376

378 for (int Idx = 0; Idx < 16; Idx++)

379 RevMask.push_back(15 - Idx);

380 return Builder.CreateShuffleVector(LD, LD, RevMask);

381 }

382

383 llvm::Function *Lvx = CGM.getIntrinsic(Intrinsic::ppc_altivec_lvx);

384 llvm::Function *Lvs = CGM.getIntrinsic(IsLE ? Intrinsic::ppc_altivec_lvsr

385 : Intrinsic::ppc_altivec_lvsl);

386 llvm::Function *Vperm = CGM.getIntrinsic(Intrinsic::ppc_altivec_vperm);

388 Int8Ty, Op0, ConstantInt::get(Op1->getType(), NumBytes - 1));

389 Value *LoLd = Builder.CreateCall(Lvx, Op0, "ld.lo");

390 Value *HiLd = Builder.CreateCall(Lvx, HiMem, "ld.hi");

391 Value *Mask1 = Builder.CreateCall(Lvs, Op0, "mask1");

392

393 Op0 = IsLE ? HiLd : LoLd;

394 Op1 = IsLE ? LoLd : HiLd;

395 Value *AllElts = Builder.CreateCall(Vperm, {Op0, Op1, Mask1}, "shuffle1");

396 Constant *Zero = llvm::Constant::getNullValue(IsLE ? ResTy : AllElts->getType());

397

398 if (IsLE) {

400 for (int Idx = 0; Idx < 16; Idx++) {

401 int Val = (NumBytes - Idx - 1 >= 0) ? (NumBytes - Idx - 1)

402 : 16 - (NumBytes - Idx);

403 Consts.push_back(Val);

404 }

405 return Builder.CreateShuffleVector(Builder.CreateBitCast(AllElts, ResTy),

406 Zero, Consts);

407 }

409 for (int Idx = 0; Idx < 16; Idx++)

410 Consts.push_back(Builder.getInt8(NumBytes + Idx));

411 Value *Mask2 = ConstantVector::get(Consts);

412 return Builder.CreateBitCast(

413 Builder.CreateCall(Vperm, {Zero, AllElts, Mask2}, "shuffle2"), ResTy);

414 }

415 case PPC::BI__builtin_vsx_strmb: {

421 auto StoreSubVec = [&](unsigned Width, unsigned Offset, unsigned EltNo) {

422

423

424 if (Width == 16) {

425 Value *StVec = Op2;

426 if (IsLE) {

428 for (int Idx = 0; Idx < 16; Idx++)

429 RevMask.push_back(15 - Idx);

430 StVec = Builder.CreateShuffleVector(Op2, Op2, RevMask);

431 }

432 return Builder.CreateStore(

434 }

436 unsigned NumElts = 0;

437 switch (Width) {

438 default:

439 llvm_unreachable("width for stores must be a power of 2");

440 case 8:

442 NumElts = 2;

443 break;

444 case 4:

446 NumElts = 4;

447 break;

448 case 2:

450 NumElts = 8;

451 break;

452 case 1:

454 NumElts = 16;

455 break;

456 }

458 Op2, llvm::FixedVectorType::get(ConvTy, NumElts));

461 Value *Elt = Builder.CreateExtractElement(Vec, EltNo);

462 if (IsLE && Width > 1) {

463 Function *F = CGM.getIntrinsic(Intrinsic::bswap, ConvTy);

464 Elt = Builder.CreateCall(F, Elt);

465 }

466 return Builder.CreateStore(

468 };

469 unsigned Stored = 0;

470 unsigned RemainingBytes = NumBytes;

472 if (NumBytes == 16)

473 return StoreSubVec(16, 0, 0);

474 if (NumBytes >= 8) {

475 Result = StoreSubVec(8, NumBytes - 8, IsLE ? 0 : 1);

476 RemainingBytes -= 8;

477 Stored += 8;

478 }

479 if (RemainingBytes >= 4) {

480 Result = StoreSubVec(4, NumBytes - Stored - 4,

481 IsLE ? (Stored >> 2) : 3 - (Stored >> 2));

482 RemainingBytes -= 4;

483 Stored += 4;

484 }

485 if (RemainingBytes >= 2) {

486 Result = StoreSubVec(2, NumBytes - Stored - 2,

487 IsLE ? (Stored >> 1) : 7 - (Stored >> 1));

488 RemainingBytes -= 2;

489 Stored += 2;

490 }

491 if (RemainingBytes)

493 StoreSubVec(1, NumBytes - Stored - 1, IsLE ? Stored : 15 - Stored);

495 }

496

497 case PPC::BI__builtin_vsx_xvsqrtsp:

498 case PPC::BI__builtin_vsx_xvsqrtdp: {

501 if (Builder.getIsFPConstrained()) {

502 llvm::Function *F = CGM.getIntrinsic(

503 Intrinsic::experimental_constrained_sqrt, ResultType);

504 return Builder.CreateConstrainedFPCall(F, X);

505 } else {

506 llvm::Function *F = CGM.getIntrinsic(Intrinsic::sqrt, ResultType);

507 return Builder.CreateCall(F, X);

508 }

509 }

510

511 case PPC::BI__builtin_altivec_vclzb:

512 case PPC::BI__builtin_altivec_vclzh:

513 case PPC::BI__builtin_altivec_vclzw:

514 case PPC::BI__builtin_altivec_vclzd: {

517 Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);

518 Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ResultType);

519 return Builder.CreateCall(F, {X, Undef});

520 }

521 case PPC::BI__builtin_altivec_vctzb:

522 case PPC::BI__builtin_altivec_vctzh:

523 case PPC::BI__builtin_altivec_vctzw:

524 case PPC::BI__builtin_altivec_vctzd: {

527 Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);

528 Function *F = CGM.getIntrinsic(Intrinsic::cttz, ResultType);

529 return Builder.CreateCall(F, {X, Undef});

530 }

531 case PPC::BI__builtin_altivec_vinsd:

532 case PPC::BI__builtin_altivec_vinsw:

533 case PPC::BI__builtin_altivec_vinsd_elt:

534 case PPC::BI__builtin_altivec_vinsw_elt: {

539

540 bool IsUnaligned = (BuiltinID == PPC::BI__builtin_altivec_vinsw ||

541 BuiltinID == PPC::BI__builtin_altivec_vinsd);

542

543 bool Is32bit = (BuiltinID == PPC::BI__builtin_altivec_vinsw ||

544 BuiltinID == PPC::BI__builtin_altivec_vinsw_elt);

545

546

547 ConstantInt *ArgCI = dyn_cast(Op2);

548 assert(ArgCI &&

549 "Third Arg to vinsw/vinsd intrinsic must be a constant integer!");

550

551

552

553 int ValidMaxValue = 0;

554 if (IsUnaligned)

555 ValidMaxValue = (Is32bit) ? 12 : 8;

556 else

557 ValidMaxValue = (Is32bit) ? 3 : 1;

558

559

560 int64_t ConstArg = ArgCI->getSExtValue();

561

562

563 std::string RangeErrMsg = IsUnaligned ? "byte" : "element";

564 RangeErrMsg += " number " + llvm::to_string(ConstArg);

565 RangeErrMsg += " is outside of the valid range [0, ";

566 RangeErrMsg += llvm::to_string(ValidMaxValue) + "]";

567

568

569 if (ConstArg < 0 || ConstArg > ValidMaxValue)

571

572

573 if (!IsUnaligned) {

574 ConstArg *= Is32bit ? 4 : 8;

575

576 if (getTarget().isLittleEndian())

577 ConstArg = (Is32bit ? 12 : 8) - ConstArg;

578 }

579

580 ID = Is32bit ? Intrinsic::ppc_altivec_vinsw : Intrinsic::ppc_altivec_vinsd;

581 Op2 = ConstantInt::getSigned(Int32Ty, ConstArg);

582

583 Op0 =

584 Is32bit

585 ? Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int32Ty, 4))

586 : Builder.CreateBitCast(Op0,

587 llvm::FixedVectorType::get(Int64Ty, 2));

588 return Builder.CreateBitCast(

589 Builder.CreateCall(CGM.getIntrinsic(ID), {Op0, Op1, Op2}), ResultType);

590 }

591 case PPC::BI__builtin_altivec_vadduqm:

592 case PPC::BI__builtin_altivec_vsubuqm: {

595 llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128);

596 Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int128Ty, 1));

597 Op1 = Builder.CreateBitCast(Op1, llvm::FixedVectorType::get(Int128Ty, 1));

598 if (BuiltinID == PPC::BI__builtin_altivec_vadduqm)

599 return Builder.CreateAdd(Op0, Op1, "vadduqm");

600 else

601 return Builder.CreateSub(Op0, Op1, "vsubuqm");

602 }

603 case PPC::BI__builtin_altivec_vaddcuq_c:

604 case PPC::BI__builtin_altivec_vsubcuq_c: {

608 llvm::Type *V1I128Ty = llvm::FixedVectorType::get(

610 Ops.push_back(Builder.CreateBitCast(Op0, V1I128Ty));

611 Ops.push_back(Builder.CreateBitCast(Op1, V1I128Ty));

612 ID = (BuiltinID == PPC::BI__builtin_altivec_vaddcuq_c)

613 ? Intrinsic::ppc_altivec_vaddcuq

614 : Intrinsic::ppc_altivec_vsubcuq;

615 return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");

616 }

617 case PPC::BI__builtin_altivec_vaddeuqm_c:

618 case PPC::BI__builtin_altivec_vaddecuq_c:

619 case PPC::BI__builtin_altivec_vsubeuqm_c:

620 case PPC::BI__builtin_altivec_vsubecuq_c: {

625 llvm::Type *V1I128Ty = llvm::FixedVectorType::get(

627 Ops.push_back(Builder.CreateBitCast(Op0, V1I128Ty));

628 Ops.push_back(Builder.CreateBitCast(Op1, V1I128Ty));

629 Ops.push_back(Builder.CreateBitCast(Op2, V1I128Ty));

630 switch (BuiltinID) {

631 default:

632 llvm_unreachable("Unsupported intrinsic!");

633 case PPC::BI__builtin_altivec_vaddeuqm_c:

634 ID = Intrinsic::ppc_altivec_vaddeuqm;

635 break;

636 case PPC::BI__builtin_altivec_vaddecuq_c:

637 ID = Intrinsic::ppc_altivec_vaddecuq;

638 break;

639 case PPC::BI__builtin_altivec_vsubeuqm_c:

640 ID = Intrinsic::ppc_altivec_vsubeuqm;

641 break;

642 case PPC::BI__builtin_altivec_vsubecuq_c:

643 ID = Intrinsic::ppc_altivec_vsubecuq;

644 break;

645 }

646 return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");

647 }

648 case PPC::BI__builtin_ppc_rldimi:

649 case PPC::BI__builtin_ppc_rlwimi: {

654

655

656 if (BuiltinID == PPC::BI__builtin_ppc_rldimi &&

657 getTarget().getTriple().isPPC64()) {

660 Value *Shift = Builder.CreateCall(F, {Op0, Op0, Op2});

661 return Builder.CreateOr(Builder.CreateAnd(Shift, Op3),

663 }

664 return Builder.CreateCall(

665 CGM.getIntrinsic(BuiltinID == PPC::BI__builtin_ppc_rldimi

666 ? Intrinsic::ppc_rldimi

667 : Intrinsic::ppc_rlwimi),

668 {Op0, Op1, Op2, Op3});

669 }

670 case PPC::BI__builtin_ppc_rlwnm: {

674 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_rlwnm),

675 {Op0, Op1, Op2});

676 }

677 case PPC::BI__builtin_ppc_poppar4:

678 case PPC::BI__builtin_ppc_poppar8: {

683

686 if (Result->getType() != ResultType)

688 "cast");

690 }

691 case PPC::BI__builtin_ppc_cmpb: {

694 if (getTarget().getTriple().isPPC64()) {

697 return Builder.CreateCall(F, {Op0, Op1}, "cmpb");

698 }

699

700

701

702

703

704

705

706

707

708

709

710

711

712

717 Constant *ShiftAmt = ConstantInt::get(Int64Ty, 32);

718 Value *ArgOneHi =

720 Value *ArgTwoHi =

723 Builder.CreateCall(F, {ArgOneLo, ArgTwoLo}, "cmpb"), Int64Ty);

725 Builder.CreateCall(F, {ArgOneHi, ArgTwoHi}, "cmpb"), Int64Ty);

726 Value *ResHi = Builder.CreateShl(ResHiShift, ShiftAmt);

727 return Builder.CreateOr(ResLo, ResHi);

728 }

729

730 case PPC::BI__builtin_vsx_xvcpsgnsp:

731 case PPC::BI__builtin_vsx_xvcpsgndp: {

735 ID = Intrinsic::copysign;

736 llvm::Function *F = CGM.getIntrinsic(ID, ResultType);

737 return Builder.CreateCall(F, {X, Y});

738 }

739

740 case PPC::BI__builtin_vsx_xvrspip:

741 case PPC::BI__builtin_vsx_xvrdpip:

742 case PPC::BI__builtin_vsx_xvrdpim:

743 case PPC::BI__builtin_vsx_xvrspim:

744 case PPC::BI__builtin_vsx_xvrdpi:

745 case PPC::BI__builtin_vsx_xvrspi:

746 case PPC::BI__builtin_vsx_xvrdpic:

747 case PPC::BI__builtin_vsx_xvrspic:

748 case PPC::BI__builtin_vsx_xvrdpiz:

749 case PPC::BI__builtin_vsx_xvrspiz: {

752 if (BuiltinID == PPC::BI__builtin_vsx_xvrdpim ||

753 BuiltinID == PPC::BI__builtin_vsx_xvrspim)

754 ID = Builder.getIsFPConstrained()

755 ? Intrinsic::experimental_constrained_floor

756 : Intrinsic::floor;

757 else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpi ||

758 BuiltinID == PPC::BI__builtin_vsx_xvrspi)

759 ID = Builder.getIsFPConstrained()

760 ? Intrinsic::experimental_constrained_round

761 : Intrinsic::round;

762 else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpic ||

763 BuiltinID == PPC::BI__builtin_vsx_xvrspic)

764 ID = Builder.getIsFPConstrained()

765 ? Intrinsic::experimental_constrained_rint

766 : Intrinsic::rint;

767 else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpip ||

768 BuiltinID == PPC::BI__builtin_vsx_xvrspip)

769 ID = Builder.getIsFPConstrained()

770 ? Intrinsic::experimental_constrained_ceil

771 : Intrinsic::ceil;

772 else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpiz ||

773 BuiltinID == PPC::BI__builtin_vsx_xvrspiz)

774 ID = Builder.getIsFPConstrained()

775 ? Intrinsic::experimental_constrained_trunc

776 : Intrinsic::trunc;

777 llvm::Function *F = CGM.getIntrinsic(ID, ResultType);

778 return Builder.getIsFPConstrained() ? Builder.CreateConstrainedFPCall(F, X)

780 }

781

782

783 case PPC::BI__builtin_vsx_xvabsdp:

784 case PPC::BI__builtin_vsx_xvabssp: {

787 llvm::Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType);

788 return Builder.CreateCall(F, X);

789 }

790

791

792 case PPC::BI__builtin_ppc_recipdivf:

793 case PPC::BI__builtin_ppc_recipdivd:

794 case PPC::BI__builtin_ppc_rsqrtf:

795 case PPC::BI__builtin_ppc_rsqrtd: {

796 FastMathFlags FMF = Builder.getFastMathFlags();

797 Builder.getFastMathFlags().setFast();

800

801 if (BuiltinID == PPC::BI__builtin_ppc_recipdivf ||

802 BuiltinID == PPC::BI__builtin_ppc_recipdivd) {

804 Value *FDiv = Builder.CreateFDiv(X, Y, "recipdiv");

805 Builder.getFastMathFlags() &= (FMF);

806 return FDiv;

807 }

808 auto *One = ConstantFP::get(ResultType, 1.0);

809 llvm::Function *F = CGM.getIntrinsic(Intrinsic::sqrt, ResultType);

811 Builder.getFastMathFlags() &= (FMF);

812 return FDiv;

813 }

814 case PPC::BI__builtin_ppc_alignx: {

818 if (AlignmentCI->getValue().ugt(llvm::Value::MaximumAlignment))

819 AlignmentCI = ConstantInt::get(AlignmentCI->getIntegerType(),

820 llvm::Value::MaximumAlignment);

821

824 AlignmentCI, nullptr);

825 return Op1;

826 }

827 case PPC::BI__builtin_ppc_rdlam: {

831 llvm::Type *Ty = Op0->getType();

832 Value *ShiftAmt = Builder.CreateIntCast(Op1, Ty, false);

833 Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty);

834 Value *Rotate = Builder.CreateCall(F, {Op0, Op0, ShiftAmt});

835 return Builder.CreateAnd(Rotate, Op2);

836 }

837 case PPC::BI__builtin_ppc_load2r: {

838 Function *F = CGM.getIntrinsic(Intrinsic::ppc_load2r);

840 Value *LoadIntrinsic = Builder.CreateCall(F, {Op0});

842 }

843

844 case PPC::BI__builtin_ppc_fnmsub:

845 case PPC::BI__builtin_ppc_fnmsubs:

846 case PPC::BI__builtin_vsx_xvmaddadp:

847 case PPC::BI__builtin_vsx_xvmaddasp:

848 case PPC::BI__builtin_vsx_xvnmaddadp:

849 case PPC::BI__builtin_vsx_xvnmaddasp:

850 case PPC::BI__builtin_vsx_xvmsubadp:

851 case PPC::BI__builtin_vsx_xvmsubasp:

852 case PPC::BI__builtin_vsx_xvnmsubadp:

853 case PPC::BI__builtin_vsx_xvnmsubasp: {

858 llvm::Function *F;

859 if (Builder.getIsFPConstrained())

860 F = CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, ResultType);

861 else

862 F = CGM.getIntrinsic(Intrinsic::fma, ResultType);

863 switch (BuiltinID) {

864 case PPC::BI__builtin_vsx_xvmaddadp:

865 case PPC::BI__builtin_vsx_xvmaddasp:

866 if (Builder.getIsFPConstrained())

867 return Builder.CreateConstrainedFPCall(F, {X, Y, Z});

868 else

869 return Builder.CreateCall(F, {X, Y, Z});

870 case PPC::BI__builtin_vsx_xvnmaddadp:

871 case PPC::BI__builtin_vsx_xvnmaddasp:

872 if (Builder.getIsFPConstrained())

873 return Builder.CreateFNeg(

874 Builder.CreateConstrainedFPCall(F, {X, Y, Z}), "neg");

875 else

876 return Builder.CreateFNeg(Builder.CreateCall(F, {X, Y, Z}), "neg");

877 case PPC::BI__builtin_vsx_xvmsubadp:

878 case PPC::BI__builtin_vsx_xvmsubasp:

879 if (Builder.getIsFPConstrained())

880 return Builder.CreateConstrainedFPCall(

881 F, {X, Y, Builder.CreateFNeg(Z, "neg")});

882 else

883 return Builder.CreateCall(F, {X, Y, Builder.CreateFNeg(Z, "neg")});

884 case PPC::BI__builtin_ppc_fnmsub:

885 case PPC::BI__builtin_ppc_fnmsubs:

886 case PPC::BI__builtin_vsx_xvnmsubadp:

887 case PPC::BI__builtin_vsx_xvnmsubasp:

888 if (Builder.getIsFPConstrained())

889 return Builder.CreateFNeg(

890 Builder.CreateConstrainedFPCall(

891 F, {X, Y, Builder.CreateFNeg(Z, "neg")}),

892 "neg");

893 else

894 return Builder.CreateCall(

895 CGM.getIntrinsic(Intrinsic::ppc_fnmsub, ResultType), {X, Y, Z});

896 }

897 llvm_unreachable("Unknown FMA operation");

898 return nullptr;

899 }

900

901 case PPC::BI__builtin_vsx_insertword: {

905 llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_vsx_xxinsertw);

906

907

908

909 ConstantInt *ArgCI = dyn_cast(Op2);

910 assert(ArgCI &&

911 "Third arg to xxinsertw intrinsic must be constant integer");

912 const int64_t MaxIndex = 12;

913 int64_t Index = std::clamp(ArgCI->getSExtValue(), (int64_t)0, MaxIndex);

914

915

916

917

918

919

920 std::swap(Op0, Op1);

921

922

923

924 Op1 = Builder.CreateBitCast(Op1, llvm::FixedVectorType::get(Int64Ty, 2));

925

926 if (getTarget().isLittleEndian()) {

927

928 Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int64Ty, 2));

929 Op0 = Builder.CreateShuffleVector(Op0, Op0, {1, 0});

930

931

932 Index = MaxIndex - Index;

933 }

934

935

936 Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int32Ty, 4));

937 Op2 = ConstantInt::getSigned(Int32Ty, Index);

938 return Builder.CreateCall(F, {Op0, Op1, Op2});

939 }

940

941 case PPC::BI__builtin_vsx_extractuword: {

944 llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_vsx_xxextractuw);

945

946

947 Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int64Ty, 2));

948

949

950

951 ConstantInt *ArgCI = dyn_cast(Op1);

952 assert(ArgCI &&

953 "Second Arg to xxextractuw intrinsic must be a constant integer!");

954 const int64_t MaxIndex = 12;

955 int64_t Index = std::clamp(ArgCI->getSExtValue(), (int64_t)0, MaxIndex);

956

957 if (getTarget().isLittleEndian()) {

958

959 Index = MaxIndex - Index;

960 Op1 = ConstantInt::getSigned(Int32Ty, Index);

961

962

964

965 Value *ShuffleCall =

967 return ShuffleCall;

968 } else {

969 Op1 = ConstantInt::getSigned(Int32Ty, Index);

970 return Builder.CreateCall(F, {Op0, Op1});

971 }

972 }

973

974 case PPC::BI__builtin_vsx_xxpermdi: {

978 ConstantInt *ArgCI = dyn_cast(Op2);

979 assert(ArgCI && "Third arg must be constant integer!");

980

981 unsigned Index = ArgCI->getZExtValue();

982 Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int64Ty, 2));

983 Op1 = Builder.CreateBitCast(Op1, llvm::FixedVectorType::get(Int64Ty, 2));

984

985

986

987

988 int ElemIdx0 = (Index & 2) >> 1;

989 int ElemIdx1 = 2 + (Index & 1);

990

991 int ShuffleElts[2] = {ElemIdx0, ElemIdx1};

992 Value *ShuffleCall = Builder.CreateShuffleVector(Op0, Op1, ShuffleElts);

995 return Builder.CreateBitCast(ShuffleCall, RetTy);

996 }

997

998 case PPC::BI__builtin_vsx_xxsldwi: {

1002 ConstantInt *ArgCI = dyn_cast(Op2);

1003 assert(ArgCI && "Third argument must be a compile time constant");

1004 unsigned Index = ArgCI->getZExtValue() & 0x3;

1005 Op0 = Builder.CreateBitCast(Op0, llvm::FixedVectorType::get(Int32Ty, 4));

1006 Op1 = Builder.CreateBitCast(Op1, llvm::FixedVectorType::get(Int32Ty, 4));

1007

1008

1009 int ElemIdx0;

1010 int ElemIdx1;

1011 int ElemIdx2;

1012 int ElemIdx3;

1013 if (getTarget().isLittleEndian()) {

1014

1015

1016

1017 ElemIdx0 = (8 - Index) % 8;

1018 ElemIdx1 = (9 - Index) % 8;

1019 ElemIdx2 = (10 - Index) % 8;

1020 ElemIdx3 = (11 - Index) % 8;

1021 } else {

1022

1023 ElemIdx0 = Index;

1024 ElemIdx1 = Index + 1;

1025 ElemIdx2 = Index + 2;

1026 ElemIdx3 = Index + 3;

1027 }

1028

1029 int ShuffleElts[4] = {ElemIdx0, ElemIdx1, ElemIdx2, ElemIdx3};

1030 Value *ShuffleCall = Builder.CreateShuffleVector(Op0, Op1, ShuffleElts);

1033 return Builder.CreateBitCast(ShuffleCall, RetTy);

1034 }

1035

1036 case PPC::BI__builtin_pack_vector_int128: {

1040 Value *PoisonValue =

1041 llvm::PoisonValue::get(llvm::FixedVectorType::get(Op0->getType(), 2));

1043 PoisonValue, Op0, (uint64_t)(isLittleEndian ? 1 : 0));

1044 Res = Builder.CreateInsertElement(Res, Op1,

1045 (uint64_t)(isLittleEndian ? 0 : 1));

1047 }

1048

1049 case PPC::BI__builtin_unpack_vector_int128: {

1055

1056 if (getTarget().isLittleEndian())

1057 Index =

1058 ConstantInt::get(Index->getIntegerType(), 1 - Index->getZExtValue());

1059

1060 return Builder.CreateExtractElement(Unpacked, Index);

1061 }

1062

1063 case PPC::BI__builtin_ppc_sthcx: {

1064 llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_sthcx);

1067 return Builder.CreateCall(F, {Op0, Op1});

1068 }

1069

1070

1071

1072

1073

1074

1075

1076#define CUSTOM_BUILTIN(Name, Intr, Types, Accumulate, Feature) \

1077 case PPC::BI__builtin_##Name:

1078#include "clang/Basic/BuiltinsPPC.def"

1079 {

1081 for (unsigned i = 0, e = E->getNumArgs(); i != e; i++)

1083 Ops.push_back(

1085 else

1087

1088

1089

1090

1091 if (BuiltinID == PPC::BI__builtin_mma_disassemble_acc ||

1092 BuiltinID == PPC::BI__builtin_vsx_disassemble_pair ||

1093 BuiltinID == PPC::BI__builtin_mma_disassemble_pair) {

1094 unsigned NumVecs = 2;

1095 auto Intrinsic = Intrinsic::ppc_vsx_disassemble_pair;

1096 if (BuiltinID == PPC::BI__builtin_mma_disassemble_acc) {

1097 NumVecs = 4;

1098 Intrinsic = Intrinsic::ppc_mma_disassemble_acc;

1099 }

1100 llvm::Function *F = CGM.getIntrinsic(Intrinsic);

1104 llvm::Type *VTy = llvm::FixedVectorType::get(Int8Ty, 16);

1105 Value *Ptr = Ops[0];

1106 for (unsigned i=0; i<NumVecs; i++) {

1108 llvm::ConstantInt* Index = llvm::ConstantInt::get(IntTy, i);

1109 Value *GEP = Builder.CreateInBoundsGEP(VTy, Ptr, Index);

1110 Builder.CreateAlignedStore(Vec, GEP, MaybeAlign(16));

1111 }

1112 return Call;

1113 }

1114 if (BuiltinID == PPC::BI__builtin_vsx_build_pair ||

1115 BuiltinID == PPC::BI__builtin_mma_build_acc) {

1116

1117

1118

1119

1120

1121

1122 if (getTarget().isLittleEndian())

1123 std::reverse(Ops.begin() + 1, Ops.end());

1124 }

1126 switch (BuiltinID) {

1127 #define CUSTOM_BUILTIN(Name, Intr, Types, Acc, Feature) \

1128 case PPC::BI__builtin_##Name: \

1129 ID = Intrinsic::ppc_##Intr; \

1130 Accumulate = Acc; \

1131 break;

1132 #include "clang/Basic/BuiltinsPPC.def"

1133 }

1134 if (BuiltinID == PPC::BI__builtin_vsx_lxvp ||

1135 BuiltinID == PPC::BI__builtin_vsx_stxvp ||

1136 BuiltinID == PPC::BI__builtin_mma_lxvp ||

1137 BuiltinID == PPC::BI__builtin_mma_stxvp) {

1138 if (BuiltinID == PPC::BI__builtin_vsx_lxvp ||

1139 BuiltinID == PPC::BI__builtin_mma_lxvp) {

1140 Ops[0] = Builder.CreateGEP(Int8Ty, Ops[1], Ops[0]);

1141 } else {

1142 Ops[1] = Builder.CreateGEP(Int8Ty, Ops[2], Ops[1]);

1143 }

1144 Ops.pop_back();

1145 llvm::Function *F = CGM.getIntrinsic(ID);

1146 return Builder.CreateCall(F, Ops, "");

1147 }

1152 CallOps.push_back(Acc);

1153 }

1154 if (BuiltinID == PPC::BI__builtin_mma_dmmr ||

1155 BuiltinID == PPC::BI__builtin_mma_dmxor ||

1156 BuiltinID == PPC::BI__builtin_mma_disassemble_dmr ||

1157 BuiltinID == PPC::BI__builtin_mma_dmsha2hash) {

1160 }

1161 if (BuiltinID == PPC::BI__builtin_mma_disassemble_dmr)

1162 return Builder.CreateAlignedStore(Ops[1], Ops[0], MaybeAlign());

1163 for (unsigned i=1; i<Ops.size(); i++)

1164 CallOps.push_back(Ops[i]);

1165 llvm::Function *F = CGM.getIntrinsic(ID);

1167 return Builder.CreateAlignedStore(Call, Ops[0], MaybeAlign());

1168 }

1169

1170 case PPC::BI__builtin_ppc_compare_and_swap:

1171 case PPC::BI__builtin_ppc_compare_and_swaplp: {

1174 Value *OldVal = Builder.CreateLoad(OldValAddr);

1180 llvm::AtomicOrdering::Monotonic, llvm::AtomicOrdering::Monotonic, true);

1181

1182

1183

1184

1185

1186

1187

1188 Value *LoadedVal = Pair.first.getScalarVal();

1189 Builder.CreateStore(LoadedVal, OldValAddr);

1190 return Builder.CreateZExt(Pair.second, Builder.getInt32Ty());

1191 }

1192 case PPC::BI__builtin_ppc_fetch_and_add:

1193 case PPC::BI__builtin_ppc_fetch_and_addlp: {

1195 llvm::AtomicOrdering::Monotonic);

1196 }

1197 case PPC::BI__builtin_ppc_fetch_and_and:

1198 case PPC::BI__builtin_ppc_fetch_and_andlp: {

1200 llvm::AtomicOrdering::Monotonic);

1201 }

1202

1203 case PPC::BI__builtin_ppc_fetch_and_or:

1204 case PPC::BI__builtin_ppc_fetch_and_orlp: {

1206 llvm::AtomicOrdering::Monotonic);

1207 }

1208 case PPC::BI__builtin_ppc_fetch_and_swap:

1209 case PPC::BI__builtin_ppc_fetch_and_swaplp: {

1211 llvm::AtomicOrdering::Monotonic);

1212 }

1213 case PPC::BI__builtin_ppc_ldarx:

1214 case PPC::BI__builtin_ppc_lwarx:

1215 case PPC::BI__builtin_ppc_lharx:

1216 case PPC::BI__builtin_ppc_lbarx:

1218 case PPC::BI__builtin_ppc_mfspr: {

1220 llvm::Type *RetType = CGM.getDataLayout().getTypeSizeInBits(VoidPtrTy) == 32

1223 Function *F = CGM.getIntrinsic(Intrinsic::ppc_mfspr, RetType);

1224 return Builder.CreateCall(F, {Op0});

1225 }

1226 case PPC::BI__builtin_ppc_mtspr: {

1229 llvm::Type *RetType = CGM.getDataLayout().getTypeSizeInBits(VoidPtrTy) == 32

1232 Function *F = CGM.getIntrinsic(Intrinsic::ppc_mtspr, RetType);

1233 return Builder.CreateCall(F, {Op0, Op1});

1234 }

1235 case PPC::BI__builtin_ppc_popcntb: {

1239 return Builder.CreateCall(F, {ArgValue}, "popcntb");

1240 }

1241 case PPC::BI__builtin_ppc_mtfsf: {

1242

1243

1247 llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_mtfsf);

1248 return Builder.CreateCall(F, {Op0, Cast}, "");

1249 }

1250

1251 case PPC::BI__builtin_ppc_swdiv_nochk:

1252 case PPC::BI__builtin_ppc_swdivs_nochk: {

1255 FastMathFlags FMF = Builder.getFastMathFlags();

1256 Builder.getFastMathFlags().setFast();

1257 Value *FDiv = Builder.CreateFDiv(Op0, Op1, "swdiv_nochk");

1258 Builder.getFastMathFlags() &= (FMF);

1259 return FDiv;

1260 }

1261 case PPC::BI__builtin_ppc_fric:

1263 *this, E, Intrinsic::rint,

1264 Intrinsic::experimental_constrained_rint))

1266 case PPC::BI__builtin_ppc_frim:

1267 case PPC::BI__builtin_ppc_frims:

1269 *this, E, Intrinsic::floor,

1270 Intrinsic::experimental_constrained_floor))

1272 case PPC::BI__builtin_ppc_frin:

1273 case PPC::BI__builtin_ppc_frins:

1275 *this, E, Intrinsic::round,

1276 Intrinsic::experimental_constrained_round))

1278 case PPC::BI__builtin_ppc_frip:

1279 case PPC::BI__builtin_ppc_frips:

1281 *this, E, Intrinsic::ceil,

1282 Intrinsic::experimental_constrained_ceil))

1284 case PPC::BI__builtin_ppc_friz:

1285 case PPC::BI__builtin_ppc_frizs:

1287 *this, E, Intrinsic::trunc,

1288 Intrinsic::experimental_constrained_trunc))

1290 case PPC::BI__builtin_ppc_fsqrt:

1291 case PPC::BI__builtin_ppc_fsqrts:

1293 *this, E, Intrinsic::sqrt,

1294 Intrinsic::experimental_constrained_sqrt))

1296 case PPC::BI__builtin_ppc_test_data_class: {

1299 return Builder.CreateCall(

1300 CGM.getIntrinsic(Intrinsic::ppc_test_data_class, Op0->getType()),

1301 {Op0, Op1}, "test_data_class");

1302 }

1303 case PPC::BI__builtin_ppc_maxfe: {

1308 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_maxfe),

1309 {Op0, Op1, Op2, Op3});

1310 }

1311 case PPC::BI__builtin_ppc_maxfl: {

1316 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_maxfl),

1317 {Op0, Op1, Op2, Op3});

1318 }

1319 case PPC::BI__builtin_ppc_maxfs: {

1324 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_maxfs),

1325 {Op0, Op1, Op2, Op3});

1326 }

1327 case PPC::BI__builtin_ppc_minfe: {

1332 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_minfe),

1333 {Op0, Op1, Op2, Op3});

1334 }

1335 case PPC::BI__builtin_ppc_minfl: {

1340 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_minfl),

1341 {Op0, Op1, Op2, Op3});

1342 }

1343 case PPC::BI__builtin_ppc_minfs: {

1348 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_minfs),

1349 {Op0, Op1, Op2, Op3});

1350 }

1351 case PPC::BI__builtin_ppc_swdiv:

1352 case PPC::BI__builtin_ppc_swdivs: {

1355 return Builder.CreateFDiv(Op0, Op1, "swdiv");

1356 }

1357 case PPC::BI__builtin_ppc_set_fpscr_rn:

1358 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_setrnd),

1359 {EmitScalarExpr(E->getArg(0))});

1360 case PPC::BI__builtin_ppc_mffs:

1361 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_readflm));

1362 }

1363}