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);
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