1 //===------ RewriteByReferenceParameters.cpp --------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass introduces separate 'alloca' instructions for read-only
10 // by-reference function parameters to indicate that these paramters are
11 // read-only. After this transformation -mem2reg has more freedom to promote
12 // variables to registers, which allows SCEV to work in more cases.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "polly/RewriteByReferenceParameters.h"
17 #include "polly/LinkAllPasses.h"
18 #include "llvm/IR/Instruction.h"
19 #include "llvm/IR/Instructions.h"
20 #include "llvm/Pass.h"
21 
22 #define DEBUG_TYPE "polly-rewrite-byref-params"
23 
24 using namespace llvm;
25 
26 namespace {
tryRewriteInstruction(Instruction & Inst)27 static void tryRewriteInstruction(Instruction &Inst) {
28   BasicBlock *Entry = &Inst.getParent()->getParent()->getEntryBlock();
29 
30   auto *Call = dyn_cast<CallInst>(&Inst);
31 
32   if (!Call)
33     return;
34 
35   llvm::Function *F = Call->getCalledFunction();
36 
37   if (!F)
38     return;
39 
40   // We currently match for a very specific function. In case this proves
41   // useful, we can make this code dependent on readonly metadata.
42   if (!F->hasName() || F->getName() != "_gfortran_transfer_integer_write")
43     return;
44 
45   auto *BitCast = dyn_cast<BitCastInst>(Call->getOperand(1));
46 
47   if (!BitCast)
48     return;
49 
50   auto *Alloca = dyn_cast<AllocaInst>(BitCast->getOperand(0));
51 
52   if (!Alloca)
53     return;
54 
55   std::string InstName = Alloca->getName().str();
56 
57   auto NewAlloca =
58       new AllocaInst(Alloca->getAllocatedType(), 0,
59                      "polly_byref_alloca_" + InstName, &*Entry->begin());
60 
61   auto *LoadedVal = new LoadInst(Alloca->getAllocatedType(), Alloca,
62                                  "polly_byref_load_" + InstName, &Inst);
63 
64   new StoreInst(LoadedVal, NewAlloca, &Inst);
65   auto *NewBitCast = new BitCastInst(NewAlloca, BitCast->getType(),
66                                      "polly_byref_cast_" + InstName, &Inst);
67   Call->setOperand(1, NewBitCast);
68 }
69 
runRewriteByrefParams(Function & F)70 static void runRewriteByrefParams(Function &F) {
71   for (BasicBlock &BB : F)
72     for (Instruction &Inst : BB)
73       tryRewriteInstruction(Inst);
74 }
75 
76 class RewriteByrefParamsWrapperPass : public FunctionPass {
77 private:
78   RewriteByrefParamsWrapperPass(const RewriteByrefParamsWrapperPass &) = delete;
79   const RewriteByrefParamsWrapperPass &
80   operator=(const RewriteByrefParamsWrapperPass &) = delete;
81 
82 public:
83   static char ID;
RewriteByrefParamsWrapperPass()84   explicit RewriteByrefParamsWrapperPass() : FunctionPass(ID) {}
85 
getAnalysisUsage(AnalysisUsage & AU) const86   virtual void getAnalysisUsage(AnalysisUsage &AU) const override {}
87 
runOnFunction(Function & F)88   virtual bool runOnFunction(Function &F) override {
89     runRewriteByrefParams(F);
90     return true;
91   }
92 };
93 
94 char RewriteByrefParamsWrapperPass::ID;
95 } // anonymous namespace
96 
createRewriteByrefParamsWrapperPass()97 Pass *polly::createRewriteByrefParamsWrapperPass() {
98   return new RewriteByrefParamsWrapperPass();
99 }
100 
101 llvm::PreservedAnalyses
run(llvm::Function & F,llvm::FunctionAnalysisManager & FAM)102 polly ::RewriteByrefParamsPass::run(llvm::Function &F,
103                                     llvm::FunctionAnalysisManager &FAM) {
104   runRewriteByrefParams(F);
105   return PreservedAnalyses::none();
106 }
107 
108 INITIALIZE_PASS_BEGIN(RewriteByrefParamsWrapperPass,
109                       "polly-rewrite-byref-params",
110                       "Polly - Rewrite by reference parameters", false, false)
111 INITIALIZE_PASS_END(RewriteByrefParamsWrapperPass, "polly-rewrite-byref-params",
112                     "Polly - Rewrite by reference parameters", false, false)
113