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/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"
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
> {
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())
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
)
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
114 Attribute NoInline
= AS
.getAttribute(Attribute::NoInline
);
115 bool RemoveNoInline
= false;
116 if (NoInline
.isValid()) {
117 RemoveNoInline
= !O
.shouldKeep();
119 AttrsToPreserve
.addAttribute(NoInline
);
122 for (Attribute A
: AS
) {
123 if (A
.isEnumAttribute()) {
124 Attribute::AttrKind Kind
= A
.getKindAsEnum();
125 if (Kind
== Attribute::NoInline
)
128 if (RemoveNoInline
&& Kind
== Attribute::OptimizeNone
)
131 // TODO: Could only remove this if there are no constrained calls in the
133 if (Kind
== Attribute::StrictFP
) {
134 AttrsToPreserve
.addAttribute(A
);
140 AttrsToPreserve
.addAttribute(A
);
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");