1 //===- ReduceAttributes.cpp - Specialized Delta Pass ----------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements a function which calls the Generic Delta pass in order
10 // to reduce uninteresting attributes.
12 //===----------------------------------------------------------------------===//
14 #include "ReduceAttributes.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/ADT/iterator_range.h"
23 #include "llvm/IR/Attributes.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/GlobalVariable.h"
26 #include "llvm/IR/InstVisitor.h"
27 #include "llvm/IR/InstrTypes.h"
28 #include "llvm/IR/Intrinsics.h"
29 #include "llvm/IR/Module.h"
30 #include "llvm/Support/raw_ostream.h"
45 /// Given ChunksToKeep, produce a map of global variables/functions/calls
46 /// and indexes of attributes to be preserved for each of them.
47 class AttributeRemapper
: public InstVisitor
<AttributeRemapper
> {
52 AttributeRemapper(Oracle
&O
, LLVMContext
&C
) : O(O
), Context(C
) {}
54 void visitModule(Module
&M
) {
55 for (GlobalVariable
&GV
: M
.globals())
56 visitGlobalVariable(GV
);
59 void visitGlobalVariable(GlobalVariable
&GV
) {
60 // Global variables only have one attribute set.
61 AttributeSet AS
= GV
.getAttributes();
62 if (AS
.hasAttributes()) {
63 AttrBuilder
AttrsToPreserve(Context
);
64 visitAttributeSet(AS
, AttrsToPreserve
);
65 GV
.setAttributes(AttributeSet::get(Context
, AttrsToPreserve
));
69 void visitFunction(Function
&F
) {
70 // We can neither add nor remove attributes from intrinsics.
71 if (F
.getIntrinsicID() == Intrinsic::not_intrinsic
)
72 F
.setAttributes(visitAttributeList(F
.getAttributes()));
75 void visitCallBase(CallBase
&CB
) {
76 CB
.setAttributes(visitAttributeList(CB
.getAttributes()));
79 AttributeSet
visitAttributeIndex(AttributeList AL
, unsigned Index
) {
80 AttrBuilder
AttributesToPreserve(Context
);
81 visitAttributeSet(AL
.getAttributes(Index
), AttributesToPreserve
);
83 if (AttributesToPreserve
.attrs().empty())
85 return AttributeSet::get(Context
, AttributesToPreserve
);
88 AttributeList
visitAttributeList(AttributeList AL
) {
89 SmallVector
<std::pair
<unsigned, AttributeSet
>> NewAttrList
;
90 NewAttrList
.reserve(AL
.getNumAttrSets());
92 for (unsigned SetIdx
: AL
.indexes()) {
93 if (SetIdx
== AttributeList::FunctionIndex
)
96 AttributeSet AttrSet
= visitAttributeIndex(AL
, SetIdx
);
97 if (AttrSet
.hasAttributes())
98 NewAttrList
.emplace_back(SetIdx
, AttrSet
);
101 // FIXME: It's ridiculous that indexes() doesn't give us the correct order
102 // for contructing a new AttributeList. Special case the function index so
103 // we don't have to sort.
104 AttributeSet FnAttrSet
=
105 visitAttributeIndex(AL
, AttributeList::FunctionIndex
);
106 if (FnAttrSet
.hasAttributes())
107 NewAttrList
.emplace_back(AttributeList::FunctionIndex
, FnAttrSet
);
109 return AttributeList::get(Context
, NewAttrList
);
112 void visitAttributeSet(const AttributeSet
&AS
, AttrBuilder
&AttrsToPreserve
) {
113 // Optnone requires noinline, so removing noinline requires removing the
115 Attribute NoInline
= AS
.getAttribute(Attribute::NoInline
);
116 bool RemoveNoInline
= false;
117 if (NoInline
.isValid()) {
118 RemoveNoInline
= !O
.shouldKeep();
120 AttrsToPreserve
.addAttribute(NoInline
);
123 for (Attribute A
: AS
) {
124 if (A
.isEnumAttribute()) {
125 Attribute::AttrKind Kind
= A
.getKindAsEnum();
126 if (Kind
== Attribute::NoInline
)
129 if (RemoveNoInline
&& Kind
== Attribute::OptimizeNone
)
132 // TODO: Could only remove this if there are no constrained calls in the
134 if (Kind
== Attribute::StrictFP
) {
135 AttrsToPreserve
.addAttribute(A
);
141 AttrsToPreserve
.addAttribute(A
);
148 /// Removes out-of-chunk attributes from module.
149 static void extractAttributesFromModule(Oracle
&O
, ReducerWorkItem
&WorkItem
) {
150 AttributeRemapper
R(O
, WorkItem
.getContext());
151 R
.visit(WorkItem
.getModule());
154 void llvm::reduceAttributesDeltaPass(TestRunner
&Test
) {
155 runDeltaPass(Test
, extractAttributesFromModule
, "Reducing Attributes");