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_LOOP_GUEST_CONTEXT_OPTIMIZER_H_
18 #define BERBERIS_BACKEND_X86_64_LOOP_GUEST_CONTEXT_OPTIMIZER_H_
19 
20 #include <iterator>
21 #include <optional>
22 #include <utility>
23 
24 #include "berberis/backend/x86_64/machine_ir.h"
25 #include "berberis/backend/x86_64/machine_ir_analysis.h"
26 #include "berberis/base/arena_vector.h"
27 
28 namespace berberis::x86_64 {
29 
30 // Types exported for testing:
31 enum class MovType { kMovq, kMovdqa, kMovw, kMovsd };
32 
33 struct MappedRegInfo {
34   MachineReg reg;
35   MovType mov_type;
36   bool is_modified;
37 };
38 
39 using MemRegMap = ArenaVector<std::optional<MappedRegInfo>>;
40 
41 // Functions exported for testing:
42 void ReplaceGetAndUpdateMap(MachineIR* ir,
43                             const MachineInsnList::iterator insn_it,
44                             MemRegMap& mem_reg_map);
45 void ReplacePutAndUpdateMap(MachineIR* ir,
46                             const MachineInsnList::iterator insn_it,
47                             MemRegMap& mem_reg_map);
48 void GenerateGetInsns(MachineIR* ir, MachineBasicBlock* bb, const MemRegMap& mem_reg_map);
49 void GeneratePutInsns(MachineIR* ir, MachineBasicBlock* bb, const MemRegMap& mem_reg_map);
50 void GenerateGetsInPreloop(MachineIR* ir, const Loop* loop, const MemRegMap& mem_reg_map);
51 void GeneratePutsInPostloop(MachineIR* ir, const Loop* loop, const MemRegMap& mem_reg_map);
52 ArenaVector<int> CountGuestRegAccesses(const MachineIR* ir, const Loop* loop);
53 
54 using OffsetCounterMap = ArenaVector<std::pair<size_t, int>>;
55 OffsetCounterMap GetSortedOffsetCounters(MachineIR* ir, Loop* loop);
56 
57 struct OptimizeLoopParams {
58   size_t general_reg_limit = 12;
59   size_t simd_reg_limit = 12;
60 };
61 
62 void OptimizeLoop(MachineIR* machine_ir,
63                   Loop* loop,
64                   const OptimizeLoopParams& params = OptimizeLoopParams());
65 
66 // Loop optimization interface:
67 void RemoveLoopGuestContextAccesses(MachineIR* machine_ir);
68 
69 }  // namespace berberis::x86_64
70 
71 #endif  // BERBERIS_BACKEND_X86_64_LOOP_GUEST_CONTEXT_OPTIMIZER_H_
72