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