xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Utils/StripGCRelocates.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- StripGCRelocates.cpp - Remove gc.relocates inserted by RewriteStatePoints===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This is a little utility pass that removes the gc.relocates inserted by
100b57cec5SDimitry Andric // RewriteStatepointsForGC. Note that the generated IR is incorrect,
110b57cec5SDimitry Andric // but this is useful as a single pass in itself, for analysis of IR, without
1281ad6265SDimitry Andric // the GC.relocates. The statepoint and gc.result intrinsics would still be
130b57cec5SDimitry Andric // present.
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric 
16e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/StripGCRelocates.h"
170b57cec5SDimitry Andric #include "llvm/IR/Function.h"
180b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h"
190b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
200b57cec5SDimitry Andric #include "llvm/IR/Statepoint.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric 
stripGCRelocates(Function & F)24e8d8bef9SDimitry Andric static bool stripGCRelocates(Function &F) {
250b57cec5SDimitry Andric   // Nothing to do for declarations.
260b57cec5SDimitry Andric   if (F.isDeclaration())
270b57cec5SDimitry Andric     return false;
280b57cec5SDimitry Andric   SmallVector<GCRelocateInst *, 20> GCRelocates;
290b57cec5SDimitry Andric   // TODO: We currently do not handle gc.relocates that are in landing pads,
300b57cec5SDimitry Andric   // i.e. not bound to a single statepoint token.
310b57cec5SDimitry Andric   for (Instruction &I : instructions(F)) {
320b57cec5SDimitry Andric     if (auto *GCR = dyn_cast<GCRelocateInst>(&I))
335ffd83dbSDimitry Andric       if (isa<GCStatepointInst>(GCR->getOperand(0)))
340b57cec5SDimitry Andric         GCRelocates.push_back(GCR);
350b57cec5SDimitry Andric   }
360b57cec5SDimitry Andric   // All gc.relocates are bound to a single statepoint token. The order of
370b57cec5SDimitry Andric   // visiting gc.relocates for deletion does not matter.
380b57cec5SDimitry Andric   for (GCRelocateInst *GCRel : GCRelocates) {
390b57cec5SDimitry Andric     Value *OrigPtr = GCRel->getDerivedPtr();
400b57cec5SDimitry Andric     Value *ReplaceGCRel = OrigPtr;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric     // All gc_relocates are i8 addrspace(1)* typed, we need a bitcast from i8
430b57cec5SDimitry Andric     // addrspace(1)* to the type of the OrigPtr, if the are not the same.
440b57cec5SDimitry Andric     if (GCRel->getType() != OrigPtr->getType())
45*0fca6ea1SDimitry Andric       ReplaceGCRel = new BitCastInst(OrigPtr, GCRel->getType(), "cast", GCRel->getIterator());
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric     // Replace all uses of gc.relocate and delete the gc.relocate
480b57cec5SDimitry Andric     // There maybe unncessary bitcasts back to the OrigPtr type, an instcombine
490b57cec5SDimitry Andric     // pass would clear this up.
500b57cec5SDimitry Andric     GCRel->replaceAllUsesWith(ReplaceGCRel);
510b57cec5SDimitry Andric     GCRel->eraseFromParent();
520b57cec5SDimitry Andric   }
530b57cec5SDimitry Andric   return !GCRelocates.empty();
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
run(Function & F,FunctionAnalysisManager & AM)56e8d8bef9SDimitry Andric PreservedAnalyses StripGCRelocates::run(Function &F,
57e8d8bef9SDimitry Andric                                         FunctionAnalysisManager &AM) {
58e8d8bef9SDimitry Andric   if (!stripGCRelocates(F))
59e8d8bef9SDimitry Andric     return PreservedAnalyses::all();
60e8d8bef9SDimitry Andric 
61e8d8bef9SDimitry Andric   // Removing gc.relocate preserves the CFG, but most other analysis probably
62e8d8bef9SDimitry Andric   // need to re-run.
63e8d8bef9SDimitry Andric   PreservedAnalyses PA;
64e8d8bef9SDimitry Andric   PA.preserveSet<CFGAnalyses>();
65e8d8bef9SDimitry Andric   return PA;
66e8d8bef9SDimitry Andric }
67