1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_PARALLEL_MOVE_RESOLVER_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_PARALLEL_MOVE_RESOLVER_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include "base/arena_containers.h" 21*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 22*795d594fSAndroid Build Coastguard Worker #include "base/value_object.h" 23*795d594fSAndroid Build Coastguard Worker #include "data_type.h" 24*795d594fSAndroid Build Coastguard Worker #include "locations.h" 25*795d594fSAndroid Build Coastguard Worker 26*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker class HParallelMove; 29*795d594fSAndroid Build Coastguard Worker class MoveOperands; 30*795d594fSAndroid Build Coastguard Worker 31*795d594fSAndroid Build Coastguard Worker // Helper classes to resolve a set of parallel moves. Architecture dependent code generator must 32*795d594fSAndroid Build Coastguard Worker // have their own subclass that implements corresponding virtual functions. 33*795d594fSAndroid Build Coastguard Worker class ParallelMoveResolver : public ValueObject { 34*795d594fSAndroid Build Coastguard Worker public: ParallelMoveResolver(ArenaAllocator * allocator)35*795d594fSAndroid Build Coastguard Worker explicit ParallelMoveResolver(ArenaAllocator* allocator) 36*795d594fSAndroid Build Coastguard Worker : moves_(allocator->Adapter(kArenaAllocParallelMoveResolver)) { 37*795d594fSAndroid Build Coastguard Worker moves_.reserve(32); 38*795d594fSAndroid Build Coastguard Worker } ~ParallelMoveResolver()39*795d594fSAndroid Build Coastguard Worker virtual ~ParallelMoveResolver() {} 40*795d594fSAndroid Build Coastguard Worker 41*795d594fSAndroid Build Coastguard Worker // Resolve a set of parallel moves, emitting assembler instructions. 42*795d594fSAndroid Build Coastguard Worker virtual void EmitNativeCode(HParallelMove* parallel_move) = 0; 43*795d594fSAndroid Build Coastguard Worker 44*795d594fSAndroid Build Coastguard Worker protected: 45*795d594fSAndroid Build Coastguard Worker // Build the initial list of moves. 46*795d594fSAndroid Build Coastguard Worker void BuildInitialMoveList(HParallelMove* parallel_move); 47*795d594fSAndroid Build Coastguard Worker 48*795d594fSAndroid Build Coastguard Worker ArenaVector<MoveOperands*> moves_; 49*795d594fSAndroid Build Coastguard Worker 50*795d594fSAndroid Build Coastguard Worker private: 51*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolver); 52*795d594fSAndroid Build Coastguard Worker }; 53*795d594fSAndroid Build Coastguard Worker 54*795d594fSAndroid Build Coastguard Worker // This helper class uses swap to resolve dependencies and may emit swap. 55*795d594fSAndroid Build Coastguard Worker class ParallelMoveResolverWithSwap : public ParallelMoveResolver { 56*795d594fSAndroid Build Coastguard Worker public: ParallelMoveResolverWithSwap(ArenaAllocator * allocator)57*795d594fSAndroid Build Coastguard Worker explicit ParallelMoveResolverWithSwap(ArenaAllocator* allocator) 58*795d594fSAndroid Build Coastguard Worker : ParallelMoveResolver(allocator) {} ~ParallelMoveResolverWithSwap()59*795d594fSAndroid Build Coastguard Worker virtual ~ParallelMoveResolverWithSwap() {} 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker // Resolve a set of parallel moves, emitting assembler instructions. 62*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(HParallelMove* parallel_move) override; 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker protected: 65*795d594fSAndroid Build Coastguard Worker class ScratchRegisterScope : public ValueObject { 66*795d594fSAndroid Build Coastguard Worker public: 67*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope(ParallelMoveResolverWithSwap* resolver, 68*795d594fSAndroid Build Coastguard Worker int blocked, 69*795d594fSAndroid Build Coastguard Worker int if_scratch, 70*795d594fSAndroid Build Coastguard Worker int number_of_registers); 71*795d594fSAndroid Build Coastguard Worker ~ScratchRegisterScope(); 72*795d594fSAndroid Build Coastguard Worker GetRegister()73*795d594fSAndroid Build Coastguard Worker int GetRegister() const { return reg_; } IsSpilled()74*795d594fSAndroid Build Coastguard Worker bool IsSpilled() const { return spilled_; } 75*795d594fSAndroid Build Coastguard Worker 76*795d594fSAndroid Build Coastguard Worker private: 77*795d594fSAndroid Build Coastguard Worker ParallelMoveResolverWithSwap* resolver_; 78*795d594fSAndroid Build Coastguard Worker int reg_; 79*795d594fSAndroid Build Coastguard Worker bool spilled_; 80*795d594fSAndroid Build Coastguard Worker }; 81*795d594fSAndroid Build Coastguard Worker 82*795d594fSAndroid Build Coastguard Worker // Return true if the location can be scratched. 83*795d594fSAndroid Build Coastguard Worker bool IsScratchLocation(Location loc); 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker // Allocate a scratch register for performing a move. The method will try to use 86*795d594fSAndroid Build Coastguard Worker // a register that is the destination of a move, but that move has not been emitted yet. 87*795d594fSAndroid Build Coastguard Worker int AllocateScratchRegister(int blocked, int if_scratch, int register_count, bool* spilled); 88*795d594fSAndroid Build Coastguard Worker 89*795d594fSAndroid Build Coastguard Worker // Emit a move. 90*795d594fSAndroid Build Coastguard Worker virtual void EmitMove(size_t index) = 0; 91*795d594fSAndroid Build Coastguard Worker 92*795d594fSAndroid Build Coastguard Worker // Execute a move by emitting a swap of two operands. 93*795d594fSAndroid Build Coastguard Worker virtual void EmitSwap(size_t index) = 0; 94*795d594fSAndroid Build Coastguard Worker 95*795d594fSAndroid Build Coastguard Worker virtual void SpillScratch(int reg) = 0; 96*795d594fSAndroid Build Coastguard Worker virtual void RestoreScratch(int reg) = 0; 97*795d594fSAndroid Build Coastguard Worker 98*795d594fSAndroid Build Coastguard Worker static constexpr int kNoRegister = -1; 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker private: 101*795d594fSAndroid Build Coastguard Worker // Perform the move at the moves_ index in question (possibly requiring 102*795d594fSAndroid Build Coastguard Worker // other moves to satisfy dependencies). 103*795d594fSAndroid Build Coastguard Worker // 104*795d594fSAndroid Build Coastguard Worker // Return whether another move in the dependency cycle needs to swap. This 105*795d594fSAndroid Build Coastguard Worker // is to handle 64bits swaps: 106*795d594fSAndroid Build Coastguard Worker // 1) In the case of register pairs, where we want the pair to swap first to avoid 107*795d594fSAndroid Build Coastguard Worker // building pairs that are unexpected by the code generator. For example, if 108*795d594fSAndroid Build Coastguard Worker // we were to swap R1 with R2, we would need to update all locations using 109*795d594fSAndroid Build Coastguard Worker // R2 to R1. So a (R2,R3) pair register could become (R1,R3). We could make 110*795d594fSAndroid Build Coastguard Worker // the code generator understand such pairs, but it's easier and cleaner to 111*795d594fSAndroid Build Coastguard Worker // just not create such pairs and exchange pairs in priority. 112*795d594fSAndroid Build Coastguard Worker // 2) Even when the architecture does not have pairs, we must handle 64bits swaps 113*795d594fSAndroid Build Coastguard Worker // first. Consider the case: (R0->R1) (R1->S) (S->R0), where 'S' is a single 114*795d594fSAndroid Build Coastguard Worker // stack slot. If we end up swapping S and R0, S will only contain the low bits 115*795d594fSAndroid Build Coastguard Worker // of R0. If R0->R1 is for a 64bits instruction, R1 will therefore not contain 116*795d594fSAndroid Build Coastguard Worker // the right value. 117*795d594fSAndroid Build Coastguard Worker MoveOperands* PerformMove(size_t index); 118*795d594fSAndroid Build Coastguard Worker 119*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverWithSwap); 120*795d594fSAndroid Build Coastguard Worker }; 121*795d594fSAndroid Build Coastguard Worker 122*795d594fSAndroid Build Coastguard Worker // This helper class uses additional scratch registers to resolve dependencies. It supports all kind 123*795d594fSAndroid Build Coastguard Worker // of dependency cycles and does not care about the register layout. 124*795d594fSAndroid Build Coastguard Worker class ParallelMoveResolverNoSwap : public ParallelMoveResolver { 125*795d594fSAndroid Build Coastguard Worker public: ParallelMoveResolverNoSwap(ArenaAllocator * allocator)126*795d594fSAndroid Build Coastguard Worker explicit ParallelMoveResolverNoSwap(ArenaAllocator* allocator) 127*795d594fSAndroid Build Coastguard Worker : ParallelMoveResolver(allocator), 128*795d594fSAndroid Build Coastguard Worker scratches_(allocator->Adapter(kArenaAllocParallelMoveResolver)), 129*795d594fSAndroid Build Coastguard Worker pending_moves_(allocator->Adapter(kArenaAllocParallelMoveResolver)), 130*795d594fSAndroid Build Coastguard Worker allocator_(allocator) { 131*795d594fSAndroid Build Coastguard Worker scratches_.reserve(32); 132*795d594fSAndroid Build Coastguard Worker pending_moves_.reserve(8); 133*795d594fSAndroid Build Coastguard Worker } ~ParallelMoveResolverNoSwap()134*795d594fSAndroid Build Coastguard Worker virtual ~ParallelMoveResolverNoSwap() {} 135*795d594fSAndroid Build Coastguard Worker 136*795d594fSAndroid Build Coastguard Worker // Resolve a set of parallel moves, emitting assembler instructions. 137*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(HParallelMove* parallel_move) override; 138*795d594fSAndroid Build Coastguard Worker 139*795d594fSAndroid Build Coastguard Worker protected: 140*795d594fSAndroid Build Coastguard Worker // Called at the beginning of EmitNativeCode(). A subclass may put some architecture dependent 141*795d594fSAndroid Build Coastguard Worker // initialization here. 142*795d594fSAndroid Build Coastguard Worker virtual void PrepareForEmitNativeCode() = 0; 143*795d594fSAndroid Build Coastguard Worker 144*795d594fSAndroid Build Coastguard Worker // Called at the end of EmitNativeCode(). A subclass may put some architecture dependent cleanup 145*795d594fSAndroid Build Coastguard Worker // here. All scratch locations will be removed after this call. 146*795d594fSAndroid Build Coastguard Worker virtual void FinishEmitNativeCode() = 0; 147*795d594fSAndroid Build Coastguard Worker 148*795d594fSAndroid Build Coastguard Worker // Allocate a scratch location to perform a move from input kind of location. A subclass should 149*795d594fSAndroid Build Coastguard Worker // implement this to get the best fit location. If there is no suitable physical register, it can 150*795d594fSAndroid Build Coastguard Worker // also return a stack slot. 151*795d594fSAndroid Build Coastguard Worker virtual Location AllocateScratchLocationFor(Location::Kind kind) = 0; 152*795d594fSAndroid Build Coastguard Worker 153*795d594fSAndroid Build Coastguard Worker // Called after a move which takes a scratch location as source. A subclass can defer the cleanup 154*795d594fSAndroid Build Coastguard Worker // to FinishEmitNativeCode(). 155*795d594fSAndroid Build Coastguard Worker virtual void FreeScratchLocation(Location loc) = 0; 156*795d594fSAndroid Build Coastguard Worker 157*795d594fSAndroid Build Coastguard Worker // Emit a move. 158*795d594fSAndroid Build Coastguard Worker virtual void EmitMove(size_t index) = 0; 159*795d594fSAndroid Build Coastguard Worker 160*795d594fSAndroid Build Coastguard Worker // Return a scratch location from the moves which exactly matches the kind. 161*795d594fSAndroid Build Coastguard Worker // Return Location::NoLocation() if no matching scratch location can be found. 162*795d594fSAndroid Build Coastguard Worker Location GetScratchLocation(Location::Kind kind); 163*795d594fSAndroid Build Coastguard Worker 164*795d594fSAndroid Build Coastguard Worker // Add a location to the scratch list which can be returned from GetScratchLocation() to resolve 165*795d594fSAndroid Build Coastguard Worker // dependency cycles. 166*795d594fSAndroid Build Coastguard Worker void AddScratchLocation(Location loc); 167*795d594fSAndroid Build Coastguard Worker 168*795d594fSAndroid Build Coastguard Worker // Remove a location from the scratch list. 169*795d594fSAndroid Build Coastguard Worker void RemoveScratchLocation(Location loc); 170*795d594fSAndroid Build Coastguard Worker 171*795d594fSAndroid Build Coastguard Worker // List of scratch locations. 172*795d594fSAndroid Build Coastguard Worker ArenaVector<Location> scratches_; 173*795d594fSAndroid Build Coastguard Worker 174*795d594fSAndroid Build Coastguard Worker private: 175*795d594fSAndroid Build Coastguard Worker // Perform the move at the given index in `moves_` (possibly requiring other moves to satisfy 176*795d594fSAndroid Build Coastguard Worker // dependencies). 177*795d594fSAndroid Build Coastguard Worker void PerformMove(size_t index); 178*795d594fSAndroid Build Coastguard Worker 179*795d594fSAndroid Build Coastguard Worker void UpdateMoveSource(Location from, Location to); 180*795d594fSAndroid Build Coastguard Worker 181*795d594fSAndroid Build Coastguard Worker void AddPendingMove(Location source, Location destination, DataType::Type type); 182*795d594fSAndroid Build Coastguard Worker 183*795d594fSAndroid Build Coastguard Worker void DeletePendingMove(MoveOperands* move); 184*795d594fSAndroid Build Coastguard Worker 185*795d594fSAndroid Build Coastguard Worker // Find a move that may be unblocked after (loc -> XXX) is performed. 186*795d594fSAndroid Build Coastguard Worker MoveOperands* GetUnblockedPendingMove(Location loc); 187*795d594fSAndroid Build Coastguard Worker 188*795d594fSAndroid Build Coastguard Worker // Return true if the location is blocked by outstanding moves. 189*795d594fSAndroid Build Coastguard Worker bool IsBlockedByMoves(Location loc); 190*795d594fSAndroid Build Coastguard Worker 191*795d594fSAndroid Build Coastguard Worker // Return the number of pending moves. 192*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfPendingMoves(); 193*795d594fSAndroid Build Coastguard Worker 194*795d594fSAndroid Build Coastguard Worker // Additional pending moves which might be added to resolve dependency cycle. 195*795d594fSAndroid Build Coastguard Worker ArenaVector<MoveOperands*> pending_moves_; 196*795d594fSAndroid Build Coastguard Worker 197*795d594fSAndroid Build Coastguard Worker // Used to allocate pending MoveOperands. 198*795d594fSAndroid Build Coastguard Worker ArenaAllocator* const allocator_; 199*795d594fSAndroid Build Coastguard Worker 200*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverNoSwap); 201*795d594fSAndroid Build Coastguard Worker }; 202*795d594fSAndroid Build Coastguard Worker 203*795d594fSAndroid Build Coastguard Worker } // namespace art 204*795d594fSAndroid Build Coastguard Worker 205*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_OPTIMIZING_PARALLEL_MOVE_RESOLVER_H_ 206