|
37 | 37 | // memory that ends up in one of the runtime equivalents, since this can
|
38 | 38 | // happen if e.g. a library that was compiled without interposition returns
|
39 | 39 | // an allocation that can be validly passed to `free`.
|
| 40 | +// |
| 41 | +// 3. MathFixup (required): Some accelerators might have an incomplete |
| 42 | +// implementation for the intrinsics used to implement some of the math |
| 43 | +// functions in <cmath> / their corresponding libcall lowerings. Since this |
| 44 | +// can vary quite significantly between accelerators, we replace calls to a |
| 45 | +// set of intrinsics / lib functions known to be problematic with calls to a |
| 46 | +// HIPSTDPAR specific forwarding layer, which gives an uniform interface for |
| 47 | +// accelerators to implement in their own runtime components. This pass |
| 48 | +// should run before AcceleratorCodeSelection so as to prevent the spurious |
| 49 | +// removal of the HIPSTDPAR specific forwarding functions. |
40 | 50 | //===----------------------------------------------------------------------===//
|
41 | 51 |
|
42 | 52 | #include "llvm/Transforms/HipStdPar/HipStdPar.h"
|
|
49 | 59 | #include "llvm/IR/Constants.h"
|
50 | 60 | #include "llvm/IR/Function.h"
|
51 | 61 | #include "llvm/IR/IRBuilder.h"
|
| 62 | +#include "llvm/IR/Intrinsics.h" |
52 | 63 | #include "llvm/IR/Module.h"
|
53 | 64 | #include "llvm/Transforms/Utils/ModuleUtils.h"
|
54 | 65 |
|
@@ -519,3 +530,110 @@ HipStdParAllocationInterpositionPass::run(Module &M, ModuleAnalysisManager&) {
|
519 | 530 |
|
520 | 531 | return PreservedAnalyses::none();
|
521 | 532 | }
|
| 533 | + |
| 534 | +static constexpr std::pair<StringLiteral, StringLiteral> MathLibToHipStdPar[]{ |
| 535 | + {"acosh", "__hipstdpar_acosh_f64"}, |
| 536 | + {"acoshf", "__hipstdpar_acosh_f32"}, |
| 537 | + {"asinh", "__hipstdpar_asinh_f64"}, |
| 538 | + {"asinhf", "__hipstdpar_asinh_f32"}, |
| 539 | + {"atanh", "__hipstdpar_atanh_f64"}, |
| 540 | + {"atanhf", "__hipstdpar_atanh_f32"}, |
| 541 | + {"cbrt", "__hipstdpar_cbrt_f64"}, |
| 542 | + {"cbrtf", "__hipstdpar_cbrt_f32"}, |
| 543 | + {"erf", "__hipstdpar_erf_f64"}, |
| 544 | + {"erff", "__hipstdpar_erf_f32"}, |
| 545 | + {"erfc", "__hipstdpar_erfc_f64"}, |
| 546 | + {"erfcf", "__hipstdpar_erfc_f32"}, |
| 547 | + {"fdim", "__hipstdpar_fdim_f64"}, |
| 548 | + {"fdimf", "__hipstdpar_fdim_f32"}, |
| 549 | + {"expm1", "__hipstdpar_expm1_f64"}, |
| 550 | + {"expm1f", "__hipstdpar_expm1_f32"}, |
| 551 | + {"hypot", "__hipstdpar_hypot_f64"}, |
| 552 | + {"hypotf", "__hipstdpar_hypot_f32"}, |
| 553 | + {"ilogb", "__hipstdpar_ilogb_f64"}, |
| 554 | + {"ilogbf", "__hipstdpar_ilogb_f32"}, |
| 555 | + {"lgamma", "__hipstdpar_lgamma_f64"}, |
| 556 | + {"lgammaf", "__hipstdpar_lgamma_f32"}, |
| 557 | + {"log1p", "__hipstdpar_log1p_f64"}, |
| 558 | + {"log1pf", "__hipstdpar_log1p_f32"}, |
| 559 | + {"logb", "__hipstdpar_logb_f64"}, |
| 560 | + {"logbf", "__hipstdpar_logb_f32"}, |
| 561 | + {"nextafter", "__hipstdpar_nextafter_f64"}, |
| 562 | + {"nextafterf", "__hipstdpar_nextafter_f32"}, |
| 563 | + {"nexttoward", "__hipstdpar_nexttoward_f64"}, |
| 564 | + {"nexttowardf", "__hipstdpar_nexttoward_f32"}, |
| 565 | + {"remainder", "__hipstdpar_remainder_f64"}, |
| 566 | + {"remainderf", "__hipstdpar_remainder_f32"}, |
| 567 | + {"remquo", "__hipstdpar_remquo_f64"}, |
| 568 | + {"remquof", "__hipstdpar_remquo_f32"}, |
| 569 | + {"scalbln", "__hipstdpar_scalbln_f64"}, |
| 570 | + {"scalblnf", "__hipstdpar_scalbln_f32"}, |
| 571 | + {"scalbn", "__hipstdpar_scalbn_f64"}, |
| 572 | + {"scalbnf", "__hipstdpar_scalbn_f32"}, |
| 573 | + {"tgamma", "__hipstdpar_tgamma_f64"}, |
| 574 | + {"tgammaf", "__hipstdpar_tgamma_f32"}}; |
| 575 | + |
| 576 | +PreservedAnalyses HipStdParMathFixupPass::run(Module &M, |
| 577 | + ModuleAnalysisManager &) { |
| 578 | + if (M.empty()) |
| 579 | + return PreservedAnalyses::all(); |
| 580 | + |
| 581 | + SmallVector<std::pair<Function *, std::string>> ToReplace; |
| 582 | + for (auto &&F : M) { |
| 583 | + if (!F.hasName()) |
| 584 | + continue; |
| 585 | + |
| 586 | + StringRef N = F.getName(); |
| 587 | + Intrinsic::ID ID = F.getIntrinsicID(); |
| 588 | + |
| 589 | + switch (ID) { |
| 590 | + case Intrinsic::not_intrinsic: { |
| 591 | + auto It = |
| 592 | + find_if(MathLibToHipStdPar, [&](auto &&M) { return M.first == N; }); |
| 593 | + if (It == std::cend(MathLibToHipStdPar)) |
| 594 | + continue; |
| 595 | + ToReplace.emplace_back(&F, It->second); |
| 596 | + break; |
| 597 | + } |
| 598 | + case Intrinsic::acos: |
| 599 | + case Intrinsic::asin: |
| 600 | + case Intrinsic::atan: |
| 601 | + case Intrinsic::atan2: |
| 602 | + case Intrinsic::cosh: |
| 603 | + case Intrinsic::modf: |
| 604 | + case Intrinsic::sinh: |
| 605 | + case Intrinsic::tan: |
| 606 | + case Intrinsic::tanh: |
| 607 | + break; |
| 608 | + default: { |
| 609 | + if (F.getReturnType()->isDoubleTy()) { |
| 610 | + switch (ID) { |
| 611 | + case Intrinsic::cos: |
| 612 | + case Intrinsic::exp: |
| 613 | + case Intrinsic::exp2: |
| 614 | + case Intrinsic::log: |
| 615 | + case Intrinsic::log10: |
| 616 | + case Intrinsic::log2: |
| 617 | + case Intrinsic::pow: |
| 618 | + case Intrinsic::sin: |
| 619 | + break; |
| 620 | + default: |
| 621 | + continue; |
| 622 | + } |
| 623 | + break; |
| 624 | + } |
| 625 | + continue; |
| 626 | + } |
| 627 | + } |
| 628 | + |
| 629 | + ToReplace.emplace_back(&F, N); |
| 630 | + llvm::replace(ToReplace.back().second, '.', '_'); |
| 631 | + StringRef Prefix = "llvm"; |
| 632 | + ToReplace.back().second.replace(0, Prefix.size(), "__hipstdpar"); |
| 633 | + } |
| 634 | + for (auto &&[F, NewF] : ToReplace) |
| 635 | + F->replaceAllUsesWith( |
| 636 | + M.getOrInsertFunction(NewF, F->getFunctionType()).getCallee()); |
| 637 | + |
| 638 | + return PreservedAnalyses::none(); |
| 639 | +} |
0 commit comments