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