LLVM 22.0.0git
NVPTXTagInvariantLoads.cpp
Go to the documentation of this file.
1//===------ NVPTXTagInvariantLoads.cpp - Tag invariant loads --------------===//
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 invaraint load tagging. It traverses load instructions
10// in a function, and determines if each load can be tagged as invariant.
11//
12// We currently infer invariance for loads from
13// - constant global variables, and
14// - kernel function pointer params that are noalias (i.e. __restrict) and
15// never written to.
16//
17// TODO: Perform a more powerful invariance analysis (ideally IPO).
18//
19//===----------------------------------------------------------------------===//
20
21#include "NVPTXUtilities.h"
25#include "llvm/IR/Metadata.h"
27
28using namespace llvm;
29
30static bool isInvariantLoad(const LoadInst *LI, const bool IsKernelFn) {
31 // Don't bother with non-global loads
33 return false;
34
35 // If the load is already marked as invariant, we don't need to do anything
36 if (LI->getMetadata(LLVMContext::MD_invariant_load))
37 return false;
38
39 // We use getUnderlyingObjects() here instead of getUnderlyingObject()
40 // mainly because the former looks through phi nodes while the latter does
41 // not. We need to look through phi nodes to handle pointer induction
42 // variables.
45
46 return all_of(Objs, [&](const Value *V) {
47 if (const auto *A = dyn_cast<const Argument>(V))
48 return IsKernelFn && ((A->onlyReadsMemory() && A->hasNoAliasAttr()) ||
50 if (const auto *GV = dyn_cast<const GlobalVariable>(V))
51 return GV->isConstant();
52 return false;
53 });
54}
55
57 LI->setMetadata(LLVMContext::MD_invariant_load,
58 MDNode::get(LI->getContext(), {}));
59}
60
62 const bool IsKernelFn = isKernelFunction(F);
63
64 bool Changed = false;
65 for (auto &I : instructions(F)) {
66 if (auto *LI = dyn_cast<LoadInst>(&I)) {
67 if (isInvariantLoad(LI, IsKernelFn)) {
69 Changed = true;
70 }
71 }
72 }
73 return Changed;
74}
75
76namespace {
77
78struct NVPTXTagInvariantLoadLegacyPass : public FunctionPass {
79 static char ID;
80
81 NVPTXTagInvariantLoadLegacyPass() : FunctionPass(ID) {}
82 bool runOnFunction(Function &F) override;
83};
84
85} // namespace
86
87INITIALIZE_PASS(NVPTXTagInvariantLoadLegacyPass, "nvptx-tag-invariant-loads",
88 "NVPTX Tag Invariant Loads", false, false)
89
90bool NVPTXTagInvariantLoadLegacyPass::runOnFunction(Function &F) {
91 return tagInvariantLoads(F);
92}
93
94char NVPTXTagInvariantLoadLegacyPass::ID = 0;
95
97 return new NVPTXTagInvariantLoadLegacyPass();
98}
99
104}
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static bool runOnFunction(Function &F, bool PostInlining)
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file contains the declarations for metadata subclasses.
NVPTX address space definition.
static void markLoadsAsInvariant(LoadInst *LI)
static bool tagInvariantLoads(Function &F)
static bool isInvariantLoad(const LoadInst *LI, const bool IsKernelFn)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:255
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:314
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
Definition: Instruction.h:428
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
Definition: Metadata.cpp:1718
An instruction for reading from memory.
Definition: Instructions.h:180
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Definition: Instructions.h:265
Value * getPointerOperand()
Definition: Instructions.h:259
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1565
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:118
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
LLVM Value Representation.
Definition: Value.h:75
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:1101
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1744
FunctionPass * createNVPTXTagInvariantLoadsPass()
bool isParamGridConstant(const Argument &Arg)
bool isKernelFunction(const Function &F)
LLVM_ABI void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=MaxLookupSearchDepth)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)