LLVM: lib/Target/AMDGPU/AMDGPULibCalls.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

24#include

25

26#define DEBUG_TYPE "amdgpu-simplifylib"

27

28using namespace llvm;

30

32 cl::desc("Enable pre-link mode optimizations"),

35

37 cl::desc("Comma separated list of functions to replace with native, or all"),

40

41#define MATH_PI numbers::pi

42#define MATH_E numbers::e

43#define MATH_SQRT2 numbers::sqrt2

44#define MATH_SQRT1_2 numbers::inv_sqrt2

45

46namespace llvm {

47

49private:

53

55

56

57 bool AllNative = false;

58

59 bool useNativeFunc(const StringRef F) const;

60

61

62

64

65 bool parseFunctionName(const StringRef &FMangledName, FuncInfo &FInfo);

66

67 bool TDOFold(CallInst *CI, const FuncInfo &FInfo);

68

69

70

71

73

74

76

77

78 bool sincosUseNative(CallInst *aCI, const FuncInfo &FInfo);

79

80

81 bool evaluateScalarMathFunc(const FuncInfo &FInfo, double &Res0, double &Res1,

83 bool evaluateCall(CallInst *aCI, const FuncInfo &FInfo);

84

85

86

87 std::tuple<Value *, Value *, Value *> insertSinCos(Value *Arg,

91

92

94

95

97 const FuncInfo &FInfo);

98

99

101

102

103

104 bool shouldReplaceLibcallWithIntrinsic(const CallInst *CI,

105 bool AllowMinSizeF32 = false,

106 bool AllowF64 = false,

107 bool AllowStrictFP = false);

110

113 bool AllowMinSizeF32 = false,

114 bool AllowF64 = false,

115 bool AllowStrictFP = false);

116

117protected:

119

121

123 I->replaceAllUsesWith(With);

124 I->eraseFromParent();

125 }

126

130

131public:

133

135

138

139

141};

142

143}

144

145template

147 const Twine &Name = "") {

148 CallInst *R = B.CreateCall(Callee, Arg, Name);

150 R->setCallingConv(F->getCallingConv());

151 return R;

152}

153

154template

156 Value *Arg2, const Twine &Name = "") {

157 CallInst *R = B.CreateCall(Callee, {Arg1, Arg2}, Name);

159 R->setCallingConv(F->getCallingConv());

160 return R;

161}

162

166 PowNExpTy = VectorType::get(PowNExpTy, VecTy->getElementCount());

167

169 {FT->getParamType(0), PowNExpTy}, false);

170}

171

172

173

174

179

180

191 {0.5, 0.0},

192 {0.5, -0.0},

193 {0.0, 1.0},

194 {1.0, -1.0}

195};

197 {0.0, 0.0},

198 {-0.0, -0.0},

201};

203 {0.0, 0.0},

204 {-0.0, -0.0}

205};

207 {0.0, 0.0},

208 {-0.0, -0.0},

209 {0.5, 1.0},

210 {-0.5, -1.0}

211};

213 {0.0, 0.0},

214 {-0.0, -0.0},

217};

219 {0.0, 0.0},

220 {-0.0, -0.0}

221};

223 {0.0, 0.0},

224 {-0.0, -0.0},

225 {0.25, 1.0},

226 {-0.25, -1.0}

227};

229 {0.0, 0.0},

230 {-0.0, -0.0},

231 {1.0, 1.0},

232 {-1.0, -1.0},

233};

235 {1.0, 0.0},

236 {1.0, -0.0}

237};

239 {1.0, 0.0},

240 {1.0, -0.0}

241};

243 {1.0, 0.0},

244 {1.0, -0.0}

245};

247 {1.0, 0.0},

248 {1.0, -0.0}

249};

251 {0.0, 0.0},

252 {-0.0, -0.0}

253};

255 {1.0, 0.0},

256 {1.0, -0.0},

258};

260 {1.0, 0.0},

261 {1.0, -0.0},

262 {2.0, 1.0}

263};

265 {1.0, 0.0},

266 {1.0, -0.0},

267 {10.0, 1.0}

268};

270 {0.0, 0.0},

271 {-0.0, -0.0}

272};

278 {0.0, 1.0},

279 {1.0, 2.0}

280};

282 {0.0, 1.0},

283 {1.0, 10.0}

284};

290 {0.0, 0.0},

291 {-0.0, -0.0}

292};

294 {0.0, 0.0},

295 {-0.0, -0.0}

296};

298 {0.0, 0.0},

299 {-0.0, -0.0}

300};

302 {0.0, 0.0},

303 {1.0, 1.0},

305};

307 {0.0, 0.0},

308 {-0.0, -0.0}

309};

311 {0.0, 0.0},

312 {-0.0, -0.0}

313};

315 {0.0, 0.0},

316 {-0.0, -0.0}

317};

319 {1.0, 1.0},

320 {1.0, 2.0},

321 {2.0, 3.0},

322 {6.0, 4.0}

323};

324

326 switch(id) {

342 return true;

343 default:;

344 }

345 return false;

346}

347

349

351 switch(id) {

389 default:;

390 }

392}

393

397

401

402FunctionCallee AMDGPULibCalls::getFunction(Module *M, const FuncInfo &fInfo) {

403

404

405

407 : AMDGPULibFunc::getFunction(M, fInfo);

408}

409

410bool AMDGPULibCalls::parseFunctionName(const StringRef &FMangledName,

411 FuncInfo &FInfo) {

413}

414

418

421

422 return FPOp->isFast();

423}

424

430

431bool AMDGPULibCalls::useNativeFunc(const StringRef F) const {

433}

434

436 AllNative = useNativeFunc("all") ||

439}

440

