• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 bool CheckArrayFieldObject(RuntimeInterface::ArrayField kind, Inst *inst);
47 bool CheckArrayField(RuntimeInterface::ArrayField kind, Inst *inst, Inst *&arrayOriginRef);
48 
49 // If object input has known class, return pointer to the class, else returns nullptr
50 RuntimeInterface::ClassPtr GetClassPtrForObject(Inst *inst, size_t inputNum = 0);
51 RuntimeInterface::ClassPtr GetObjectClass(Inst *inst);
52 RuntimeInterface::ClassPtr GetClass(Inst *inst);
53 
IsInstInDifferentBlocks(Inst * i1,Inst * i2)54 inline bool IsInstInDifferentBlocks(Inst *i1, Inst *i2)
55 {
56     return i1->GetBasicBlock() != i2->GetBasicBlock();
57 }
58 
InstHasPseudoInputs(Inst * inst)59 inline bool InstHasPseudoInputs(Inst *inst)
60 {
61     return inst->GetOpcode() == Opcode::WrapObjectNative;
62 }
63 
64 // This function bypass all blocks and delete 'SaveStateOSR' if the block is no longer the header of the loop
65 void CleanupGraphSaveStateOSR(Graph *graph);
66 
67 class IsSaveState;
68 class IsSaveStateCanTriggerGc;
69 // returns true is there is SaveState/SafePoint between instructions
70 template <typename T = IsSaveState>
71 bool HasSaveStateBetween(Inst *domInst, Inst *inst);
72 
73 bool IsSaveStateForGc(const Inst *inst);
74 
75 /**
76  * Functions below are using for create bridge in SaveStates between source instruction and target instruction.
77  * It use in GVN etc. It inserts `source` instruction into `SaveStates` on each path between `source` and
78  * `target` instructions to save the object in case GC is triggered on this path.
79  * Instructions on how to use it: compiler/docs/bridges.md
80  */
81 class SaveStateBridgesBuilder {
82 public:
83     ArenaVector<Inst *> *SearchMissingObjInSaveStates(Graph *graph, Inst *source, Inst *target,
84                                                       Inst *stopSearch = nullptr, BasicBlock *targetBlock = nullptr);
85     void CreateBridgeInSS(Inst *source);
86     void SearchAndCreateMissingObjInSaveState(Graph *graph, Inst *source, Inst *target, Inst *stopSearchInst = nullptr,
87                                               BasicBlock *targetBlock = nullptr);
88     void FixInstUsageInSS(Graph *graph, Inst *inst);
89     void FixSaveStatesInBB(BasicBlock *block);
90     void FixPhisWithCheckInputs(BasicBlock *block);
91     void DumpBridges(std::ostream &out, Inst *source);
92 
93 private:
94     void SearchSSOnWay(BasicBlock *block, Inst *startFrom, Inst *sourceInst, Marker visited, Inst *stopSearch);
95     bool IsSaveStateForGc(Inst *inst);
96     void ProcessSSUserPreds(Graph *graph, Inst *inst, Inst *targetInst);
97     void SearchInSaveStateAndFillBridgeVector(Inst *inst, Inst *searchedInst);
98     void FixUsageInstInOtherBB(BasicBlock *block, Inst *inst);
99     void FixUsagePhiInBB(BasicBlock *block, Inst *inst);
100     void DeleteUnrealObjInSaveState(Inst *ss);
101     /**
102      * Pointer to moved out to class for reduce memory usage in each pair of equal instructions.
103      * When using functions, it looks like we work as if every time get a new vector,
104      * but one vector is always used and cleaned before use.
105      */
106     ArenaVector<Inst *> *bridges_ {nullptr};
107 };
108 
109 class InstAppender {
110 public:
block_(block)111     explicit InstAppender(BasicBlock *block, Inst *insertAfter = nullptr) : block_(block), prev_(insertAfter) {}
112     ~InstAppender() = default;
113     DEFAULT_MOVE_SEMANTIC(InstAppender);
114     NO_COPY_SEMANTIC(InstAppender);
115 
116     void Append(Inst *inst);
117     void Append(std::initializer_list<Inst *> instructions);
118 
119 private:
120     BasicBlock *block_;
121     Inst *prev_ {nullptr};
122 };
123 
124 bool StoreValueCanBeObject(Inst *inst);
125 
126 bool IsConditionEqual(const Inst *inst0, const Inst *inst1, bool inverted);
127 
128 }  // namespace ark::compiler
129 
130 #endif  // COMPILER_OPTIMIZER_IR_ANALYSIS_H
131