ReduceOperandBundles.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. //===- ReduceOperandBundes.cpp - Specialized Delta Pass -------------------===//
  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 file implements a function which calls the Generic Delta pass in order
  10. // to reduce uninteresting operand bundes from calls.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "ReduceOperandBundles.h"
  14. #include "Delta.h"
  15. #include "TestRunner.h"
  16. #include "llvm/ADT/ArrayRef.h"
  17. #include "llvm/ADT/DenseMap.h"
  18. #include "llvm/ADT/STLExtras.h"
  19. #include "llvm/ADT/Sequence.h"
  20. #include "llvm/ADT/iterator_range.h"
  21. #include "llvm/IR/InstVisitor.h"
  22. #include "llvm/IR/InstrTypes.h"
  23. #include "llvm/Support/raw_ostream.h"
  24. #include <algorithm>
  25. #include <iterator>
  26. #include <vector>
  27. namespace llvm {
  28. class Module;
  29. } // namespace llvm
  30. using namespace llvm;
  31. namespace {
  32. /// Given ChunksToKeep, produce a map of calls and indexes of operand bundles
  33. /// to be preserved for each call.
  34. class OperandBundleRemapper : public InstVisitor<OperandBundleRemapper> {
  35. Oracle &O;
  36. public:
  37. DenseMap<CallBase *, std::vector<unsigned>> CallsToRefine;
  38. explicit OperandBundleRemapper(Oracle &O) : O(O) {}
  39. /// So far only CallBase sub-classes can have operand bundles.
  40. /// Let's see which of the operand bundles of this call are to be kept.
  41. void visitCallBase(CallBase &Call) {
  42. if (!Call.hasOperandBundles())
  43. return; // No bundles to begin with.
  44. // Insert this call into map, we will likely want to rebuild it.
  45. auto &OperandBundlesToKeepIndexes = CallsToRefine[&Call];
  46. OperandBundlesToKeepIndexes.reserve(Call.getNumOperandBundles());
  47. // Enumerate every operand bundle on this call.
  48. for (unsigned BundleIndex : seq(0U, Call.getNumOperandBundles()))
  49. if (O.shouldKeep()) // Should we keep this one?
  50. OperandBundlesToKeepIndexes.emplace_back(BundleIndex);
  51. }
  52. };
  53. struct OperandBundleCounter : public InstVisitor<OperandBundleCounter> {
  54. /// How many features (in this case, operand bundles) did we count, total?
  55. int OperandBundeCount = 0;
  56. /// So far only CallBase sub-classes can have operand bundles.
  57. void visitCallBase(CallBase &Call) {
  58. // Just accumulate the total number of operand bundles.
  59. OperandBundeCount += Call.getNumOperandBundles();
  60. }
  61. };
  62. } // namespace
  63. static void maybeRewriteCallWithDifferentBundles(
  64. CallBase *OrigCall, ArrayRef<unsigned> OperandBundlesToKeepIndexes) {
  65. if (OperandBundlesToKeepIndexes.size() == OrigCall->getNumOperandBundles())
  66. return; // Not modifying operand bundles of this call after all.
  67. std::vector<OperandBundleDef> NewBundles;
  68. NewBundles.reserve(OperandBundlesToKeepIndexes.size());
  69. // Actually copy over the bundles that we want to keep.
  70. transform(OperandBundlesToKeepIndexes, std::back_inserter(NewBundles),
  71. [OrigCall](unsigned Index) {
  72. return OperandBundleDef(OrigCall->getOperandBundleAt(Index));
  73. });
  74. // Finally actually replace the bundles on the call.
  75. CallBase *NewCall = CallBase::Create(OrigCall, NewBundles, OrigCall);
  76. OrigCall->replaceAllUsesWith(NewCall);
  77. OrigCall->eraseFromParent();
  78. }
  79. /// Removes out-of-chunk operand bundles from calls.
  80. static void extractOperandBundesFromModule(Oracle &O, Module &Program) {
  81. OperandBundleRemapper R(O);
  82. R.visit(Program);
  83. for (const auto &I : R.CallsToRefine)
  84. maybeRewriteCallWithDifferentBundles(I.first, I.second);
  85. }
  86. void llvm::reduceOperandBundesDeltaPass(TestRunner &Test) {
  87. outs() << "*** Reducing OperandBundes...\n";
  88. runDeltaPass(Test, extractOperandBundesFromModule);
  89. }