https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The reason why that would work in this case is that we have
  info = {};
as the first stmt that mentions it, but doesn't take address of info.
Then there is
  if (something)
    fortify_panic ();
The condition isn't possibly indirect stmt, fortify_panic is (it is a call),
but none of the info vars are addressable at that point.  Then there is:
  i2c_new_device(&info);
which first takes info's address and is also (afterwards) a possibly indirect
call (so, we first need to walk explicit references and then handle the
possibly indirect, not the other way around).  But, in this spot only one of
the info vars is live/addressable, not all of them (on fortify_panic () all 4
info vars are live, but none is addressable).
  info ={v} {CLOBBER};
Finally, the var is no longer live nor addressable.

Now, if you change the code so that 
i2c_new_device(&info);
comes first and then
f(a);
this would no longer be optimized, because in the common fortify_panic call all
4 info vars would be addressable (even escaped to another function).

That said, if it is the same type of variable and it can't be shared, I wonder
why the kernel just doesn't use the same variable.
Like:
        switch (model) {
                struct i2c_board_info info;
        case 1:
                info = (struct i2c_board_info) {};
                f(a);
                i2c_new_device(&info);
                break;
        case 2:
                info = (struct i2c_board_info) {};
                f(b);
                i2c_new_device(&info);
                break;
...
        }
(or memset or whatever).

Reply via email to