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/STLExtras.h"
19 #include "llvm/ADT/Sequence.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/IR/Attributes.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/IR/GlobalVariable.h"
24 #include "llvm/IR/InstVisitor.h"
25 #include "llvm/IR/InstrTypes.h"
26 #include "llvm/IR/Intrinsics.h"
27 #include "llvm/IR/Module.h"
28 #include "llvm/Support/raw_ostream.h"
42 /// Given ChunksToKeep, produce a map of global variables/functions/calls
43 /// and indexes of attributes to be preserved for each of them.
44 class AttributeRemapper
: public InstVisitor
<AttributeRemapper
> {
49 AttributeRemapper(Oracle
&O
, LLVMContext
&C
) : O(O
), Context(C
) {}
51 void visitModule(Module
&M
) {
52 for (GlobalVariable
&GV
: M
.globals())
53 visitGlobalVariable(GV
);
56 void visitGlobalVariable(GlobalVariable
&GV
) {
57 // Global variables only have one attribute set.
58 AttributeSet AS
= GV
.getAttributes();
59 if (AS
.hasAttributes()) {
60 AttrBuilder
AttrsToPreserve(Context
);
61 visitAttributeSet(AS
, AttrsToPreserve
);
62 GV
.setAttributes(AttributeSet::get(Context
, AttrsToPreserve
));
66 void visitFunction(Function
&F
) {
67 // We can neither add nor remove attributes from intrinsics.
68 if (F
.getIntrinsicID() == Intrinsic::not_intrinsic
)
69 F
.setAttributes(visitAttributeList(F
.getAttributes()));
72 void visitCallBase(CallBase
&CB
) {
73 CB
.setAttributes(visitAttributeList(CB
.getAttributes()));
76 AttributeSet
visitAttributeIndex(AttributeList AL
, unsigned Index
) {
77 AttrBuilder
AttributesToPreserve(Context
);
78 visitAttributeSet(AL
.getAttributes(Index
), AttributesToPreserve
);
80 if (AttributesToPreserve
.attrs().empty())
82 return AttributeSet::get(Context
, AttributesToPreserve
);
85 AttributeList
visitAttributeList(AttributeList AL
) {
86 SmallVector
<std::pair
<unsigned, AttributeSet
>> NewAttrList
;
87 NewAttrList
.reserve(AL
.getNumAttrSets());
89 for (unsigned SetIdx
: AL
.indexes()) {
90 if (SetIdx
== AttributeList::FunctionIndex
)
93 AttributeSet AttrSet
= visitAttributeIndex(AL
, SetIdx
);
94 if (AttrSet
.hasAttributes())
95 NewAttrList
.emplace_back(SetIdx
, AttrSet
);
98 // FIXME: It's ridiculous that indexes() doesn't give us the correct order
99 // for contructing a new AttributeList. Special case the function index so
100 // we don't have to sort.
101 AttributeSet FnAttrSet
=
102 visitAttributeIndex(AL
, AttributeList::FunctionIndex
);
103 if (FnAttrSet
.hasAttributes())
104 NewAttrList
.emplace_back(AttributeList::FunctionIndex
, FnAttrSet
);
106 return AttributeList::get(Context
, NewAttrList
);
109 void visitAttributeSet(const AttributeSet
&AS
, AttrBuilder
&AttrsToPreserve
) {
110 // Optnone requires noinline, so removing noinline requires removing the
112 Attribute NoInline
= AS
.getAttribute(Attribute::NoInline
);
113 bool RemoveNoInline
= false;
114 if (NoInline
.isValid()) {
115 RemoveNoInline
= !O
.shouldKeep();
117 AttrsToPreserve
.addAttribute(NoInline
);
120 for (Attribute A
: AS
) {
121 if (A
.isEnumAttribute()) {
122 Attribute::AttrKind Kind
= A
.getKindAsEnum();
123 if (Kind
== Attribute::NoInline
)
126 if (RemoveNoInline
&& Kind
== Attribute::OptimizeNone
)
129 // TODO: Could only remove this if there are no constrained calls in the
131 if (Kind
== Attribute::StrictFP
) {
132 AttrsToPreserve
.addAttribute(A
);
138 AttrsToPreserve
.addAttribute(A
);
145 /// Removes out-of-chunk attributes from module.
146 static void extractAttributesFromModule(Oracle
&O
, ReducerWorkItem
&WorkItem
) {
147 AttributeRemapper
R(O
, WorkItem
.getContext());
148 R
.visit(WorkItem
.getModule());
151 void llvm::reduceAttributesDeltaPass(TestRunner
&Test
) {
152 runDeltaPass(Test
, extractAttributesFromModule
, "Reducing Attributes");