On Thu, Oct 3, 2024 at 7:51 AM Filip Kastl <fka...@suse.cz> wrote:
>
> Hi All,
>
> While toying with the switch conversion GIMPLE pass I noticed that the pass
> generates a dead statement.  I wanted to investigate why this happens and
> potentially fix this.  However after looking into the part of the pass
> responsible for generating the code in question I still have no idea why the
> dead statement is generated.  Can someone more experienced look at this and
> tell me what is going on, please?
>
> Let's say I'm compiling this C testcase
>
> int main()
> {
>     switch (a % 4)
>     {
>         case 0: return 10;
>         case 1: return 20;
>         case 2: return 30;
>         default: return 40;
>     }
> }
>
> Since the switch computes a linear function, the linear transformation feature
> of switch conversion triggers -- with cofficients A = 10 and B = 10 in this
> case.  This is the relevant GCC source code.  It is a part of the
> switch_conversion::build_one_array () function:
>
>       if (dump_file && coeff_a.to_uhwi () > 0)
>         fprintf (dump_file, "Linear transformation with A = %" PRId64
>                  " and B = %" PRId64 "\n", coeff_a.to_shwi (),
>                  coeff_b.to_shwi ());
>
>       /* We must use type of constructor values.  */
>       gimple_seq seq = NULL;
>       tree tmp = gimple_convert (&seq, type, m_index_expr);
>       tree tmp2 = gimple_build (&seq, MULT_EXPR, type,
>                                 wide_int_to_tree (type, coeff_a), tmp);
>       tree tmp3 = gimple_build (&seq, PLUS_EXPR, type, tmp2,
>                                 wide_int_to_tree (type, coeff_b));
>       tree tmp4 = gimple_convert (&seq, TREE_TYPE (name), tmp3);
>       gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
>       load = gimple_build_assign (name, tmp4);

Both gimple_build uses gimple_simplify to build the gimple (which does
simplifications).
Note gimple_convert just calls gimple_build (unless it is already the
correct type).
You can find which simplifications is done by adding the `-folding`
option to the dump option (note this option is not documented but that
is PR 114892).

Thanks,
Andrew Pinski


>
> Before this code is run, the GIMPLE of the basic block in question looks like
> this (output of debug_bb (m_switch_bb)):
>
> a.0_1 = a;
> _2 = a.0_1 % 4;
> _9 = (unsigned int) _2;
> switch (_2) <default: <L4> [INV], case 0: <L6> [INV], case 1: <L1> [INV], 
> case 2: <L2> [INV], case 3: <L3> [INV]>
>
> What I would expect to see is something like this (also output of debug_bb ()
> but this time after the code I listed was run):
>
> a.0_1 = a;
> _2 = a.0_1 % 4;
> _9 = (unsigned int) _2;
> _7 = (unsigned int) _2;
> _8 = 10 * _7;
> _10 = _8 + 10;
> switch (_2) <default: <L4> [INV], case 0: <L6> [INV], case 1: <L1> [INV], 
> case 2: <L2> [INV], case 3: <L3> [INV]>
>
> but what I instead see is this:
>
> a.0_1 = a;
> _2 = a.0_1 % 4;
> _9 = (unsigned int) _2;
> _7 = (unsigned int) _2;
> _6 = 10 * _7;
> _5 = _7 + 1;
> _10 = _5 * 10;
> _11 = (int) _10;
> switch (_2) <default: <L4> [INV], case 0: <L6> [INV], case 1: <L1> [INV], 
> case 2: <L2> [INV], case 3: <L3> [INV]>
>
> The first thing I noticed is that there are two multiplications instead of one
> and that the result of one of them doesn't get used (this redundant
> multiplication is the original reason I started looking into this).  But there
> is also a cast to int that I don't see how the GCC code created and the order
> of the non-dead multiplication and addition is switched and the added constant
> (coefficient B) is 1 instead of 10 (which is correct but just not what I 
> expect
> from reading the code).
>
> What am I not seeing here?  Does gsi_insert_seq_before do some optimizations 
> on
> the seq it inserts?
>
> Thanks,
> Filip Kastl

Reply via email to