1 /*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef COMPILER_OPTIMIZER_IR_ANALYSIS_H
17 #define COMPILER_OPTIMIZER_IR_ANALYSIS_H
18
19 #include "graph.h"
20
21 #include <optional>
22
23 namespace ark::compiler {
24
25 /// The file contains small analysis functions which can be used in different passes
26 class Inst;
27 class BasicBlock;
28 // returns Store value, for StoreArrayPair and StoreArrayPairI saved not last store value in second_value
29 Inst *InstStoredValue(Inst *inst, Inst **secondValue);
30 Inst *InstStoredValue(Inst *inst);
31
32 template <typename T = Inst>
33 bool HasOsrEntryBetween(T *dominate, T *current);
34 bool HasTryBlockBetween(Inst *dominateInst, Inst *inst);
35 bool IsSuitableForImplicitNullCheck(const Inst *inst);
36 bool IsInstNotNull(const Inst *inst);
37 bool CheckFcmpInputs(Inst *input0, Inst *input1);
38 bool CheckFcmpWithConstInput(Inst *input0, Inst *input1);
39 int64_t GetPowerOfTwo(uint64_t n);
40 bool CanRemoveOverflowCheck(Inst *inst, Marker marker);
41 bool IsCastAllowedInBytecode(const Inst *inst);
42 bool IsInputTypeMismatch(Inst *inst, int32_t inputIndex, Arch arch);
43 bool ApplyForCastJoin(Inst *cast, Inst *input, Inst *origInst, Arch arch);
44 SaveStateInst *CopySaveState(Graph *graph, SaveStateInst *inst);
45 std::optional<bool> IsIfInverted(BasicBlock *phiBlock, IfImmInst *ifImm);
46
47 // If object input has known class, return pointer to the class, else returns nullptr
48 RuntimeInterface::ClassPtr GetClassPtrForObject(Inst *inst, size_t inputNum = 0);
49 RuntimeInterface::ClassPtr GetObjectClass(Inst *inst);
50 RuntimeInterface::ClassPtr GetClass(Inst *inst);
51
IsInstInDifferentBlocks(Inst * i1,Inst * i2)52 inline bool IsInstInDifferentBlocks(Inst *i1, Inst *i2)
53 {
54 return i1->GetBasicBlock() != i2->GetBasicBlock();
55 }
56
57 // This function bypass all blocks and delete 'SaveStateOSR' if the block is no longer the header of the loop
58 void CleanupGraphSaveStateOSR(Graph *graph);
59
60 class IsSaveState;
61 class IsSaveStateCanTriggerGc;
62 // returns true is there is SaveState/SafePoint between instructions
63 template <typename T = IsSaveState>
64 bool HasSaveStateBetween(Inst *domInst, Inst *inst);
65
66 bool IsSaveStateForGc(const Inst *inst);
67
68 /**
69 * Functions below are using for create bridge in SaveStates between source instruction and target instruction.
70 * It use in GVN etc. It inserts `source` instruction into `SaveStates` on each path between `source` and
71 * `target` instructions to save the object in case GC is triggered on this path.
72 * Instructions on how to use it: compiler/docs/bridges.md
73 */
74 class SaveStateBridgesBuilder {
75 public:
76 ArenaVector<Inst *> *SearchMissingObjInSaveStates(Graph *graph, Inst *source, Inst *target,
77 Inst *stopSearch = nullptr, BasicBlock *targetBlock = nullptr);
78 void CreateBridgeInSS(Inst *source);
79 void SearchAndCreateMissingObjInSaveState(Graph *graph, Inst *source, Inst *target, Inst *stopSearchInst = nullptr,
80 BasicBlock *targetBlock = nullptr);
81 void FixInstUsageInSS(Graph *graph, Inst *inst);
82 void FixSaveStatesInBB(BasicBlock *block);
83 void FixPhisWithCheckInputs(BasicBlock *block);
84 void DumpBridges(std::ostream &out, Inst *source);
85
86 private:
87 void SearchSSOnWay(BasicBlock *block, Inst *startFrom, Inst *sourceInst, Marker visited, Inst *stopSearch);
88 bool IsSaveStateForGc(Inst *inst);
89 void ProcessSSUserPreds(Graph *graph, Inst *inst, Inst *targetInst);
90 void SearchInSaveStateAndFillBridgeVector(Inst *inst, Inst *searchedInst);
91 void FixUsageInstInOtherBB(BasicBlock *block, Inst *inst);
92 void FixUsagePhiInBB(BasicBlock *block, Inst *inst);
93 void DeleteUnrealObjInSaveState(Inst *ss);
94 /**
95 * Pointer to moved out to class for reduce memory usage in each pair of equal instructions.
96 * When using functions, it looks like we work as if every time get a new vector,
97 * but one vector is always used and cleaned before use.
98 */
99 ArenaVector<Inst *> *bridges_ {nullptr};
100 };
101
102 class InstAppender {
103 public:
block_(block)104 explicit InstAppender(BasicBlock *block, Inst *insertAfter = nullptr) : block_(block), prev_(insertAfter) {}
105 ~InstAppender() = default;
106 DEFAULT_MOVE_SEMANTIC(InstAppender);
107 NO_COPY_SEMANTIC(InstAppender);
108
109 void Append(Inst *inst);
110 void Append(std::initializer_list<Inst *> instructions);
111
112 private:
113 BasicBlock *block_;
114 Inst *prev_ {nullptr};
115 };
116
117 bool StoreValueCanBeObject(Inst *inst);
118
119 bool IsConditionEqual(const Inst *inst0, const Inst *inst1, bool inverted);
120
121 } // namespace ark::compiler
122
123 #endif // COMPILER_OPTIMIZER_IR_ANALYSIS_H
124