441bool AMDGPULibCalls::sincosUseNative(CallInst *aCI, const FuncInfo &FInfo) {

442 bool native_sin = useNativeFunc("sin");

443 bool native_cos = useNativeFunc("cos");

444

445 if (native_sin && native_cos) {

448

452

456

460 if (sinExpr && cosExpr) {

466

468 << " with native version of sin/cos");

469

471 return true;

472 }

473 }

474 return false;

475}

476

480 return false;

481

482 FuncInfo FInfo;

483 if (!parseFunctionName(Callee->getName(), FInfo) || !FInfo.isMangled() ||

486 !(AllNative || useNativeFunc(FInfo.getName()))) {

487 return false;

488 }

489

491 return sincosUseNative(aCI, FInfo);

492

495 if (F)

496 return false;

497

500 << " with native version");

501 return true;

502}

503

504

505

506

507

508

509

510

512 const FuncInfo &FInfo) {

514 if (!Callee->isDeclaration())

515 return false;

516

517 assert(Callee->hasName() && "Invalid read_pipe/write_pipe function");

518 auto *M = Callee->getParent();

519 std::string Name = std::string(Callee->getName());

520 auto NumArg = CI->arg_size();

521 if (NumArg != 4 && NumArg != 6)

522 return false;

527 if (!PacketSize || !PacketAlign)

528 return false;

529

532 if (Alignment != Size)

533 return false;

534

535 unsigned PtrArgLoc = CI->arg_size() - 3;

538

540 for (unsigned I = 0; I != PtrArgLoc; ++I)

543

544 Name = Name + "_" + std::to_string(Size);

549 if (F)

550 return false;

551

553 for (unsigned I = 0; I != PtrArgLoc; ++I)

555 Args.push_back(PtrArg);

556

557 auto *NCI = B.CreateCall(F, Args);

562

563 return true;

564}

565

569 return true;

571 return false;

572

574 return CF->getValueAPF().isInteger();

575

578 if (VFVTy && CV) {

579 unsigned NumElts = VFVTy->getNumElements();

580 for (unsigned i = 0; i != NumElts; ++i) {

582 if (!Elt)

583 return false;

585 continue;

586

589 return false;

590 }

591

592 return true;

593 }

594

596 if (I)

597 return false;

598

599 switch (I->getOpcode()) {

600 case Instruction::SIToFP:

601 case Instruction::UIToFP:

602

604 return true;

605

606

607

609 case Instruction::Call: {

612 case Intrinsic::trunc:

613 case Intrinsic:🤣

614 case Intrinsic::ceil:

615 case Intrinsic::rint:

616 case Intrinsic::nearbyint:

617 case Intrinsic::round:

618 case Intrinsic::roundeven:

621 default:

622 break;

623 }

624

625 break;

626 }

627 default:

628 break;

629 }

630

631 return false;

632}

633

634

637

638 if (!Callee || Callee->isIntrinsic() || CI->isNoBuiltin())

639 return false;

640

641 FuncInfo FInfo;

642 if (!parseFunctionName(Callee->getName(), FInfo))

643 return false;

644

645

646

648 return false;

649

650 LLVM_DEBUG(dbgs() << "AMDIC: try folding " << *CI << '\n');

651

652 if (TDOFold(CI, FInfo))

653 return true;

654

657 B.setIsFPConstrained(true);

658

660

661

662

664 return true;

665

666

668 B.setFastMathFlags(FMF);

669

670

671

672

673 switch (FInfo.getId()) {

675 if (FMF.none())

676 return false;

677 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::exp,

680 if (FMF.none())

681 return false;

682 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::exp2,

685 if (FMF.none())

686 return false;

687 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::log,

690 if (FMF.none())

691 return false;

692 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::log2,

695 if (FMF.none())

696 return false;

697 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::log10,

700 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::minnum,

701 true, true);

703 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::maxnum,

704 true, true);

706 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::fma, true,

707 true);

709 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::fmuladd,

710 true, true);

712 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::fabs, true,

713 true, true);

715 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::copysign,

716 true, true, true);

718 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::floor, true,

719 true);

721 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::ceil, true,

722 true);

724 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::trunc, true,

725 true);

727 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::rint, true,

728 true);

730 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::round, true,

731 true);

733 if (!shouldReplaceLibcallWithIntrinsic(CI, true, true))

734 return false;

735

739 Value *SplatArg1 = B.CreateVectorSplat(VecTy->getElementCount(), Arg1);

741 }

742

744 CI->getModule(), Intrinsic::ldexp,

745 {CI->getType(), CI->getArgOperand(1)->getType()}));

746 return true;

747 }

749 Module *M = Callee->getParent();

753

754

755

756 if (PowrFunc &&

758 FPOp->getOperand(0),

760 Call->setCalledFunction(PowrFunc);

761 return fold_pow(FPOp, B, PowrInfo) || true;

762 }

763

764

765 if (isKnownIntegral(FPOp->getOperand(1), M->getDataLayout(),

766 FPOp->getFastMathFlags())) {

770 if (PownFunc) {

771

772

773

774 Value *CastedArg =

775 B.CreateFPToSI(FPOp->getOperand(1), PownType->getParamType(1));

776

777 Call->removeParamAttrs(

778 1, AttributeFuncs::typeIncompatible(CastedArg->getType(),

779 Call->getParamAttributes(1)));

780 Call->setCalledFunction(PownFunc);

781 Call->setArgOperand(1, CastedArg);

782 return fold_pow(FPOp, B, PownInfo) || true;

783 }

784 }

785

786 return fold_pow(FPOp, B, FInfo);

787 }

790 return fold_pow(FPOp, B, FInfo);

792 return fold_rootn(FPOp, B, FInfo);

794

795 return tryReplaceLibcallWithSimpleIntrinsic(

796 B, CI, Intrinsic::sqrt, true, true, false);

799 return fold_sincos(FPOp, B, FInfo);

800 default:

801 break;

802 }

803 } else {

804

805 switch (FInfo.getId()) {

810 return fold_read_write_pipe(CI, B, FInfo);

811 default:

812 break;

813 }

814 }

