1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 //
10 /// GenXRematerialization
11 /// ---------------------
12 ///
13 /// This pass performs rematerialization to reduce register pressure.
14 ///
15 //===----------------------------------------------------------------------===//
16 #include "GenX.h"
17 #include "GenXBaling.h"
18 #include "GenXLiveness.h"
19 #include "GenXModule.h"
20 #include "GenXNumbering.h"
21 #include "GenXPressureTracker.h"
22 #include "GenXUtil.h"
23 #include "llvm/Pass.h"
24 #include "Probe/Assertion.h"
25 
26 using namespace llvm;
27 using namespace genx;
28 
29 namespace {
30 
31 class GenXRematerialization : public FGPassImplInterface,
32                               public IDMixin<GenXRematerialization> {
33   GenXBaling *Baling = nullptr;
34   GenXLiveness *Liveness = nullptr;
35   GenXNumbering *Numbering = nullptr;
36   bool Modified = false;
37 
38 public:
GenXRematerialization()39   explicit GenXRematerialization() {}
getPassName()40   static StringRef getPassName() { return "GenX rematerialization pass"; }
41   static void getAnalysisUsage(AnalysisUsage &AU);
42   bool runOnFunctionGroup(FunctionGroup &FG) override;
43 
44 private:
45   void remat(Function *F, PressureTracker &RP);
46 };
47 
48 } // namespace
49 
50 namespace llvm {
51 void initializeGenXRematerializationWrapperPass(PassRegistry &);
52 using GenXRematerializationWrapper =
53     FunctionGroupWrapperPass<GenXRematerialization>;
54 } // namespace llvm
55 INITIALIZE_PASS_BEGIN(GenXRematerializationWrapper,
56                       "GenXRematerializationWrapper",
57                       "GenXRematerializationWrapper", false, false)
INITIALIZE_PASS_DEPENDENCY(GenXGroupBalingWrapper)58 INITIALIZE_PASS_DEPENDENCY(GenXGroupBalingWrapper)
59 INITIALIZE_PASS_DEPENDENCY(GenXLivenessWrapper)
60 INITIALIZE_PASS_DEPENDENCY(GenXNumberingWrapper)
61 INITIALIZE_PASS_END(GenXRematerializationWrapper,
62                     "GenXRematerializationWrapper",
63                     "GenXRematerializationWrapper", false, false)
64 
65 ModulePass *llvm::createGenXRematerializationWrapperPass() {
66   initializeGenXRematerializationWrapperPass(*PassRegistry::getPassRegistry());
67   return new GenXRematerializationWrapper;
68 }
69 
getAnalysisUsage(AnalysisUsage & AU)70 void GenXRematerialization::getAnalysisUsage(AnalysisUsage &AU) {
71   AU.addRequired<GenXGroupBaling>();
72   AU.addRequired<GenXLiveness>();
73   AU.addRequired<GenXNumbering>();
74   AU.addPreserved<GenXModule>();
75   AU.addPreserved<FunctionGroupAnalysis>();
76   AU.setPreservesCFG();
77 }
78 
runOnFunctionGroup(FunctionGroup & FG)79 bool GenXRematerialization::runOnFunctionGroup(FunctionGroup &FG) {
80   if (skipOptWithLargeBlock(FG))
81     return false;
82 
83   Modified = false;
84   Baling = &getAnalysis<GenXGroupBaling>();
85   Liveness = &getAnalysis<GenXLiveness>();
86   Numbering = &getAnalysis<GenXNumbering>();
87   const auto &DL = FG.getModule()->getDataLayout();
88   PressureTracker RP(DL, FG, Liveness);
89   for (auto fgi = FG.begin(), fge = FG.end(); fgi != fge; ++fgi)
90     remat(*fgi, RP);
91   return Modified;
92 }
93 
remat(Function * F,PressureTracker & RP)94 void GenXRematerialization::remat(Function *F, PressureTracker &RP) {
95   // Collect rematerialization candidates.
96   std::vector<Use *> Candidates;
97   for (auto &BB : F->getBasicBlockList()) {
98     for (auto &Inst : BB.getInstList()) {
99       // (1) upward cast
100       if (auto CI = dyn_cast<CastInst>(&Inst)) {
101         if (CI->getOpcode() != Instruction::UIToFP &&
102             CI->getOpcode() != Instruction::SIToFP)
103           continue;
104         if (!CI->getType()->isVectorTy())
105           continue;
106         if (CI->getSrcTy()->getScalarSizeInBits() >=
107             CI->getDestTy()->getScalarSizeInBits())
108           continue;
109         if (Inst.isUsedOutsideOfBlock(&BB) || Inst.getNumUses() <= 2)
110           continue;
111         LiveRange *LR = Liveness->getLiveRangeOrNull(CI);
112         if (!LR || LR->value_size() != 1)
113           continue;
114         IGC_ASSERT(LR->value_begin()->getValue() == CI);
115         unsigned B = Numbering->getNumber(CI);
116         for (auto &U : CI->uses()) {
117           auto UI = U.getUser();
118           unsigned E = Numbering->getNumber(UI);
119           if (E > B && RP.intersectWithRedRegion(B, E))
120             Candidates.push_back(&U);
121         }
122       }
123     }
124   }
125 
126   // Do rematerialization.
127   for (auto U : Candidates) {
128     Instruction *Inst = cast<Instruction>(U->get());
129     Instruction *UI = cast<Instruction>(U->getUser());
130     Instruction *Clone = Inst->clone();
131     Clone->insertBefore(UI);
132     U->set(Clone);
133     Modified = true;
134   }
135 }
136