[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / tools / llvm-reduce / deltas / ReduceAttributes.cpp
blob538fd6a8454c378630a6f7c6faea715ce80e85fe
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.
12 //===----------------------------------------------------------------------===//
14 #include "ReduceAttributes.h"
15 #include "Delta.h"
16 #include "TestRunner.h"
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/Sequence.h"
21 #include "llvm/ADT/SmallVector.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>
36 namespace llvm {
37 class LLVMContext;
38 } // namespace llvm
40 using namespace llvm;
42 namespace {
44 /// Given ChunksToKeep, produce a map of global variables/functions/calls
45 /// and indexes of attributes to be preserved for each of them.
46 class AttributeRemapper : public InstVisitor<AttributeRemapper> {
47 Oracle &O;
48 LLVMContext &Context;
50 public:
51 AttributeRemapper(Oracle &O, LLVMContext &C) : O(O), Context(C) {}
53 void visitModule(Module &M) {
54 for (GlobalVariable &GV : M.globals())
55 visitGlobalVariable(GV);
58 void visitGlobalVariable(GlobalVariable &GV) {
59 // Global variables only have one attribute set.
60 AttributeSet AS = GV.getAttributes();
61 if (AS.hasAttributes()) {
62 AttrBuilder AttrsToPreserve(Context);
63 visitAttributeSet(AS, AttrsToPreserve);
64 GV.setAttributes(AttributeSet::get(Context, AttrsToPreserve));
68 void visitFunction(Function &F) {
69 // We can neither add nor remove attributes from intrinsics.
70 if (F.getIntrinsicID() == Intrinsic::not_intrinsic)
71 F.setAttributes(visitAttributeList(F.getAttributes()));
74 void visitCallBase(CallBase &CB) {
75 CB.setAttributes(visitAttributeList(CB.getAttributes()));
78 AttributeSet visitAttributeIndex(AttributeList AL, unsigned Index) {
79 AttrBuilder AttributesToPreserve(Context);
80 visitAttributeSet(AL.getAttributes(Index), AttributesToPreserve);
82 if (AttributesToPreserve.attrs().empty())
83 return {};
84 return AttributeSet::get(Context, AttributesToPreserve);
87 AttributeList visitAttributeList(AttributeList AL) {
88 SmallVector<std::pair<unsigned, AttributeSet>> NewAttrList;
89 NewAttrList.reserve(AL.getNumAttrSets());
91 for (unsigned SetIdx : AL.indexes()) {
92 if (SetIdx == AttributeList::FunctionIndex)
93 continue;
95 AttributeSet AttrSet = visitAttributeIndex(AL, SetIdx);
96 if (AttrSet.hasAttributes())
97 NewAttrList.emplace_back(SetIdx, AttrSet);
100 // FIXME: It's ridiculous that indexes() doesn't give us the correct order
101 // for contructing a new AttributeList. Special case the function index so
102 // we don't have to sort.
103 AttributeSet FnAttrSet =
104 visitAttributeIndex(AL, AttributeList::FunctionIndex);
105 if (FnAttrSet.hasAttributes())
106 NewAttrList.emplace_back(AttributeList::FunctionIndex, FnAttrSet);
108 return AttributeList::get(Context, NewAttrList);
111 void visitAttributeSet(const AttributeSet &AS, AttrBuilder &AttrsToPreserve) {
112 // Optnone requires noinline, so removing noinline requires removing the
113 // pair.
114 Attribute NoInline = AS.getAttribute(Attribute::NoInline);
115 bool RemoveNoInline = false;
116 if (NoInline.isValid()) {
117 RemoveNoInline = !O.shouldKeep();
118 if (!RemoveNoInline)
119 AttrsToPreserve.addAttribute(NoInline);
122 for (Attribute A : AS) {
123 if (A.isEnumAttribute()) {
124 Attribute::AttrKind Kind = A.getKindAsEnum();
125 if (Kind == Attribute::NoInline)
126 continue;
128 if (RemoveNoInline && Kind == Attribute::OptimizeNone)
129 continue;
131 // TODO: Could only remove this if there are no constrained calls in the
132 // function.
133 if (Kind == Attribute::StrictFP) {
134 AttrsToPreserve.addAttribute(A);
135 continue;
139 if (O.shouldKeep())
140 AttrsToPreserve.addAttribute(A);
145 } // namespace
147 /// Removes out-of-chunk attributes from module.
148 static void extractAttributesFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
149 AttributeRemapper R(O, WorkItem.getContext());
150 R.visit(WorkItem.getModule());
153 void llvm::reduceAttributesDeltaPass(TestRunner &Test) {
154 runDeltaPass(Test, extractAttributesFromModule, "Reducing Attributes");