1bf215546Sopenharmony_ci/* -*- c++ -*- */ 2bf215546Sopenharmony_ci/* 3bf215546Sopenharmony_ci * Copyright © 2016 Intel Corporation 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22bf215546Sopenharmony_ci * IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#ifndef BRW_IR_ANALYSIS_H 26bf215546Sopenharmony_ci#define BRW_IR_ANALYSIS_H 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_cinamespace brw { 29bf215546Sopenharmony_ci /** 30bf215546Sopenharmony_ci * Bitset of state categories that can influence the result of IR analysis 31bf215546Sopenharmony_ci * passes. 32bf215546Sopenharmony_ci */ 33bf215546Sopenharmony_ci enum analysis_dependency_class { 34bf215546Sopenharmony_ci /** 35bf215546Sopenharmony_ci * The analysis doesn't depend on the IR, its result is effectively a 36bf215546Sopenharmony_ci * constant during the compilation. 37bf215546Sopenharmony_ci */ 38bf215546Sopenharmony_ci DEPENDENCY_NOTHING = 0, 39bf215546Sopenharmony_ci /** 40bf215546Sopenharmony_ci * The analysis depends on the set of instructions in the program and 41bf215546Sopenharmony_ci * their naming. Note that because instructions are named sequentially 42bf215546Sopenharmony_ci * by IP this implies a dependency on the control flow edges between 43bf215546Sopenharmony_ci * instructions. This will be signaled whenever instructions are 44bf215546Sopenharmony_ci * inserted, removed or reordered in the program. 45bf215546Sopenharmony_ci */ 46bf215546Sopenharmony_ci DEPENDENCY_INSTRUCTION_IDENTITY = 0x1, 47bf215546Sopenharmony_ci /** 48bf215546Sopenharmony_ci * The analysis is sensitive to the detailed semantics of instructions 49bf215546Sopenharmony_ci * in the program, where "detailed" means any change in the instruction 50bf215546Sopenharmony_ci * data structures other than the linked-list pointers (which are 51bf215546Sopenharmony_ci * already covered by DEPENDENCY_INSTRUCTION_IDENTITY). E.g. changing 52bf215546Sopenharmony_ci * the negate or abs flags of an instruction source would signal this 53bf215546Sopenharmony_ci * flag alone because it would preserve all other instruction dependency 54bf215546Sopenharmony_ci * classes. 55bf215546Sopenharmony_ci */ 56bf215546Sopenharmony_ci DEPENDENCY_INSTRUCTION_DETAIL = 0x2, 57bf215546Sopenharmony_ci /** 58bf215546Sopenharmony_ci * The analysis depends on the set of data flow edges between 59bf215546Sopenharmony_ci * instructions. This will be signaled whenever the dataflow relation 60bf215546Sopenharmony_ci * between instructions has potentially changed, e.g. when the VGRF 61bf215546Sopenharmony_ci * index of an instruction source or destination changes (in which case 62bf215546Sopenharmony_ci * it will appear in combination with DEPENDENCY_INSTRUCTION_DETAIL), or 63bf215546Sopenharmony_ci * when data-dependent instructions are reordered (in which case it will 64bf215546Sopenharmony_ci * appear in combination with DEPENDENCY_INSTRUCTION_IDENTITY). 65bf215546Sopenharmony_ci */ 66bf215546Sopenharmony_ci DEPENDENCY_INSTRUCTION_DATA_FLOW = 0x4, 67bf215546Sopenharmony_ci /** 68bf215546Sopenharmony_ci * The analysis depends on all instruction dependency classes. These 69bf215546Sopenharmony_ci * will typically be signaled simultaneously when inserting or removing 70bf215546Sopenharmony_ci * instructions in the program (or if you're feeling too lazy to read 71bf215546Sopenharmony_ci * through your optimization pass to figure out which of the instruction 72bf215546Sopenharmony_ci * dependency classes above it invalidates). 73bf215546Sopenharmony_ci */ 74bf215546Sopenharmony_ci DEPENDENCY_INSTRUCTIONS = 0x7, 75bf215546Sopenharmony_ci /** 76bf215546Sopenharmony_ci * The analysis depends on the set of VGRFs in the program and their 77bf215546Sopenharmony_ci * naming. This will be signaled when VGRFs are allocated or released. 78bf215546Sopenharmony_ci */ 79bf215546Sopenharmony_ci DEPENDENCY_VARIABLES = 0x8, 80bf215546Sopenharmony_ci /** 81bf215546Sopenharmony_ci * The analysis depends on the set of basic blocks in the program, their 82bf215546Sopenharmony_ci * control flow edges and naming. 83bf215546Sopenharmony_ci */ 84bf215546Sopenharmony_ci DEPENDENCY_BLOCKS = 0x10, 85bf215546Sopenharmony_ci /** 86bf215546Sopenharmony_ci * The analysis depends on the program being literally the same (good 87bf215546Sopenharmony_ci * luck...), any change in the input invalidates previous analysis 88bf215546Sopenharmony_ci * computations. 89bf215546Sopenharmony_ci */ 90bf215546Sopenharmony_ci DEPENDENCY_EVERYTHING = ~0 91bf215546Sopenharmony_ci }; 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci inline analysis_dependency_class 94bf215546Sopenharmony_ci operator|(analysis_dependency_class x, analysis_dependency_class y) 95bf215546Sopenharmony_ci { 96bf215546Sopenharmony_ci return static_cast<analysis_dependency_class>( 97bf215546Sopenharmony_ci static_cast<unsigned>(x) | static_cast<unsigned>(y)); 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci} 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci/** 102bf215546Sopenharmony_ci * Instantiate a program analysis class \p L which can calculate an object of 103bf215546Sopenharmony_ci * type \p T as result. \p C is a closure that encapsulates whatever 104bf215546Sopenharmony_ci * information is required as argument to run the analysis pass. The purpose 105bf215546Sopenharmony_ci * of this class is to make sure that: 106bf215546Sopenharmony_ci * 107bf215546Sopenharmony_ci * - The analysis pass is executed lazily whenever it's needed and multiple 108bf215546Sopenharmony_ci * executions are optimized out as long as the cached result remains marked 109bf215546Sopenharmony_ci * up-to-date. 110bf215546Sopenharmony_ci * 111bf215546Sopenharmony_ci * - There is no way to access the cached analysis result without first 112bf215546Sopenharmony_ci * calling L::require(), which makes sure that the analysis pass is rerun 113bf215546Sopenharmony_ci * if necessary. 114bf215546Sopenharmony_ci * 115bf215546Sopenharmony_ci * - The cached result doesn't become inconsistent with the program for as 116bf215546Sopenharmony_ci * long as it remains marked up-to-date. (This is only enforced in debug 117bf215546Sopenharmony_ci * builds for performance reasons) 118bf215546Sopenharmony_ci * 119bf215546Sopenharmony_ci * The requirements on \p T are the following: 120bf215546Sopenharmony_ci * 121bf215546Sopenharmony_ci * - Constructible with a single argument, as in 'x = T(c)' for \p c of type 122bf215546Sopenharmony_ci * \p C. 123bf215546Sopenharmony_ci * 124bf215546Sopenharmony_ci * - 'x.dependency_class()' on const \p x returns a bitset of 125bf215546Sopenharmony_ci * brw::analysis_dependency_class specifying the set of IR objects that are 126bf215546Sopenharmony_ci * required to remain invariant for the cached analysis result to be 127bf215546Sopenharmony_ci * considered valid. 128bf215546Sopenharmony_ci * 129bf215546Sopenharmony_ci * - 'x.validate(c)' on const \p x returns a boolean result specifying 130bf215546Sopenharmony_ci * whether the analysis result \p x is consistent with the input IR. This 131bf215546Sopenharmony_ci * is currently only used for validation in debug builds. 132bf215546Sopenharmony_ci */ 133bf215546Sopenharmony_citemplate<class T, class C> 134bf215546Sopenharmony_ciclass brw_analysis { 135bf215546Sopenharmony_cipublic: 136bf215546Sopenharmony_ci /** 137bf215546Sopenharmony_ci * Construct a program analysis. \p c is an arbitrary object 138bf215546Sopenharmony_ci * passed as argument to the constructor of the analysis result 139bf215546Sopenharmony_ci * object of type \p T. 140bf215546Sopenharmony_ci */ 141bf215546Sopenharmony_ci brw_analysis(const C *c) : c(c), p(NULL) {} 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci /** 144bf215546Sopenharmony_ci * Destroy a program analysis. 145bf215546Sopenharmony_ci */ 146bf215546Sopenharmony_ci ~brw_analysis() 147bf215546Sopenharmony_ci { 148bf215546Sopenharmony_ci delete p; 149bf215546Sopenharmony_ci } 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci /** 152bf215546Sopenharmony_ci * Obtain the result of a program analysis. This gives a 153bf215546Sopenharmony_ci * guaranteed up-to-date result, the analysis pass will be 154bf215546Sopenharmony_ci * rerun implicitly if it has become stale. 155bf215546Sopenharmony_ci */ 156bf215546Sopenharmony_ci T & 157bf215546Sopenharmony_ci require() 158bf215546Sopenharmony_ci { 159bf215546Sopenharmony_ci if (p) 160bf215546Sopenharmony_ci assert(p->validate(c)); 161bf215546Sopenharmony_ci else 162bf215546Sopenharmony_ci p = new T(c); 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci return *p; 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci const T & 168bf215546Sopenharmony_ci require() const 169bf215546Sopenharmony_ci { 170bf215546Sopenharmony_ci return const_cast<brw_analysis<T, C> *>(this)->require(); 171bf215546Sopenharmony_ci } 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci /** 174bf215546Sopenharmony_ci * Report that dependencies of the analysis pass may have changed 175bf215546Sopenharmony_ci * since the last calculation and the cached analysis result may 176bf215546Sopenharmony_ci * have to be discarded. 177bf215546Sopenharmony_ci */ 178bf215546Sopenharmony_ci void 179bf215546Sopenharmony_ci invalidate(brw::analysis_dependency_class c) 180bf215546Sopenharmony_ci { 181bf215546Sopenharmony_ci if (p && (c & p->dependency_class())) { 182bf215546Sopenharmony_ci delete p; 183bf215546Sopenharmony_ci p = NULL; 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci } 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ciprivate: 188bf215546Sopenharmony_ci const C *c; 189bf215546Sopenharmony_ci T *p; 190bf215546Sopenharmony_ci}; 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci#endif 193