Skip to content
  • Faith Ekstrand's avatar
    nir/validate: Use a single set for SSA def validation · 712f9993
    Faith Ekstrand authored
    
    
    The current SSA def validation we do in nir_validate validates three
    things:
    
     1. That each SSA def is only ever used in the function in which it is
        defined.
    
     2. That an nir_src exists in an SSA def's use list if and only if it
        points to that SSA def.
    
     3. That each nir_src is in the correct use list (uses or if_uses) based
        on whether it's an if condition or not.
    
    The way we were doing this before was that we had a hash table which
    provided a map from SSA def to a small ssa_def_validate_state data
    structure which contained a pointer to the nir_function_impl and two
    hash sets, one for each use list.  This meant piles of allocation and
    creating of little hash sets.  It also meant one hash lookup for each
    SSA def plus one per use as well as two per src (because we have to look
    up the ssa_def_validate_state and then look up the use.)  It also
    involved a second walk over the instructions as a post-validate step.
    
    This commit changes us to use a single low-collision hash set of SSA
    sources for all of this by being a bit more clever.  We accomplish the
    objectives above as follows:
    
     1. The list is clear when we start validating a function.  If the
        nir_src references an SSA def which is defined in a different
        function, it simply won't be in the set.
    
     2. When validating the SSA defs, we walk the uses and verify that they
        have is_ssa set and that the SSA def points to the SSA def we're
        validating.  This catches the case of a nir_src being in the wrong
        list.  We then put the nir_src in the set and, when we validate the
        nir_src, we assert that it's in the set.  This takes care of any
        cases where a nir_src isn't in the use list.  After checking that
        the nir_src is in the set, we remove it from the set and, at the end
        of nir_function_impl validation, we assert that the set is empty.
        This takes care of any cases where a nir_src is in a use list but
        the instruction is no longer in the shader.
    
     3. When we put a nir_src in the set, we set the bottom bit of the
        pointer to 1 if it's the condition of an if.  This lets us detect
        whether or not a nir_src is in the right list.
    
    When running shader-db with an optimized debug build of mesa on my
    laptop, I get the following shader-db CPU times:
    
       With NIR_VALIDATE=0       3033.34 seconds
       Before this commit       20224.83 seconds
       After this commit         6255.50 seconds
    
    Assuming shader-db is a representative sampling of GLSL shaders, this
    means that making this change yields an 81% reduction in the time spent
    in nir_validate.  It still isn't cheap but enabling validation now only
    increases compile times by 2x instead of 6.6x.
    
    Reviewed-by: default avatarEric Anholt <eric@anholt.net>
    Reviewed-by: default avatarThomas Helland <thomashelland90@gmail.com>
    712f9993