ReduceAttributes.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. //===- ReduceAttributes.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 attributes.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "ReduceAttributes.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/SmallVector.h"
  21. #include "llvm/ADT/iterator_range.h"
  22. #include "llvm/IR/Attributes.h"
  23. #include "llvm/IR/Function.h"
  24. #include "llvm/IR/GlobalVariable.h"
  25. #include "llvm/IR/InstVisitor.h"
  26. #include "llvm/IR/InstrTypes.h"
  27. #include "llvm/IR/Intrinsics.h"
  28. #include "llvm/IR/Module.h"
  29. #include "llvm/Support/raw_ostream.h"
  30. #include <algorithm>
  31. #include <cassert>
  32. #include <iterator>
  33. #include <utility>
  34. #include <vector>
  35. namespace llvm {
  36. class LLVMContext;
  37. } // namespace llvm
  38. using namespace llvm;
  39. namespace {
  40. using AttrPtrVecTy = std::vector<const Attribute *>;
  41. using AttrPtrIdxVecVecTy = std::pair<unsigned, AttrPtrVecTy>;
  42. using AttrPtrVecVecTy = SmallVector<AttrPtrIdxVecVecTy, 3>;
  43. /// Given ChunksToKeep, produce a map of global variables/functions/calls
  44. /// and indexes of attributes to be preserved for each of them.
  45. class AttributeRemapper : public InstVisitor<AttributeRemapper> {
  46. Oracle &O;
  47. public:
  48. DenseMap<GlobalVariable *, AttrPtrVecTy> GlobalVariablesToRefine;
  49. DenseMap<Function *, AttrPtrVecVecTy> FunctionsToRefine;
  50. DenseMap<CallBase *, AttrPtrVecVecTy> CallsToRefine;
  51. explicit AttributeRemapper(Oracle &O) : O(O) {}
  52. void visitModule(Module &M) {
  53. for (GlobalVariable &GV : M.getGlobalList())
  54. visitGlobalVariable(GV);
  55. }
  56. void visitGlobalVariable(GlobalVariable &GV) {
  57. // Global variables only have one attribute set.
  58. const AttributeSet &AS = GV.getAttributes();
  59. if (AS.hasAttributes())
  60. visitAttributeSet(AS, GlobalVariablesToRefine[&GV]);
  61. }
  62. void visitFunction(Function &F) {
  63. if (F.getIntrinsicID() != Intrinsic::not_intrinsic)
  64. return; // We can neither add nor remove attributes from intrinsics.
  65. visitAttributeList(F.getAttributes(), FunctionsToRefine[&F]);
  66. }
  67. void visitCallBase(CallBase &I) {
  68. visitAttributeList(I.getAttributes(), CallsToRefine[&I]);
  69. }
  70. void visitAttributeList(const AttributeList &AL,
  71. AttrPtrVecVecTy &AttributeSetsToPreserve) {
  72. assert(AttributeSetsToPreserve.empty() && "Should not be sharing vectors.");
  73. AttributeSetsToPreserve.reserve(AL.getNumAttrSets());
  74. for (unsigned SetIdx : AL.indexes()) {
  75. AttrPtrIdxVecVecTy AttributesToPreserve;
  76. AttributesToPreserve.first = SetIdx;
  77. visitAttributeSet(AL.getAttributes(AttributesToPreserve.first),
  78. AttributesToPreserve.second);
  79. if (!AttributesToPreserve.second.empty())
  80. AttributeSetsToPreserve.emplace_back(std::move(AttributesToPreserve));
  81. }
  82. }
  83. void visitAttributeSet(const AttributeSet &AS,
  84. AttrPtrVecTy &AttrsToPreserve) {
  85. assert(AttrsToPreserve.empty() && "Should not be sharing vectors.");
  86. AttrsToPreserve.reserve(AS.getNumAttributes());
  87. for (const Attribute &A : AS)
  88. if (O.shouldKeep())
  89. AttrsToPreserve.emplace_back(&A);
  90. }
  91. };
  92. struct AttributeCounter : public InstVisitor<AttributeCounter> {
  93. /// How many features (in this case, attributes) did we count, total?
  94. int AttributeCount = 0;
  95. void visitModule(Module &M) {
  96. for (GlobalVariable &GV : M.getGlobalList())
  97. visitGlobalVariable(GV);
  98. }
  99. void visitGlobalVariable(GlobalVariable &GV) {
  100. // Global variables only have one attribute set.
  101. visitAttributeSet(GV.getAttributes());
  102. }
  103. void visitFunction(Function &F) {
  104. if (F.getIntrinsicID() != Intrinsic::not_intrinsic)
  105. return; // We can neither add nor remove attributes from intrinsics.
  106. visitAttributeList(F.getAttributes());
  107. }
  108. void visitCallBase(CallBase &I) { visitAttributeList(I.getAttributes()); }
  109. void visitAttributeList(const AttributeList &AL) {
  110. for (const AttributeSet &AS : AL)
  111. visitAttributeSet(AS);
  112. }
  113. void visitAttributeSet(const AttributeSet &AS) {
  114. AttributeCount += AS.getNumAttributes();
  115. }
  116. };
  117. } // namespace
  118. AttributeSet
  119. convertAttributeRefToAttributeSet(LLVMContext &C,
  120. ArrayRef<const Attribute *> Attributes) {
  121. AttrBuilder B(C);
  122. for (const Attribute *A : Attributes)
  123. B.addAttribute(*A);
  124. return AttributeSet::get(C, B);
  125. }
  126. AttributeList convertAttributeRefVecToAttributeList(
  127. LLVMContext &C, ArrayRef<AttrPtrIdxVecVecTy> AttributeSets) {
  128. std::vector<std::pair<unsigned, AttributeSet>> SetVec;
  129. SetVec.reserve(AttributeSets.size());
  130. transform(AttributeSets, std::back_inserter(SetVec),
  131. [&C](const AttrPtrIdxVecVecTy &V) {
  132. return std::make_pair(
  133. V.first, convertAttributeRefToAttributeSet(C, V.second));
  134. });
  135. sort(SetVec, [](const std::pair<unsigned, AttributeSet> &LHS,
  136. const std::pair<unsigned, AttributeSet> &RHS) {
  137. return LHS.first < RHS.first; // All values are unique.
  138. });
  139. return AttributeList::get(C, SetVec);
  140. }
  141. /// Removes out-of-chunk attributes from module.
  142. static void extractAttributesFromModule(Oracle &O, Module &Program) {
  143. AttributeRemapper R(O);
  144. R.visit(Program);
  145. LLVMContext &C = Program.getContext();
  146. for (const auto &I : R.GlobalVariablesToRefine)
  147. I.first->setAttributes(convertAttributeRefToAttributeSet(C, I.second));
  148. for (const auto &I : R.FunctionsToRefine)
  149. I.first->setAttributes(convertAttributeRefVecToAttributeList(C, I.second));
  150. for (const auto &I : R.CallsToRefine)
  151. I.first->setAttributes(convertAttributeRefVecToAttributeList(C, I.second));
  152. }
  153. void llvm::reduceAttributesDeltaPass(TestRunner &Test) {
  154. outs() << "*** Reducing Attributes...\n";
  155. runDeltaPass(Test, extractAttributesFromModule);
  156. }