1d88c1a5aSDimitry Andric //===- StripGCRelocates.cpp - Remove gc.relocates inserted by RewriteStatePoints===//
2d88c1a5aSDimitry Andric //
3d88c1a5aSDimitry Andric //                     The LLVM Compiler Infrastructure
4d88c1a5aSDimitry Andric //
5d88c1a5aSDimitry Andric // This file is distributed under the University of Illinois Open Source
6d88c1a5aSDimitry Andric // License. See LICENSE.TXT for details.
7d88c1a5aSDimitry Andric //
8d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===//
9d88c1a5aSDimitry Andric //
10d88c1a5aSDimitry Andric // This is a little utility pass that removes the gc.relocates inserted by
11d88c1a5aSDimitry Andric // RewriteStatepointsForGC. Note that the generated IR is incorrect,
12d88c1a5aSDimitry Andric // but this is useful as a single pass in itself, for analysis of IR, without
13d88c1a5aSDimitry Andric // the GC.relocates. The statepoint and gc.result instrinsics would still be
14d88c1a5aSDimitry Andric // present.
15d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===//
16d88c1a5aSDimitry Andric 
17d88c1a5aSDimitry Andric #include "llvm/IR/Function.h"
18d88c1a5aSDimitry Andric #include "llvm/IR/InstIterator.h"
19d88c1a5aSDimitry Andric #include "llvm/IR/Instructions.h"
20d88c1a5aSDimitry Andric #include "llvm/IR/Statepoint.h"
21d88c1a5aSDimitry Andric #include "llvm/IR/Type.h"
22d88c1a5aSDimitry Andric #include "llvm/Pass.h"
23d88c1a5aSDimitry Andric #include "llvm/Support/raw_ostream.h"
24d88c1a5aSDimitry Andric 
25d88c1a5aSDimitry Andric using namespace llvm;
26d88c1a5aSDimitry Andric 
27d88c1a5aSDimitry Andric namespace {
28d88c1a5aSDimitry Andric struct StripGCRelocates : public FunctionPass {
29d88c1a5aSDimitry Andric   static char ID; // Pass identification, replacement for typeid
StripGCRelocates__anon6b7889f10111::StripGCRelocates30d88c1a5aSDimitry Andric   StripGCRelocates() : FunctionPass(ID) {
31d88c1a5aSDimitry Andric     initializeStripGCRelocatesPass(*PassRegistry::getPassRegistry());
32d88c1a5aSDimitry Andric   }
33d88c1a5aSDimitry Andric 
getAnalysisUsage__anon6b7889f10111::StripGCRelocates34d88c1a5aSDimitry Andric   void getAnalysisUsage(AnalysisUsage &Info) const override {}
35d88c1a5aSDimitry Andric 
36d88c1a5aSDimitry Andric   bool runOnFunction(Function &F) override;
37d88c1a5aSDimitry Andric 
38d88c1a5aSDimitry Andric };
39d88c1a5aSDimitry Andric char StripGCRelocates::ID = 0;
40d88c1a5aSDimitry Andric }
41d88c1a5aSDimitry Andric 
runOnFunction(Function & F)42d88c1a5aSDimitry Andric bool StripGCRelocates::runOnFunction(Function &F) {
43d88c1a5aSDimitry Andric   // Nothing to do for declarations.
44d88c1a5aSDimitry Andric   if (F.isDeclaration())
45d88c1a5aSDimitry Andric     return false;
46d88c1a5aSDimitry Andric   SmallVector<GCRelocateInst *, 20> GCRelocates;
47d88c1a5aSDimitry Andric   // TODO: We currently do not handle gc.relocates that are in landing pads,
48d88c1a5aSDimitry Andric   // i.e. not bound to a single statepoint token.
49d88c1a5aSDimitry Andric   for (Instruction &I : instructions(F)) {
50d88c1a5aSDimitry Andric     if (auto *GCR = dyn_cast<GCRelocateInst>(&I))
51d88c1a5aSDimitry Andric       if (isStatepoint(GCR->getOperand(0)))
52d88c1a5aSDimitry Andric         GCRelocates.push_back(GCR);
53d88c1a5aSDimitry Andric   }
54d88c1a5aSDimitry Andric   // All gc.relocates are bound to a single statepoint token. The order of
55d88c1a5aSDimitry Andric   // visiting gc.relocates for deletion does not matter.
56d88c1a5aSDimitry Andric   for (GCRelocateInst *GCRel : GCRelocates) {
57d88c1a5aSDimitry Andric     Value *OrigPtr = GCRel->getDerivedPtr();
58d88c1a5aSDimitry Andric     Value *ReplaceGCRel = OrigPtr;
59d88c1a5aSDimitry Andric 
60d88c1a5aSDimitry Andric     // All gc_relocates are i8 addrspace(1)* typed, we need a bitcast from i8
61d88c1a5aSDimitry Andric     // addrspace(1)* to the type of the OrigPtr, if the are not the same.
62d88c1a5aSDimitry Andric     if (GCRel->getType() != OrigPtr->getType())
63d88c1a5aSDimitry Andric       ReplaceGCRel = new BitCastInst(OrigPtr, GCRel->getType(), "cast", GCRel);
64d88c1a5aSDimitry Andric 
65d88c1a5aSDimitry Andric     // Replace all uses of gc.relocate and delete the gc.relocate
66d88c1a5aSDimitry Andric     // There maybe unncessary bitcasts back to the OrigPtr type, an instcombine
67d88c1a5aSDimitry Andric     // pass would clear this up.
68d88c1a5aSDimitry Andric     GCRel->replaceAllUsesWith(ReplaceGCRel);
69d88c1a5aSDimitry Andric     GCRel->eraseFromParent();
70d88c1a5aSDimitry Andric   }
71d88c1a5aSDimitry Andric   return !GCRelocates.empty();
72d88c1a5aSDimitry Andric }
73d88c1a5aSDimitry Andric 
74d88c1a5aSDimitry Andric INITIALIZE_PASS(StripGCRelocates, "strip-gc-relocates",
75d88c1a5aSDimitry Andric                 "Strip gc.relocates inserted through RewriteStatepointsForGC",
76d88c1a5aSDimitry Andric                 true, false)
77