815

816 return false;

817}

818

819bool AMDGPULibCalls::TDOFold(CallInst *CI, const FuncInfo &FInfo) {

820

823 return false;

824

825 int const sz = (int)tr.size();

827

831 for (int eltNo = 0; eltNo < getVecSize(FInfo); ++eltNo) {

833 CV->getElementAsConstant((unsigned)eltNo));

834 assert(eltval && "Non-FP arguments in math function!");

835 bool found = false;

836 for (int i=0; i < sz; ++i) {

839 found = true;

840 break;

841 }

842 }

843 if (!found) {

844

845 return false;

846 }

847 }

848 LLVMContext &context = CI->getContext();

852 for (double D : DVal)

856 } else {

859 }

860 LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *nval << "\n");

862 return true;

863 }

864 } else {

865

867 for (int i = 0; i < sz; ++i) {

868 if (CF->isExactlyValue(tr[i].input)) {

869 Value *nval = ConstantFP::get(CF->getType(), tr[i].result);

870 LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *nval << "\n");

872 return true;

873 }

874 }

875 }

876 }

877

878 return false;

879}

880

881namespace llvm {

882static double log2(double V) {

883#if _XOPEN_SOURCE >= 600 || defined(_ISOC99_SOURCE) || _POSIX_C_SOURCE >= 200112L

884 return ::log2(V);

885#else

887#endif

888}

889}

890

892 const FuncInfo &FInfo) {

896 "fold_pow: encounter a wrong function call");

897

898 Module *M = B.GetInsertBlock()->getModule();

902

903 const APFloat *CF = nullptr;

904 const APInt *CINT = nullptr;

907

908

909 int ci_opr1 = (CINT ? (int)CINT->getSExtValue() : 0x1111111);

910

911 if ((CF && CF->isZero()) || (CINT && ci_opr1 == 0)) {

912

913 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> 1\n");

914 Constant *cnval = ConstantFP::get(eltType, 1.0);

917 }

919 return true;

920 }

921 if ((CF && CF->isExactlyValue(1.0)) || (CINT && ci_opr1 == 1)) {

922

923 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << "\n");

925 return true;

926 }

927 if ((CF && CF->isExactlyValue(2.0)) || (CINT && ci_opr1 == 2)) {

928

929 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << " * "

930 << *opr0 << "\n");

931 Value *nval = B.CreateFMul(opr0, opr0, "__pow2");

933 return true;

934 }

935 if ((CF && CF->isExactlyValue(-1.0)) || (CINT && ci_opr1 == -1)) {

936

937 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> 1 / " << *opr0 << "\n");

938 Constant *cnval = ConstantFP::get(eltType, 1.0);

941 }

942 Value *nval = B.CreateFDiv(cnval, opr0, "__powrecip");

944 return true;

945 }

946

948

950 if (FunctionCallee FPExpr =

953 FInfo))) {

954 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << FInfo.getName()

955 << '(' << *opr0 << ")\n");

957 : "__pow2rsqrt");

959 return true;

960 }

961 }

962

964 return false;

965

966

967

968

969 if (CF) {

973 int ival = (int)dval;

974 if ((double)ival == dval) {

975 ci_opr1 = ival;

976 } else

977 ci_opr1 = 0x11111111;

978 }

979

980

981

982 unsigned abs_opr1 = (ci_opr1 < 0) ? -ci_opr1 : ci_opr1;

983 if (abs_opr1 <= 12) {

986 if (abs_opr1 == 0) {

987 cnval = ConstantFP::get(eltType, 1.0);

990 }

991 nval = cnval;

992 } else {

993 Value *valx2 = nullptr;

994 nval = nullptr;

995 while (abs_opr1 > 0) {

996 valx2 = valx2 ? B.CreateFMul(valx2, valx2, "__powx2") : opr0;

997 if (abs_opr1 & 1) {

998 nval = nval ? B.CreateFMul(nval, valx2, "__powprod") : valx2;

999 }

1000 abs_opr1 >>= 1;

1001 }

1002 }

1003

1004 if (ci_opr1 < 0) {

1005 cnval = ConstantFP::get(eltType, 1.0);

1008 }

1009 nval = B.CreateFDiv(cnval, nval, "__1powprod");

1010 }

1012 << ((ci_opr1 < 0) ? "1/prod(" : "prod(") << *opr0

1013 << ")\n");

1015 return true;

1016 }

1017

1018

1019 const bool ShouldUseIntrinsic = eltType->isFloatTy() || eltType->isHalfTy();

1020

1021

1022

1023 FunctionCallee ExpExpr;

1024 if (ShouldUseIntrinsic)

1027 else {

1029 if (!ExpExpr)

1030 return false;

1031 }

1032

1033 bool needlog = false;

1034 bool needabs = false;

1035 bool needcopysign = false;

1038 CF = nullptr;

1040

1041 if (CF) {

1045

1046 V = log2(std::abs(V));

1047 cnval = ConstantFP::get(eltType, V);

1050 } else {

1051 needlog = true;

1053 }

1054 } else {

1056

1057 if (!CDV) {

1058 needlog = true;

1060 } else {

1062 "Wrong vector size detected");

1063

1065 for (int i=0; i < getVecSize(FInfo); ++i) {

1067 if (V < 0.0) needcopysign = true;

1068 V = log2(std::abs(V));

1070 }

1073 for (double D : DVal)

1077 } else {

1080 }

1081 }

1082 }

1083

1085

1086

1088 return false;

1089 }

1090

1092 if (needabs) {

1093 nval = B.CreateUnaryIntrinsic(Intrinsic::fabs, opr0, nullptr, "__fabs");

1094 } else {

1095 nval = cnval ? cnval : opr0;

1096 }

