<p dir="ltr"><br>
On Mar 15, 2016 7:48 AM, "Connor Abbott" <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>> wrote:<br>
><br>
> On Tue, Mar 15, 2016 at 10:43 AM, Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>> wrote:<br>
> > On Tue, Mar 15, 2016 at 5:53 AM, Iago Toral <<a href="mailto:itoral@igalia.com">itoral@igalia.com</a>> wrote:<br>
> >> On Mon, 2016-03-14 at 16:48 -0700, Jason Ekstrand wrote:<br>
> >>><br>
> >>><br>
> >>> On Mon, Mar 7, 2016 at 12:46 AM, Samuel Iglesias Gonsálvez<br>
> >>> <<a href="mailto:siglesias@igalia.com">siglesias@igalia.com</a>> wrote:<br>
> >>>         From: Connor Abbott <<a href="mailto:connor.w.abbott@intel.com">connor.w.abbott@intel.com</a>><br>
> >>><br>
> >>>         v2: Use the bit-size information from the opcode information<br>
> >>>         if defined (Iago)<br>
> >>><br>
> >>>         Signed-off-by: Iago Toral Quiroga <<a href="mailto:itoral@igalia.com">itoral@igalia.com</a>><br>
> >>><br>
> >>>         FIXME: This should be squashed into the previous commit so we<br>
> >>>         don't break<br>
> >>>         the build. The break happens because the python script that<br>
> >>>         generates the<br>
> >>>         constant folding pass does not know how to handle the sized<br>
> >>>         types introduced<br>
> >>>         by the previous commit until this patch, so it ends up<br>
> >>>         generating code with<br>
> >>>         invalid types. Keep it separated for review purposes.<br>
> >>>         ---<br>
> >>>          src/compiler/nir/nir_constant_expressions.h  |   2 +-<br>
> >>>          src/compiler/nir/nir_constant_expressions.py | 246<br>
> >>>         +++++++++++++++++----------<br>
> >>>          src/compiler/nir/nir_opt_constant_folding.c  |  24 ++-<br>
> >>>          3 files changed, 182 insertions(+), 90 deletions(-)<br>
> >>><br>
> >>>         diff --git a/src/compiler/nir/nir_constant_expressions.h<br>
> >>>         b/src/compiler/nir/nir_constant_expressions.h<br>
> >>>         index 97997f2..201f278 100644<br>
> >>>         --- a/src/compiler/nir/nir_constant_expressions.h<br>
> >>>         +++ b/src/compiler/nir/nir_constant_expressions.h<br>
> >>>         @@ -28,4 +28,4 @@<br>
> >>>          #include "nir.h"<br>
> >>><br>
> >>>          nir_const_value nir_eval_const_opcode(nir_op op, unsigned<br>
> >>>         num_components,<br>
> >>>         -                                      nir_const_value *src);<br>
> >>>         +                                      unsigned bit_size,<br>
> >>>         nir_const_value *src);<br>
> >>>         diff --git a/src/compiler/nir/nir_constant_expressions.py<br>
> >>>         b/src/compiler/nir/nir_constant_expressions.py<br>
> >>>         index 32784f6..972d281 100644<br>
> >>>         --- a/src/compiler/nir/nir_constant_expressions.py<br>
> >>>         +++ b/src/compiler/nir/nir_constant_expressions.py<br>
> >>>         @@ -1,4 +1,43 @@<br>
> >>>          #! /usr/bin/python2<br>
> >>>         +<br>
> >>>         +def type_has_size(type_):<br>
> >>>         +    return type_[-1:].isdigit()<br>
> >>>         +<br>
> >>>         +def type_sizes(type_):<br>
> >>>         +    if type_.endswith("8"):<br>
> >>>         +        return [8]<br>
> >>>         +    elif type_.endswith("16"):<br>
> >>>         +        return [16]<br>
> >>>         +    elif type_.endswith("32"):<br>
> >>>         +        return [32]<br>
> >>>         +    elif type_.endswith("64"):<br>
> >>>         +        return [64]<br>
> >>>         +    else:<br>
> >>>         +        return [32, 64]<br>
> >>>         +<br>
> >>>         +def type_add_size(type_, size):<br>
> >>>         +    if type_has_size(type_):<br>
> >>>         +        return type_<br>
> >>>         +    return type_ + str(size)<br>
> >>>         +<br>
> >>>         +def get_const_field(type_):<br>
> >>>         +    if type_ == "int32":<br>
> >>>         +        return "i"<br>
> >>>         +    if type_ == "uint32":<br>
> >>>         +        return "u"<br>
> >>>         +    if type_ == "int64":<br>
> >>>         +        return "l"<br>
> >>>         +    if type_ == "uint64":<br>
> >>>         +        return "ul"<br>
> >>>         +    if type_ == "bool32":<br>
> >>>         +        return "b"<br>
> >>>         +    if type_ == "float32":<br>
> >>>         +        return "f"<br>
> >>>         +    if type_ == "float64":<br>
> >>>         +        return "d"<br>
> >>>         +    raise Exception(str(type_))<br>
> >>>         +    assert(0)<br>
> >>>         +<br>
> >>>          template = """\<br>
> >>>          /*<br>
> >>>           * Copyright (C) 2014 Intel Corporation<br>
> >>>         @@ -205,110 +244,140 @@ unpack_half_1x16(uint16_t u)<br>
> >>>          }<br>
> >>><br>
> >>>          /* Some typed vector structures to make things like src0.y<br>
> >>>         work */<br>
> >>>         -% for type in ["float", "int", "uint", "bool"]:<br>
> >>>         -struct ${type}_vec {<br>
> >>>         -   ${type} x;<br>
> >>>         -   ${type} y;<br>
> >>>         -   ${type} z;<br>
> >>>         -   ${type} w;<br>
> >>>         +typedef float float32_t;<br>
> >>>         +typedef double float64_t;<br>
> >>>         +typedef bool bool32_t;<br>
> >>>         +% for type in ["float", "int", "uint"]:<br>
> >>>         +% for width in [32, 64]:<br>
> >>>         +struct ${type}${width}_vec {<br>
> >>>         +   ${type}${width}_t x;<br>
> >>>         +   ${type}${width}_t y;<br>
> >>>         +   ${type}${width}_t z;<br>
> >>>         +   ${type}${width}_t w;<br>
> >>>          };<br>
> >>>          % endfor<br>
> >>>         +% endfor<br>
> >>>         +<br>
> >>>         +struct bool32_vec {<br>
> >>>         +    bool x;<br>
> >>>         +    bool y;<br>
> >>>         +    bool z;<br>
> >>>         +    bool w;<br>
> >>>         +};<br>
> >>><br>
> >>>          % for name, op in sorted(opcodes.iteritems()):<br>
> >>>          static nir_const_value<br>
> >>>         -evaluate_${name}(unsigned num_components, nir_const_value<br>
> >>>         *_src)<br>
> >>>         +evaluate_${name}(unsigned num_components, unsigned bit_size,<br>
> >>>         +                 nir_const_value *_src)<br>
> >>>          {<br>
> >>>             nir_const_value _dst_val = { { {0, 0, 0, 0} } };<br>
> >>><br>
> >>>         -   ## For each non-per-component input, create a variable<br>
> >>>         srcN that<br>
> >>>         -   ## contains x, y, z, and w elements which are filled in<br>
> >>>         with the<br>
> >>>         -   ## appropriately-typed values.<br>
> >>>         -   % for j in range(op.num_inputs):<br>
> >>>         -      % if op.input_sizes[j] == 0:<br>
> >>>         -         <% continue %><br>
> >>>         -      % elif "src" + str(j) not in op.const_expr:<br>
> >>>         -         ## Avoid unused variable warnings<br>
> >>>         -         <% continue %><br>
> >>>         -      %endif<br>
> >>>         -<br>
> >>>         -      struct ${op.input_types[j]}_vec src${j} = {<br>
> >>>         -      % for k in range(op.input_sizes[j]):<br>
> >>>         -         % if op.input_types[j] == "bool":<br>
> >>>         -            _src[${j}].u[${k}] != 0,<br>
> >>>         -         % else:<br>
> >>>         -            _src[${j}].${op.input_types[j][:1]}[${k}],<br>
> >>>         -         % endif<br>
> >>>         -      % endfor<br>
> >>>         -      };<br>
> >>>         -   % endfor<br>
> >>>         +   switch (bit_size) {<br>
> >>>         +   % for bit_size in [32, 64]:<br>
> >>>         +   case ${bit_size}: {<br>
> >>>         +      <%<br>
> >>>         +      output_type = type_add_size(op.output_type, bit_size)<br>
> >>>         +      input_types = [type_add_size(type_, bit_size) for type_<br>
> >>>         in op.input_types]<br>
> >>>         +      %><br>
> >>>         +<br>
> >>>         +      ## For each non-per-component input, create a variable<br>
> >>>         srcN that<br>
> >>>         +      ## contains x, y, z, and w elements which are filled in<br>
> >>>         with the<br>
> >>>         +      ## appropriately-typed values.<br>
> >>>         +      % for j in range(op.num_inputs):<br>
> >>>         +         % if op.input_sizes[j] == 0:<br>
> >>>         +            <% continue %><br>
> >>>         +         % elif "src" + str(j) not in op.const_expr:<br>
> >>>         +            ## Avoid unused variable warnings<br>
> >>>         +            <% continue %><br>
> >>>         +         %endif<br>
> >>><br>
> >>>         -   % if op.output_size == 0:<br>
> >>>         -      ## For per-component instructions, we need to iterate<br>
> >>>         over the<br>
> >>>         -      ## components and apply the constant expression one<br>
> >>>         component<br>
> >>>         -      ## at a time.<br>
> >>>         -      for (unsigned _i = 0; _i < num_components; _i++) {<br>
> >>>         -         ## For each per-component input, create a variable<br>
> >>>         srcN that<br>
> >>>         -         ## contains the value of the current (_i'th)<br>
> >>>         component.<br>
> >>>         -         % for j in range(op.num_inputs):<br>
> >>>         -            % if op.input_sizes[j] != 0:<br>
> >>>         -               <% continue %><br>
> >>>         -            % elif "src" + str(j) not in op.const_expr:<br>
> >>>         -               ## Avoid unused variable warnings<br>
> >>>         -               <% continue %><br>
> >>>         -            % elif op.input_types[j] == "bool":<br>
> >>>         -               bool src${j} = _src[${j}].u[_i] != 0;<br>
> >>>         +         struct ${input_types[j]}_vec src${j} = {<br>
> >>>         +         % for k in range(op.input_sizes[j]):<br>
> >>>         +            % if input_types[j] == "bool32":<br>
> >>>         +               _src[${j}].u[${k}] != 0,<br>
> >>>                      % else:<br>
> >>>         -               ${op.input_types[j]} src${j} =<br>
> >>>         _src[${j}].${op.input_types[j][:1]}[_i];<br>
> >>>         +<br>
> >>>          _src[${j}].${get_const_field(input_types[j])}[${k}],<br>
> >>>                      % endif<br>
> >>>                   % endfor<br>
> >>>         +         };<br>
> >>>         +      % endfor<br>
> >>>         +<br>
> >>>         +      % if op.output_size == 0:<br>
> >>>         +         ## For per-component instructions, we need to<br>
> >>>         iterate over the<br>
> >>>         +         ## components and apply the constant expression one<br>
> >>>         component<br>
> >>>         +         ## at a time.<br>
> >>>         +         for (unsigned _i = 0; _i < num_components; _i++) {<br>
> >>>         +            ## For each per-component input, create a<br>
> >>>         variable srcN that<br>
> >>>         +            ## contains the value of the current (_i'th)<br>
> >>>         component.<br>
> >>>         +            % for j in range(op.num_inputs):<br>
> >>>         +               % if op.input_sizes[j] != 0:<br>
> >>>         +                  <% continue %><br>
> >>>         +               % elif "src" + str(j) not in op.const_expr:<br>
> >>>         +                  ## Avoid unused variable warnings<br>
> >>>         +                  <% continue %><br>
> >>>         +               % elif input_types[j] == "bool32":<br>
> >>>         +                  bool src${j} = _src[${j}].u[_i] != 0;<br>
> >>>         +               % else:<br>
> >>>         +                  ${input_types[j]}_t src${j} =<br>
> >>>         +<br>
> >>>          _src[${j}].${get_const_field(input_types[j])}[_i];<br>
> >>>         +               % endif<br>
> >>>         +            % endfor<br>
> >>>         +<br>
> >>>         +            ## Create an appropriately-typed variable dst and<br>
> >>>         assign the<br>
> >>>         +            ## result of the const_expr to it.  If const_expr<br>
> >>>         already contains<br>
> >>>         +            ## writes to dst, just include const_expr<br>
> >>>         directly.<br>
> >>>         +            % if "dst" in op.const_expr:<br>
> >>>         +               ${output_type}_t dst;<br>
> >>>         +               ${op.const_expr}<br>
> >>>         +            % else:<br>
> >>>         +               ${output_type}_t dst = ${op.const_expr};<br>
> >>>         +            % endif<br>
> >>>         +<br>
> >>>         +            ## Store the current component of the actual<br>
> >>>         destination to the<br>
> >>>         +            ## value of dst.<br>
> >>>         +            % if output_type == "bool32":<br>
> >>>         +               ## Sanitize the C value to a proper NIR bool<br>
> >>>         +               _dst_val.u[_i] = dst ? NIR_TRUE : NIR_FALSE;<br>
> >>>         +            % else:<br>
> >>>         +               _dst_val.${get_const_field(output_type)}[_i] =<br>
> >>>         dst;<br>
> >>>         +            % endif<br>
> >>>         +         }<br>
> >>>         +      % else:<br>
> >>>         +         ## In the non-per-component case, create a struct<br>
> >>>         dst with<br>
> >>>         +         ## appropriately-typed elements x, y, z, and w and<br>
> >>>         assign the result<br>
> >>>         +         ## of the const_expr to all components of dst, or<br>
> >>>         include the<br>
> >>>         +         ## const_expr directly if it writes to dst already.<br>
> >>>         +         struct ${output_type}_vec dst;<br>
> >>><br>
> >>>         -         ## Create an appropriately-typed variable dst and<br>
> >>>         assign the<br>
> >>>         -         ## result of the const_expr to it.  If const_expr<br>
> >>>         already contains<br>
> >>>         -         ## writes to dst, just include const_expr directly.<br>
> >>>                   % if "dst" in op.const_expr:<br>
> >>>         -            ${op.output_type} dst;<br>
> >>>                      ${op.const_expr}<br>
> >>>                   % else:<br>
> >>>         -            ${op.output_type} dst = ${op.const_expr};<br>
> >>>         +            ## Splat the value to all components.  This way<br>
> >>>         expressions which<br>
> >>>         +            ## write the same value to all components don't<br>
> >>>         need to explicitly<br>
> >>>         +            ## write to dest.  One such example is fnoise<br>
> >>>         which has a<br>
> >>>         +            ## const_expr of 0.0f.<br>
> >>>         +            dst.x = dst.y = dst.z = dst.w = ${op.const_expr};<br>
> >>>                   % endif<br>
> >>><br>
> >>>         -         ## Store the current component of the actual<br>
> >>>         destination to the<br>
> >>>         -         ## value of dst.<br>
> >>>         -         % if op.output_type == "bool":<br>
> >>>         -            ## Sanitize the C value to a proper NIR bool<br>
> >>>         -            _dst_val.u[_i] = dst ? NIR_TRUE : NIR_FALSE;<br>
> >>>         -         % else:<br>
> >>>         -            _dst_val.${op.output_type[:1]}[_i] = dst;<br>
> >>>         -         % endif<br>
> >>>         -      }<br>
> >>>         -   % else:<br>
> >>>         -      ## In the non-per-component case, create a struct dst<br>
> >>>         with<br>
> >>>         -      ## appropriately-typed elements x, y, z, and w and<br>
> >>>         assign the result<br>
> >>>         -      ## of the const_expr to all components of dst, or<br>
> >>>         include the<br>
> >>>         -      ## const_expr directly if it writes to dst already.<br>
> >>>         -      struct ${op.output_type}_vec dst;<br>
> >>>         -<br>
> >>>         -      % if "dst" in op.const_expr:<br>
> >>>         -         ${op.const_expr}<br>
> >>>         -      % else:<br>
> >>>         -         ## Splat the value to all components.  This way<br>
> >>>         expressions which<br>
> >>>         -         ## write the same value to all components don't need<br>
> >>>         to explicitly<br>
> >>>         -         ## write to dest.  One such example is fnoise which<br>
> >>>         has a<br>
> >>>         -         ## const_expr of 0.0f.<br>
> >>>         -         dst.x = dst.y = dst.z = dst.w = ${op.const_expr};<br>
> >>>         +         ## For each component in the destination, copy the<br>
> >>>         value of dst to<br>
> >>>         +         ## the actual destination.<br>
> >>>         +         % for k in range(op.output_size):<br>
> >>>         +            % if output_type == "bool32":<br>
> >>>         +               ## Sanitize the C value to a proper NIR bool<br>
> >>>         +               _dst_val.u[${k}] = dst.${"xyzw"[k]} ?<br>
> >>>         NIR_TRUE : NIR_FALSE;<br>
> >>>         +            % else:<br>
> >>>         +               _dst_val.${get_const_field(output_type)}[${k}]<br>
> >>>         = dst.${"xyzw"[k]};<br>
> >>>         +            % endif<br>
> >>>         +         % endfor<br>
> >>>                % endif<br>
> >>><br>
> >>>         -      ## For each component in the destination, copy the<br>
> >>>         value of dst to<br>
> >>>         -      ## the actual destination.<br>
> >>>         -      % for k in range(op.output_size):<br>
> >>>         -         % if op.output_type == "bool":<br>
> >>>         -            ## Sanitize the C value to a proper NIR bool<br>
> >>>         -            _dst_val.u[${k}] = dst.${"xyzw"[k]} ? NIR_TRUE :<br>
> >>>         NIR_FALSE;<br>
> >>>         -         % else:<br>
> >>>         -            _dst_val.${op.output_type[:1]}[${k}] =<br>
> >>>         dst.${"xyzw"[k]};<br>
> >>>         -         % endif<br>
> >>>         -      % endfor<br>
> >>>         -   % endif<br>
> >>>         +      break;<br>
> >>>         +   }<br>
> >>>         +   % endfor<br>
> >>>         +<br>
> >>>         +   default:<br>
> >>>         +      unreachable("unknown bit width");<br>
> >>>         +   }<br>
> >>><br>
> >>>             return _dst_val;<br>
> >>>          }<br>
> >>>         @@ -316,12 +385,12 @@ evaluate_${name}(unsigned<br>
> >>>         num_components, nir_const_value *_src)<br>
> >>><br>
> >>>          nir_const_value<br>
> >>>          nir_eval_const_opcode(nir_op op, unsigned num_components,<br>
> >>>         -                      nir_const_value *src)<br>
> >>>         +                      unsigned bit_width, nir_const_value<br>
> >>>         *src)<br>
> >>>          {<br>
> >>>             switch (op) {<br>
> >>>          % for name in sorted(opcodes.iterkeys()):<br>
> >>>             case nir_op_${name}: {<br>
> >>>         -      return evaluate_${name}(num_components, src);<br>
> >>>         +      return evaluate_${name}(num_components, bit_width,<br>
> >>>         src);<br>
> >>>                break;<br>
> >>>             }<br>
> >>>          % endfor<br>
> >>>         @@ -333,4 +402,7 @@ nir_eval_const_opcode(nir_op op, unsigned<br>
> >>>         num_components,<br>
> >>>          from nir_opcodes import opcodes<br>
> >>>          from mako.template import Template<br>
> >>><br>
> >>>         -print Template(template).render(opcodes=opcodes)<br>
> >>>         +print Template(template).render(opcodes=opcodes,<br>
> >>>         type_sizes=type_sizes,<br>
> >>>         +                                type_has_size=type_has_size,<br>
> >>>         +                                type_add_size=type_add_size,<br>
> >>>         +<br>
> >>>         get_const_field=get_const_field)<br>
> >>>         diff --git a/src/compiler/nir/nir_opt_constant_folding.c<br>
> >>>         b/src/compiler/nir/nir_opt_constant_folding.c<br>
> >>>         index 04876a4..29905a0 100644<br>
> >>>         --- a/src/compiler/nir/nir_opt_constant_folding.c<br>
> >>>         +++ b/src/compiler/nir/nir_opt_constant_folding.c<br>
> >>>         @@ -46,10 +46,23 @@ constant_fold_alu_instr(nir_alu_instr<br>
> >>>         *instr, void *mem_ctx)<br>
> >>>             if (!instr->dest.dest.is_ssa)<br>
> >>>                return false;<br>
> >>><br>
> >>>         +   unsigned bit_size = 0;<br>
> >>>         +   if (!(nir_op_infos[instr->op].output_type &<br>
> >>>         NIR_ALU_TYPE_SIZE_MASK))<br>
> >>>         +      bit_size = instr->dest.dest.ssa.bit_size;<br>
> >>>         +   else<br>
> >>>         +      bit_size = nir_op_infos[instr->op].output_type &<br>
> >>>         NIR_ALU_TYPE_SIZE_MASK;<br>
> >>><br>
> >>><br>
> >>> This isn't right.  We need to look at all the unsized types and try to<br>
> >>> pull it from one of those.  We shouldn't fall back to grabbing from<br>
> >>> the sized type.<br>
> >><br>
> >> Ok, so you don't like that in the case that the alu operation has a<br>
> >> sized destination we grab the bit-size from the opcode definition? I am<br>
> >> not sure I see the problem with that... isn't the opcode mandating a<br>
> >> specific bit-size in that case? How can the bit-size we want be<br>
> >> different from that?<br>
> >><br>
> >>><br>
> >>>         +<br>
> >>>             for (unsigned i = 0; i <<br>
> >>>         nir_op_infos[instr->op].num_inputs; i++) {<br>
> >>>                if (!instr->src[i].src.is_ssa)<br>
> >>>                   return false;<br>
> >>><br>
> >>>         +      if (bit_size == 0) {<br>
> >>>         +         if (!(nir_op_infos[instr->op].input_sizes[i] &<br>
> >>>         NIR_ALU_TYPE_SIZE_MASK))<br>
> >>>         +            bit_size = instr->src[i].src.ssa->bit_size;<br>
> >>>         +         else<br>
> >>>         +            bit_size = nir_op_infos[instr->op].input_sizes[i]<br>
> >>>         & NIR_ALU_TYPE_SIZE_MASK;<br>
> >>><br>
> >>><br>
> >>> Same here.  If they don't have any unsized sources or destinations to<br>
> >>> grab from, we should let bit_size be zero.<br>
> >><br>
> >> But if we have an opcode with all sized 64-bit types then...<br>
> >><br>
> >>> Also, if we have multiple sources with the same unsized type, we<br>
> >>> should assert that the sizes match.<br>
> >>><br>
> >>><br>
> >>>         +      }<br>
> >>>         +<br>
> >>>                nir_instr *src_instr =<br>
> >>>         instr->src[i].src.ssa->parent_instr;<br>
> >>><br>
> >>>                if (src_instr->type != nir_instr_type_load_const)<br>
> >>>         @@ -58,24 +71,31 @@ constant_fold_alu_instr(nir_alu_instr<br>
> >>>         *instr, void *mem_ctx)<br>
> >>><br>
> >>>                for (unsigned j = 0; j <<br>
> >>>         nir_ssa_alu_instr_src_components(instr, i);<br>
> >>>                     j++) {<br>
> >>>         -         src[i].u[j] =<br>
> >>>         load_const->value.u[instr->src[i].swizzle[j]];<br>
> >>>         +         if (load_const->def.bit_size == 64)<br>
> >>>         +            src[i].ul[j] =<br>
> >>>         load_const->value.ul[instr->src[i].swizzle[j]];<br>
> >>>         +         else<br>
> >>>         +            src[i].u[j] =<br>
> >>>         load_const->value.u[instr->src[i].swizzle[j]];<br>
> >>>                }<br>
> >>><br>
> >>>                /* We shouldn't have any source modifiers in the<br>
> >>>         optimization loop. */<br>
> >>>                assert(!instr->src[i].abs && !instr->src[i].negate);<br>
> >>>             }<br>
> >>><br>
> >>>         +   if (bit_size == 0)<br>
> >>>         +      bit_size = 32;<br>
> >><br>
> >> ... this default to 32 here would not be correct any more. If at this<br>
> >> point the bit-size is 0 (meaning that all inputs and output are sized)<br>
> >> then we should take the bit-size from the opcode's output type, which is<br>
> >> known to be sized, right?<br>
> ><br>
> > Not quite. xd<br>
><br>
> Err, whoops...<br>
><br>
> Not quite. If any of the operands or the destination is already sized<br>
> by the opcode, then the constant propagation code we generated has all<br>
> of the information it needs. The only case where we need to figure<br>
> anything out is if there are unsized types, in which case we know the<br>
> bitsizes match -- we just need to find the first unsized type and pass<br>
> the bitsize of that. If all the operands and the destination are<br>
> sized, then the bit_size will be ignored and it's fine if it's 0.</p>
<p dir="ltr">More to the point, you could have an instruction with, say, two unsized inputs and a sized destination (comparison operations are an example of this). In this case, the two sources have to match but they don't have to match the destination; the destination size is fixed.  Dies that make sense?</p>
<p dir="ltr">> ><br>
> >><br>
> >>><br>
> >>> Then it'll get set here.<br>
> >>><br>
> >>><br>
> >>>         +<br>
> >>>             /* We shouldn't have any saturate modifiers in the<br>
> >>>         optimization loop. */<br>
> >>>             assert(!instr->dest.saturate);<br>
> >>><br>
> >>>             nir_const_value dest =<br>
> >>>                nir_eval_const_opcode(instr->op,<br>
> >>>         instr->dest.dest.ssa.num_components,<br>
> >>>         -                            src);<br>
> >>>         +                            bit_size, src);<br>
> >>><br>
> >>>             nir_load_const_instr *new_instr =<br>
> >>>                nir_load_const_instr_create(mem_ctx,<br>
> >>><br>
> >>>          instr->dest.dest.ssa.num_components);<br>
> >>><br>
> >>>         +   new_instr->def.bit_size = instr->dest.dest.ssa.bit_size;<br>
> >>>             new_instr->value = dest;<br>
> >>><br>
> >>>             nir_instr_insert_before(&instr->instr, &new_instr->instr);<br>
> >>>         --<br>
> >>>         2.7.0<br>
> >>><br>
> >>>         _______________________________________________<br>
> >>>         mesa-dev mailing list<br>
> >>>         <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> >>>         <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
> >>><br>
> >>><br>
> >>> _______________________________________________<br>
> >>> mesa-dev mailing list<br>
> >>> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> >>> <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
> >><br>
> >><br>
> >> _______________________________________________<br>
> >> mesa-dev mailing list<br>
> >> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> >> <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</p>