On 10/29/19 2:03 PM, Mikael Tillenius wrote: > Hi > > I am using a cross compiler for Renesas H8S. In a few places it > generates really bad code. Given the following program: > > struct s { > char a, b; > char c[11]; > } x[2]; > > void test(int n) > { > struct s *sp = &x[n]; > > sp->a = 1; > sp->b = 1; > } > > I would expect that the pointer "sp" is calculated once and reused to > access the fields "a" and "b". But instead the pointer is recalculated > for each access. This generates a lot of extra code, including calls to > __mulhi3. I have tested with gcc 8.2 and 9.2 and with different > optimization levels (-O1, -O2, -Os) all with the same result. With -O0 > "sp" is only calculated once and kept as a variable on the stack but the > rest of the code is not as good as it could be. The best work around > seems to be to declare "sp" as volatile: "struct s *volatile sp = > &x[n];". Then "sp" is only calculated once and kept on the stack and the > surrounding code can be optimized. > > So my question is: where should I start looking for a fix to this? The > other targets I tried (ARM, x86, x86_64) behave as expected and > calculates the pointer once and keeps it in a register. As we leave gimple the code looks like: MEM <struct s[2]> [(struct s *)&x][n_1(D)].a = 1; MEM <struct s[2]> [(struct s *)&x][n_1(D)].b = 1; One might argue that DOM or FRE should have created a common subexpression for the address arithmetic here. Even so it's not bad. CSE doesn't do its job though. THere's clearly a REG_EQUAL note which should have allowed it to at least cleanup the redundant multiplication for the address calculation. I recommend filing a bug report. Note that the H8 port is on the list of ports that are be deprecated in gcc-10 unless someone steps forward to take care of some significant maintenance tasks. Deprecation in gcc-10 would mean the port would be removed in gcc-11 unless someone steps up to take care of those maintenance tasks. Jeff