1097 if (needlog) {

1098 FunctionCallee LogExpr;

1099 if (ShouldUseIntrinsic) {

1102 } else {

1104 if (!LogExpr)

1105 return false;

1106 }

1107

1109 }

1110

1112

1113 opr1 = B.CreateSIToFP(opr1, nval->getType(), "pownI2F");

1114 }

1115 nval = B.CreateFMul(opr1, nval, "__ylogx");

1117

1118 if (needcopysign) {

1124 opr_n = B.CreateZExtOrTrunc(opr_n, nTy, "__ytou");

1125 else

1126 opr_n = B.CreateFPToSI(opr1, nTy, "__ytou");

1127

1128 Value *sign = B.CreateShl(opr_n, size-1, "__yeven");

1129 sign = B.CreateAnd(B.CreateBitCast(opr0, nTy), sign, "__pow_sign");

1130 nval = B.CreateOr(B.CreateBitCast(nval, nTy), sign);

1131 nval = B.CreateBitCast(nval, opr0->getType());

1132 }

1133

1135 << "exp2(" << *opr1 << " * log2(" << *opr0 << "))\n");

1137

1138 return true;

1139}

1140

1142 const FuncInfo &FInfo) {

1145

1146 const APInt *CINT = nullptr;

1148 return false;

1149

1150 Function *Parent = B.GetInsertBlock()->getParent();

1151

1153 if (ci_opr1 == 1 && !Parent->hasFnAttribute(Attribute::StrictFP)) {

1154

1155

1156

1157 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << '\n');

1159 return true;

1160 }

1161

1162 Module *M = B.GetInsertBlock()->getModule();

1163

1165 if (ci_opr1 == 2 &&

1166 shouldReplaceLibcallWithIntrinsic(CI,

1167 true,

1168 true)) {

1169

1170 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> sqrt(" << *opr0 << ")\n");

1171

1172 CallInst *NewCall = B.CreateUnaryIntrinsic(Intrinsic::sqrt, opr0, CI);

1174

1175

1176

1177 MDBuilder MDHelper(M->getContext());

1178 MDNode *FPMD = MDHelper.createFPMath(std::max(FPOp->getFPAccuracy(), 2.0f));

1179 NewCall->setMetadata(LLVMContext::MD_fpmath, FPMD);

1180

1182 return true;

1183 }

1184

1185 if (ci_opr1 == 3) {

1186 if (FunctionCallee FPExpr =

1188 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> cbrt(" << *opr0

1189 << ")\n");

1192 return true;

1193 }

1194 } else if (ci_opr1 == -1) {

1195 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> 1.0 / " << *opr0 << "\n");

1196 Value *nval = B.CreateFDiv(ConstantFP::get(opr0->getType(), 1.0),

1197 opr0,

1198 "__rootn2div");

1200 return true;

1201 }

1202

1203 if (ci_opr1 == -2 &&

1204 shouldReplaceLibcallWithIntrinsic(CI,

1205 true,

1206 true)) {

1207

1208

1209

1210

1211 MDBuilder MDHelper(M->getContext());

1212 MDNode *FPMD = MDHelper.createFPMath(std::max(FPOp->getFPAccuracy(), 2.0f));

1213

1214

1217

1218 CallInst *Sqrt = B.CreateUnaryIntrinsic(Intrinsic::sqrt, opr0, CI);

1220 B.CreateFDiv(ConstantFP::get(opr0->getType(), 1.0), Sqrt));

1223 RSqrt->setMetadata(LLVMContext::MD_fpmath, FPMD);

1224

1225 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> rsqrt(" << *opr0

1226 << ")\n");

1228 return true;

1229 }

1230

1231 return false;

1232}

1233

1234

1236 const FuncInfo &FInfo) {

1238 return nullptr;

1239 FuncInfo nf = FInfo;

1241 return getFunction(M, nf);

1242}

1243

1244

1245

1246

1247bool AMDGPULibCalls::shouldReplaceLibcallWithIntrinsic(const CallInst *CI,

1248 bool AllowMinSizeF32,

1249 bool AllowF64,

1250 bool AllowStrictFP) {

1252 const bool IsF32 = FltTy->isFloatTy();

1253

1254

1255 if (!IsF32 && !FltTy->isHalfTy() && (!AllowF64 || !FltTy->isDoubleTy()))

1256 return false;

1257

1258

1259

1261 return false;

1262

1264

1265 if (!AllowStrictFP && ParentF->hasFnAttribute(Attribute::StrictFP))

1266 return false;

1267

1268 if (IsF32 && !AllowMinSizeF32 && ParentF->hasMinSize())

1269 return false;

1270 return true;

1271}

1272

1273void AMDGPULibCalls::replaceLibCallWithSimpleIntrinsic(IRBuilder<> &B,

1281 if (Arg0VecTy && !Arg1VecTy) {

1282 Value *SplatRHS = B.CreateVectorSplat(Arg0VecTy->getElementCount(), Arg1);

1284 } else if (!Arg0VecTy && Arg1VecTy) {

1285 Value *SplatLHS = B.CreateVectorSplat(Arg1VecTy->getElementCount(), Arg0);

1287 }

1288 }

1289

1291 CI->getModule(), IntrID, {CI->getType()}));

1292}

1293

1294bool AMDGPULibCalls::tryReplaceLibcallWithSimpleIntrinsic(

1296 bool AllowF64, bool AllowStrictFP) {

1297 if (!shouldReplaceLibcallWithIntrinsic(CI, AllowMinSizeF32, AllowF64,

1298 AllowStrictFP))

1299 return false;

1300 replaceLibCallWithSimpleIntrinsic(B, CI, IntrID);

1301 return true;

1302}

1303

1304std::tuple<Value *, Value *, Value *>

1307 DebugLoc DL = B.getCurrentDebugLocation();

1308 Function *F = B.GetInsertBlock()->getParent();

1309 B.SetInsertPointPastAllocas(F);

