1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2014 Intel Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg * 23b8e80941Smrg * Authors: 24b8e80941Smrg * Connor Abbott (cwabbott0@gmail.com) 25b8e80941Smrg * 26b8e80941Smrg */ 27b8e80941Smrg 28b8e80941Smrg#ifndef NIR_CONTROL_FLOW_H 29b8e80941Smrg#define NIR_CONTROL_FLOW_H 30b8e80941Smrg 31b8e80941Smrg#include "nir.h" 32b8e80941Smrg 33b8e80941Smrg#ifdef __cplusplus 34b8e80941Smrgextern "C" { 35b8e80941Smrg#endif 36b8e80941Smrg 37b8e80941Smrg/** NIR Control Flow Modification 38b8e80941Smrg * 39b8e80941Smrg * This file contains various APIs that make modifying control flow in NIR, 40b8e80941Smrg * while maintaining the invariants checked by the validator, much easier. 41b8e80941Smrg * There are two parts to this: 42b8e80941Smrg * 43b8e80941Smrg * 1. Inserting control flow (ifs and loops) in various places, for creating 44b8e80941Smrg * IR either from scratch or as part of some lowering pass. 45b8e80941Smrg * 2. Taking existing pieces of the IR and either moving them around or 46b8e80941Smrg * deleting them. 47b8e80941Smrg */ 48b8e80941Smrg 49b8e80941Smrg/** Control flow insertion. */ 50b8e80941Smrg 51b8e80941Smrg/** puts a control flow node where the cursor is */ 52b8e80941Smrgvoid nir_cf_node_insert(nir_cursor cursor, nir_cf_node *node); 53b8e80941Smrg 54b8e80941Smrg/** puts a control flow node immediately after another control flow node */ 55b8e80941Smrgstatic inline void 56b8e80941Smrgnir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after) 57b8e80941Smrg{ 58b8e80941Smrg nir_cf_node_insert(nir_after_cf_node(node), after); 59b8e80941Smrg} 60b8e80941Smrg 61b8e80941Smrg/** puts a control flow node immediately before another control flow node */ 62b8e80941Smrgstatic inline void 63b8e80941Smrgnir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before) 64b8e80941Smrg{ 65b8e80941Smrg nir_cf_node_insert(nir_before_cf_node(node), before); 66b8e80941Smrg} 67b8e80941Smrg 68b8e80941Smrg/** puts a control flow node at the beginning of a list from an if, loop, or function */ 69b8e80941Smrgstatic inline void 70b8e80941Smrgnir_cf_node_insert_begin(struct exec_list *list, nir_cf_node *node) 71b8e80941Smrg{ 72b8e80941Smrg nir_cf_node_insert(nir_before_cf_list(list), node); 73b8e80941Smrg} 74b8e80941Smrg 75b8e80941Smrg/** puts a control flow node at the end of a list from an if, loop, or function */ 76b8e80941Smrgstatic inline void 77b8e80941Smrgnir_cf_node_insert_end(struct exec_list *list, nir_cf_node *node) 78b8e80941Smrg{ 79b8e80941Smrg nir_cf_node_insert(nir_after_cf_list(list), node); 80b8e80941Smrg} 81b8e80941Smrg 82b8e80941Smrg 83b8e80941Smrg/** Control flow motion. 84b8e80941Smrg * 85b8e80941Smrg * These functions let you take a part of a control flow list (basically 86b8e80941Smrg * equivalent to a series of statement in GLSL) and "extract" it from the IR, 87b8e80941Smrg * so that it's a free-floating piece of IR that can be either re-inserted 88b8e80941Smrg * somewhere else or deleted entirely. A few notes on using it: 89b8e80941Smrg * 90b8e80941Smrg * 1. Phi nodes are considered attached to the piece of control flow that 91b8e80941Smrg * their sources come from. There are three places where phi nodes can 92b8e80941Smrg * occur, which are the three places where a block can have multiple 93b8e80941Smrg * predecessors: 94b8e80941Smrg * 95b8e80941Smrg * 1) After an if statement, if neither branch ends in a jump. 96b8e80941Smrg * 2) After a loop, if there are multiple breaks. 97b8e80941Smrg * 3) At the beginning of a loop. 98b8e80941Smrg * 99b8e80941Smrg * For #1, the phi node is considered to be part of the if, and for #2 and 100b8e80941Smrg * #3 the phi node is considered to be part of the loop. This allows us to 101b8e80941Smrg * keep phis intact, but it means that phi nodes cannot be separated from 102b8e80941Smrg * the control flow they come from. For example, extracting an if without 103b8e80941Smrg * extracting all the phi nodes after it is not allowed, and neither is 104b8e80941Smrg * extracting only some of the phi nodes at the beginning of a block. It 105b8e80941Smrg * also means that extracting from the beginning of a basic block actually 106b8e80941Smrg * means extracting from the first non-phi instruction, since there's no 107b8e80941Smrg * situation where extracting phi nodes without extracting what comes 108b8e80941Smrg * before them makes any sense. 109b8e80941Smrg * 110b8e80941Smrg * 2. Phi node sources are guaranteed to remain valid, meaning that they still 111b8e80941Smrg * correspond one-to-one with the predecessors of the basic block they're 112b8e80941Smrg * part of. In addition, the original sources will be preserved unless they 113b8e80941Smrg * correspond to a break or continue that was deleted. However, no attempt 114b8e80941Smrg * is made to ensure that SSA form is maintained. In particular, it is 115b8e80941Smrg * *not* guaranteed that definitions of SSA values will dominate all their 116b8e80941Smrg * uses after all is said and done. Either the caller must ensure that this 117b8e80941Smrg * is the case, or it must insert extra phi nodes to restore SSA. 118b8e80941Smrg * 119b8e80941Smrg * 3. It is invalid to move a piece of IR with a break/continue outside of the 120b8e80941Smrg * loop it references. Doing this will result in invalid 121b8e80941Smrg * successors/predecessors and phi node sources. 122b8e80941Smrg * 123b8e80941Smrg * 4. It is invalid to move a piece of IR from one function implementation to 124b8e80941Smrg * another. 125b8e80941Smrg * 126b8e80941Smrg * 5. Extracting a control flow list will leave lots of dangling references to 127b8e80941Smrg * and from other pieces of the IR. It also leaves things in a not 100% 128b8e80941Smrg * consistent state. This means that some things (e.g. inserting 129b8e80941Smrg * instructions) might not work reliably on the extracted control flow. It 130b8e80941Smrg * also means that extracting control flow without re-inserting it or 131b8e80941Smrg * deleting it is a Bad Thing (tm). 132b8e80941Smrg */ 133b8e80941Smrg 134b8e80941Smrgtypedef struct { 135b8e80941Smrg struct exec_list list; 136b8e80941Smrg nir_function_impl *impl; /* for cleaning up if the list is deleted */ 137b8e80941Smrg} nir_cf_list; 138b8e80941Smrg 139b8e80941Smrgvoid nir_cf_extract(nir_cf_list *extracted, nir_cursor begin, nir_cursor end); 140b8e80941Smrg 141b8e80941Smrgvoid nir_cf_reinsert(nir_cf_list *cf_list, nir_cursor cursor); 142b8e80941Smrg 143b8e80941Smrgvoid nir_cf_delete(nir_cf_list *cf_list); 144b8e80941Smrg 145b8e80941Smrgvoid nir_cf_list_clone(nir_cf_list *dst, nir_cf_list *src, nir_cf_node *parent, 146b8e80941Smrg struct hash_table *remap_table); 147b8e80941Smrg 148b8e80941Smrgstatic inline void 149b8e80941Smrgnir_cf_list_clone_and_reinsert(nir_cf_list *src_list, nir_cf_node *parent, 150b8e80941Smrg nir_cursor cursor, 151b8e80941Smrg struct hash_table *remap_table) 152b8e80941Smrg{ 153b8e80941Smrg nir_cf_list list; 154b8e80941Smrg nir_cf_list_clone(&list, src_list, parent, remap_table); 155b8e80941Smrg nir_cf_reinsert(&list, cursor); 156b8e80941Smrg} 157b8e80941Smrg 158b8e80941Smrgstatic inline void 159b8e80941Smrgnir_cf_list_extract(nir_cf_list *extracted, struct exec_list *cf_list) 160b8e80941Smrg{ 161b8e80941Smrg nir_cf_extract(extracted, nir_before_cf_list(cf_list), 162b8e80941Smrg nir_after_cf_list(cf_list)); 163b8e80941Smrg} 164b8e80941Smrg 165b8e80941Smrg/** removes a control flow node, doing any cleanup necessary */ 166b8e80941Smrgstatic inline void 167b8e80941Smrgnir_cf_node_remove(nir_cf_node *node) 168b8e80941Smrg{ 169b8e80941Smrg nir_cf_list list; 170b8e80941Smrg nir_cf_extract(&list, nir_before_cf_node(node), nir_after_cf_node(node)); 171b8e80941Smrg nir_cf_delete(&list); 172b8e80941Smrg} 173b8e80941Smrg 174b8e80941Smrg#ifdef __cplusplus 175b8e80941Smrg} 176b8e80941Smrg#endif 177b8e80941Smrg 178b8e80941Smrg#endif /* NIR_CONTROL_FLOW_H */ 179