• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/LinkAllPasses.h"
17 #include "llvm/IR/Instruction.h"
18 #include "llvm/IR/Instructions.h"
19 #include "llvm/Pass.h"
20 
21 #define DEBUG_TYPE "polly-rewrite-byref-params"
22 
23 using namespace llvm;
24 
25 namespace {
26 
27 class RewriteByrefParams : public FunctionPass {
28 private:
29   RewriteByrefParams(const RewriteByrefParams &) = delete;
30   const RewriteByrefParams &operator=(const RewriteByrefParams &) = delete;
31 
32 public:
33   static char ID;
RewriteByrefParams()34   explicit RewriteByrefParams() : FunctionPass(ID) {}
35 
getAnalysisUsage(AnalysisUsage & AU) const36   virtual void getAnalysisUsage(AnalysisUsage &AU) const override {}
37 
tryRewriteInstruction(Instruction & Inst)38   void tryRewriteInstruction(Instruction &Inst) {
39     BasicBlock *Entry = &Inst.getParent()->getParent()->getEntryBlock();
40 
41     auto *Call = dyn_cast<CallInst>(&Inst);
42 
43     if (!Call)
44       return;
45 
46     llvm::Function *F = Call->getCalledFunction();
47 
48     if (!F)
49       return;
50 
51     // We currently match for a very specific function. In case this proves
52     // useful, we can make this code dependent on readonly metadata.
53     if (!F->hasName() || F->getName() != "_gfortran_transfer_integer_write")
54       return;
55 
56     auto *BitCast = dyn_cast<BitCastInst>(Call->getOperand(1));
57 
58     if (!BitCast)
59       return;
60 
61     auto *Alloca = dyn_cast<AllocaInst>(BitCast->getOperand(0));
62 
63     if (!Alloca)
64       return;
65 
66     std::string InstName = Alloca->getName().str();
67 
68     auto NewAlloca =
69         new AllocaInst(Alloca->getAllocatedType(), 0,
70                        "polly_byref_alloca_" + InstName, &*Entry->begin());
71 
72     auto *LoadedVal = new LoadInst(Alloca->getAllocatedType(), Alloca,
73                                    "polly_byref_load_" + InstName, &Inst);
74 
75     new StoreInst(LoadedVal, NewAlloca, &Inst);
76     auto *NewBitCast = new BitCastInst(NewAlloca, BitCast->getType(),
77                                        "polly_byref_cast_" + InstName, &Inst);
78     Call->setOperand(1, NewBitCast);
79   }
80 
runOnFunction(Function & F)81   virtual bool runOnFunction(Function &F) override {
82     for (BasicBlock &BB : F)
83       for (Instruction &Inst : BB)
84         tryRewriteInstruction(Inst);
85 
86     return true;
87   }
88 };
89 
90 char RewriteByrefParams::ID;
91 } // anonymous namespace
92 
createRewriteByrefParamsPass()93 Pass *polly::createRewriteByrefParamsPass() { return new RewriteByrefParams(); }
94 
95 INITIALIZE_PASS_BEGIN(RewriteByrefParams, "polly-rewrite-byref-params",
96                       "Polly - Rewrite by reference parameters", false, false)
97 INITIALIZE_PASS_END(RewriteByrefParams, "polly-rewrite-byref-params",
98                     "Polly - Rewrite by reference parameters", false, false)
99