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