• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "operand.h"
17 
18 namespace maplebe {
IsMoveWidableImmediate(uint64 val,uint32 bitLen)19 bool IsMoveWidableImmediate(uint64 val, uint32 bitLen)
20 {
21     if (bitLen == k64BitSize) {
22         /* 0xHHHH000000000000 or 0x0000HHHH00000000, return true */
23         if (((val & ((static_cast<uint64>(0xffff)) << k48BitSize)) == val) ||
24             ((val & ((static_cast<uint64>(0xffff)) << k32BitSize)) == val)) {
25             return true;
26         }
27     } else {
28         /* get lower 32 bits */
29         val &= static_cast<uint64>(0xffffffff);
30     }
31     /* 0x00000000HHHH0000 or 0x000000000000HHHH, return true */
32     return ((val & ((static_cast<uint64>(0xffff)) << k16BitSize)) == val ||
33             (val & ((static_cast<uint64>(0xffff)) << 0)) == val);
34 }
35 
BetterUseMOVZ(uint64 val)36 bool BetterUseMOVZ(uint64 val)
37 {
38     int32 n16zerosChunks = 0;
39     int32 n16onesChunks = 0;
40     uint64 sa = 0;
41     /* a 64 bits number is split 4 chunks, each chunk has 16 bits. check each chunk whether is all 1 or is all 0 */
42     for (uint64 i = 0; i < k4BitSize; ++i, sa += k16BitSize) {
43         uint64 chunkVal = (val >> (static_cast<uint64>(sa))) & 0x0000FFFFUL;
44         if (chunkVal == 0) {
45             ++n16zerosChunks;
46         } else if (chunkVal == 0xFFFFUL) {
47             ++n16onesChunks;
48         }
49     }
50     /*
51      * note that since we already check if the value
52      * can be movable with as a single mov instruction,
53      * we should not expect either n_16zeros_chunks>=3 or n_16ones_chunks>=3
54      */
55 #if DEBUG
56     constexpr uint32 kN16ChunksCheck = 2;
57     DEBUG_ASSERT(static_cast<uint32>(n16zerosChunks) <= kN16ChunksCheck, "n16zerosChunks ERR");
58     DEBUG_ASSERT(static_cast<uint32>(n16onesChunks) <= kN16ChunksCheck, "n16onesChunks ERR");
59 #endif
60     return (n16zerosChunks >= n16onesChunks);
61 }
62 
operator ==(const RegOperand & o) const63 bool RegOperand::operator==(const RegOperand &o) const
64 {
65     regno_t myRn = GetRegisterNumber();
66     uint32 mySz = GetSize();
67     uint32 myFl = regFlag;
68     regno_t otherRn = o.GetRegisterNumber();
69     uint32 otherSz = o.GetSize();
70     uint32 otherFl = o.regFlag;
71 
72     if (IsPhysicalRegister()) {
73         return (myRn == otherRn && mySz == otherSz && myFl == otherFl);
74     }
75     return (myRn == otherRn && mySz == otherSz);
76 }
77 
operator <(const RegOperand & o) const78 bool RegOperand::operator<(const RegOperand &o) const
79 {
80     regno_t myRn = GetRegisterNumber();
81     uint32 mySz = GetSize();
82     uint32 myFl = regFlag;
83     regno_t otherRn = o.GetRegisterNumber();
84     uint32 otherSz = o.GetSize();
85     uint32 otherFl = o.regFlag;
86     return myRn < otherRn || (myRn == otherRn && mySz < otherSz) ||
87            (myRn == otherRn && mySz == otherSz && myFl < otherFl);
88 }
89 
GetOffset() const90 Operand *MemOperand::GetOffset() const
91 {
92     switch (addrMode) {
93         case kAddrModeBOi:
94             return GetOffsetOperand();
95         case kAddrModeBOrX:
96             return GetIndexRegister();
97         case kAddrModeLiteral:
98             break;
99         case kAddrModeLo12Li:
100             break;
101         default:
102             DEBUG_ASSERT(false, "error memoperand dump");
103             break;
104     }
105     return nullptr;
106 }
107 
Equals(Operand & op) const108 bool MemOperand::Equals(Operand &op) const
109 {
110     if (!op.IsMemoryAccessOperand()) {
111         return false;
112     }
113     return Equals(static_cast<MemOperand &>(op));
114 }
115 
Equals(const MemOperand & op) const116 bool MemOperand::Equals(const MemOperand &op) const
117 {
118     if (&op == this) {
119         return true;
120     }
121 
122     if (addrMode == op.GetAddrMode()) {
123         switch (addrMode) {
124             case kAddrModeBOi:
125                 return (GetBaseRegister()->Equals(*op.GetBaseRegister()) &&
126                         GetOffsetImmediate()->Equals(*op.GetOffsetImmediate()));
127             case kAddrModeBOrX:
128                 return (GetBaseRegister()->Equals(*op.GetBaseRegister()) &&
129                         GetIndexRegister()->Equals(*op.GetIndexRegister()) &&
130                         GetExtendAsString() == op.GetExtendAsString() && ShiftAmount() == op.ShiftAmount());
131             case kAddrModeLiteral:
132                 return GetSymbolName() == op.GetSymbolName();
133             case kAddrModeLo12Li:
134                 return (GetBaseRegister()->Equals(*op.GetBaseRegister()) && GetSymbolName() == op.GetSymbolName() &&
135                         GetOffsetImmediate()->Equals(*op.GetOffsetImmediate()));
136             default:
137                 DEBUG_ASSERT(false, "error memoperand");
138                 break;
139         }
140     }
141     return false;
142 }
143 
Less(const Operand & right) const144 bool MemOperand::Less(const Operand &right) const
145 {
146     if (&right == this) {
147         return false;
148     }
149 
150     /* For different type. */
151     if (GetKind() != right.GetKind()) {
152         return GetKind() < right.GetKind();
153     }
154 
155     const MemOperand *rightOpnd = static_cast<const MemOperand *>(&right);
156     if (addrMode != rightOpnd->addrMode) {
157         return addrMode < rightOpnd->addrMode;
158     }
159 
160     switch (addrMode) {
161         case kAddrModeBOi: {
162             DEBUG_ASSERT(idxOpt == kIntact, "Should not compare pre/post index addressing.");
163 
164             RegOperand *baseReg = GetBaseRegister();
165             RegOperand *rbaseReg = rightOpnd->GetBaseRegister();
166             CHECK_FATAL(baseReg != nullptr, "nullptr check");
167             int32 nRet = baseReg->RegCompare(*rbaseReg);
168             if (nRet == 0) {
169                 Operand *ofstOpnd = GetOffsetOperand();
170                 const Operand *rofstOpnd = rightOpnd->GetOffsetOperand();
171                 return ofstOpnd->Less(*rofstOpnd);
172             }
173             return nRet < 0;
174         }
175         case kAddrModeBOrX: {
176             if (noExtend != rightOpnd->noExtend) {
177                 return noExtend;
178             }
179             if (!noExtend && extend != rightOpnd->extend) {
180                 return extend < rightOpnd->extend;
181             }
182             RegOperand *indexReg = GetIndexRegister();
183             const RegOperand *rindexReg = rightOpnd->GetIndexRegister();
184             CHECK_FATAL(indexReg != nullptr, "nullptr check");
185             return indexReg->Less(*rindexReg);
186         }
187         case kAddrModeLiteral: {
188             return static_cast<const void *>(GetSymbol()) < static_cast<const void *>(rightOpnd->GetSymbol());
189         }
190         case kAddrModeLo12Li: {
191             if (GetSymbol() != rightOpnd->GetSymbol()) {
192                 return static_cast<const void *>(GetSymbol()) < static_cast<const void *>(rightOpnd->GetSymbol());
193             }
194             Operand *ofstOpnd = GetOffsetOperand();
195             const Operand *rofstOpnd = rightOpnd->GetOffsetOperand();
196             return ofstOpnd->Less(*rofstOpnd);
197         }
198         default:
199             DEBUG_ASSERT(false, "Internal error.");
200             return false;
201     }
202 }
203 
204 const char *CondOperand::ccStrs[kCcLast] = {"EQ", "NE", "CS", "HS", "CC", "LO", "MI", "PL", "VS",
205                                             "VC", "HI", "LS", "GE", "LT", "GT", "LE", "AL"};
206 
Less(const Operand & right) const207 bool CondOperand::Less(const Operand &right) const
208 {
209     if (&right == this) {
210         return false;
211     }
212 
213     /* For different type. */
214     if (GetKind() != right.GetKind()) {
215         return GetKind() < right.GetKind();
216     }
217 
218     const CondOperand *rightOpnd = static_cast<const CondOperand *>(&right);
219 
220     /* The same type. */
221     if (cc == CC_AL || rightOpnd->cc == CC_AL) {
222         return false;
223     }
224     return cc < rightOpnd->cc;
225 }
226 
GetLeastCommonValidBit() const227 uint32 PhiOperand::GetLeastCommonValidBit() const
228 {
229     uint32 leastCommonVb = 0;
230     for (auto phiOpnd : phiList) {
231         uint32 curVb = phiOpnd.second->GetValidBitsNum();
232         if (curVb > leastCommonVb) {
233             leastCommonVb = curVb;
234         }
235     }
236     return leastCommonVb;
237 }
IsRedundancy() const238 bool PhiOperand::IsRedundancy() const
239 {
240     uint32 srcSsaIdx = 0;
241     for (auto phiOpnd : phiList) {
242         if (srcSsaIdx == 0) {
243             srcSsaIdx = phiOpnd.second->GetRegisterNumber();
244         }
245         if (srcSsaIdx != phiOpnd.second->GetRegisterNumber()) {
246             return false;
247         }
248     }
249     return true;
250 }
251 } /* namespace maplebe */
252