Path: blob/21.2-virgl/src/compiler/nir/nir_control_flow.h
4546 views
/*1* Copyright © 2014 Intel Corporation2*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, sublicense,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 the next11* paragraph) shall be included in all copies or substantial portions of the12* 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 NONINFRINGEMENT. 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 OTHER DEALINGS20* IN THE SOFTWARE.21*22* Authors:23* Connor Abbott ([email protected])24*25*/2627#ifndef NIR_CONTROL_FLOW_H28#define NIR_CONTROL_FLOW_H2930#include "nir.h"3132#ifdef __cplusplus33extern "C" {34#endif3536/** NIR Control Flow Modification37*38* This file contains various APIs that make modifying control flow in NIR,39* while maintaining the invariants checked by the validator, much easier.40* There are two parts to this:41*42* 1. Inserting control flow (ifs and loops) in various places, for creating43* IR either from scratch or as part of some lowering pass.44* 2. Taking existing pieces of the IR and either moving them around or45* deleting them.46*/4748/** Control flow insertion. */4950/** puts a control flow node where the cursor is */51void nir_cf_node_insert(nir_cursor cursor, nir_cf_node *node);5253/** puts a control flow node immediately after another control flow node */54static inline void55nir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after)56{57nir_cf_node_insert(nir_after_cf_node(node), after);58}5960/** puts a control flow node immediately before another control flow node */61static inline void62nir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before)63{64nir_cf_node_insert(nir_before_cf_node(node), before);65}6667/** puts a control flow node at the beginning of a list from an if, loop, or function */68static inline void69nir_cf_node_insert_begin(struct exec_list *list, nir_cf_node *node)70{71nir_cf_node_insert(nir_before_cf_list(list), node);72}7374/** puts a control flow node at the end of a list from an if, loop, or function */75static inline void76nir_cf_node_insert_end(struct exec_list *list, nir_cf_node *node)77{78nir_cf_node_insert(nir_after_cf_list(list), node);79}808182/** Control flow motion.83*84* These functions let you take a part of a control flow list (basically85* equivalent to a series of statement in GLSL) and "extract" it from the IR,86* so that it's a free-floating piece of IR that can be either re-inserted87* somewhere else or deleted entirely. A few notes on using it:88*89* 1. Phi nodes are considered attached to the piece of control flow that90* their sources come from. There are three places where phi nodes can91* occur, which are the three places where a block can have multiple92* predecessors:93*94* 1) After an if statement, if neither branch ends in a jump.95* 2) After a loop, if there are multiple breaks.96* 3) At the beginning of a loop.97*98* For #1, the phi node is considered to be part of the if, and for #2 and99* #3 the phi node is considered to be part of the loop. This allows us to100* keep phis intact, but it means that phi nodes cannot be separated from101* the control flow they come from. For example, extracting an if without102* extracting all the phi nodes after it is not allowed, and neither is103* extracting only some of the phi nodes at the beginning of a block. It104* also means that extracting from the beginning of a basic block actually105* means extracting from the first non-phi instruction, since there's no106* situation where extracting phi nodes without extracting what comes107* before them makes any sense.108*109* 2. Phi node sources are guaranteed to remain valid, meaning that they still110* correspond one-to-one with the predecessors of the basic block they're111* part of. In addition, the original sources will be preserved unless they112* correspond to a break or continue that was deleted. However, no attempt113* is made to ensure that SSA form is maintained. In particular, it is114* *not* guaranteed that definitions of SSA values will dominate all their115* uses after all is said and done. Either the caller must ensure that this116* is the case, or it must insert extra phi nodes to restore SSA.117*118* 3. It is invalid to move a piece of IR with a break/continue outside of the119* loop it references. Doing this will result in invalid120* successors/predecessors and phi node sources.121*122* 4. It is invalid to move a piece of IR from one function implementation to123* another.124*125* 5. Extracting a control flow list will leave lots of dangling references to126* and from other pieces of the IR. It also leaves things in a not 100%127* consistent state. This means that some things (e.g. inserting128* instructions) might not work reliably on the extracted control flow. It129* also means that extracting control flow without re-inserting it or130* deleting it is a Bad Thing (tm).131*/132133typedef struct {134struct exec_list list;135nir_function_impl *impl; /* for cleaning up if the list is deleted */136} nir_cf_list;137138void nir_cf_extract(nir_cf_list *extracted, nir_cursor begin, nir_cursor end);139140void nir_cf_reinsert(nir_cf_list *cf_list, nir_cursor cursor);141142void nir_cf_delete(nir_cf_list *cf_list);143144void nir_cf_list_clone(nir_cf_list *dst, nir_cf_list *src, nir_cf_node *parent,145struct hash_table *remap_table);146147static inline void148nir_cf_list_clone_and_reinsert(nir_cf_list *src_list, nir_cf_node *parent,149nir_cursor cursor,150struct hash_table *remap_table)151{152nir_cf_list list;153nir_cf_list_clone(&list, src_list, parent, remap_table);154nir_cf_reinsert(&list, cursor);155}156157static inline void158nir_cf_list_extract(nir_cf_list *extracted, struct exec_list *cf_list)159{160nir_cf_extract(extracted, nir_before_cf_list(cf_list),161nir_after_cf_list(cf_list));162}163164/** removes a control flow node, doing any cleanup necessary */165static inline void166nir_cf_node_remove(nir_cf_node *node)167{168nir_cf_list list;169nir_cf_extract(&list, nir_before_cf_node(node), nir_after_cf_node(node));170nir_cf_delete(&list);171}172173/** inserts undef phi sources from predcessor into phis of the block */174void nir_insert_phi_undef(nir_block *block, nir_block *pred);175176#ifdef __cplusplus177}178#endif179180#endif /* NIR_CONTROL_FLOW_H */181182183