1*0b57cec5SDimitry Andric //===-- AMDGPUFixFunctionBitcasts.cpp - Fix function bitcasts -------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric ///
9*0b57cec5SDimitry Andric /// \file
10*0b57cec5SDimitry Andric /// Promote indirect (bitcast) calls to direct calls when they are statically
11*0b57cec5SDimitry Andric /// known to be direct. Required when InstCombine is not run (e.g. at OptNone)
12*0b57cec5SDimitry Andric /// because AMDGPU does not support indirect calls.
13*0b57cec5SDimitry Andric ///
14*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
15*0b57cec5SDimitry Andric 
16*0b57cec5SDimitry Andric #include "AMDGPU.h"
17*0b57cec5SDimitry Andric #include "llvm/IR/InstVisitor.h"
18*0b57cec5SDimitry Andric #include "llvm/Pass.h"
19*0b57cec5SDimitry Andric #include "llvm/Transforms/Utils/CallPromotionUtils.h"
20*0b57cec5SDimitry Andric 
21*0b57cec5SDimitry Andric using namespace llvm;
22*0b57cec5SDimitry Andric 
23*0b57cec5SDimitry Andric #define DEBUG_TYPE "amdgpu-fix-function-bitcasts"
24*0b57cec5SDimitry Andric 
25*0b57cec5SDimitry Andric namespace {
26*0b57cec5SDimitry Andric class AMDGPUFixFunctionBitcasts final
27*0b57cec5SDimitry Andric     : public ModulePass,
28*0b57cec5SDimitry Andric       public InstVisitor<AMDGPUFixFunctionBitcasts> {
29*0b57cec5SDimitry Andric 
30*0b57cec5SDimitry Andric   bool runOnModule(Module &M) override;
31*0b57cec5SDimitry Andric 
32*0b57cec5SDimitry Andric   bool Modified;
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric public:
visitCallBase(CallBase & CB)35*0b57cec5SDimitry Andric   void visitCallBase(CallBase &CB) {
36*0b57cec5SDimitry Andric     if (CB.getCalledFunction())
37*0b57cec5SDimitry Andric       return;
38*0b57cec5SDimitry Andric     auto *Callee =
39*0b57cec5SDimitry Andric         dyn_cast<Function>(CB.getCalledOperand()->stripPointerCasts());
40*0b57cec5SDimitry Andric     if (Callee && isLegalToPromote(CB, Callee)) {
41*0b57cec5SDimitry Andric       promoteCall(CB, Callee);
42*0b57cec5SDimitry Andric       Modified = true;
43*0b57cec5SDimitry Andric     }
44*0b57cec5SDimitry Andric   }
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric   static char ID;
AMDGPUFixFunctionBitcasts()47*0b57cec5SDimitry Andric   AMDGPUFixFunctionBitcasts() : ModulePass(ID) {}
48*0b57cec5SDimitry Andric };
49*0b57cec5SDimitry Andric } // End anonymous namespace
50*0b57cec5SDimitry Andric 
51*0b57cec5SDimitry Andric char AMDGPUFixFunctionBitcasts::ID = 0;
52*0b57cec5SDimitry Andric char &llvm::AMDGPUFixFunctionBitcastsID = AMDGPUFixFunctionBitcasts::ID;
53*0b57cec5SDimitry Andric INITIALIZE_PASS(AMDGPUFixFunctionBitcasts, DEBUG_TYPE,
54*0b57cec5SDimitry Andric                 "Fix function bitcasts for AMDGPU", false, false)
55*0b57cec5SDimitry Andric 
createAMDGPUFixFunctionBitcastsPass()56*0b57cec5SDimitry Andric ModulePass *llvm::createAMDGPUFixFunctionBitcastsPass() {
57*0b57cec5SDimitry Andric   return new AMDGPUFixFunctionBitcasts();
58*0b57cec5SDimitry Andric }
59*0b57cec5SDimitry Andric 
runOnModule(Module & M)60*0b57cec5SDimitry Andric bool AMDGPUFixFunctionBitcasts::runOnModule(Module &M) {
61*0b57cec5SDimitry Andric   Modified = false;
62*0b57cec5SDimitry Andric   visit(M);
63   return Modified;
64 }
65