1 /* 2 * Copyright (C) 2023 The Android Open Source Project 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 17 #ifndef BERBERIS_BACKEND_X86_64_INSN_FOLDING_H_ 18 #define BERBERIS_BACKEND_X86_64_INSN_FOLDING_H_ 19 20 #include <tuple> 21 22 #include "berberis/backend/x86_64/machine_ir.h" 23 #include "berberis/base/arena_vector.h" 24 25 namespace berberis::x86_64 { 26 27 // The DefMap class stores a map between registers and their latest definitions and positions. 28 class DefMap { 29 public: DefMap(size_t size,Arena * arena)30 DefMap(size_t size, Arena* arena) 31 : def_map_(size, {nullptr, 0}, arena), flags_reg_(kInvalidMachineReg), index_(0) {} Get(MachineReg reg)32 [[nodiscard]] std::pair<const MachineInsn*, int> Get(MachineReg reg) const { 33 if (!reg.IsVReg()) { 34 return {nullptr, 0}; 35 } 36 return def_map_.at(reg.GetVRegIndex()); 37 } Get(MachineReg reg,int use_index)38 [[nodiscard]] std::pair<const MachineInsn*, int> Get(MachineReg reg, int use_index) const { 39 if (!reg.IsVReg()) { 40 return {nullptr, 0}; 41 } 42 auto [def_insn, def_insn_index] = def_map_.at(reg.GetVRegIndex()); 43 if (!def_insn || def_insn_index > use_index) { 44 return {nullptr, 0}; 45 } 46 return {def_insn, def_insn_index}; 47 } 48 void ProcessInsn(const MachineInsn* insn); 49 void Initialize(); 50 51 private: Set(MachineReg reg,const MachineInsn * insn)52 void Set(MachineReg reg, const MachineInsn* insn) { 53 if (reg.IsVReg()) { 54 def_map_.at(reg.GetVRegIndex()) = std::pair(insn, index_); 55 } 56 } 57 void MapDefRegs(const MachineInsn* insn); 58 ArenaVector<std::pair<const MachineInsn*, int>> def_map_; 59 MachineReg flags_reg_; 60 int index_; 61 }; 62 63 class InsnFolding { 64 public: InsnFolding(DefMap & def_map,MachineIR * machine_ir)65 explicit InsnFolding(DefMap& def_map, MachineIR* machine_ir) 66 : def_map_(def_map), machine_ir_(machine_ir) {} 67 68 std::tuple<bool, MachineInsn*> TryFoldInsn(const MachineInsn* insn); 69 70 private: 71 DefMap& def_map_; 72 MachineIR* machine_ir_; 73 bool IsRegImm(MachineReg reg, uint64_t* imm) const; 74 bool IsWritingSameFlagsValue(const MachineInsn* insn) const; 75 template <bool is_input_64bit> 76 std::tuple<bool, MachineInsn*> TryFoldImmediateInput(const MachineInsn* insn); 77 std::tuple<bool, MachineInsn*> TryFoldRedundantMovl(const MachineInsn* insn); 78 MachineInsn* NewImmInsnFromRegInsn(const MachineInsn* insn, int32_t imm); 79 }; 80 81 void FoldInsns(MachineIR* machine_ir); 82 83 void FoldWriteFlags(MachineIR* machine_ir); 84 85 } // namespace berberis::x86_64 86 87 #endif // BERBERIS_BACKEND_X86_64_INSN_FOLDING_H_ 88