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 #ifndef MAPLEBE_INCLUDE_CG_EBO_H 17 #define MAPLEBE_INCLUDE_CG_EBO_H 18 19 #include "cg_phase.h" 20 #include "cgbb.h" 21 #include "live.h" 22 #include "loop.h" 23 24 namespace maplebe { 25 namespace { 26 constexpr uint32 kEboDefaultMemHash = 0; 27 constexpr uint32 kEboNoAliasMemHash = 1; 28 constexpr uint32 kEboSpillMemHash = 2; 29 constexpr uint32 kEboCopyInsnHash = 3; 30 constexpr uint32 kEboReservedInsnHash = 4; 31 constexpr uint32 kEboMaxExpInsnHash = 1024; 32 constexpr uint32 kEboMaxOpndHash = 521; 33 constexpr uint32 kEboMaxInsnHash = kEboReservedInsnHash + kEboMaxExpInsnHash; 34 }; // namespace 35 36 #define EBO_EXP_INSN_HASH(val) ((kEboMaxExpInsnHash - 1ULL) & (static_cast<uint64>(val) >> 6)) 37 38 /* forward decls */ 39 class InsnInfo; 40 41 struct OpndInfo { OpndInfoOpndInfo42 explicit OpndInfo(Operand &opnd) : opnd(&opnd) {} 43 44 virtual ~OpndInfo() = default; 45 46 int32 hashVal = 0; /* Mem operand is placed in hash table, this is the hashVal of it, and otherwise -1. */ 47 Operand *opnd; /* Operand */ 48 Operand *replacementOpnd = nullptr; /* Rename opnd with this new name. */ 49 OpndInfo *replacementInfo = nullptr; /* Rename opnd with this info. */ 50 BB *bb = nullptr; /* The Definining bb. */ 51 Insn *insn = nullptr; /* The Defining insn. */ 52 InsnInfo *insnInfo = nullptr; 53 bool redefinedInBB = false; /* A following definition exisit in bb. */ 54 bool redefined = false; /* A following definition exisit. */ 55 Insn *redefinedInsn = nullptr; /* Next defined insn if redefinedInBB is true */ 56 #if TARGARM32 57 bool mayReDef = false; 58 #endif 59 OpndInfo *same = nullptr; /* Other definitions of the same operand. */ 60 OpndInfo *prev = nullptr; 61 OpndInfo *next = nullptr; 62 OpndInfo *hashNext = nullptr; 63 int32 refCount = 0; /* Number of references to the operand. */ 64 }; 65 66 struct MemOpndInfo : public OpndInfo { MemOpndInfoMemOpndInfo67 explicit MemOpndInfo(Operand &opnd) : OpndInfo(opnd) {} 68 69 ~MemOpndInfo() override = default; 70 GetBaseInfoMemOpndInfo71 OpndInfo *GetBaseInfo() const 72 { 73 return base; 74 } 75 GetOffsetInfoMemOpndInfo76 OpndInfo *GetOffsetInfo() const 77 { 78 return offset; 79 } 80 SetBaseInfoMemOpndInfo81 void SetBaseInfo(OpndInfo &baseInfo) 82 { 83 base = &baseInfo; 84 } 85 SetOffsetInfoMemOpndInfo86 void SetOffsetInfo(OpndInfo &offInfo) 87 { 88 offset = &offInfo; 89 } 90 91 private: 92 OpndInfo *base = nullptr; 93 OpndInfo *offset = nullptr; 94 }; 95 96 class InsnInfo { 97 public: InsnInfo(MemPool & memPool,Insn & insn)98 InsnInfo(MemPool &memPool, Insn &insn) 99 : alloc(&memPool), 100 bb(insn.GetBB()), 101 insn(&insn), 102 result(alloc.Adapter()), 103 origOpnd(alloc.Adapter()), 104 optimalOpnd(alloc.Adapter()) 105 { 106 } 107 108 virtual ~InsnInfo() = default; 109 MapleAllocator alloc; 110 uint32 hashIndex = 0; 111 bool mustNotBeRemoved = false; /* Some condition requires this insn. */ 112 BB *bb; /* The defining bb. */ 113 Insn *insn; /* The defining insn. */ 114 InsnInfo *same = nullptr; /* Other insns with the same hash value. */ 115 InsnInfo *prev = nullptr; 116 InsnInfo *next = nullptr; 117 MapleVector<OpndInfo *> result; /* Result array. */ 118 MapleVector<OpndInfo *> origOpnd; 119 MapleVector<OpndInfo *> optimalOpnd; 120 }; 121 122 class Ebo { 123 public: Ebo(CGFunc & func,MemPool & memPool,LiveAnalysis * live,bool before,const std::string & phase)124 Ebo(CGFunc &func, MemPool &memPool, LiveAnalysis *live, bool before, const std::string &phase) 125 : cgFunc(&func), 126 beforeRegAlloc(before), 127 phaseName(phase), 128 live(live), 129 eboMp(&memPool), 130 eboAllocator(&memPool), 131 visitedBBs(eboAllocator.Adapter()), 132 vRegInfo(eboAllocator.Adapter()), 133 exprInfoTable(eboAllocator.Adapter()), 134 insnInfoTable(eboAllocator.Adapter()) 135 { 136 } 137 138 virtual ~Ebo() = default; 139 140 MemOpndInfo *GetMemInfo(InsnInfo &insnInfo); SetInsnInfo(uint32 hashVal,InsnInfo & info)141 void SetInsnInfo(uint32 hashVal, InsnInfo &info) 142 { 143 DEBUG_ASSERT(hashVal < insnInfoTable.size(), "hashVal out of insnInfoTable range"); 144 insnInfoTable.at(hashVal) = &info; 145 } 146 IncRef(OpndInfo & info)147 void IncRef(OpndInfo &info) const 148 { 149 ++info.refCount; 150 } 151 DecRef(OpndInfo & info)152 void DecRef(OpndInfo &info) const 153 { 154 --info.refCount; 155 } 156 bool IsSaveReg(const Operand &opnd); 157 bool IsFrameReg(Operand &opnd) const; 158 bool OperandEqual(const Operand &op1, const Operand &op2) const; 159 Operand *GetZeroOpnd(uint32 size) const; 160 bool IsPhysicalReg(const Operand &opnd) const; 161 bool HasAssignedReg(const Operand &opnd) const; 162 bool IsOfSameClass(const Operand &op0, const Operand &op1) const; 163 bool OpndAvailableInBB(const BB &bb, OpndInfo *info); 164 bool ForwardPropCheck(const Operand *opndReplace, const OpndInfo &opndInfo, const Operand &opnd, Insn &insn); 165 bool RegForwardCheck(Insn &insn, const Operand &opnd, const Operand *opndReplace, Operand &oldOpnd, 166 const OpndInfo *tmpInfo); IsNotVisited(const BB & bb)167 bool IsNotVisited(const BB &bb) 168 { 169 return !visitedBBs.at(bb.GetId()); 170 }; 171 SetBBVisited(const BB & bb)172 void SetBBVisited(const BB &bb) 173 { 174 visitedBBs.at(bb.GetId()) = true; 175 }; 176 177 void UpdateOpndInfo(const Operand &opnd, OpndInfo &opndInfo, OpndInfo *newInfo, int32 hashVal); 178 void SetOpndInfo(const Operand &opnd, OpndInfo *opndInfo, int32 hashVal); 179 bool RegistersIdentical(const Operand &op0, const Operand &op1) const; 180 OpndInfo *GetOpndInfo(const Operand &opnd, int32 hashVal) const; 181 OpndInfo *GetNewOpndInfo(BB &bb, Insn *insn, Operand &opnd, int32 hashVal); 182 OpndInfo *OperandInfoUse(BB ¤tBB, Operand &localOpnd); 183 InsnInfo *GetNewInsnInfo(Insn &insn); 184 int32 ComputeOpndHash(const Operand &opnd) const; 185 uint32 ComputeHashVal(Insn &insn, const MapleVector<OpndInfo *> &opndInfos) const; 186 void MarkOpndLiveIntoBB(const Operand &opnd, BB &into, BB &def) const; 187 void RemoveInsn(InsnInfo &info); 188 void RemoveUses(uint32 opndNum, const MapleVector<OpndInfo *> &origInfo); 189 void HashInsn(Insn &insn, const MapleVector<OpndInfo *> &origInfo, const MapleVector<OpndInfo *> &opndInfos); 190 InsnInfo *LocateInsnInfo(const OpndInfo &info); 191 void UpdateNextInfo(const OpndInfo &opndInfo); 192 void BackupOpndInfoList(OpndInfo *saveLast); 193 void BackupInsnInfoList(InsnInfo *saveLast); 194 void AddBB2EB(BB &bb); 195 void EboInit(); 196 void EboProcessSingleBB(); 197 void EboProcess(); 198 void Run(); PhaseName()199 std::string PhaseName() const 200 { 201 return phaseName; 202 } 203 204 protected: 205 CGFunc *cgFunc; 206 bool beforeRegAlloc; /* True if perform Ebo before register allocation. */ 207 virtual OpndInfo *OperandInfoDef(BB ¤tBB, Insn ¤tInsn, Operand &localOpnd) = 0; 208 virtual const RegOperand &GetRegOperand(const Operand &opnd) const = 0; 209 virtual bool IsGlobalNeeded(Insn &insn) const = 0; 210 virtual bool IsDecoupleStaticOp(Insn &insn) const = 0; 211 virtual bool IsFmov(const Insn &insn) const = 0; 212 virtual int32 GetOffsetVal(const MemOperand &mem) const = 0; 213 virtual bool OperandEqSpecial(const Operand &op1, const Operand &op2) const = 0; 214 virtual void BuildCallerSaveRegisters() = 0; 215 virtual void DefineAsmRegisters(InsnInfo &insnInfo) = 0; 216 virtual void DefineCallerSaveRegisters(InsnInfo &insnInfo) = 0; 217 virtual void DefineReturnUseRegister(Insn &insn) = 0; 218 virtual void DefineCallUseSpecialRegister(Insn &insn) = 0; 219 virtual void DefineClinitSpecialRegisters(InsnInfo &insnInfo) = 0; 220 virtual bool IsMovToSIMDVmov(Insn &insn, const Insn &replaceInsn) const = 0; 221 virtual bool IsPseudoRet(Insn &insn) const = 0; 222 virtual bool IsAdd(const Insn &insn) const = 0; 223 virtual bool IsClinitCheck(const Insn &insn) const = 0; 224 virtual bool IsLastAndBranch(BB &bb, Insn &insn) const = 0; 225 virtual bool IsSameRedefine(BB &bb, Insn &insn, OpndInfo &opndInfo) const = 0; 226 virtual bool ResIsNotDefAndUse(Insn &insn) const = 0; 227 virtual bool LiveOutOfBB(const Operand &opnd, const BB &bb) const = 0; 228 virtual bool IsInvalidReg(const RegOperand &opnd) const = 0; 229 virtual bool IsZeroRegister(const Operand &opnd) const = 0; 230 virtual bool IsConstantImmOrReg(const Operand &opnd) const = 0; 231 OpndInfo *BuildMemOpndInfo(BB &bb, Insn &insn, Operand &opnd, uint32 opndIndex); 232 OpndInfo *BuildOperandInfo(BB &bb, Insn &insn, Operand &opnd, uint32 opndIndex, MapleVector<OpndInfo *> &origInfos); 233 void FindRedundantInsns(BB &bb, Insn *&insn, const Insn *prev, bool insnReplaced, MapleVector<Operand *> &opnds, 234 MapleVector<OpndInfo *> &opndInfos, const MapleVector<OpndInfo *> &origInfos); 235 void PreProcessSpecialInsn(Insn &insn); 236 237 std::string phaseName; 238 LiveAnalysis *live; 239 uint32 bbNum = 0; /* bb numbers for an extend block. */ 240 MemPool *eboMp; 241 MapleAllocator eboAllocator; 242 MapleVector<bool> visitedBBs; 243 OpndInfo *firstOpndInfo = nullptr; 244 OpndInfo *lastOpndInfo = nullptr; 245 InsnInfo *firstInsnInfo = nullptr; 246 InsnInfo *lastInsnInfo = nullptr; 247 MapleUnorderedMap<uint32, OpndInfo *> vRegInfo; 248 MapleVector<OpndInfo *> exprInfoTable; 249 MapleVector<InsnInfo *> insnInfoTable; 250 bool optSuccess = false; 251 }; 252 253 MAPLE_FUNC_PHASE_DECLARE(CgEbo0, maplebe::CGFunc) 254 MAPLE_FUNC_PHASE_DECLARE(CgEbo1, maplebe::CGFunc) 255 MAPLE_FUNC_PHASE_DECLARE(CgPostEbo, maplebe::CGFunc) 256 } /* namespace maplebe */ 257 258 #endif /* MAPLEBE_INCLUDE_CG_EBO_H */ 259