loop_analysis.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. /*
  2. * Copyright © 2010 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
  21. * DEALINGS IN THE SOFTWARE.
  22. */
  23. #include "glsl_types.h"
  24. #include "loop_analysis.h"
  25. #include "ir_hierarchical_visitor.h"
  26. #include "ir_variable_refcount.h"
  27. static bool is_loop_terminator(ir_if *ir);
  28. static bool used_outside_loops(exec_node *head, ir_variable *var, bool first_assignment);
  29. static bool all_expression_operands_are_loop_constant(ir_rvalue *,
  30. hash_table *);
  31. static ir_rvalue *get_basic_induction_increment(ir_assignment *, hash_table *);
  32. /**
  33. * Record the fact that the given loop variable was referenced inside the loop.
  34. *
  35. * \arg in_assignee is true if the reference was on the LHS of an assignment.
  36. *
  37. * \arg in_conditional_code_or_nested_loop is true if the reference occurred
  38. * inside an if statement or a nested loop.
  39. *
  40. * \arg current_assignment is the ir_assignment node that the loop variable is
  41. * on the LHS of, if any (ignored if \c in_assignee is false).
  42. */
  43. void
  44. loop_variable::record_reference(bool in_assignee,
  45. bool in_conditional_code_or_nested_loop,
  46. ir_assignment *current_assignment)
  47. {
  48. if (in_assignee) {
  49. assert(current_assignment != NULL);
  50. if (in_conditional_code_or_nested_loop ||
  51. current_assignment->condition != NULL) {
  52. this->conditional_or_nested_assignment = true;
  53. }
  54. if (this->first_assignment == NULL) {
  55. assert(this->num_assignments == 0);
  56. this->first_assignment = current_assignment;
  57. }
  58. this->num_assignments++;
  59. } else if (this->first_assignment == current_assignment) {
  60. /* This catches the case where the variable is used in the RHS of an
  61. * assignment where it is also in the LHS.
  62. */
  63. this->read_before_write = true;
  64. }
  65. }
  66. loop_state::loop_state()
  67. {
  68. this->ht = hash_table_ctor(0, hash_table_pointer_hash,
  69. hash_table_pointer_compare);
  70. this->ht_inductors = hash_table_ctor(0, hash_table_pointer_hash,
  71. hash_table_pointer_compare);
  72. this->ht_non_inductors = hash_table_ctor(0, hash_table_pointer_hash,
  73. hash_table_pointer_compare);
  74. this->mem_ctx = ralloc_context(NULL);
  75. this->loop_found = false;
  76. }
  77. loop_state::~loop_state()
  78. {
  79. hash_table_dtor(this->ht);
  80. hash_table_dtor(this->ht_inductors);
  81. hash_table_dtor(this->ht_non_inductors);
  82. ralloc_free(this->mem_ctx);
  83. }
  84. loop_variable_state *
  85. loop_state::insert(ir_loop *ir)
  86. {
  87. loop_variable_state *ls = new(this->mem_ctx) loop_variable_state;
  88. hash_table_insert(this->ht, ls, ir);
  89. this->loop_found = true;
  90. return ls;
  91. }
  92. loop_variable_state *
  93. loop_state::get(const ir_loop *ir)
  94. {
  95. return (loop_variable_state *) hash_table_find(this->ht, ir);
  96. }
  97. loop_variable_state *
  98. loop_state::get_for_inductor(const ir_variable *ir)
  99. {
  100. return (loop_variable_state *) hash_table_find(this->ht_inductors, ir);
  101. }
  102. void
  103. loop_state::insert_non_inductor(ir_variable *var)
  104. {
  105. // key doesn't matter, just needs to be non-NULL
  106. hash_table_insert(this->ht_non_inductors, this, var);
  107. }
  108. bool
  109. loop_state::insert_inductor(loop_variable* loopvar, loop_variable_state* state, ir_loop* loop)
  110. {
  111. ir_variable* var = loopvar->var;
  112. // Check if this variable is already marked as "sure can't be a private inductor variable"
  113. if (hash_table_find(this->ht_non_inductors, var))
  114. return false;
  115. // Check if this variable is used after the loop anywhere. If it is, it can't be a
  116. // variable that's private to the loop.
  117. ir_variable_refcount_visitor refs;
  118. for (exec_node* node = loop->next;
  119. !node->is_tail_sentinel();
  120. node = node->next)
  121. {
  122. ir_instruction *ir = (ir_instruction *) node;
  123. ir->accept (&refs);
  124. if (refs.find_variable_entry(var))
  125. {
  126. // add to list of "non inductors", so that next loop does not try
  127. // to add it as inductor again
  128. hash_table_insert(this->ht_non_inductors, state, var);
  129. return false;
  130. }
  131. }
  132. // Check if this variable is used before the loop anywhere. If it is, it can't be a
  133. // variable that's private to the loop.
  134. // Skip over the IR that declared the variable or assigned the initial value though.
  135. for (exec_node* node = loop->prev;
  136. !node->is_head_sentinel();
  137. node = node->prev)
  138. {
  139. ir_instruction *ir = (ir_instruction *) node;
  140. if (ir == loopvar->initial_value_ir)
  141. continue;
  142. if (ir->ir_type == ir_type_variable)
  143. continue;
  144. ir->accept (&refs);
  145. if (refs.find_variable_entry(var))
  146. {
  147. // add to list of "non inductors", so that next loop does not try
  148. // to add it as inductor again
  149. hash_table_insert(this->ht_non_inductors, state, var);
  150. return false;
  151. }
  152. }
  153. state->private_induction_variable_count++;
  154. hash_table_insert(this->ht_inductors, state, var);
  155. return true;
  156. }
  157. loop_variable *
  158. loop_variable_state::get(const ir_variable *ir)
  159. {
  160. return (loop_variable *) hash_table_find(this->var_hash, ir);
  161. }
  162. loop_variable *
  163. loop_variable_state::insert(ir_variable *var)
  164. {
  165. void *mem_ctx = ralloc_parent(this);
  166. loop_variable *lv = rzalloc(mem_ctx, loop_variable);
  167. lv->var = var;
  168. hash_table_insert(this->var_hash, lv, lv->var);
  169. this->variables.push_tail(lv);
  170. return lv;
  171. }
  172. loop_terminator *
  173. loop_variable_state::insert(ir_if *if_stmt)
  174. {
  175. void *mem_ctx = ralloc_parent(this);
  176. loop_terminator *t = new(mem_ctx) loop_terminator();
  177. t->ir = if_stmt;
  178. this->terminators.push_tail(t);
  179. return t;
  180. }
  181. /**
  182. * If the given variable already is recorded in the state for this loop,
  183. * return the corresponding loop_variable object that records information
  184. * about it.
  185. *
  186. * Otherwise, create a new loop_variable object to record information about
  187. * the variable, and set its \c read_before_write field appropriately based on
  188. * \c in_assignee.
  189. *
  190. * \arg in_assignee is true if this variable was encountered on the LHS of an
  191. * assignment.
  192. */
  193. loop_variable *
  194. loop_variable_state::get_or_insert(ir_variable *var, bool in_assignee)
  195. {
  196. loop_variable *lv = this->get(var);
  197. if (lv == NULL) {
  198. lv = this->insert(var);
  199. lv->read_before_write = !in_assignee;
  200. }
  201. return lv;
  202. }
  203. namespace {
  204. class loop_analysis : public ir_hierarchical_visitor {
  205. public:
  206. loop_analysis(loop_state *loops);
  207. virtual ir_visitor_status visit(ir_loop_jump *);
  208. virtual ir_visitor_status visit(ir_dereference_variable *);
  209. virtual ir_visitor_status visit(ir_variable *);
  210. virtual ir_visitor_status visit_enter(ir_call *);
  211. virtual ir_visitor_status visit_enter(ir_loop *);
  212. virtual ir_visitor_status visit_leave(ir_loop *);
  213. virtual ir_visitor_status visit_enter(ir_assignment *);
  214. virtual ir_visitor_status visit_leave(ir_assignment *);
  215. virtual ir_visitor_status visit_enter(ir_if *);
  216. virtual ir_visitor_status visit_leave(ir_if *);
  217. loop_state *loops;
  218. int if_statement_depth;
  219. ir_assignment *current_assignment;
  220. exec_list state;
  221. };
  222. } /* anonymous namespace */
  223. loop_analysis::loop_analysis(loop_state *loops)
  224. : loops(loops), if_statement_depth(0), current_assignment(NULL)
  225. {
  226. /* empty */
  227. }
  228. ir_visitor_status
  229. loop_analysis::visit(ir_loop_jump *ir)
  230. {
  231. (void) ir;
  232. assert(!this->state.is_empty());
  233. loop_variable_state *const ls =
  234. (loop_variable_state *) this->state.get_head();
  235. ls->num_loop_jumps++;
  236. return visit_continue;
  237. }
  238. ir_visitor_status
  239. loop_analysis::visit(ir_variable *var)
  240. {
  241. // if inside a loop, simply continue - we're only interested in variables declared
  242. // entirely outside of any loops
  243. if (!this->state.is_empty())
  244. return visit_continue;
  245. // Check if this variable is used outside a loop anywhere. If it is, it can't be a
  246. // variable that's private to the loop, so can't be an inductor.
  247. // This doesn't reject all possible non-inductors, notably anything declared in an
  248. // outer loop that isn't an inductor in an inner loop, but it can eliminate some
  249. // problem cases
  250. if (used_outside_loops(var->next, var, false))
  251. {
  252. // add to list of "non inductors"
  253. loops->insert_non_inductor(var);
  254. }
  255. return visit_continue;
  256. }
  257. ir_visitor_status
  258. loop_analysis::visit_enter(ir_call *)
  259. {
  260. /* Mark every loop that we're currently analyzing as containing an ir_call
  261. * (even those at outer nesting levels).
  262. */
  263. foreach_in_list(loop_variable_state, ls, &this->state) {
  264. ls->contains_calls = true;
  265. }
  266. return visit_continue_with_parent;
  267. }
  268. ir_visitor_status
  269. loop_analysis::visit(ir_dereference_variable *ir)
  270. {
  271. /* If we're not somewhere inside a loop, there's nothing to do.
  272. */
  273. if (this->state.is_empty())
  274. return visit_continue;
  275. bool nested = false;
  276. foreach_in_list(loop_variable_state, ls, &this->state) {
  277. ir_variable *var = ir->variable_referenced();
  278. loop_variable *lv = ls->get_or_insert(var, this->in_assignee);
  279. lv->record_reference(this->in_assignee,
  280. nested || this->if_statement_depth > 0,
  281. this->current_assignment);
  282. nested = true;
  283. }
  284. return visit_continue;
  285. }
  286. ir_visitor_status
  287. loop_analysis::visit_enter(ir_loop *ir)
  288. {
  289. loop_variable_state *ls = this->loops->insert(ir);
  290. this->state.push_head(ls);
  291. return visit_continue;
  292. }
  293. ir_visitor_status
  294. loop_analysis::visit_leave(ir_loop *ir)
  295. {
  296. loop_variable_state *const ls =
  297. (loop_variable_state *) this->state.pop_head();
  298. /* Function calls may contain side effects. These could alter any of our
  299. * variables in ways that cannot be known, and may even terminate shader
  300. * execution (say, calling discard in the fragment shader). So we can't
  301. * rely on any of our analysis about assignments to variables.
  302. *
  303. * We could perform some conservative analysis (prove there's no statically
  304. * possible assignment, etc.) but it isn't worth it for now; function
  305. * inlining will allow us to unroll loops anyway.
  306. */
  307. if (ls->contains_calls)
  308. return visit_continue;
  309. foreach_in_list(ir_instruction, node, &ir->body_instructions) {
  310. /* Skip over declarations at the start of a loop.
  311. */
  312. if (node->as_variable())
  313. continue;
  314. ir_if *if_stmt = ((ir_instruction *) node)->as_if();
  315. if ((if_stmt != NULL) && is_loop_terminator(if_stmt))
  316. ls->insert(if_stmt);
  317. else
  318. break;
  319. }
  320. foreach_in_list_safe(loop_variable, lv, &ls->variables) {
  321. ir_variable *var = lv->var;
  322. if (var != NULL) {
  323. lv->initial_value = find_initial_value(ir, var, &lv->initial_value_ir);
  324. }
  325. /* Move variables that are already marked as being loop constant to
  326. * a separate list. These trivially don't need to be tested.
  327. */
  328. if (lv->is_loop_constant()) {
  329. lv->remove();
  330. ls->constants.push_tail(lv);
  331. }
  332. }
  333. /* Each variable assigned in the loop that isn't already marked as being loop
  334. * constant might still be loop constant. The requirements at this point
  335. * are:
  336. *
  337. * - Variable is written before it is read.
  338. *
  339. * - Only one assignment to the variable.
  340. *
  341. * - All operands on the RHS of the assignment are also loop constants.
  342. *
  343. * The last requirement is the reason for the progress loop. A variable
  344. * marked as a loop constant on one pass may allow other variables to be
  345. * marked as loop constant on following passes.
  346. */
  347. bool progress;
  348. do {
  349. progress = false;
  350. foreach_in_list_safe(loop_variable, lv, &ls->variables) {
  351. if (lv->conditional_or_nested_assignment || (lv->num_assignments > 1))
  352. continue;
  353. /* Process the RHS of the assignment. If all of the variables
  354. * accessed there are loop constants, then add this
  355. */
  356. ir_rvalue *const rhs = lv->first_assignment->rhs;
  357. if (all_expression_operands_are_loop_constant(rhs, ls->var_hash)) {
  358. lv->rhs_clean = true;
  359. if (lv->is_loop_constant()) {
  360. progress = true;
  361. lv->remove();
  362. ls->constants.push_tail(lv);
  363. }
  364. }
  365. }
  366. } while (progress);
  367. /* The remaining variables that are not loop invariant might be loop
  368. * induction variables.
  369. */
  370. foreach_in_list_safe(loop_variable, lv, &ls->variables) {
  371. /* If there is more than one assignment to a variable, it cannot be a
  372. * loop induction variable. This isn't strictly true, but this is a
  373. * very simple induction variable detector, and it can't handle more
  374. * complex cases.
  375. */
  376. if (lv->num_assignments > 1)
  377. continue;
  378. /* All of the variables with zero assignments in the loop are loop
  379. * invariant, and they should have already been filtered out.
  380. */
  381. assert(lv->num_assignments == 1);
  382. assert(lv->first_assignment != NULL);
  383. /* The assignment to the variable in the loop must be unconditional and
  384. * not inside a nested loop.
  385. */
  386. if (lv->conditional_or_nested_assignment)
  387. continue;
  388. /* Basic loop induction variables have a single assignment in the loop
  389. * that has the form 'VAR = VAR + i' or 'VAR = VAR - i' where i is a
  390. * loop invariant.
  391. */
  392. ir_rvalue *const inc =
  393. get_basic_induction_increment(lv->first_assignment, ls->var_hash);
  394. if (inc != NULL) {
  395. lv->increment = inc;
  396. if (loops->insert_inductor(lv, ls, ir)) {
  397. lv->remove();
  398. ls->induction_variables.push_tail(lv);
  399. }
  400. }
  401. }
  402. /* Search the loop terminating conditions for those of the form 'i < c'
  403. * where i is a loop induction variable, c is a constant, and < is any
  404. * relative operator. From each of these we can infer an iteration count.
  405. * Also figure out which terminator (if any) produces the smallest
  406. * iteration count--this is the limiting terminator.
  407. */
  408. foreach_in_list(loop_terminator, t, &ls->terminators) {
  409. ir_if *if_stmt = t->ir;
  410. /* If-statements can be either 'if (expr)' or 'if (deref)'. We only care
  411. * about the former here.
  412. */
  413. ir_expression *cond = if_stmt->condition->as_expression();
  414. if (cond == NULL)
  415. continue;
  416. switch (cond->operation) {
  417. case ir_binop_less:
  418. case ir_binop_greater:
  419. case ir_binop_lequal:
  420. case ir_binop_gequal: {
  421. /* The expressions that we care about will either be of the form
  422. * 'counter < limit' or 'limit < counter'. Figure out which is
  423. * which.
  424. */
  425. ir_rvalue *counter = cond->operands[0]->as_dereference_variable();
  426. ir_constant *limit = cond->operands[1]->as_constant();
  427. enum ir_expression_operation cmp = cond->operation;
  428. if (limit == NULL) {
  429. counter = cond->operands[1]->as_dereference_variable();
  430. limit = cond->operands[0]->as_constant();
  431. switch (cmp) {
  432. case ir_binop_less: cmp = ir_binop_greater; break;
  433. case ir_binop_greater: cmp = ir_binop_less; break;
  434. case ir_binop_lequal: cmp = ir_binop_gequal; break;
  435. case ir_binop_gequal: cmp = ir_binop_lequal; break;
  436. default: assert(!"Should not get here.");
  437. }
  438. }
  439. if ((counter == NULL) || (limit == NULL))
  440. break;
  441. ir_variable *var = counter->variable_referenced();
  442. loop_variable *lv = ls->get(var);
  443. if (lv != NULL && lv->is_induction_var()) {
  444. t->iterations = calculate_iterations(lv->initial_value, limit, lv->increment,
  445. cmp);
  446. if (t->iterations >= 0 &&
  447. (ls->limiting_terminator == NULL ||
  448. t->iterations < ls->limiting_terminator->iterations)) {
  449. ls->limiting_terminator = t;
  450. }
  451. }
  452. break;
  453. }
  454. default:
  455. break;
  456. }
  457. }
  458. return visit_continue;
  459. }
  460. ir_visitor_status
  461. loop_analysis::visit_enter(ir_if *ir)
  462. {
  463. (void) ir;
  464. if (!this->state.is_empty())
  465. this->if_statement_depth++;
  466. return visit_continue;
  467. }
  468. ir_visitor_status
  469. loop_analysis::visit_leave(ir_if *ir)
  470. {
  471. (void) ir;
  472. if (!this->state.is_empty())
  473. this->if_statement_depth--;
  474. return visit_continue;
  475. }
  476. ir_visitor_status
  477. loop_analysis::visit_enter(ir_assignment *ir)
  478. {
  479. /* If we're not somewhere inside a loop, there's nothing to do.
  480. */
  481. if (this->state.is_empty())
  482. return visit_continue_with_parent;
  483. this->current_assignment = ir;
  484. return visit_continue;
  485. }
  486. ir_visitor_status
  487. loop_analysis::visit_leave(ir_assignment *ir)
  488. {
  489. /* Since the visit_enter exits with visit_continue_with_parent for this
  490. * case, the loop state stack should never be empty here.
  491. */
  492. assert(!this->state.is_empty());
  493. assert(this->current_assignment == ir);
  494. this->current_assignment = NULL;
  495. return visit_continue;
  496. }
  497. class examine_rhs : public ir_hierarchical_visitor {
  498. public:
  499. examine_rhs(hash_table *loop_variables)
  500. {
  501. this->only_uses_loop_constants = true;
  502. this->loop_variables = loop_variables;
  503. }
  504. virtual ir_visitor_status visit(ir_dereference_variable *ir)
  505. {
  506. loop_variable *lv =
  507. (loop_variable *) hash_table_find(this->loop_variables, ir->var);
  508. assert(lv != NULL);
  509. if (lv->is_loop_constant()) {
  510. return visit_continue;
  511. } else {
  512. this->only_uses_loop_constants = false;
  513. return visit_stop;
  514. }
  515. }
  516. hash_table *loop_variables;
  517. bool only_uses_loop_constants;
  518. };
  519. bool
  520. all_expression_operands_are_loop_constant(ir_rvalue *ir, hash_table *variables)
  521. {
  522. examine_rhs v(variables);
  523. ir->accept(&v);
  524. return v.only_uses_loop_constants;
  525. }
  526. ir_rvalue *
  527. get_basic_induction_increment(ir_assignment *ir, hash_table *var_hash)
  528. {
  529. /* The RHS must be a binary expression.
  530. */
  531. ir_expression *const rhs = ir->rhs->as_expression();
  532. if ((rhs == NULL)
  533. || ((rhs->operation != ir_binop_add)
  534. && (rhs->operation != ir_binop_sub)))
  535. return NULL;
  536. /* One of the of operands of the expression must be the variable assigned.
  537. * If the operation is subtraction, the variable in question must be the
  538. * "left" operand.
  539. */
  540. ir_variable *const var = ir->lhs->variable_referenced();
  541. ir_variable *const op0 = rhs->operands[0]->variable_referenced();
  542. ir_variable *const op1 = rhs->operands[1]->variable_referenced();
  543. if (((op0 != var) && (op1 != var))
  544. || ((op1 == var) && (rhs->operation == ir_binop_sub)))
  545. return NULL;
  546. ir_rvalue *inc = (op0 == var) ? rhs->operands[1] : rhs->operands[0];
  547. if (inc->as_constant() == NULL) {
  548. ir_variable *const inc_var = inc->variable_referenced();
  549. if (inc_var != NULL) {
  550. loop_variable *lv =
  551. (loop_variable *) hash_table_find(var_hash, inc_var);
  552. if (lv == NULL || !lv->is_loop_constant()) {
  553. assert(lv != NULL);
  554. inc = NULL;
  555. }
  556. } else
  557. inc = NULL;
  558. }
  559. if ((inc != NULL) && (rhs->operation == ir_binop_sub)) {
  560. void *mem_ctx = ralloc_parent(ir);
  561. inc = new(mem_ctx) ir_expression(ir_unop_neg,
  562. inc->type,
  563. inc->clone(mem_ctx, NULL),
  564. NULL);
  565. }
  566. return inc;
  567. }
  568. /**
  569. * Detect whether an if-statement is a loop terminating condition
  570. *
  571. * Detects if-statements of the form
  572. *
  573. * (if (expression bool ...) (break))
  574. */
  575. bool
  576. is_loop_terminator(ir_if *ir)
  577. {
  578. if (!ir->else_instructions.is_empty())
  579. return false;
  580. ir_instruction *const inst =
  581. (ir_instruction *) ir->then_instructions.get_head();
  582. if (inst == NULL)
  583. return false;
  584. if (inst->ir_type != ir_type_loop_jump)
  585. return false;
  586. ir_loop_jump *const jump = (ir_loop_jump *) inst;
  587. if (jump->mode != ir_loop_jump::jump_break)
  588. return false;
  589. return true;
  590. }
  591. bool
  592. used_outside_loops(exec_node *head, ir_variable *var, bool first_assignment)
  593. {
  594. ir_variable_refcount_visitor refs;
  595. for (exec_node* node = head;
  596. !node->is_tail_sentinel();
  597. node = node->next)
  598. {
  599. ir_instruction *ir = (ir_instruction *) node;
  600. if (ir->ir_type == ir_type_variable)
  601. continue;
  602. // ignore the first assignment
  603. if (!first_assignment && ir->ir_type == ir_type_assignment)
  604. {
  605. ir_assignment *assign = ir->as_assignment();
  606. ir_variable *assignee = assign->lhs->whole_variable_referenced();
  607. if(assignee == var)
  608. {
  609. first_assignment = true;
  610. continue;
  611. }
  612. }
  613. // we don't want to recurse into loops
  614. if (ir->ir_type == ir_type_loop)
  615. continue;
  616. // recurse only for if statements, the other case we would need to recurse is
  617. // loops, but we are looking for uses outside of loops.
  618. if (ir->ir_type == ir_type_if)
  619. {
  620. ir_if *irif = ir->as_if();
  621. if (used_outside_loops(irif->then_instructions.head, var, first_assignment))
  622. return true;
  623. if (used_outside_loops(irif->else_instructions.head, var, first_assignment))
  624. return true;
  625. // if we didn't find in each branch with our recursion, skip
  626. // otherwise the accept (&refs) below will recurse into loops
  627. // and may give a false positive.
  628. continue;
  629. }
  630. // we know that we're not inside a loop as we haven't recursed inside,
  631. // and we started outside of a loop, so any references to this variable
  632. // mean it is used outside of any loops
  633. ir->accept (&refs);
  634. if (refs.find_variable_entry(var))
  635. {
  636. return true;
  637. }
  638. }
  639. return false;
  640. }
  641. loop_state *
  642. analyze_loop_variables(exec_list *instructions)
  643. {
  644. loop_state *loops = new loop_state;
  645. loop_analysis v(loops);
  646. v.run(instructions);
  647. return v.loops;
  648. }