1310

1311 AllocaInst *Alloc = B.CreateAlloca(Arg->getType(), nullptr, "__sincos_");

1312

1314

1315

1316

1317

1318 B.SetInsertPoint(ArgInst->getParent(), ++ArgInst->getIterator());

1319

1320

1321 B.SetCurrentDebugLocation(DL);

1322 }

1323

1325

1326

1327

1328

1329 Value *CastAlloc = B.CreateAddrSpaceCast(Alloc, CosPtrTy);

1330

1331 CallInst *SinCos = CreateCallEx2(B, Fsincos, Arg, CastAlloc);

1332

1333

1334

1335

1336 LoadInst *LoadCos = B.CreateLoad(Alloc->getAllocatedType(), Alloc);

1337 return {SinCos, LoadCos, SinCos};

1338}

1339

1340

1342 const FuncInfo &fInfo) {

1345

1349 return false;

1350

1352

1354

1355

1357 return false;

1358

1360

1361 Function *F = B.GetInsertBlock()->getParent();

1363

1364

1365

1367 SinCosLibFuncPrivate.getLeads()[0].PtrKind =

1369

1371 SinCosLibFuncGeneric.getLeads()[0].PtrKind =

1373

1374 FunctionCallee FSinCosPrivate = getFunction(M, SinCosLibFuncPrivate);

1375 FunctionCallee FSinCosGeneric = getFunction(M, SinCosLibFuncGeneric);

1376 FunctionCallee FSinCos = FSinCosPrivate ? FSinCosPrivate : FSinCosGeneric;

1377 if (!FSinCos)

1378 return false;

1379

1384 fInfo);

1385 const std::string PairName = PartnerInfo.mangle();

1386

1389 const std::string SinCosPrivateName = SinCosLibFuncPrivate.mangle();

1390 const std::string SinCosGenericName = SinCosLibFuncGeneric.mangle();

1391

1392

1394 MDNode *FPMath = CI->getMetadata(LLVMContext::MD_fpmath);

1395

1397

1398 for (User* U : CArgVal->users()) {

1401 continue;

1402

1404 if (!UCallee)

1405 continue;

1406

1407 bool Handled = true;

1408

1409 if (UCallee->getName() == SinName)

1411 else if (UCallee->getName() == CosName)

1413 else if (UCallee->getName() == SinCosPrivateName ||

1414 UCallee->getName() == SinCosGenericName)

1416 else

1417 Handled = false;

1418

1419 if (Handled) {

1422 FMF &= OtherOp->getFastMathFlags();

1424 FPMath, XI->getMetadata(LLVMContext::MD_fpmath));

1425 }

1426 }

1427

1428 if (SinCalls.empty() || CosCalls.empty())

1429 return false;

1430

1431 B.setFastMathFlags(FMF);

1432 B.setDefaultFPMathTag(FPMath);

1434 B.SetCurrentDebugLocation(DbgLoc);

1435

1436 auto [Sin, Cos, SinCos] = insertSinCos(CArgVal, FMF, B, FSinCos);

1437

1439 for (CallInst *C : Calls)

1440 C->replaceAllUsesWith(Res);

1441

1442

1443 };

1444

1445 replaceTrigInsts(SinCalls, Sin);

1446 replaceTrigInsts(CosCalls, Cos);

1447 replaceTrigInsts(SinCosCalls, SinCos);

1448

1449

1451 return true;

1452}

1453

1454bool AMDGPULibCalls::evaluateScalarMathFunc(const FuncInfo &FInfo, double &Res0,

1455 double &Res1, Constant *copr0,

1457

1458

1459

1460 double opr0 = 0.0, opr1 = 0.0;

1463 if (fpopr0) {

1467 }

1468

1469 if (fpopr1) {

1473 }

1474

1475 switch (FInfo.getId()) {

1476 default : return false;

1477

1479 Res0 = acos(opr0);

1480 return true;

1481

1483

1484 Res0 = log(opr0 + sqrt(opr0*opr0 - 1.0));

1485 return true;

1486

1488 Res0 = acos(opr0) / MATH_PI;

1489 return true;

1490

1492 Res0 = asin(opr0);

1493 return true;

1494

1496

1497 Res0 = log(opr0 + sqrt(opr0*opr0 + 1.0));

1498 return true;

1499

1501 Res0 = asin(opr0) / MATH_PI;

1502 return true;

1503

1505 Res0 = atan(opr0);

1506 return true;

1507

1509

1510 Res0 = (log(opr0 + 1.0) - log(opr0 - 1.0))/2.0;

1511 return true;

1512

1514 Res0 = atan(opr0) / MATH_PI;

1515 return true;

1516

1518 Res0 = (opr0 < 0.0) ? -pow(-opr0, 1.0/3.0) : pow(opr0, 1.0/3.0);

1519 return true;

1520

1522 Res0 = cos(opr0);

1523 return true;

1524

1526 Res0 = cosh(opr0);

1527 return true;

1528

1530 Res0 = cos(MATH_PI * opr0);

1531 return true;

1532

1534 Res0 = exp(opr0);

1535 return true;

1536

1538 Res0 = pow(2.0, opr0);

1539 return true;

1540

1542 Res0 = pow(10.0, opr0);

1543 return true;

1544

1546 Res0 = log(opr0);

1547 return true;

1548

1550 Res0 = log(opr0) / log(2.0);

1551 return true;

1552

1554 Res0 = log(opr0) / log(10.0);

1555 return true;

1556

1558 Res0 = 1.0 / sqrt(opr0);

1559 return true;

1560

1562 Res0 = sin(opr0);

1563 return true;

1564

1566 Res0 = sinh(opr0);

1567 return true;

1568

1570 Res0 = sin(MATH_PI * opr0);

1571 return true;

1572

1574 Res0 = tan(opr0);

1575 return true;

1576

1578 Res0 = tanh(opr0);

1579 return true;

1580

1582 Res0 = tan(MATH_PI * opr0);

1583 return true;

1584

1585

1588 Res0 = pow(opr0, opr1);

1589 return true;

1590

1593 double val = (double)iopr1->getSExtValue();

1594 Res0 = pow(opr0, val);

1595 return true;

1596 }

1597 return false;

1598 }

