Path: blob/21.2-virgl/src/intel/compiler/brw_cfg.h
4550 views
/*1* Copyright © 2012 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* Eric Anholt <[email protected]>24*25*/2627#ifndef BRW_CFG_H28#define BRW_CFG_H2930#include "brw_ir.h"31#ifdef __cplusplus32#include "brw_ir_analysis.h"33#endif3435struct bblock_t;3637/**38* CFG edge types.39*40* A logical edge represents a potential control flow path of the original41* scalar program, while a physical edge represents a control flow path that42* may not have existed in the original program but was introduced during43* vectorization in order to implement divergent control flow of different44* shader invocations within the same SIMD thread.45*46* All logical edges in the CFG are considered to be physical edges but not47* the other way around -- I.e. the logical CFG is a subset of the physical48* one.49*/50enum bblock_link_kind {51bblock_link_logical = 0,52bblock_link_physical53};5455struct bblock_link {56#ifdef __cplusplus57DECLARE_RALLOC_CXX_OPERATORS(bblock_link)5859bblock_link(bblock_t *block, enum bblock_link_kind kind)60: block(block), kind(kind)61{62}63#endif6465struct exec_node link;66struct bblock_t *block;6768/* Type of this CFG edge. Because bblock_link_logical also implies69* bblock_link_physical, the proper way to test for membership of edge 'l'70* in CFG kind 'k' is 'l.kind <= k'.71*/72enum bblock_link_kind kind;73};7475struct backend_shader;76struct cfg_t;7778struct bblock_t {79#ifdef __cplusplus80DECLARE_RALLOC_CXX_OPERATORS(bblock_t)8182explicit bblock_t(cfg_t *cfg);8384void add_successor(void *mem_ctx, bblock_t *successor,85enum bblock_link_kind kind);86bool is_predecessor_of(const bblock_t *block,87enum bblock_link_kind kind) const;88bool is_successor_of(const bblock_t *block,89enum bblock_link_kind kind) const;90bool can_combine_with(const bblock_t *that) const;91void combine_with(bblock_t *that);92void dump() const;9394backend_instruction *start();95const backend_instruction *start() const;96backend_instruction *end();97const backend_instruction *end() const;9899bblock_t *next();100const bblock_t *next() const;101bblock_t *prev();102const bblock_t *prev() const;103104bool starts_with_control_flow() const;105bool ends_with_control_flow() const;106107backend_instruction *first_non_control_flow_inst();108backend_instruction *last_non_control_flow_inst();109#endif110111struct exec_node link;112struct cfg_t *cfg;113114int start_ip;115int end_ip;116117/**118* Change in end_ip since the last time IPs of later blocks were updated.119*/120int end_ip_delta;121122struct exec_list instructions;123struct exec_list parents;124struct exec_list children;125int num;126};127128static inline struct backend_instruction *129bblock_start(struct bblock_t *block)130{131return (struct backend_instruction *)exec_list_get_head(&block->instructions);132}133134static inline const struct backend_instruction *135bblock_start_const(const struct bblock_t *block)136{137return (const struct backend_instruction *)exec_list_get_head_const(&block->instructions);138}139140static inline struct backend_instruction *141bblock_end(struct bblock_t *block)142{143return (struct backend_instruction *)exec_list_get_tail(&block->instructions);144}145146static inline const struct backend_instruction *147bblock_end_const(const struct bblock_t *block)148{149return (const struct backend_instruction *)exec_list_get_tail_const(&block->instructions);150}151152static inline struct bblock_t *153bblock_next(struct bblock_t *block)154{155if (exec_node_is_tail_sentinel(block->link.next))156return NULL;157158return (struct bblock_t *)block->link.next;159}160161static inline const struct bblock_t *162bblock_next_const(const struct bblock_t *block)163{164if (exec_node_is_tail_sentinel(block->link.next))165return NULL;166167return (const struct bblock_t *)block->link.next;168}169170static inline struct bblock_t *171bblock_prev(struct bblock_t *block)172{173if (exec_node_is_head_sentinel(block->link.prev))174return NULL;175176return (struct bblock_t *)block->link.prev;177}178179static inline const struct bblock_t *180bblock_prev_const(const struct bblock_t *block)181{182if (exec_node_is_head_sentinel(block->link.prev))183return NULL;184185return (const struct bblock_t *)block->link.prev;186}187188static inline bool189bblock_starts_with_control_flow(const struct bblock_t *block)190{191enum opcode op = bblock_start_const(block)->opcode;192return op == BRW_OPCODE_DO || op == BRW_OPCODE_ENDIF;193}194195static inline bool196bblock_ends_with_control_flow(const struct bblock_t *block)197{198enum opcode op = bblock_end_const(block)->opcode;199return op == BRW_OPCODE_IF ||200op == BRW_OPCODE_ELSE ||201op == BRW_OPCODE_WHILE ||202op == BRW_OPCODE_BREAK ||203op == BRW_OPCODE_CONTINUE;204}205206static inline struct backend_instruction *207bblock_first_non_control_flow_inst(struct bblock_t *block)208{209struct backend_instruction *inst = bblock_start(block);210if (bblock_starts_with_control_flow(block))211#ifdef __cplusplus212inst = (struct backend_instruction *)inst->next;213#else214inst = (struct backend_instruction *)inst->link.next;215#endif216return inst;217}218219static inline struct backend_instruction *220bblock_last_non_control_flow_inst(struct bblock_t *block)221{222struct backend_instruction *inst = bblock_end(block);223if (bblock_ends_with_control_flow(block))224#ifdef __cplusplus225inst = (struct backend_instruction *)inst->prev;226#else227inst = (struct backend_instruction *)inst->link.prev;228#endif229return inst;230}231232#ifdef __cplusplus233inline backend_instruction *234bblock_t::start()235{236return bblock_start(this);237}238239inline const backend_instruction *240bblock_t::start() const241{242return bblock_start_const(this);243}244245inline backend_instruction *246bblock_t::end()247{248return bblock_end(this);249}250251inline const backend_instruction *252bblock_t::end() const253{254return bblock_end_const(this);255}256257inline bblock_t *258bblock_t::next()259{260return bblock_next(this);261}262263inline const bblock_t *264bblock_t::next() const265{266return bblock_next_const(this);267}268269inline bblock_t *270bblock_t::prev()271{272return bblock_prev(this);273}274275inline const bblock_t *276bblock_t::prev() const277{278return bblock_prev_const(this);279}280281inline bool282bblock_t::starts_with_control_flow() const283{284return bblock_starts_with_control_flow(this);285}286287inline bool288bblock_t::ends_with_control_flow() const289{290return bblock_ends_with_control_flow(this);291}292293inline backend_instruction *294bblock_t::first_non_control_flow_inst()295{296return bblock_first_non_control_flow_inst(this);297}298299inline backend_instruction *300bblock_t::last_non_control_flow_inst()301{302return bblock_last_non_control_flow_inst(this);303}304#endif305306struct cfg_t {307#ifdef __cplusplus308DECLARE_RALLOC_CXX_OPERATORS(cfg_t)309310cfg_t(const backend_shader *s, exec_list *instructions);311~cfg_t();312313void remove_block(bblock_t *block);314315bblock_t *first_block();316const bblock_t *first_block() const;317bblock_t *last_block();318const bblock_t *last_block() const;319320bblock_t *new_block();321void set_next_block(bblock_t **cur, bblock_t *block, int ip);322void make_block_array();323324void dump();325void dump_cfg();326327/**328* Propagate bblock_t::end_ip_delta data through the CFG.329*/330inline void adjust_block_ips();331332#endif333const struct backend_shader *s;334void *mem_ctx;335336/** Ordered list (by ip) of basic blocks */337struct exec_list block_list;338struct bblock_t **blocks;339int num_blocks;340};341342static inline struct bblock_t *343cfg_first_block(struct cfg_t *cfg)344{345return (struct bblock_t *)exec_list_get_head(&cfg->block_list);346}347348static inline const struct bblock_t *349cfg_first_block_const(const struct cfg_t *cfg)350{351return (const struct bblock_t *)exec_list_get_head_const(&cfg->block_list);352}353354static inline struct bblock_t *355cfg_last_block(struct cfg_t *cfg)356{357return (struct bblock_t *)exec_list_get_tail(&cfg->block_list);358}359360static inline const struct bblock_t *361cfg_last_block_const(const struct cfg_t *cfg)362{363return (const struct bblock_t *)exec_list_get_tail_const(&cfg->block_list);364}365366#ifdef __cplusplus367inline bblock_t *368cfg_t::first_block()369{370return cfg_first_block(this);371}372373const inline bblock_t *374cfg_t::first_block() const375{376return cfg_first_block_const(this);377}378379inline bblock_t *380cfg_t::last_block()381{382return cfg_last_block(this);383}384385const inline bblock_t *386cfg_t::last_block() const387{388return cfg_last_block_const(this);389}390#endif391392/* Note that this is implemented with a double for loop -- break will393* break from the inner loop only!394*/395#define foreach_block_and_inst(__block, __type, __inst, __cfg) \396foreach_block (__block, __cfg) \397foreach_inst_in_block (__type, __inst, __block)398399/* Note that this is implemented with a double for loop -- break will400* break from the inner loop only!401*/402#define foreach_block_and_inst_safe(__block, __type, __inst, __cfg) \403foreach_block_safe (__block, __cfg) \404foreach_inst_in_block_safe (__type, __inst, __block)405406#define foreach_block(__block, __cfg) \407foreach_list_typed (bblock_t, __block, link, &(__cfg)->block_list)408409#define foreach_block_reverse(__block, __cfg) \410foreach_list_typed_reverse (bblock_t, __block, link, &(__cfg)->block_list)411412#define foreach_block_safe(__block, __cfg) \413foreach_list_typed_safe (bblock_t, __block, link, &(__cfg)->block_list)414415#define foreach_block_reverse_safe(__block, __cfg) \416foreach_list_typed_reverse_safe (bblock_t, __block, link, &(__cfg)->block_list)417418#define foreach_inst_in_block(__type, __inst, __block) \419foreach_in_list(__type, __inst, &(__block)->instructions)420421#define foreach_inst_in_block_safe(__type, __inst, __block) \422for (__type *__inst = (__type *)__block->instructions.head_sentinel.next, \423*__next = (__type *)__inst->next; \424__next != NULL; \425__inst = __next, \426__next = (__type *)__next->next)427428#define foreach_inst_in_block_reverse(__type, __inst, __block) \429foreach_in_list_reverse(__type, __inst, &(__block)->instructions)430431#define foreach_inst_in_block_reverse_safe(__type, __inst, __block) \432foreach_in_list_reverse_safe(__type, __inst, &(__block)->instructions)433434#define foreach_inst_in_block_starting_from(__type, __scan_inst, __inst) \435for (__type *__scan_inst = (__type *)__inst->next; \436!__scan_inst->is_tail_sentinel(); \437__scan_inst = (__type *)__scan_inst->next)438439#define foreach_inst_in_block_reverse_starting_from(__type, __scan_inst, __inst) \440for (__type *__scan_inst = (__type *)__inst->prev; \441!__scan_inst->is_head_sentinel(); \442__scan_inst = (__type *)__scan_inst->prev)443444#ifdef __cplusplus445inline void446cfg_t::adjust_block_ips()447{448int delta = 0;449450foreach_block(block, this) {451block->start_ip += delta;452block->end_ip += delta;453454delta += block->end_ip_delta;455456block->end_ip_delta = 0;457}458}459460namespace brw {461/**462* Immediate dominator tree analysis of a shader.463*/464struct idom_tree {465idom_tree(const backend_shader *s);466~idom_tree();467468bool469validate(const backend_shader *) const470{471/* FINISHME */472return true;473}474475analysis_dependency_class476dependency_class() const477{478return DEPENDENCY_BLOCKS;479}480481const bblock_t *482parent(const bblock_t *b) const483{484assert(unsigned(b->num) < num_parents);485return parents[b->num];486}487488bblock_t *489parent(bblock_t *b) const490{491assert(unsigned(b->num) < num_parents);492return parents[b->num];493}494495bblock_t *496intersect(bblock_t *b1, bblock_t *b2) const;497498void499dump() const;500501private:502unsigned num_parents;503bblock_t **parents;504};505}506#endif507508#endif /* BRW_CFG_H */509510511