1 //===-- BPFASpaceCastSimplifyPass.cpp - BPF addrspacecast simplications --===//
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 //===----------------------------------------------------------------------===//
12 #define DEBUG_TYPE "bpf-aspace-simplify"
19 AddrSpaceCastInst
*OuterCast
;
21 // Match chain of instructions:
22 // %inner = addrspacecast N->M
23 // %gep = getelementptr %inner, ...
24 // %outer = addrspacecast M->N %gep
26 static std::optional
<CastGEPCast
> match(Value
*I
) {
27 auto *OuterCast
= dyn_cast
<AddrSpaceCastInst
>(I
);
30 auto *GEP
= dyn_cast
<GetElementPtrInst
>(OuterCast
->getPointerOperand());
33 auto *InnerCast
= dyn_cast
<AddrSpaceCastInst
>(GEP
->getPointerOperand());
36 if (InnerCast
->getSrcAddressSpace() != OuterCast
->getDestAddressSpace())
38 if (InnerCast
->getDestAddressSpace() != OuterCast
->getSrcAddressSpace())
40 return CastGEPCast
{OuterCast
};
43 static PointerType
*changeAddressSpace(PointerType
*Ty
, unsigned AS
) {
44 return Ty
->get(Ty
->getContext(), AS
);
47 // Assuming match(this->OuterCast) is true, convert:
48 // (addrspacecast M->N (getelementptr (addrspacecast N->M ptr) ...))
50 // (getelementptr ptr ...)
51 GetElementPtrInst
*rewrite() {
52 auto *GEP
= cast
<GetElementPtrInst
>(OuterCast
->getPointerOperand());
53 auto *InnerCast
= cast
<AddrSpaceCastInst
>(GEP
->getPointerOperand());
54 unsigned AS
= OuterCast
->getDestAddressSpace();
55 auto *NewGEP
= cast
<GetElementPtrInst
>(GEP
->clone());
56 NewGEP
->setName(GEP
->getName());
57 NewGEP
->insertAfter(OuterCast
);
58 NewGEP
->setOperand(0, InnerCast
->getPointerOperand());
59 auto *GEPTy
= cast
<PointerType
>(GEP
->getType());
60 NewGEP
->mutateType(changeAddressSpace(GEPTy
, AS
));
61 OuterCast
->replaceAllUsesWith(NewGEP
);
62 OuterCast
->eraseFromParent();
64 GEP
->eraseFromParent();
65 if (InnerCast
->use_empty())
66 InnerCast
->eraseFromParent();
71 } // anonymous namespace
73 PreservedAnalyses
BPFASpaceCastSimplifyPass::run(Function
&F
,
74 FunctionAnalysisManager
&AM
) {
75 SmallVector
<CastGEPCast
, 16> WorkList
;
77 for (BasicBlock
&BB
: F
) {
78 for (Instruction
&I
: BB
)
79 if (auto It
= CastGEPCast::match(&I
))
80 WorkList
.push_back(It
.value());
81 Changed
|= !WorkList
.empty();
83 while (!WorkList
.empty()) {
84 CastGEPCast InsnChain
= WorkList
.pop_back_val();
85 GetElementPtrInst
*NewGEP
= InsnChain
.rewrite();
86 for (User
*U
: NewGEP
->users())
87 if (auto It
= CastGEPCast::match(U
))
88 WorkList
.push_back(It
.value());
91 return Changed
? PreservedAnalyses::none() : PreservedAnalyses::all();