1 /*
2 * Copyright (c) 2023 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 #include "ext_constantfold.h"
17 #include <climits>
18
19 namespace maple {
20 // This class is designed to further identify simplification
21 // patterns that have not been covered in ConstantFold.
22
ExtSimplify(StmtNode * node)23 StmtNode *ExtConstantFold::ExtSimplify(StmtNode *node)
24 {
25 CHECK_NULL_FATAL(node);
26 switch (node->GetOpCode()) {
27 case OP_block:
28 return ExtSimplifyBlock(static_cast<BlockNode *>(node));
29 case OP_if:
30 return ExtSimplifyIf(static_cast<IfStmtNode *>(node));
31 case OP_dassign:
32 return ExtSimplifyDassign(static_cast<DassignNode *>(node));
33 case OP_iassign:
34 return ExtSimplifyIassign(static_cast<IassignNode *>(node));
35 case OP_dowhile:
36 case OP_while:
37 return ExtSimplifyWhile(static_cast<WhileStmtNode *>(node));
38 default:
39 return node;
40 }
41 }
42
DispatchFold(BaseNode * node)43 BaseNode *ExtConstantFold::DispatchFold(BaseNode *node)
44 {
45 // Not trying all possiblities.
46 // For simplicity, stop looking further down the expression once OP_OP_cior/OP_cand (etc) are seen
47 CHECK_NULL_FATAL(node);
48 switch (node->GetOpCode()) {
49 case OP_cior:
50 case OP_lior:
51 case OP_cand:
52 case OP_land:
53 case OP_abs:
54 case OP_bnot:
55 case OP_lnot:
56 case OP_neg:
57 case OP_recip:
58 case OP_sqrt:
59 return ExtFoldUnary(static_cast<UnaryNode *>(node));
60 case OP_add:
61 case OP_ashr:
62 case OP_band:
63 case OP_bior:
64 case OP_bxor:
65 case OP_div:
66 case OP_lshr:
67 case OP_max:
68 case OP_min:
69 case OP_mul:
70 case OP_rem:
71 case OP_shl:
72 case OP_sub:
73 case OP_eq:
74 case OP_ne:
75 case OP_ge:
76 case OP_gt:
77 case OP_le:
78 case OP_lt:
79 case OP_cmp:
80 return ExtFoldBinary(static_cast<BinaryNode *>(node));
81 case OP_select:
82 return ExtFoldTernary(static_cast<TernaryNode *>(node));
83 default:
84 return node;
85 }
86 }
87
ExtFoldUnary(UnaryNode * node)88 BaseNode *ExtConstantFold::ExtFoldUnary(UnaryNode *node)
89 {
90 CHECK_NULL_FATAL(node);
91 BaseNode *result = nullptr;
92 result = DispatchFold(node->Opnd(0));
93 if (result != node->Opnd(0)) {
94 node->SetOpnd(result, 0);
95 }
96 return node;
97 }
98
ExtFoldBinary(BinaryNode * node)99 BaseNode *ExtConstantFold::ExtFoldBinary(BinaryNode *node)
100 {
101 CHECK_NULL_FATAL(node);
102 BaseNode *result = nullptr;
103 result = DispatchFold(node->Opnd(0));
104 if (result != node->Opnd(0)) {
105 node->SetOpnd(result, 0);
106 }
107 result = DispatchFold(node->Opnd(1));
108 if (result != node->Opnd(1)) {
109 node->SetOpnd(result, 1);
110 }
111 return node;
112 }
113
ExtFoldTernary(TernaryNode * node)114 BaseNode *ExtConstantFold::ExtFoldTernary(TernaryNode *node)
115 {
116 CHECK_NULL_FATAL(node);
117 BaseNode *result = nullptr;
118 result = DispatchFold(node->Opnd(kFirstOpnd));
119 if (result != node->Opnd(kFirstOpnd)) {
120 node->SetOpnd(result, kFirstOpnd);
121 }
122 result = DispatchFold(node->Opnd(kSecondOpnd));
123 if (result != node->Opnd(kSecondOpnd)) {
124 node->SetOpnd(result, kSecondOpnd);
125 }
126 result = DispatchFold(node->Opnd(kThirdOpnd));
127 if (result != node->Opnd(kThirdOpnd)) {
128 node->SetOpnd(result, kThirdOpnd);
129 }
130 return node;
131 }
132
ExtFold(BaseNode * node)133 BaseNode *ExtConstantFold::ExtFold(BaseNode *node)
134 {
135 if (node == nullptr || kOpcodeInfo.IsStmt(node->GetOpCode())) {
136 return nullptr;
137 }
138 return DispatchFold(node);
139 }
140
ExtSimplifyBlock(BlockNode * node)141 StmtNode *ExtConstantFold::ExtSimplifyBlock(BlockNode *node)
142 {
143 CHECK_NULL_FATAL(node);
144 if (node->GetFirst() == nullptr) {
145 return node;
146 }
147 StmtNode *s = node->GetFirst();
148 do {
149 (void)ExtSimplify(s);
150 s = s->GetNext();
151 ;
152 } while (s != nullptr);
153 return node;
154 }
155
ExtSimplifyIf(IfStmtNode * node)156 StmtNode *ExtConstantFold::ExtSimplifyIf(IfStmtNode *node)
157 {
158 CHECK_NULL_FATAL(node);
159 (void)ExtSimplify(node->GetThenPart());
160 if (node->GetElsePart()) {
161 (void)ExtSimplify(node->GetElsePart());
162 }
163 BaseNode *origTest = node->Opnd();
164 BaseNode *returnValue = ExtFold(node->Opnd());
165 if (returnValue != origTest) {
166 node->SetOpnd(returnValue, 0);
167 }
168 return node;
169 }
170
ExtSimplifyDassign(DassignNode * node)171 StmtNode *ExtConstantFold::ExtSimplifyDassign(DassignNode *node)
172 {
173 CHECK_NULL_FATAL(node);
174 BaseNode *returnValue = ExtFold(node->GetRHS());
175 if (returnValue != node->GetRHS()) {
176 node->SetRHS(returnValue);
177 }
178 return node;
179 }
180
ExtSimplifyIassign(IassignNode * node)181 StmtNode *ExtConstantFold::ExtSimplifyIassign(IassignNode *node)
182 {
183 CHECK_NULL_FATAL(node);
184 BaseNode *returnValue = ExtFold(node->GetRHS());
185 if (returnValue != node->GetRHS()) {
186 node->SetRHS(returnValue);
187 }
188 return node;
189 }
190
ExtSimplifyWhile(WhileStmtNode * node)191 StmtNode *ExtConstantFold::ExtSimplifyWhile(WhileStmtNode *node)
192 {
193 CHECK_NULL_FATAL(node);
194 if (node->Opnd(0) == nullptr) {
195 return node;
196 }
197 BaseNode *returnValue = ExtFold(node->Opnd(0));
198 if (returnValue != node->Opnd(0)) {
199 node->SetOpnd(returnValue, 0);
200 }
201 return node;
202 }
203 } // namespace maple
204