• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2023 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "pipeline/jit/pi/utils/opcode_util.h"
17 #include "pipeline/jit/pi/pydef.h"
18 
19 namespace mindspore {
20 namespace pijit {
21 
22 Opcode Opcode::opmap[Opcode::kMaxCode];
23 const Opcode Opcode::k_ILLEGAL_OPCODE = {"ILLEGAL_OPCODE", ILLEGAL_OPCODE, Opcode::Class::kOther, 0};
24 
25 enum OpcodeFlag {
26   kJRel = 1 << 0,      // is jump relative
27   kJAbs = 1 << 1,      // is jump relative
28   kNotFall = 1 << 2,   // jump directly, return, raise
29   kHasConst = 1 << 3,  // has const in co_consts
30   kHasName = 1 << 4,   // has name in co_names
31   kHasFree = 1 << 5,   // has free variable operations, not is 'free' of this function
32   kCanDel = 1 << 6,    // can be remove if result is unused
33   /**
34    * Maybe remove if result is unused.
35    * Generally or literally, it's no side effect, check it and parse
36    * all user-defined operation to call function while graph building
37    */
38   kMayDel = 1 << 7,
39 };
40 
Opcode()41 Opcode::Opcode() { *this = k_ILLEGAL_OPCODE; }
42 
IsJRel() const43 bool Opcode::IsJRel() const { return flag_ & kJRel; }
IsJAbs() const44 bool Opcode::IsJAbs() const { return flag_ & kJAbs; }
IsNotFall() const45 bool Opcode::IsNotFall() const { return flag_ & kNotFall; }
HasName() const46 bool Opcode::HasName() const { return flag_ & kHasName; }
HasFree() const47 bool Opcode::HasFree() const { return flag_ & kHasFree; }
HasConst() const48 bool Opcode::HasConst() const { return flag_ & kHasConst; }
CanDelete(int oparg) const49 bool Opcode::CanDelete(int oparg) const { return (flag_ & kCanDel) || CheckIsOp(oparg); }
MayDelete(int oparg) const50 bool Opcode::MayDelete(int oparg) const { return (flag_ & kMayDel) || CanDelete(oparg); }
CheckIsOp(int oparg,bool * invert) const51 bool Opcode::CheckIsOp(int oparg, bool *invert) const {
52 #if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9)
53   if (invert != nullptr) {
54     *invert = oparg == PyCmp_IS_NOT;
55   }
56   return code_ == COMPARE_OP ? oparg == PyCmp_IS : false;
57 #else
58   if (invert != nullptr) {
59     *invert = oparg;
60   }
61   return code_ == IS_OP;
62 #endif
63 }
CheckContainsOp(int oparg,bool * invert) const64 bool Opcode::CheckContainsOp(int oparg, bool *invert) const {
65 #if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9)
66   if (invert != nullptr) {
67     *invert = oparg == PyCmp_NOT_IN;
68   }
69   return code_ == COMPARE_OP ? oparg == PyCmp_IN : false;
70 #else
71   if (invert != nullptr) {
72     *invert = oparg;
73   }
74   return code_ == CONTAINS_OP;
75 #endif
76 }
77 
HasArg() const78 bool Opcode::HasArg() const { return HAS_ARG(code_); }
79 
Map()80 const Opcode *Opcode::Map() {
81   static bool init = false;
82   if (init) {
83     return opmap;
84   }
85   init = true;
86 
87 #define DEF_OPCODE(name, cls, flag) \
88   opmap[(name)] = (name) == ILLEGAL_OPCODE ? Opcode::k_ILLEGAL_OPCODE : Opcode(#name, (name), (cls), (flag));
89 
90 #include "opcode_attr.def"
91 #undef DEF_OPCODE
92 
93   return opmap;
94 }
95 
JumpTarget(int pc,int off) const96 int Opcode::JumpTarget(int pc, int off) const {
97 #if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION < 10)
98   constexpr int mul = sizeof(_Py_CODEUNIT);
99 #else
100   constexpr int mul = 1;
101 #endif
102   if (IsJRel()) {
103     return pc + 1 + off / mul;
104   }
105   if (IsJAbs()) {
106     return off / mul;
107   }
108   return -1;
109 }
JumpOffset(int pc,int tar) const110 int Opcode::JumpOffset(int pc, int tar) const {
111 #if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION < 10)
112   constexpr int mul = sizeof(_Py_CODEUNIT);
113 #else
114   constexpr int mul = 1;
115 #endif
116   if (IsJRel()) {
117     return (tar - pc - 1) * mul;
118   }
119   if (IsJAbs()) {
120     return tar * mul;
121   }
122   return -1;
123 }
124 
125 }  // namespace pijit
126 }  // namespace mindspore
127