1599

1602 double val = (double)iopr1->getSExtValue();

1603 Res0 = pow(opr0, 1.0 / val);

1604 return true;

1605 }

1606 return false;

1607 }

1608

1609

1611 Res0 = sin(opr0);

1612 Res1 = cos(opr0);

1613 return true;

1614 }

1615

1616 return false;

1617}

1618

1619bool AMDGPULibCalls::evaluateCall(CallInst *aCI, const FuncInfo &FInfo) {

1620 int numArgs = (int)aCI->arg_size();

1621 if (numArgs > 3)

1622 return false;

1623

1626 if (numArgs > 0) {

1628 return false;

1629 }

1630

1631 if (numArgs > 1) {

1634 return false;

1635 }

1636 }

1637

1638

1639

1640

1641 double DVal0[16], DVal1[16];

1642 int FuncVecSize = getVecSize(FInfo);

1644 if (FuncVecSize == 1) {

1645 if (!evaluateScalarMathFunc(FInfo, DVal0[0], DVal1[0], copr0, copr1)) {

1646 return false;

1647 }

1648 } else {

1651 for (int i = 0; i < FuncVecSize; ++i) {

1654 if (!evaluateScalarMathFunc(FInfo, DVal0[i], DVal1[i], celt0, celt1)) {

1655 return false;

1656 }

1657 }

1658 }

1659

1660 LLVMContext &context = aCI->getContext();

1662 if (FuncVecSize == 1) {

1663 nval0 = ConstantFP::get(aCI->getType(), DVal0[0]);

1664 if (hasTwoResults)

1665 nval1 = ConstantFP::get(aCI->getType(), DVal1[0]);

1666 } else {

1669 for (int i = 0; i < FuncVecSize; ++i)

1670 FVal0.push_back((float)DVal0[i]);

1673 if (hasTwoResults) {

1674 for (int i = 0; i < FuncVecSize; ++i)

1675 FVal1.push_back((float)DVal1[i]);

1678 }

1679 } else {

1682 if (hasTwoResults) {

1685 }

1686 }

1687 }

1688

1689 if (hasTwoResults) {

1690

1692 "math function with ptr arg not supported yet");

1694 }

1695

1697 return true;

1698}

1699

1704 Simplifier.initFunction(F, AM);

1705

1707

1709 F.printAsOperand(dbgs(), false, F.getParent()); dbgs() << '\n';);

1710

1711 for (auto &BB : F) {

1713

1715 ++I;

1716

1717 if (CI) {

1718 if (Simplifier.fold(CI))

1720 }

1721 }

1722 }

1724}

1725

1730

1733 Simplifier.initFunction(F, AM);

1734

1736 for (auto &BB : F) {

1738

1740 ++I;

1741 if (CI && Simplifier.useNative(CI))

1743 }

1744 }

1746}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static bool isKnownIntegral(const Value *V, const DataLayout &DL, FastMathFlags FMF)

Definition AMDGPULibCalls.cpp:566

static const TableEntry tbl_log[]

Definition AMDGPULibCalls.cpp:273

static const TableEntry tbl_tgamma[]

Definition AMDGPULibCalls.cpp:318

static AMDGPULibFunc::EType getArgType(const AMDGPULibFunc &FInfo)

Definition AMDGPULibCalls.cpp:398

static const TableEntry tbl_expm1[]

Definition AMDGPULibCalls.cpp:269

static const TableEntry tbl_asinpi[]

Definition AMDGPULibCalls.cpp:206

static const TableEntry tbl_cos[]

Definition AMDGPULibCalls.cpp:234

#define MATH_SQRT2

Definition AMDGPULibCalls.cpp:43

static const TableEntry tbl_exp10[]

Definition AMDGPULibCalls.cpp:264

static CallInst * CreateCallEx(IRB &B, FunctionCallee Callee, Value *Arg, const Twine &Name="")

Definition AMDGPULibCalls.cpp:146

static CallInst * CreateCallEx2(IRB &B, FunctionCallee Callee, Value *Arg1, Value *Arg2, const Twine &Name="")

Definition AMDGPULibCalls.cpp:155

static const TableEntry tbl_rsqrt[]

Definition AMDGPULibCalls.cpp:285

static const TableEntry tbl_atanh[]

Definition AMDGPULibCalls.cpp:218

static const TableEntry tbl_cosh[]

Definition AMDGPULibCalls.cpp:238

static const TableEntry tbl_asin[]

Definition AMDGPULibCalls.cpp:196

static const TableEntry tbl_sinh[]

Definition AMDGPULibCalls.cpp:293

static const TableEntry tbl_acos[]

Definition AMDGPULibCalls.cpp:181

static const TableEntry tbl_tan[]

Definition AMDGPULibCalls.cpp:306

static const TableEntry tbl_cospi[]

Definition AMDGPULibCalls.cpp:242

static const TableEntry tbl_tanpi[]

Definition AMDGPULibCalls.cpp:314

static cl::opt< bool > EnablePreLink("amdgpu-prelink", cl::desc("Enable pre-link mode optimizations"), cl::init(false), cl::Hidden)

static bool HasNative(AMDGPULibFunc::EFuncId id)

Definition AMDGPULibCalls.cpp:325

ArrayRef< TableEntry > TableRef

Definition AMDGPULibCalls.cpp:348

static int getVecSize(const AMDGPULibFunc &FInfo)

Definition AMDGPULibCalls.cpp:394

static const TableEntry tbl_sin[]

