brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · b1125de Raw
156 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements a function which calls the Generic Delta pass in order10// to reduce uninteresting attributes.11//12//===----------------------------------------------------------------------===//13 14#include "ReduceAttributes.h"15#include "llvm/ADT/ArrayRef.h"16#include "llvm/ADT/SmallVector.h"17#include "llvm/IR/Attributes.h"18#include "llvm/IR/Function.h"19#include "llvm/IR/InstVisitor.h"20 21using namespace llvm;22 23namespace {24 25/// Given ChunksToKeep, produce a map of global variables/functions/calls26/// and indexes of attributes to be preserved for each of them.27class AttributeRemapper : public InstVisitor<AttributeRemapper> {28  Oracle &O;29  LLVMContext &Context;30  bool HasControlledConvergence = true;31 32public:33  AttributeRemapper(Oracle &O, Module &M) : O(O), Context(M.getContext()) {34 35    // Check if there are any convergence intrinsics used. We cannot remove the36    // convergent attribute if a function uses convergencectrl bundles. As a37    // simple filter, check if any of the intrinsics are used in the module.38    //39    // TODO: This could be done per-function. We should be eliminating40    // convergent if there are no convergent token uses in a function.41    HasControlledConvergence = any_of(42        ArrayRef<Intrinsic::ID>{Intrinsic::experimental_convergence_anchor,43                                Intrinsic::experimental_convergence_entry,44                                Intrinsic::experimental_convergence_loop},45        [&M](Intrinsic::ID ID) {46          return Intrinsic::getDeclarationIfExists(&M, ID);47        });48  }49 50  void visitModule(Module &M) {51    for (GlobalVariable &GV : M.globals())52      visitGlobalVariable(GV);53  }54 55  void visitGlobalVariable(GlobalVariable &GV) {56    // Global variables only have one attribute set.57    AttributeSet AS = GV.getAttributes();58    if (AS.hasAttributes()) {59      AttrBuilder AttrsToPreserve(Context);60      visitAttributeSet(AS, AttrsToPreserve);61      GV.setAttributes(AttributeSet::get(Context, AttrsToPreserve));62    }63  }64 65  void visitFunction(Function &F) {66    // We can neither add nor remove attributes from intrinsics.67    if (F.getIntrinsicID() == Intrinsic::not_intrinsic)68      F.setAttributes(visitAttributeList(F.getAttributes()));69  }70 71  void visitCallBase(CallBase &CB) {72    CB.setAttributes(visitAttributeList(CB.getAttributes()));73  }74 75  AttributeSet visitAttributeIndex(AttributeList AL, unsigned Index) {76    AttrBuilder AttributesToPreserve(Context);77    visitAttributeSet(AL.getAttributes(Index), AttributesToPreserve);78 79    if (AttributesToPreserve.attrs().empty())80      return {};81    return AttributeSet::get(Context, AttributesToPreserve);82  }83 84  AttributeList visitAttributeList(AttributeList AL) {85    SmallVector<std::pair<unsigned, AttributeSet>> NewAttrList;86    NewAttrList.reserve(AL.getNumAttrSets());87 88    for (unsigned SetIdx : AL.indexes()) {89      if (SetIdx == AttributeList::FunctionIndex)90        continue;91 92      AttributeSet AttrSet = visitAttributeIndex(AL, SetIdx);93      if (AttrSet.hasAttributes())94        NewAttrList.emplace_back(SetIdx, AttrSet);95    }96 97    // FIXME: It's ridiculous that indexes() doesn't give us the correct order98    // for contructing a new AttributeList. Special case the function index so99    // we don't have to sort.100    AttributeSet FnAttrSet =101        visitAttributeIndex(AL, AttributeList::FunctionIndex);102    if (FnAttrSet.hasAttributes())103      NewAttrList.emplace_back(AttributeList::FunctionIndex, FnAttrSet);104 105    return AttributeList::get(Context, NewAttrList);106  }107 108  void visitAttributeSet(const AttributeSet &AS, AttrBuilder &AttrsToPreserve) {109    // Optnone requires noinline, so removing noinline requires removing the110    // pair.111    Attribute NoInline = AS.getAttribute(Attribute::NoInline);112    bool RemoveNoInline = false;113    if (NoInline.isValid()) {114      RemoveNoInline = !O.shouldKeep();115      if (!RemoveNoInline)116        AttrsToPreserve.addAttribute(NoInline);117    }118 119    for (Attribute A : AS) {120      if (A.isEnumAttribute()) {121        Attribute::AttrKind Kind = A.getKindAsEnum();122        if (Kind == Attribute::NoInline)123          continue;124 125        if (RemoveNoInline && Kind == Attribute::OptimizeNone)126          continue;127 128        // TODO: Could only remove this if there are no constrained calls in the129        // function.130        if (Kind == Attribute::StrictFP) {131          AttrsToPreserve.addAttribute(A);132          continue;133        }134 135        // TODO: Could only remove this if there are no convergence tokens in136        // the function.137        if (Kind == Attribute::Convergent && HasControlledConvergence) {138          AttrsToPreserve.addAttribute(A);139          continue;140        }141      }142 143      if (O.shouldKeep())144        AttrsToPreserve.addAttribute(A);145    }146  }147};148 149} // namespace150 151/// Removes out-of-chunk attributes from module.152void llvm::reduceAttributesDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) {153  AttributeRemapper R(O, WorkItem.getModule());154  R.visit(WorkItem.getModule());155}156