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 "x64_local_opt.h"
17 #include "x64_reaching.h"
18 #include "operand.h"
19 #include "x64_cg.h"
20
21 namespace maplebe {
DoLocalCopyProp()22 void X64LocalOpt::DoLocalCopyProp()
23 {
24 LocalOptimizeManager optManager(*cgFunc, *GetRDInfo());
25 optManager.Optimize<LocalCopyRegProp>();
26 optManager.Optimize<X64RedundantDefRemove>();
27 }
28
CheckCondition(Insn & insn)29 bool LocalCopyRegProp::CheckCondition(Insn &insn)
30 {
31 MOperator mOp = insn.GetMachineOpcode();
32 if (mOp != MOP_movb_r_r && mOp != MOP_movw_r_r && mOp != MOP_movl_r_r && mOp != MOP_movq_r_r) {
33 return false;
34 }
35 DEBUG_ASSERT(insn.GetOperand(kInsnFirstOpnd).IsRegister(), "expects registers");
36 DEBUG_ASSERT(insn.GetOperand(kInsnSecondOpnd).IsRegister(), "expects registers");
37 auto ®Use = static_cast<RegOperand &>(insn.GetOperand(kInsnFirstOpnd));
38 auto ®Def = static_cast<RegOperand &>(insn.GetOperand(kInsnSecondOpnd));
39 if (regUse.GetRegisterNumber() == regDef.GetRegisterNumber()) {
40 return false;
41 }
42 auto &liveOutRegSet = insn.GetBB()->GetLiveOutRegNO();
43 if (liveOutRegSet.find(regDef.GetRegisterNumber()) != liveOutRegSet.end()) {
44 return false;
45 }
46 return true;
47 }
48
Optimize(BB & bb,Insn & insn)49 void LocalCopyRegProp::Optimize(BB &bb, Insn &insn)
50 {
51 InsnSet useInsnSet;
52 Insn *nextInsn = insn.GetNextMachineInsn();
53 if (nextInsn == nullptr) {
54 return;
55 }
56 auto ®Def = static_cast<RegOperand &>(insn.GetOperand(kInsnSecondOpnd));
57 reachingDef->FindRegUseBetweenInsn(regDef.GetRegisterNumber(), nextInsn, bb.GetLastInsn(), useInsnSet);
58 bool redefined = false;
59 auto &replaceOpnd = static_cast<RegOperand &>(insn.GetOperand(kInsnFirstOpnd));
60 for (Insn *tInsn : useInsnSet) {
61 std::vector<Insn *> defInsnVec =
62 reachingDef->FindRegDefBetweenInsn(replaceOpnd.GetRegisterNumber(), &insn, tInsn, false, false);
63 if (defInsnVec.size() > 0) {
64 redefined = true;
65 }
66 if (redefined) {
67 break;
68 }
69 propagateOperand(*tInsn, regDef, replaceOpnd);
70 }
71 return;
72 }
73
propagateOperand(Insn & insn,RegOperand & oldOpnd,RegOperand & replaceOpnd)74 bool LocalCopyRegProp::propagateOperand(Insn &insn, RegOperand &oldOpnd, RegOperand &replaceOpnd)
75 {
76 bool propagateSuccess = false;
77 uint32 opndNum = insn.GetOperandSize();
78 const InsnDesc *md = insn.GetDesc();
79 if (insn.IsShift() && oldOpnd.GetRegisterNumber() == x64::RCX) {
80 return false;
81 }
82 if (insn.GetMachineOpcode() == MOP_pseudo_ret_int) {
83 return false;
84 }
85 for (uint32 i = 0; i < opndNum; i++) {
86 Operand &opnd = insn.GetOperand(i);
87 if (opnd.IsList()) {
88 /* list operands are used by call,
89 * which can not be propagated
90 */
91 continue;
92 }
93
94 auto *regProp = md->opndMD[i];
95 if (regProp->IsUse() && !regProp->IsDef() && opnd.IsRegister()) {
96 RegOperand ®Opnd = static_cast<RegOperand &>(opnd);
97 if (RegOperand::IsSameReg(regOpnd, oldOpnd)) {
98 insn.SetOperand(i, replaceOpnd);
99 propagateSuccess = true;
100 }
101 }
102 }
103 return propagateSuccess;
104 }
105
Optimize(BB & bb,Insn & insn)106 void X64RedundantDefRemove::Optimize(BB &bb, Insn &insn)
107 {
108 const InsnDesc *md = insn.GetDesc();
109 RegOperand *regDef = nullptr;
110 uint32 opndNum = insn.GetOperandSize();
111 for (uint32 i = 0; i < opndNum; ++i) {
112 Operand &opnd = insn.GetOperand(i);
113 auto *opndDesc = md->opndMD[i];
114 if (opndDesc->IsRegDef()) {
115 regDef = static_cast<RegOperand *>(&opnd);
116 }
117 }
118 InsnSet useInsnSet;
119 Insn *nextInsn = insn.GetNextMachineInsn();
120 if (nextInsn == nullptr) {
121 return;
122 }
123 DEBUG_ASSERT(regDef != nullptr, "nullptr check");
124 reachingDef->FindRegUseBetweenInsn(regDef->GetRegisterNumber(), nextInsn, bb.GetLastInsn(), useInsnSet);
125 if (useInsnSet.size() == 0) {
126 bb.RemoveInsn(insn);
127 return;
128 }
129 return;
130 }
131 } // namespace maplebe
132