Definition AMDGPULibCalls.cpp:289

static const TableEntry tbl_atan[]

Definition AMDGPULibCalls.cpp:212

static const TableEntry tbl_log2[]

Definition AMDGPULibCalls.cpp:277

static const TableEntry tbl_acospi[]

Definition AMDGPULibCalls.cpp:190

static const TableEntry tbl_sqrt[]

Definition AMDGPULibCalls.cpp:301

static const TableEntry tbl_asinh[]

Definition AMDGPULibCalls.cpp:202

#define MATH_E

Definition AMDGPULibCalls.cpp:42

static TableRef getOptTable(AMDGPULibFunc::EFuncId id)

Definition AMDGPULibCalls.cpp:350

static const TableEntry tbl_acosh[]

Definition AMDGPULibCalls.cpp:187

static const TableEntry tbl_exp[]

Definition AMDGPULibCalls.cpp:254

static const TableEntry tbl_cbrt[]

Definition AMDGPULibCalls.cpp:228

static const TableEntry tbl_sinpi[]

Definition AMDGPULibCalls.cpp:297

static const TableEntry tbl_atanpi[]

Definition AMDGPULibCalls.cpp:222

#define MATH_PI

Definition AMDGPULibCalls.cpp:41

static FunctionType * getPownType(FunctionType *FT)

Definition AMDGPULibCalls.cpp:163

static const TableEntry tbl_erf[]

Definition AMDGPULibCalls.cpp:250

static const TableEntry tbl_log10[]

Definition AMDGPULibCalls.cpp:281

#define MATH_SQRT1_2

Definition AMDGPULibCalls.cpp:44

static const TableEntry tbl_erfc[]

Definition AMDGPULibCalls.cpp:246

static cl::list< std::string > UseNative("amdgpu-use-native", cl::desc("Comma separated list of functions to replace with native, or all"), cl::CommaSeparated, cl::ValueOptional, cl::Hidden)

static const TableEntry tbl_tanh[]

Definition AMDGPULibCalls.cpp:310

static const TableEntry tbl_exp2[]

Definition AMDGPULibCalls.cpp:259

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

Machine Check Debug Module

FunctionAnalysisManager FAM

#define DEBUG_WITH_TYPE(TYPE,...)

DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.

static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)

Definition AMDGPULibCalls.cpp:48

static void replaceCall(FPMathOperator *I, Value *With)

Definition AMDGPULibCalls.cpp:127

bool isUnsafeFiniteOnlyMath(const FPMathOperator *FPOp) const

Definition AMDGPULibCalls.cpp:415

bool canIncreasePrecisionOfConstantFold(const FPMathOperator *FPOp) const

Definition AMDGPULibCalls.cpp:419

bool fold(CallInst *CI)

Definition AMDGPULibCalls.cpp:635

void initNativeFuncs()

Definition AMDGPULibCalls.cpp:435

static void replaceCall(Instruction *I, Value *With)

Definition AMDGPULibCalls.cpp:122

bool useNative(CallInst *CI)

Definition AMDGPULibCalls.cpp:477

void initFunction(Function &F, FunctionAnalysisManager &FAM)

Definition AMDGPULibCalls.cpp:425

static unsigned getEPtrKindFromAddrSpace(unsigned AS)

Wrapper class for AMDGPULIbFuncImpl.

static bool parse(StringRef MangledName, AMDGPULibFunc &Ptr)

std::string getName() const

Get unmangled name for mangled library function and name for unmangled library function.

static FunctionCallee getOrInsertFunction(llvm::Module *M, const AMDGPULibFunc &fInfo)

void setPrefix(ENamePrefix PFX)

bool isCompatibleSignature(const Module &M, const FunctionType *FuncTy) const

Param * getLeads()

Get leading parameters for mangled lib functions.

ENamePrefix getPrefix() const

LLVM_ABI double convertToDouble() const

Converts this APFloat to host double value.

bool isExactlyValue(double V) const

We don't rely on operator== working on double values, as it returns true for things that are clearly ...

LLVM_ABI float convertToFloat() const

Converts this APFloat to host float value.

int64_t getSExtValue() const

Get sign extended value.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

bool empty() const

empty - Check if the array is empty.

A function analysis which provides an AssumptionCache.

A cache of @llvm.assume calls within a function.

InstListType::iterator iterator

Instruction iterators...

bool isNoBuiltin() const

Return true if the call should not be treated as a call to a builtin.

Function * getCalledFunction() const

Returns the function called, or null if this is an indirect function invocation or the function signa...

bool isStrictFP() const

Determine if the call requires strict floating point semantics.

bool isNoInline() const

Return true if the call should not be inlined.

Value * getArgOperand(unsigned i) const

void setArgOperand(unsigned i, Value *v)

FunctionType * getFunctionType() const

LLVM_ABI Intrinsic::ID getIntrinsicID() const

Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...

unsigned arg_size() const

AttributeList getAttributes() const

Return the attributes for this call.

void setCalledFunction(Function *Fn)

Sets the function called, including updating the function type.

This class represents a function call, abstracting a target machine's calling convention.

static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

LLVM_ABI APFloat getElementAsAPFloat(uint64_t i) const

If this is a sequential container of floating point type, return the specified element as an APFloat.

LLVM_ABI Constant * getElementAsConstant(uint64_t i) const

Return a Constant for a specified index's element.

LLVM_ABI uint64_t getNumElements() const

Return the number of elements in the array or vector.

A vector constant whose element type is a simple 1/2/4/8-byte integer or float/double,...

static LLVM_ABI Constant * getSplat(unsigned NumElts, Constant *Elt)

Return a ConstantVector with the specified constant in each element.

static LLVM_ABI Constant * get(LLVMContext &Context, ArrayRef< uint8_t > Elts)

get() constructors - Return a constant with vector type with an element count and element type matchi...

ConstantFP - Floating Point Values [float, double].

