Path: blob/21.2-virgl/src/gallium/drivers/lima/ir/pp/liveness.c
4574 views
/*1* Copyright (c) 2019 Lima Project2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sub license,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the11* next paragraph) shall be included in all copies or substantial portions12* of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*22*/2324#include "ppir.h"2526/* Propagates liveness from a liveness set to another by performing the27* union between sets. */28static void29ppir_liveness_propagate(ppir_compiler *comp,30BITSET_WORD *dest_set, BITSET_WORD *src_set,31uint8_t *dest_mask, uint8_t *src_mask)32{33for (int i = 0; i < BITSET_WORDS(comp->reg_num); i++)34dest_set[i] |= src_set[i];3536for (int i = 0; i < reg_mask_size(comp->reg_num); i++)37dest_mask[i] |= src_mask[i];38}3940/* Check whether two liveness sets are equal. */41static bool42ppir_liveness_set_equal(ppir_compiler *comp,43BITSET_WORD *set1, BITSET_WORD *set2,44uint8_t *mask1, uint8_t *mask2)45{46for (int i = 0; i < BITSET_WORDS(comp->reg_num); i++)47if (set1[i] != set2[i])48return false;4950for (int i = 0; i < reg_mask_size(comp->reg_num); i++)51if (mask1[i] != mask2[i])52return false;5354return true;55}5657/* Update the liveness information of the instruction by adding its srcs58* as live registers to the live_in set. */59static void60ppir_liveness_instr_srcs(ppir_compiler *comp, ppir_instr *instr)61{62for (int i = PPIR_INSTR_SLOT_NUM-1; i >= 0; i--) {63ppir_node *node = instr->slots[i];64if (!node)65continue;6667switch(node->op) {68case ppir_op_const:69case ppir_op_undef:70continue;71default:72break;73}7475for (int i = 0; i < ppir_node_get_src_num(node); i++) {76ppir_src *src = ppir_node_get_src(node, i);77if (!src || src->type == ppir_target_pipeline)78continue;7980ppir_reg *reg = ppir_src_get_reg(src);81if (!reg || reg->undef)82continue;8384unsigned int index = reg->regalloc_index;8586/* if some other op on this same instruction is writing,87* we just need to reserve a register for this particular88* instruction. */89if (src->node && src->node->instr == instr) {90BITSET_SET(instr->live_internal, index);91continue;92}9394bool live = BITSET_TEST(instr->live_set, index);95if (src->type == ppir_target_ssa) {96/* reg is read, needs to be live before instr */97if (live)98continue;99100BITSET_SET(instr->live_set, index);101}102else {103unsigned int mask = ppir_src_get_mask(src);104uint8_t live_mask = get_reg_mask(instr->live_mask, index);105106/* read reg is type register, need to check if this sets107* any additional bits in the current mask */108if (live && (live_mask == (live_mask | mask)))109continue;110111/* some new components */112set_reg_mask(instr->live_mask, index, (live_mask | mask));113BITSET_SET(instr->live_set, index);114}115}116}117}118119120/* Update the liveness information of the instruction by removing its121* dests from the live_in set. */122static void123ppir_liveness_instr_dest(ppir_compiler *comp, ppir_instr *instr)124{125for (int i = PPIR_INSTR_SLOT_NUM-1; i >= 0; i--) {126ppir_node *node = instr->slots[i];127if (!node)128continue;129130switch(node->op) {131case ppir_op_const:132case ppir_op_undef:133continue;134default:135break;136}137138ppir_dest *dest = ppir_node_get_dest(node);139if (!dest || dest->type == ppir_target_pipeline)140continue;141ppir_reg *reg = ppir_dest_get_reg(dest);142if (!reg || reg->undef)143continue;144145unsigned int index = reg->regalloc_index;146bool live = BITSET_TEST(instr->live_set, index);147148/* If a register is written but wasn't read in a later instruction, it is149* either dead code or a bug. For now, assign an interference to it to150* ensure it doesn't get assigned a live register and overwrites it. */151if (!live) {152BITSET_SET(instr->live_internal, index);153continue;154}155156if (dest->type == ppir_target_ssa) {157/* reg is written and ssa, is not live before instr */158BITSET_CLEAR(instr->live_set, index);159}160else {161unsigned int mask = dest->write_mask;162uint8_t live_mask = get_reg_mask(instr->live_mask, index);163/* written reg is type register, need to check if this clears164* the remaining mask to remove it from the live set */165if (live_mask == (live_mask & ~mask))166continue;167168set_reg_mask(instr->live_mask, index, (live_mask & ~mask));169/* unset reg if all remaining bits were cleared */170if ((live_mask & ~mask) == 0) {171BITSET_CLEAR(instr->live_set, index);172}173}174}175}176177/* Main loop, iterate blocks/instructions/ops backwards, propagate178* livenss and update liveness of each instruction. */179static bool180ppir_liveness_compute_live_sets(ppir_compiler *comp)181{182uint8_t temp_live_mask[reg_mask_size(comp->reg_num)];183BITSET_DECLARE(temp_live_set, comp->reg_num);184bool cont = false;185list_for_each_entry_rev(ppir_block, block, &comp->block_list, list) {186if (list_is_empty(&block->instr_list))187continue;188189ppir_instr *last = list_last_entry(&block->instr_list, ppir_instr, list);190assert(last);191192list_for_each_entry_rev(ppir_instr, instr, &block->instr_list, list) {193/* initial copy to check for changes */194memset(temp_live_mask, 0, sizeof(temp_live_mask));195memset(temp_live_set, 0, sizeof(temp_live_set));196197ppir_liveness_propagate(comp,198temp_live_set, instr->live_set,199temp_live_mask, instr->live_mask);200201/* inherit (or-) live variables from next instr or block */202if (instr == last) {203ppir_instr *next_instr;204/* inherit liveness from the first instruction in the next blocks */205for (int i = 0; i < 2; i++) {206ppir_block *succ = block->successors[i];207if (!succ)208continue;209210/* if the block is empty, go for the next-next until a non-empty211* one is found */212while (list_is_empty(&succ->instr_list)) {213assert(succ->successors[0] && !succ->successors[1]);214succ = succ->successors[0];215}216217next_instr = list_first_entry(&succ->instr_list, ppir_instr, list);218assert(next_instr);219220ppir_liveness_propagate(comp,221instr->live_set, next_instr->live_set,222instr->live_mask, next_instr->live_mask);223}224}225else {226ppir_instr *next_instr = LIST_ENTRY(ppir_instr, instr->list.next, list);227ppir_liveness_propagate(comp,228instr->live_set, next_instr->live_set,229instr->live_mask, next_instr->live_mask);230}231232ppir_liveness_instr_dest(comp, instr);233ppir_liveness_instr_srcs(comp, instr);234235cont |= !ppir_liveness_set_equal(comp,236temp_live_set, instr->live_set,237temp_live_mask, instr->live_mask);238}239}240241return cont;242}243244/*245* Liveness analysis is based on https://en.wikipedia.org/wiki/Live_variable_analysis246* This implementation calculates liveness for each instruction.247* The liveness set in this implementation is defined as the set of248* registers live before the instruction executes.249* Blocks/instructions/ops are iterated backwards so register reads are250* propagated up to the instruction that writes it.251*252* 1) Before computing liveness for an instruction, propagate liveness253* from the next instruction. If it is the last instruction in a254* block, propagate liveness from all possible next instructions in255* the successor blocks.256* 2) Calculate the live set for the instruction. The initial live set257* is a propagated set of the live set from the next instructions.258* - Registers which aren't touched by this instruction are kept259* intact.260* - If a register is written by this instruction, it no longer needs261* to be live before the instruction, so it is removed from the live262* set of that instruction.263* - If a register is read by this instruction, it needs to be live264* before its execution, so add it to its live set.265* - Non-ssa registers are a special case. For this, the algorithm266* keeps and updates the mask of live components following the same267* logic as above. The register is only removed from the live set of268* the instruction when no live components are left.269* - If a non-ssa register is written and read in the same270* instruction, it stays in the live set.271* - Another special case is when a register is only written and read272* within a single instruciton. In this case a register needs to be273* reserved but not propagated. The algorithm adds it to the274* live_internal set so that the register allocator properly assigns275* an interference for it.276* 3) The algorithm must run over the entire program until it converges,277* i.e. a full run happens without changes. This is because blocks278* are updated sequentially and updates in a block may need to be279* propagated to parent blocks that were already calculated in the280* current run.281*/282void283ppir_liveness_analysis(ppir_compiler *comp)284{285while (ppir_liveness_compute_live_sets(comp))286;287}288289290