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