const APFloat & getValue() const

const APFloat & getValueAPF() const

LLVM_ABI bool isExactlyValue(const APFloat &V) const

We don't rely on operator== working on double values, as it returns true for things that are clearly ...

This is the shared class of boolean and integer constants.

uint64_t getZExtValue() const

Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...

Align getAlignValue() const

Return the constant as an llvm::Align, interpreting 0 as Align(1).

This is an important base class in LLVM.

LLVM_ABI Constant * getAggregateElement(unsigned Elt) const

For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...

static LLVM_ABI DILocation * getMergedLocations(ArrayRef< DILocation * > Locs)

Try to combine the vector of locations passed as input in a single one.

A parsed version of the target data layout string in and methods for querying it.

Analysis pass which computes a DominatorTree.

Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.

Utility class for floating point operations which can have information about relaxed accuracy require...

bool isFast() const

Test if this operation allows all non-strict floating-point transforms.

bool hasNoNaNs() const

Test if this operation's arguments and results are assumed not-NaN.

FastMathFlags getFastMathFlags() const

Convenience function for getting all the fast-math flags.

bool hasNoInfs() const

Test if this operation's arguments and results are assumed not-infinite.

bool hasApproxFunc() const

Test if this operation allows approximations of math library functions or intrinsics.

LLVM_ABI float getFPAccuracy() const

Get the maximum error permitted by this operation in ULPs.

Convenience struct for specifying and reasoning about fast-math flags.

void setAllowContract(bool B=true)

A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...

FunctionType * getFunctionType()

Class to represent function types.

Type * getParamType(unsigned i) const

Parameter type accessors.

static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)

This static method is the primary way of constructing a FunctionType.

bool hasMinSize() const

Optimize this function for minimum size (-Oz).

bool hasFnAttribute(Attribute::AttrKind Kind) const

Return true if the function has the attribute.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

const DebugLoc & getDebugLoc() const

Return the debug location for this node as a DebugLoc.

LLVM_ABI const Module * getModule() const

Return the module owning the function this instruction belongs to or nullptr it the function does not...

LLVM_ABI void setFastMathFlags(FastMathFlags FMF)

Convenience function for setting multiple fast-math flags on this instruction, which must be an opera...

LLVM_ABI InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

LLVM_ABI const Function * getFunction() const

Return the function this instruction belongs to.

MDNode * getMetadata(unsigned KindID) const

Get the metadata of given kind attached to this Instruction.

LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)

Set the metadata of the specified kind to the specified node.

static LLVM_ABI MDNode * getMostGenericFPMath(MDNode *A, MDNode *B)

A Module instance is used to store all the information related to an LLVM module.

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses none()

Convenience factory function for the empty preserved set.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

An instruction for storing to memory.

StringRef - Represent a constant reference to a string, i.e.

Analysis pass providing the TargetLibraryInfo.

Provides information about what library functions are available for the current target.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

The instances of the Type class are immutable: once they are created, they are never changed.

static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)

bool isFloatTy() const

Return true if this is 'float', a 32-bit IEEE fp type.

Type * getScalarType() const

If this is a vector type, return the element type, otherwise return 'this'.

LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY

Return the basic size of this type if it is a primitive type.

bool isHalfTy() const

Return true if this is 'half', a 16-bit IEEE fp type.

LLVM_ABI Type * getWithNewType(Type *EltTy) const

Given vector type, change the element type, whilst keeping the old number of elements.

LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY

If this is a vector type, return the getPrimitiveSizeInBits value for the element type.

bool isDoubleTy() const

Return true if this is 'double', a 64-bit IEEE fp type.

bool isIntegerTy() const

True if this is an instance of IntegerType.

void dropAllReferences()

Drop all references to operands.

Value * getOperand(unsigned i) const

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

LLVM_ABI void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

iterator_range< user_iterator > users()

LLVM_ABI LLVMContext & getContext() const

All values hold a context through their type.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

LLVM_ABI void takeName(Value *V)

Transfer the name from V to this value.

Base class of all SIMD vector types.

static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)

This static method is the primary way to construct an VectorType.

self_iterator getIterator()

@ FLAT_ADDRESS

Address space for flat memory.

@ PRIVATE_ADDRESS

Address space for private memory.

LLVM_ABI APInt pow(const APInt &X, int64_t N)

Compute X^N for N>=0.

@ C

The default llvm calling convention, compatible with C.

LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})

Look up the Function declaration of the intrinsic id in the Module M.

ap_match< APInt > m_APIntAllowPoison(const APInt *&Res)

Match APInt while allowing poison in splat vector constants.

bool match(Val *V, const Pattern &P)

ap_match< APFloat > m_APFloatAllowPoison(const APFloat *&Res)

Match APFloat while allowing poison in splat vector constants.

initializer< Ty > init(const Ty &Val)

friend class Instruction

Iterator for Instructions in a `BasicBlock.

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

static double log2(double V)

Definition AMDGPULibCalls.cpp:882

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

LLVM_ABI bool isKnownNeverInfinity(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)

Return true if the floating-point scalar value is not an infinity or if the floating-point vector val...

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

auto dyn_cast_or_null(const Y &Val)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

ArrayRef(const T &OneElt) -> ArrayRef< T >

LLVM_ABI bool isKnownNeverInfOrNaN(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)

Return true if the floating-point value can never contain a NaN or infinity.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.

LLVM_ABI bool cannotBeOrderedLessThanZero(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)

Return true if we can prove that the specified FP value is either NaN or never less than -0....

Definition AMDGPULibCalls.cpp:175

double result

Definition AMDGPULibCalls.cpp:176

double input

Definition AMDGPULibCalls.cpp:177

PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)

Definition AMDGPULibCalls.cpp:1700

PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)

Definition AMDGPULibCalls.cpp:1726

This struct is a compact representation of a valid (non-zero power of two) alignment.