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