Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2012 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21.  * IN THE SOFTWARE.
  22.  *
  23.  * Authors:
  24.  *    Eric Anholt <eric@anholt.net>
  25.  *
  26.  */
  27.  
  28. #pragma once
  29. #ifndef BRW_CFG_H
  30. #define BRW_CFG_H
  31.  
  32. #include "brw_shader.h"
  33.  
  34. struct bblock_t;
  35.  
  36. struct bblock_link {
  37. #ifdef __cplusplus
  38.    DECLARE_RALLOC_CXX_OPERATORS(bblock_link)
  39.  
  40.    bblock_link(bblock_t *block)
  41.       : block(block)
  42.    {
  43.    }
  44. #endif
  45.  
  46.    struct exec_node link;
  47.    struct bblock_t *block;
  48. };
  49.  
  50. struct backend_instruction;
  51.  
  52. struct bblock_t {
  53. #ifdef __cplusplus
  54.    DECLARE_RALLOC_CXX_OPERATORS(bblock_t)
  55.  
  56.    explicit bblock_t(cfg_t *cfg);
  57.  
  58.    void add_successor(void *mem_ctx, bblock_t *successor);
  59.    bool is_predecessor_of(const bblock_t *block) const;
  60.    bool is_successor_of(const bblock_t *block) const;
  61.    bool can_combine_with(const bblock_t *that) const;
  62.    void combine_with(bblock_t *that);
  63.    void dump(backend_visitor *v) const;
  64.  
  65.    backend_instruction *start();
  66.    const backend_instruction *start() const;
  67.    backend_instruction *end();
  68.    const backend_instruction *end() const;
  69.  
  70.    bblock_t *next();
  71.    const bblock_t *next() const;
  72.    bblock_t *prev();
  73.    const bblock_t *prev() const;
  74.  
  75.    bool starts_with_control_flow() const;
  76.    bool ends_with_control_flow() const;
  77.  
  78.    backend_instruction *first_non_control_flow_inst();
  79.    backend_instruction *last_non_control_flow_inst();
  80. #endif
  81.  
  82.    struct exec_node link;
  83.    struct cfg_t *cfg;
  84.    struct bblock_t *idom;
  85.  
  86.    int start_ip;
  87.    int end_ip;
  88.  
  89.    struct exec_list instructions;
  90.    struct exec_list parents;
  91.    struct exec_list children;
  92.    int num;
  93. };
  94.  
  95. static inline struct backend_instruction *
  96. bblock_start(struct bblock_t *block)
  97. {
  98.    return (struct backend_instruction *)exec_list_get_head(&block->instructions);
  99. }
  100.  
  101. static inline const struct backend_instruction *
  102. bblock_start_const(const struct bblock_t *block)
  103. {
  104.    return (const struct backend_instruction *)exec_list_get_head_const(&block->instructions);
  105. }
  106.  
  107. static inline struct backend_instruction *
  108. bblock_end(struct bblock_t *block)
  109. {
  110.    return (struct backend_instruction *)exec_list_get_tail(&block->instructions);
  111. }
  112.  
  113. static inline const struct backend_instruction *
  114. bblock_end_const(const struct bblock_t *block)
  115. {
  116.    return (const struct backend_instruction *)exec_list_get_tail_const(&block->instructions);
  117. }
  118.  
  119. static inline struct bblock_t *
  120. bblock_next(struct bblock_t *block)
  121. {
  122.    return (struct bblock_t *)block->link.next;
  123. }
  124.  
  125. static inline const struct bblock_t *
  126. bblock_next_const(const struct bblock_t *block)
  127. {
  128.    return (const struct bblock_t *)block->link.next;
  129. }
  130.  
  131. static inline struct bblock_t *
  132. bblock_prev(struct bblock_t *block)
  133. {
  134.    return (struct bblock_t *)block->link.prev;
  135. }
  136.  
  137. static inline const struct bblock_t *
  138. bblock_prev_const(const struct bblock_t *block)
  139. {
  140.    return (const struct bblock_t *)block->link.prev;
  141. }
  142.  
  143. static inline bool
  144. bblock_starts_with_control_flow(const struct bblock_t *block)
  145. {
  146.    enum opcode op = bblock_start_const(block)->opcode;
  147.    return op == BRW_OPCODE_DO || op == BRW_OPCODE_ENDIF;
  148. }
  149.  
  150. static inline bool
  151. bblock_ends_with_control_flow(const struct bblock_t *block)
  152. {
  153.    enum opcode op = bblock_end_const(block)->opcode;
  154.    return op == BRW_OPCODE_IF ||
  155.           op == BRW_OPCODE_ELSE ||
  156.           op == BRW_OPCODE_WHILE ||
  157.           op == BRW_OPCODE_BREAK ||
  158.           op == BRW_OPCODE_CONTINUE;
  159. }
  160.  
  161. static inline struct backend_instruction *
  162. bblock_first_non_control_flow_inst(struct bblock_t *block)
  163. {
  164.    struct backend_instruction *inst = bblock_start(block);
  165.    if (bblock_starts_with_control_flow(block))
  166. #ifdef __cplusplus
  167.       inst = (struct backend_instruction *)inst->next;
  168. #else
  169.       inst = (struct backend_instruction *)inst->link.next;
  170. #endif
  171.    return inst;
  172. }
  173.  
  174. static inline struct backend_instruction *
  175. bblock_last_non_control_flow_inst(struct bblock_t *block)
  176. {
  177.    struct backend_instruction *inst = bblock_end(block);
  178.    if (bblock_ends_with_control_flow(block))
  179. #ifdef __cplusplus
  180.       inst = (struct backend_instruction *)inst->prev;
  181. #else
  182.       inst = (struct backend_instruction *)inst->link.prev;
  183. #endif
  184.    return inst;
  185. }
  186.  
  187. #ifdef __cplusplus
  188. inline backend_instruction *
  189. bblock_t::start()
  190. {
  191.    return bblock_start(this);
  192. }
  193.  
  194. inline const backend_instruction *
  195. bblock_t::start() const
  196. {
  197.    return bblock_start_const(this);
  198. }
  199.  
  200. inline backend_instruction *
  201. bblock_t::end()
  202. {
  203.    return bblock_end(this);
  204. }
  205.  
  206. inline const backend_instruction *
  207. bblock_t::end() const
  208. {
  209.    return bblock_end_const(this);
  210. }
  211.  
  212. inline bblock_t *
  213. bblock_t::next()
  214. {
  215.    return bblock_next(this);
  216. }
  217.  
  218. inline const bblock_t *
  219. bblock_t::next() const
  220. {
  221.    return bblock_next_const(this);
  222. }
  223.  
  224. inline bblock_t *
  225. bblock_t::prev()
  226. {
  227.    return bblock_prev(this);
  228. }
  229.  
  230. inline const bblock_t *
  231. bblock_t::prev() const
  232. {
  233.    return bblock_prev_const(this);
  234. }
  235.  
  236. inline bool
  237. bblock_t::starts_with_control_flow() const
  238. {
  239.    return bblock_starts_with_control_flow(this);
  240. }
  241.  
  242. inline bool
  243. bblock_t::ends_with_control_flow() const
  244. {
  245.    return bblock_ends_with_control_flow(this);
  246. }
  247.  
  248. inline backend_instruction *
  249. bblock_t::first_non_control_flow_inst()
  250. {
  251.    return bblock_first_non_control_flow_inst(this);
  252. }
  253.  
  254. inline backend_instruction *
  255. bblock_t::last_non_control_flow_inst()
  256. {
  257.    return bblock_last_non_control_flow_inst(this);
  258. }
  259. #endif
  260.  
  261. struct cfg_t {
  262. #ifdef __cplusplus
  263.    DECLARE_RALLOC_CXX_OPERATORS(cfg_t)
  264.  
  265.    cfg_t(exec_list *instructions);
  266.    ~cfg_t();
  267.  
  268.    void remove_block(bblock_t *block);
  269.  
  270.    bblock_t *new_block();
  271.    void set_next_block(bblock_t **cur, bblock_t *block, int ip);
  272.    void make_block_array();
  273.    void calculate_idom();
  274.    static bblock_t *intersect(bblock_t *b1, bblock_t *b2);
  275.  
  276.    void dump(backend_visitor *v);
  277.    void dump_cfg();
  278.    void dump_domtree();
  279. #endif
  280.    void *mem_ctx;
  281.  
  282.    /** Ordered list (by ip) of basic blocks */
  283.    struct exec_list block_list;
  284.    struct bblock_t **blocks;
  285.    int num_blocks;
  286.  
  287.    bool idom_dirty;
  288. };
  289.  
  290. /* Note that this is implemented with a double for loop -- break will
  291.  * break from the inner loop only!
  292.  */
  293. #define foreach_block_and_inst(__block, __type, __inst, __cfg) \
  294.    foreach_block (__block, __cfg)                              \
  295.       foreach_inst_in_block (__type, __inst, __block)
  296.  
  297. /* Note that this is implemented with a double for loop -- break will
  298.  * break from the inner loop only!
  299.  */
  300. #define foreach_block_and_inst_safe(__block, __type, __inst, __cfg) \
  301.    foreach_block_safe (__block, __cfg)                              \
  302.       foreach_inst_in_block_safe (__type, __inst, __block)
  303.  
  304. #define foreach_block(__block, __cfg)                          \
  305.    foreach_list_typed (bblock_t, __block, link, &(__cfg)->block_list)
  306.  
  307. #define foreach_block_reverse(__block, __cfg)                  \
  308.    foreach_list_typed_reverse (bblock_t, __block, link, &(__cfg)->block_list)
  309.  
  310. #define foreach_block_safe(__block, __cfg)                     \
  311.    foreach_list_typed_safe (bblock_t, __block, link, &(__cfg)->block_list)
  312.  
  313. #define foreach_inst_in_block(__type, __inst, __block)         \
  314.    foreach_in_list(__type, __inst, &(__block)->instructions)
  315.  
  316. #define foreach_inst_in_block_safe(__type, __inst, __block)    \
  317.    for (__type *__inst = (__type *)__block->instructions.head, \
  318.                *__next = (__type *)__inst->next,               \
  319.                *__end = (__type *)__block->instructions.tail;  \
  320.         __next != __end;                                       \
  321.         __inst = __next,                                       \
  322.         __next = (__type *)__next->next)
  323.  
  324. #define foreach_inst_in_block_reverse(__type, __inst, __block) \
  325.    foreach_in_list_reverse(__type, __inst, &(__block)->instructions)
  326.  
  327. #define foreach_inst_in_block_reverse_safe(__type, __inst, __block) \
  328.    foreach_in_list_reverse_safe(__type, __inst, &(__block)->instructions)
  329.  
  330. #define foreach_inst_in_block_starting_from(__type, __scan_inst, __inst, __block) \
  331.    for (__type *__scan_inst = (__type *)__inst->next;          \
  332.         !__scan_inst->is_tail_sentinel();                      \
  333.         __scan_inst = (__type *)__scan_inst->next)
  334.  
  335. #define foreach_inst_in_block_reverse_starting_from(__type, __scan_inst, __inst, __block) \
  336.    for (__type *__scan_inst = (__type *)__inst->prev;          \
  337.         !__scan_inst->is_head_sentinel();                      \
  338.         __scan_inst = (__type *)__scan_inst->prev)
  339.  
  340. #endif /* BRW_CFG_H */
  341.