I'm looking into a case where TER is forward propagating a series of additions across a call.

extern void foo(void);
int bar(int a, int b, int c, int d, int e, int f, int g, int h) {
  int ret;
  ret = a + b + c + d + e + f + g + h;
  foo();
  return ret;  /* 'ret' use replaced by rhs above */
}

Unfortunately by moving all the additions across the call we've extended the lifetimes of the parm regs across the call also and therefor they need to be copied into callee-saved regs to preserve their value across the call, which means bar() will have save/restore code for 8 regs instead of just 1 (to thold the result across the call).

I tried hacking tree-ssa-ter.c to not perform the replacement if the def and use cross a call (i.e. cross an is_gimple_call() stmt), but ran into cases where we don't do a valid replacement because things like __builtin_sqrtf()/__builtin_powf() are marked as calls but expand to simple instructions (on PPC anyway). The __builtin_powf() calls were actually introduced on a transformation of y*y => __builtin_powf(y,2.0).

A couple of questions:

1) Is this a valid optimization in general to attempt wrt other targets (i.e. prevent replacement across calls)? I assume this could further be refined so that we still do replacement across calls if the source operands of the expression are already live at the use point, but haven't looked into that.

2) Is there a way to recognize the __builtin_XXX() calls such that we know they result in simple insns an not a real call?


-Pat


Reply via email to