101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2014 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg * 2301e04c3fSmrg * Authors: 2401e04c3fSmrg * Connor Abbott (cwabbott0@gmail.com) 2501e04c3fSmrg * 2601e04c3fSmrg */ 2701e04c3fSmrg 2801e04c3fSmrg#ifndef NIR_CONTROL_FLOW_H 2901e04c3fSmrg#define NIR_CONTROL_FLOW_H 3001e04c3fSmrg 3101e04c3fSmrg#include "nir.h" 3201e04c3fSmrg 3301e04c3fSmrg#ifdef __cplusplus 3401e04c3fSmrgextern "C" { 3501e04c3fSmrg#endif 3601e04c3fSmrg 3701e04c3fSmrg/** NIR Control Flow Modification 3801e04c3fSmrg * 3901e04c3fSmrg * This file contains various APIs that make modifying control flow in NIR, 4001e04c3fSmrg * while maintaining the invariants checked by the validator, much easier. 4101e04c3fSmrg * There are two parts to this: 4201e04c3fSmrg * 4301e04c3fSmrg * 1. Inserting control flow (ifs and loops) in various places, for creating 4401e04c3fSmrg * IR either from scratch or as part of some lowering pass. 4501e04c3fSmrg * 2. Taking existing pieces of the IR and either moving them around or 4601e04c3fSmrg * deleting them. 4701e04c3fSmrg */ 4801e04c3fSmrg 4901e04c3fSmrg/** Control flow insertion. */ 5001e04c3fSmrg 5101e04c3fSmrg/** puts a control flow node where the cursor is */ 5201e04c3fSmrgvoid nir_cf_node_insert(nir_cursor cursor, nir_cf_node *node); 5301e04c3fSmrg 5401e04c3fSmrg/** puts a control flow node immediately after another control flow node */ 5501e04c3fSmrgstatic inline void 5601e04c3fSmrgnir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after) 5701e04c3fSmrg{ 5801e04c3fSmrg nir_cf_node_insert(nir_after_cf_node(node), after); 5901e04c3fSmrg} 6001e04c3fSmrg 6101e04c3fSmrg/** puts a control flow node immediately before another control flow node */ 6201e04c3fSmrgstatic inline void 6301e04c3fSmrgnir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before) 6401e04c3fSmrg{ 6501e04c3fSmrg nir_cf_node_insert(nir_before_cf_node(node), before); 6601e04c3fSmrg} 6701e04c3fSmrg 6801e04c3fSmrg/** puts a control flow node at the beginning of a list from an if, loop, or function */ 6901e04c3fSmrgstatic inline void 7001e04c3fSmrgnir_cf_node_insert_begin(struct exec_list *list, nir_cf_node *node) 7101e04c3fSmrg{ 7201e04c3fSmrg nir_cf_node_insert(nir_before_cf_list(list), node); 7301e04c3fSmrg} 7401e04c3fSmrg 7501e04c3fSmrg/** puts a control flow node at the end of a list from an if, loop, or function */ 7601e04c3fSmrgstatic inline void 7701e04c3fSmrgnir_cf_node_insert_end(struct exec_list *list, nir_cf_node *node) 7801e04c3fSmrg{ 7901e04c3fSmrg nir_cf_node_insert(nir_after_cf_list(list), node); 8001e04c3fSmrg} 8101e04c3fSmrg 8201e04c3fSmrg 8301e04c3fSmrg/** Control flow motion. 8401e04c3fSmrg * 8501e04c3fSmrg * These functions let you take a part of a control flow list (basically 8601e04c3fSmrg * equivalent to a series of statement in GLSL) and "extract" it from the IR, 8701e04c3fSmrg * so that it's a free-floating piece of IR that can be either re-inserted 8801e04c3fSmrg * somewhere else or deleted entirely. A few notes on using it: 8901e04c3fSmrg * 9001e04c3fSmrg * 1. Phi nodes are considered attached to the piece of control flow that 9101e04c3fSmrg * their sources come from. There are three places where phi nodes can 9201e04c3fSmrg * occur, which are the three places where a block can have multiple 9301e04c3fSmrg * predecessors: 9401e04c3fSmrg * 9501e04c3fSmrg * 1) After an if statement, if neither branch ends in a jump. 9601e04c3fSmrg * 2) After a loop, if there are multiple breaks. 9701e04c3fSmrg * 3) At the beginning of a loop. 9801e04c3fSmrg * 9901e04c3fSmrg * For #1, the phi node is considered to be part of the if, and for #2 and 10001e04c3fSmrg * #3 the phi node is considered to be part of the loop. This allows us to 10101e04c3fSmrg * keep phis intact, but it means that phi nodes cannot be separated from 10201e04c3fSmrg * the control flow they come from. For example, extracting an if without 10301e04c3fSmrg * extracting all the phi nodes after it is not allowed, and neither is 10401e04c3fSmrg * extracting only some of the phi nodes at the beginning of a block. It 10501e04c3fSmrg * also means that extracting from the beginning of a basic block actually 10601e04c3fSmrg * means extracting from the first non-phi instruction, since there's no 10701e04c3fSmrg * situation where extracting phi nodes without extracting what comes 10801e04c3fSmrg * before them makes any sense. 10901e04c3fSmrg * 11001e04c3fSmrg * 2. Phi node sources are guaranteed to remain valid, meaning that they still 11101e04c3fSmrg * correspond one-to-one with the predecessors of the basic block they're 11201e04c3fSmrg * part of. In addition, the original sources will be preserved unless they 11301e04c3fSmrg * correspond to a break or continue that was deleted. However, no attempt 11401e04c3fSmrg * is made to ensure that SSA form is maintained. In particular, it is 11501e04c3fSmrg * *not* guaranteed that definitions of SSA values will dominate all their 11601e04c3fSmrg * uses after all is said and done. Either the caller must ensure that this 11701e04c3fSmrg * is the case, or it must insert extra phi nodes to restore SSA. 11801e04c3fSmrg * 11901e04c3fSmrg * 3. It is invalid to move a piece of IR with a break/continue outside of the 12001e04c3fSmrg * loop it references. Doing this will result in invalid 12101e04c3fSmrg * successors/predecessors and phi node sources. 12201e04c3fSmrg * 12301e04c3fSmrg * 4. It is invalid to move a piece of IR from one function implementation to 12401e04c3fSmrg * another. 12501e04c3fSmrg * 12601e04c3fSmrg * 5. Extracting a control flow list will leave lots of dangling references to 12701e04c3fSmrg * and from other pieces of the IR. It also leaves things in a not 100% 12801e04c3fSmrg * consistent state. This means that some things (e.g. inserting 12901e04c3fSmrg * instructions) might not work reliably on the extracted control flow. It 13001e04c3fSmrg * also means that extracting control flow without re-inserting it or 13101e04c3fSmrg * deleting it is a Bad Thing (tm). 13201e04c3fSmrg */ 13301e04c3fSmrg 13401e04c3fSmrgtypedef struct { 13501e04c3fSmrg struct exec_list list; 13601e04c3fSmrg nir_function_impl *impl; /* for cleaning up if the list is deleted */ 13701e04c3fSmrg} nir_cf_list; 13801e04c3fSmrg 13901e04c3fSmrgvoid nir_cf_extract(nir_cf_list *extracted, nir_cursor begin, nir_cursor end); 14001e04c3fSmrg 14101e04c3fSmrgvoid nir_cf_reinsert(nir_cf_list *cf_list, nir_cursor cursor); 14201e04c3fSmrg 14301e04c3fSmrgvoid nir_cf_delete(nir_cf_list *cf_list); 14401e04c3fSmrg 14501e04c3fSmrgvoid nir_cf_list_clone(nir_cf_list *dst, nir_cf_list *src, nir_cf_node *parent, 14601e04c3fSmrg struct hash_table *remap_table); 14701e04c3fSmrg 1487e102996Smayastatic inline void 1497e102996Smayanir_cf_list_clone_and_reinsert(nir_cf_list *src_list, nir_cf_node *parent, 1507e102996Smaya nir_cursor cursor, 1517e102996Smaya struct hash_table *remap_table) 1527e102996Smaya{ 1537e102996Smaya nir_cf_list list; 1547e102996Smaya nir_cf_list_clone(&list, src_list, parent, remap_table); 1557e102996Smaya nir_cf_reinsert(&list, cursor); 1567e102996Smaya} 1577e102996Smaya 15801e04c3fSmrgstatic inline void 15901e04c3fSmrgnir_cf_list_extract(nir_cf_list *extracted, struct exec_list *cf_list) 16001e04c3fSmrg{ 16101e04c3fSmrg nir_cf_extract(extracted, nir_before_cf_list(cf_list), 16201e04c3fSmrg nir_after_cf_list(cf_list)); 16301e04c3fSmrg} 16401e04c3fSmrg 16501e04c3fSmrg/** removes a control flow node, doing any cleanup necessary */ 16601e04c3fSmrgstatic inline void 16701e04c3fSmrgnir_cf_node_remove(nir_cf_node *node) 16801e04c3fSmrg{ 16901e04c3fSmrg nir_cf_list list; 17001e04c3fSmrg nir_cf_extract(&list, nir_before_cf_node(node), nir_after_cf_node(node)); 17101e04c3fSmrg nir_cf_delete(&list); 17201e04c3fSmrg} 17301e04c3fSmrg 1747ec681f3Smrg/** inserts undef phi sources from predcessor into phis of the block */ 1757ec681f3Smrgvoid nir_insert_phi_undef(nir_block *block, nir_block *pred); 1767ec681f3Smrg 17701e04c3fSmrg#ifdef __cplusplus 17801e04c3fSmrg} 17901e04c3fSmrg#endif 18001e04c3fSmrg 18101e04c3fSmrg#endif /* NIR_CONTROL_FLOW_H */ 182