17ec681f3Smrg/* -*- c++ -*- */ 27ec681f3Smrg/* 37ec681f3Smrg * Copyright © 2016 Intel Corporation 47ec681f3Smrg * 57ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 67ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 77ec681f3Smrg * to deal in the Software without restriction, including without limitation 87ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 97ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 107ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 117ec681f3Smrg * 127ec681f3Smrg * The above copyright notice and this permission notice (including the next 137ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 147ec681f3Smrg * Software. 157ec681f3Smrg * 167ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 177ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 187ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 197ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 207ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 217ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 227ec681f3Smrg * IN THE SOFTWARE. 237ec681f3Smrg */ 247ec681f3Smrg 257ec681f3Smrg#ifndef BRW_IR_ANALYSIS_H 267ec681f3Smrg#define BRW_IR_ANALYSIS_H 277ec681f3Smrg 287ec681f3Smrgnamespace brw { 297ec681f3Smrg /** 307ec681f3Smrg * Bitset of state categories that can influence the result of IR analysis 317ec681f3Smrg * passes. 327ec681f3Smrg */ 337ec681f3Smrg enum analysis_dependency_class { 347ec681f3Smrg /** 357ec681f3Smrg * The analysis doesn't depend on the IR, its result is effectively a 367ec681f3Smrg * constant during the compilation. 377ec681f3Smrg */ 387ec681f3Smrg DEPENDENCY_NOTHING = 0, 397ec681f3Smrg /** 407ec681f3Smrg * The analysis depends on the set of instructions in the program and 417ec681f3Smrg * their naming. Note that because instructions are named sequentially 427ec681f3Smrg * by IP this implies a dependency on the control flow edges between 437ec681f3Smrg * instructions. This will be signaled whenever instructions are 447ec681f3Smrg * inserted, removed or reordered in the program. 457ec681f3Smrg */ 467ec681f3Smrg DEPENDENCY_INSTRUCTION_IDENTITY = 0x1, 477ec681f3Smrg /** 487ec681f3Smrg * The analysis is sensitive to the detailed semantics of instructions 497ec681f3Smrg * in the program, where "detailed" means any change in the instruction 507ec681f3Smrg * data structures other than the linked-list pointers (which are 517ec681f3Smrg * already covered by DEPENDENCY_INSTRUCTION_IDENTITY). E.g. changing 527ec681f3Smrg * the negate or abs flags of an instruction source would signal this 537ec681f3Smrg * flag alone because it would preserve all other instruction dependency 547ec681f3Smrg * classes. 557ec681f3Smrg */ 567ec681f3Smrg DEPENDENCY_INSTRUCTION_DETAIL = 0x2, 577ec681f3Smrg /** 587ec681f3Smrg * The analysis depends on the set of data flow edges between 597ec681f3Smrg * instructions. This will be signaled whenever the dataflow relation 607ec681f3Smrg * between instructions has potentially changed, e.g. when the VGRF 617ec681f3Smrg * index of an instruction source or destination changes (in which case 627ec681f3Smrg * it will appear in combination with DEPENDENCY_INSTRUCTION_DETAIL), or 637ec681f3Smrg * when data-dependent instructions are reordered (in which case it will 647ec681f3Smrg * appear in combination with DEPENDENCY_INSTRUCTION_IDENTITY). 657ec681f3Smrg */ 667ec681f3Smrg DEPENDENCY_INSTRUCTION_DATA_FLOW = 0x4, 677ec681f3Smrg /** 687ec681f3Smrg * The analysis depends on all instruction dependency classes. These 697ec681f3Smrg * will typically be signaled simultaneously when inserting or removing 707ec681f3Smrg * instructions in the program (or if you're feeling too lazy to read 717ec681f3Smrg * through your optimization pass to figure out which of the instruction 727ec681f3Smrg * dependency classes above it invalidates). 737ec681f3Smrg */ 747ec681f3Smrg DEPENDENCY_INSTRUCTIONS = 0x7, 757ec681f3Smrg /** 767ec681f3Smrg * The analysis depends on the set of VGRFs in the program and their 777ec681f3Smrg * naming. This will be signaled when VGRFs are allocated or released. 787ec681f3Smrg */ 797ec681f3Smrg DEPENDENCY_VARIABLES = 0x8, 807ec681f3Smrg /** 817ec681f3Smrg * The analysis depends on the set of basic blocks in the program, their 827ec681f3Smrg * control flow edges and naming. 837ec681f3Smrg */ 847ec681f3Smrg DEPENDENCY_BLOCKS = 0x10, 857ec681f3Smrg /** 867ec681f3Smrg * The analysis depends on the program being literally the same (good 877ec681f3Smrg * luck...), any change in the input invalidates previous analysis 887ec681f3Smrg * computations. 897ec681f3Smrg */ 907ec681f3Smrg DEPENDENCY_EVERYTHING = ~0 917ec681f3Smrg }; 927ec681f3Smrg 937ec681f3Smrg inline analysis_dependency_class 947ec681f3Smrg operator|(analysis_dependency_class x, analysis_dependency_class y) 957ec681f3Smrg { 967ec681f3Smrg return static_cast<analysis_dependency_class>( 977ec681f3Smrg static_cast<unsigned>(x) | static_cast<unsigned>(y)); 987ec681f3Smrg } 997ec681f3Smrg} 1007ec681f3Smrg 1017ec681f3Smrg/** 1027ec681f3Smrg * Instantiate a program analysis class \p L which can calculate an object of 1037ec681f3Smrg * type \p T as result. \p C is a closure that encapsulates whatever 1047ec681f3Smrg * information is required as argument to run the analysis pass. The purpose 1057ec681f3Smrg * of this class is to make sure that: 1067ec681f3Smrg * 1077ec681f3Smrg * - The analysis pass is executed lazily whenever it's needed and multiple 1087ec681f3Smrg * executions are optimized out as long as the cached result remains marked 1097ec681f3Smrg * up-to-date. 1107ec681f3Smrg * 1117ec681f3Smrg * - There is no way to access the cached analysis result without first 1127ec681f3Smrg * calling L::require(), which makes sure that the analysis pass is rerun 1137ec681f3Smrg * if necessary. 1147ec681f3Smrg * 1157ec681f3Smrg * - The cached result doesn't become inconsistent with the program for as 1167ec681f3Smrg * long as it remains marked up-to-date. (This is only enforced in debug 1177ec681f3Smrg * builds for performance reasons) 1187ec681f3Smrg * 1197ec681f3Smrg * The requirements on \p T are the following: 1207ec681f3Smrg * 1217ec681f3Smrg * - Constructible with a single argument, as in 'x = T(c)' for \p c of type 1227ec681f3Smrg * \p C. 1237ec681f3Smrg * 1247ec681f3Smrg * - 'x.dependency_class()' on const \p x returns a bitset of 1257ec681f3Smrg * brw::analysis_dependency_class specifying the set of IR objects that are 1267ec681f3Smrg * required to remain invariant for the cached analysis result to be 1277ec681f3Smrg * considered valid. 1287ec681f3Smrg * 1297ec681f3Smrg * - 'x.validate(c)' on const \p x returns a boolean result specifying 1307ec681f3Smrg * whether the analysis result \p x is consistent with the input IR. This 1317ec681f3Smrg * is currently only used for validation in debug builds. 1327ec681f3Smrg */ 1337ec681f3Smrgtemplate<class T, class C> 1347ec681f3Smrgclass brw_analysis { 1357ec681f3Smrgpublic: 1367ec681f3Smrg /** 1377ec681f3Smrg * Construct a program analysis. \p c is an arbitrary object 1387ec681f3Smrg * passed as argument to the constructor of the analysis result 1397ec681f3Smrg * object of type \p T. 1407ec681f3Smrg */ 1417ec681f3Smrg brw_analysis(const C *c) : c(c), p(NULL) {} 1427ec681f3Smrg 1437ec681f3Smrg /** 1447ec681f3Smrg * Destroy a program analysis. 1457ec681f3Smrg */ 1467ec681f3Smrg ~brw_analysis() 1477ec681f3Smrg { 1487ec681f3Smrg delete p; 1497ec681f3Smrg } 1507ec681f3Smrg 1517ec681f3Smrg /** 1527ec681f3Smrg * Obtain the result of a program analysis. This gives a 1537ec681f3Smrg * guaranteed up-to-date result, the analysis pass will be 1547ec681f3Smrg * rerun implicitly if it has become stale. 1557ec681f3Smrg */ 1567ec681f3Smrg T & 1577ec681f3Smrg require() 1587ec681f3Smrg { 1597ec681f3Smrg if (p) 1607ec681f3Smrg assert(p->validate(c)); 1617ec681f3Smrg else 1627ec681f3Smrg p = new T(c); 1637ec681f3Smrg 1647ec681f3Smrg return *p; 1657ec681f3Smrg } 1667ec681f3Smrg 1677ec681f3Smrg const T & 1687ec681f3Smrg require() const 1697ec681f3Smrg { 1707ec681f3Smrg return const_cast<brw_analysis<T, C> *>(this)->require(); 1717ec681f3Smrg } 1727ec681f3Smrg 1737ec681f3Smrg /** 1747ec681f3Smrg * Report that dependencies of the analysis pass may have changed 1757ec681f3Smrg * since the last calculation and the cached analysis result may 1767ec681f3Smrg * have to be discarded. 1777ec681f3Smrg */ 1787ec681f3Smrg void 1797ec681f3Smrg invalidate(brw::analysis_dependency_class c) 1807ec681f3Smrg { 1817ec681f3Smrg if (p && (c & p->dependency_class())) { 1827ec681f3Smrg delete p; 1837ec681f3Smrg p = NULL; 1847ec681f3Smrg } 1857ec681f3Smrg } 1867ec681f3Smrg 1877ec681f3Smrgprivate: 1887ec681f3Smrg const C *c; 1897ec681f3Smrg T *p; 1907ec681f3Smrg}; 1917ec681f3Smrg 1927ec681f3Smrg#endif 193