1 /*
2  * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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  * Copyright (c) 2024 Huawei Device Co., Ltd.
16  * Licensed under the Apache License, Version 2.0 (the "License");
17  * you may not use this file except in compliance with the License.
18  * You may obtain a copy of the License at
19 
20  * http://www.apache.org/licenses/LICENSE-2.0
21  *
22  * Unless required by applicable law or agreed to in writing, software
23  * distributed under the License is distributed on an "AS IS" BASIS,
24  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25  * See the License for the specific language governing permissions and
26  * limitations under the License.
27  */
28 
29 #ifndef BYTECODE_OPTIMIZER_CONSTANT_PROPAGATION_CONSTANT_PROPAGATION_H
30 #define BYTECODE_OPTIMIZER_CONSTANT_PROPAGATION_CONSTANT_PROPAGATION_H
31 
32 #include "bytecode_optimizer/ir_interface.h"
33 #include "compiler/optimizer/ir/basicblock.h"
34 #include "compiler/optimizer/ir/graph.h"
35 #include "compiler/optimizer/ir/graph_visitor.h"
36 #include "compiler/optimizer/pass.h"
37 #include "lattice_element.h"
38 #include "utils/hash.h"
39 
40 namespace panda::bytecodeopt {
41 
42 using compiler::BasicBlock;
43 using compiler::Inst;
44 using compiler::Opcode;
45 using compiler::RuntimeInterface;
46 
47 class ConstantPropagation : public compiler::Optimization, public compiler::GraphVisitor {
48 public:
49     explicit ConstantPropagation(compiler::Graph *graph, const BytecodeOptIrInterface *iface);
50     NO_MOVE_SEMANTIC(ConstantPropagation);
51     NO_COPY_SEMANTIC(ConstantPropagation);
52     ~ConstantPropagation() override = default;
53 
54     using Edge = std::pair<BasicBlock *, BasicBlock *>;
55     struct EdgeHash {
operator ()panda::bytecodeopt::ConstantPropagation::EdgeHash56         uint32_t operator()(Edge const &edge) const
57         {
58             auto block_hash = std::hash<BasicBlock *> {};
59             uint32_t lhash = block_hash(edge.first);
60             uint32_t rhash = block_hash(edge.second);
61             return merge_hashes(lhash, rhash);
62         }
63     };
64 
65     struct EdgeEqual {
operator ()panda::bytecodeopt::ConstantPropagation::EdgeEqual66         bool operator()(Edge const &edge1, Edge const &edge2) const
67         {
68             return edge1.first == edge2.first && edge1.second == edge2.second;
69         }
70     };
71 
72     bool RunImpl() override;
73 
74     const char *GetPassName() const override
75     {
76         return "SCCP";
77     }
78 
79     bool IsEnable() const override
80     {
81         return true;
82     }
83 
84     const ArenaVector<BasicBlock *> &GetBlocksToVisit() const override
85     {
86         return GetGraph()->GetBlocksRPO();
87     }
88 
89 protected:
90     void VisitDefault(Inst *inst) override;
91     static void VisitPhi(GraphVisitor *v, Inst *inst);
92     static void VisitIfImm(GraphVisitor *v, Inst *inst);
93     static void VisitCompare(GraphVisitor *v, Inst *inst);
94     static void VisitConstant(GraphVisitor *v, Inst *inst);
95     static void VisitLoadString(GraphVisitor *v, Inst *inst);
96     static void VisitIntrinsic(GraphVisitor *v, Inst *inst);
97     static void VisitCastValueToAnyType(GraphVisitor *v, Inst *inst);
98 
99 #include "compiler/optimizer/ir/visitor.inc"
100 
101 private:
102     void RunSsaEdge();
103     void ReWriteInst();
104     void RunFlowEdge();
105     void VisitInsts(BasicBlock *bb);
106     void AddUntraversedFlowEdges(BasicBlock *src, BasicBlock *dst);
107     bool GetIfTargetBlock(compiler::IfImmInst *inst, uint64_t val);
108     LatticeElement *GetOrCreateDefaultLattice(Inst *inst);
109     LatticeElement *FoldingModuleOperation(compiler::IntrinsicInst *inst);
110     LatticeElement *FoldingConstant(RuntimeInterface::IntrinsicId id);
111     LatticeElement *FoldingConstant(ConstantElement *lattice, RuntimeInterface::IntrinsicId id);
112     LatticeElement *FoldingConstant(ConstantElement *left, ConstantElement *right, RuntimeInterface::IntrinsicId id);
113     LatticeElement *FoldingCompare(const ConstantElement *left, const ConstantElement *right,
114                                    compiler::ConditionCode cc);
115 
116     LatticeElement *FoldingGreater(const ConstantElement *left, const ConstantElement *right, bool equal = false);
117     LatticeElement *FoldingLess(const ConstantElement *left, const ConstantElement *right, bool equal = false);
118     LatticeElement *FoldingEq(const ConstantElement *left, const ConstantElement *right);
119     LatticeElement *FoldingNotEq(const ConstantElement *left, const ConstantElement *right);
120     LatticeElement *FoldingLdlocalmodulevar(compiler::IntrinsicInst *inst);
121     LatticeElement *FoldingLdexternalmodulevar(compiler::IntrinsicInst *inst);
122     LatticeElement *FoldingLdobjbyname(compiler::IntrinsicInst *inst);
123 
124     Inst *CreateReplaceInst(Inst *base_inst, ConstantElement *lattice);
125     void InsertSaveState(Inst *base_inst, Inst *save_state);
126     void CheckAndAddToSsaEdge(Inst *inst, LatticeElement *current, LatticeElement *new_lattice);
127 
128 private:
129     ArenaUnorderedMap<Inst *, LatticeElement *> lattices_;
130     ArenaQueue<Edge> flow_edges_;
131     ArenaQueue<Inst *> ssa_edges_;
132     ArenaUnorderedSet<Edge, EdgeHash, EdgeEqual> executable_flag_;
133     ArenaUnorderedSet<uint32_t> executed_node_;
134     std::string record_name_;
135     const BytecodeOptIrInterface *ir_interface_;
136 };
137 
138 }  // namespace panda::bytecodeopt
139 
140 #endif  // BYTECODE_OPTIMIZER_CONSTANT_PROPAGATION_CONSTANT_PROPAGATION_H
141