LLVM 24.0.0git
NVPTXLowerAggrCopies.cpp
Go to the documentation of this file.
1//===- NVPTXLowerAggrCopies.cpp - ------------------------------*- C++ -*--===//
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// \file
10// Lower aggregate copies, memset, memcpy, memmov intrinsics into loops when
11// the size is large or is not a compile-time constant.
12//
13//===----------------------------------------------------------------------===//
14
15#include "NVPTX.h"
19#include "llvm/IR/Constants.h"
20#include "llvm/IR/DataLayout.h"
21#include "llvm/IR/Function.h"
22#include "llvm/IR/IRBuilder.h"
25#include "llvm/IR/Intrinsics.h"
26#include "llvm/IR/LLVMContext.h"
27#include "llvm/IR/Module.h"
31
32#define DEBUG_TYPE "nvptx"
33
34using namespace llvm;
35
36static const unsigned MaxAggrCopySize = 128;
37
39 AAResults &AA) {
42
43 const DataLayout &DL = F.getDataLayout();
44 LLVMContext &Context = F.getParent()->getContext();
45
46 // Collect all aggregate loads and mem* calls.
47 for (BasicBlock &BB : F) {
48 for (Instruction &I : BB) {
49 if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
50 if (!LI->hasOneUse())
51 continue;
52
53 if (DL.getTypeStoreSize(LI->getType()) < MaxAggrCopySize)
54 continue;
55
56 if (StoreInst *SI = dyn_cast<StoreInst>(LI->user_back())) {
57 if (SI->getOperand(0) != LI)
58 continue;
59 AggrLoads.push_back(LI);
60 }
61 } else if (MemIntrinsic *IntrCall = dyn_cast<MemIntrinsic>(&I)) {
62 // Convert intrinsic calls with variable size or with constant size
63 // larger than the MaxAggrCopySize threshold.
64 if (ConstantInt *LenCI = dyn_cast<ConstantInt>(IntrCall->getLength())) {
65 if (LenCI->getZExtValue() >= MaxAggrCopySize) {
66 MemCalls.push_back(IntrCall);
67 }
68 } else {
69 MemCalls.push_back(IntrCall);
70 }
71 }
72 }
73 }
74
75 if (AggrLoads.size() == 0 && MemCalls.size() == 0) {
76 return false;
77 }
78
79 //
80 // Do the transformation of an aggr load/copy/set to a loop
81 //
82 for (LoadInst *LI : AggrLoads) {
83 auto *SI = cast<StoreInst>(*LI->user_begin());
84 Value *SrcAddr = LI->getOperand(0);
85 Value *DstAddr = SI->getOperand(1);
86 unsigned NumLoads = DL.getTypeStoreSize(LI->getType());
87 ConstantInt *CopyLen =
88 ConstantInt::get(Type::getInt32Ty(Context), NumLoads);
89
91 if (AA.isNoAlias(MemoryLocation(SrcAddr, Size),
92 MemoryLocation(DstAddr, Size))) {
93 // No overlap: emit a plain memcpy loop. Expand the loop here (rather
94 // than emitting a memcpy intrinsic and letting the code below expand it)
95 // so we can pass CanOverlap = false; expandMemCpyAsLoop would
96 // conservatively assume overlap.
97 createMemCpyLoopKnownSize(/* ConvertedInst */ SI,
98 /* SrcAddr */ SrcAddr, /* DstAddr */ DstAddr,
99 /* CopyLen */ CopyLen,
100 /* SrcAlign */ LI->getAlign(),
101 /* DestAlign */ SI->getAlign(),
102 /* SrcIsVolatile */ LI->isVolatile(),
103 /* DstIsVolatile */ SI->isVolatile(),
104 /* CanOverlap */ false, TTI);
105 } else {
106 // May alias: lower as a memmove, which picks the copy direction at
107 // runtime. Emit the intrinsic here and let the loop below expand it.
108 //
109 // The pointers may alias even if they're in different address spaces
110 // (e.g. the generic addrspace may alias global). If they're in
111 // different addrspaces, cast to the generic space first, because
112 // expandMemMoveAsLoop needs to compare the pointer values to determine
113 // the copy direction.
114 IRBuilder<> Builder(SI);
115 unsigned SrcAS = LI->getPointerAddressSpace();
116 unsigned DstAS = SI->getPointerAddressSpace();
117 if (SrcAS != DstAS) {
118 PointerType *GenericPtrTy =
120 SrcAddr = Builder.CreateAddrSpaceCast(SrcAddr, GenericPtrTy);
121 DstAddr = Builder.CreateAddrSpaceCast(DstAddr, GenericPtrTy);
122 }
123 MemCalls.push_back(cast<MemMoveInst>(Builder.CreateMemMove(
124 DstAddr, SI->getAlign(), SrcAddr, LI->getAlign(), CopyLen,
125 LI->isVolatile() || SI->isVolatile())));
126 }
127
128 SI->eraseFromParent();
129 LI->eraseFromParent();
130 }
131
132 // Transform mem* intrinsic calls.
133 for (MemIntrinsic *MemCall : MemCalls) {
134 bool Expanded = true;
135 if (MemCpyInst *Memcpy = dyn_cast<MemCpyInst>(MemCall)) {
136 expandMemCpyAsLoop(Memcpy, TTI);
137 } else if (MemMoveInst *Memmove = dyn_cast<MemMoveInst>(MemCall)) {
138 Expanded = expandMemMoveAsLoop(Memmove, TTI);
139 } else if (MemSetInst *Memset = dyn_cast<MemSetInst>(MemCall)) {
140 expandMemSetAsLoop(Memset, TTI);
141 }
142 if (Expanded)
143 MemCall->eraseFromParent();
144 }
145
146 return true;
147}
148
149namespace {
150
151struct NVPTXLowerAggrCopiesLegacyPass : public FunctionPass {
152 static char ID;
153
154 NVPTXLowerAggrCopiesLegacyPass() : FunctionPass(ID) {}
155
156 void getAnalysisUsage(AnalysisUsage &AU) const override {
157 AU.addPreserved<StackProtector>();
158 AU.addRequired<TargetTransformInfoWrapperPass>();
159 AU.addRequired<AAResultsWrapperPass>();
160 }
161
162 bool runOnFunction(Function &F) override {
163 return lowerAggrCopies(
164 F, getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F),
165 getAnalysis<AAResultsWrapperPass>().getAAResults());
166 }
167
168 StringRef getPassName() const override {
169 return "Lower aggregate copies/intrinsics into loops";
170 }
171};
172
173char NVPTXLowerAggrCopiesLegacyPass::ID = 0;
174
175} // namespace
176
178 NVPTXLowerAggrCopiesLegacyPass, "nvptx-lower-aggr-copies",
179 "Lower aggregate copies, and llvm.mem* intrinsics into loops", false, false)
183 NVPTXLowerAggrCopiesLegacyPass, "nvptx-lower-aggr-copies",
184 "Lower aggregate copies, and llvm.mem* intrinsics into loops", false, false)
185
187 return new NVPTXLowerAggrCopiesLegacyPass();
188}
189
192 if (!lowerAggrCopies(F, FAM.getResult<TargetIRAnalysis>(F),
193 FAM.getResult<AAManager>(F)))
194 return PreservedAnalyses::all();
195 // Copies are expanded into loops, so the CFG is not preserved.
198 return PA;
199}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static bool lowerAggrCopies(Function &F, const TargetTransformInfo &TTI, AAResults &AA)
static const unsigned MaxAggrCopySize
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This pass exposes codegen information to IR-level passes.
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
This is the shared class of boolean and integer constants.
Definition Constants.h:87
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
An instruction for reading from memory.
static LocationSize precise(uint64_t Value)
This class wraps the llvm.memcpy intrinsic.
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memmove intrinsic.
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
Representation for a specific memory location.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
Definition Type.cpp:911
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Definition Analysis.h:132
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Analysis pass providing the TargetTransformInfo.
Wrapper pass for TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
LLVM Value Representation.
Definition Value.h:75
Abstract Attribute helper functions.
Definition Attributor.h:165
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void createMemCpyLoopKnownSize(Instruction *InsertBefore, Value *SrcAddr, Value *DstAddr, ConstantInt *CopyLen, Align SrcAlign, Align DestAlign, bool SrcIsVolatile, bool DstIsVolatile, bool CanOverlap, const TargetTransformInfo &TTI, std::optional< uint32_t > AtomicCpySize=std::nullopt, std::optional< uint64_t > AverageTripCount=std::nullopt)
Emit a loop implementing the semantics of an llvm.memcpy whose size is a compile time constant.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI bool expandMemMoveAsLoop(MemMoveInst *MemMove, const TargetTransformInfo &TTI)
Expand MemMove as a loop.
FunctionPass * createNVPTXLowerAggrCopiesLegacyPass()
TargetTransformInfo TTI
LLVM_ABI void expandMemSetAsLoop(MemSetInst *MemSet, const TargetTransformInfo *TTI=nullptr)
Expand MemSet as a loop.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI void expandMemCpyAsLoop(MemCpyInst *MemCpy, const TargetTransformInfo &TTI, ScalarEvolution *SE=nullptr)
Expand MemCpy as a loop. MemCpy is not deleted.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.