Skip to content
  • Thomas Helland's avatar
    nir: Add a loop analysis pass · 6772a17a
    Thomas Helland authored
    
    
    This pass detects induction variables and calculates the
    trip count of loops to be used for loop unrolling.
    
    V2: Rebase, adapt to removal of function overloads
    
    V3: (Timothy Arceri)
     - don't try to find trip count if loop terminator conditional is a phi
     - fix trip count for do-while loops
     - replace conditional type != alu assert with return
     - disable unrolling of loops with continues
     - multiple fixes to memory allocation, stop leaking and don't destroy
       structs we want to use for unrolling.
     - fix iteration count bugs when induction var not on RHS of condition
     - add FIXME for && conditions
     - calculate trip count for unsigned induction/limit vars
    
    V4: (Timothy Arceri)
    - count instructions in a loop
    - set the limiting_terminator even if we can't find the trip count for
     all terminators. This is needed for complex unrolling where we handle
     2 terminators and the trip count is unknown for one of them.
    - restruct structs so we don't keep information not required after
     analysis and remove dead fields.
    - force unrolling in some cases as per the rules in the GLSL IR pass
    
    V5: (Timothy Arceri)
    - fix metadata mask value 0x10 vs 0x16
    
    V6: (Timothy Arceri)
    - merge loop_variable and nir_loop_variable structs and lists suggested by Jason
    - remove induction var hash table and store pointer to induction information in
      the loop_variable suggested by Jason.
    - use lowercase list_addtail() suggested by Jason.
    - tidy up init_loop_block() as per Jasons suggestions.
    - replace switch with nir_op_infos[alu->op].num_inputs == 2 in
      is_var_basic_induction_var() as suggested by Jason.
    - use nir_block_last_instr() in and rename foreach_cf_node_ex_loop() as suggested
      by Jason.
    - fix else check for is_trivial_loop_terminator() as per Connors suggetions.
    - simplify offset for induction valiables incremented before the exit conditions is
      checked.
    - replace nir_op_isub check with assert() as it should have been lowered away.
    
    V7: (Timothy Arceri)
    - use rzalloc() on nir_loop struct creation. Worked previously because ralloc()
      was broken and always zeroed the struct.
    - fix cf_node_find_loop_jumps() to find jumps when loops contain
      nested if statements. Code is tidier as a result.
    
    V8: (Timothy Arceri)
    - move is_trivial_loop_terminator() to nir.h so we can use it to assert is
      the loop unroll pass
    - fix analysis to not bail when looking for terminator when the break is in the else
      rather then the if
    - added new loop terminator fields: break_block, continue_from_block and
      continue_from_then so we don't have to gather these when doing unrolling.
    - get correct array length when forcing unrolling of variables
      indexed arrays that are the same size as the iteration count
    - add support for induction variables of type float
    - update trival loop terminator check to allow an if containing
      instructions as long as both branches contain only a single
      block.
    
    V9: (Timothy)
     - bunch of tidy ups and simplifications suggested by Jason.
     - rewrote trivial terminator detection, now the only restriction is there
       must be no nested jumps, anything else goes.
     - rewrote the iteration test to use nir_eval_const_opcode().
     - count instruction properly even when forcing an unroll.
     - bunch of other tidy ups and simplifications.
    
    V10: (Timothy)
     - some trivial tidy ups suggested by Jason.
     - conditional fix for break inside continue branch by Jason.
    
    Reviewed-by: default avatarJason Ekstrand <jason@jlekstrand.net>
    6772a17a