https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114185
Bug ID: 114185 Summary: Missed tail-call optimization due to an argument whose address is taken Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: dizhao at os dot amperecomputing.com Target Milestone: --- GCC (with "-Ofast") doesn't perform tail call optimization on a function like: long test_func (long n, unsigned long u64arg, unsigned int u32arg, unsigned long *p) { if (n > 0) return test_func (n - 1, u64arg + (unsigned long) u32arg, u32arg, p); else return &u64arg - p; } llvm can optimize the tail call. GCC gave up tail call optimization, because the following check in find_tail_calls() failed on argument "u64arg": /* The parameter should be a real operand, so that phi node created for it at the start of the function has the meaning of copying the value. This test implies is_gimple_reg_type from the previous condition, however this one could be relaxed by being more careful with copying the new value of the parameter (emitting appropriate GIMPLE_ASSIGN and updating the virtual operands). */ if (!is_gimple_reg (param)) break; The check was to fix this ICE: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93487 . But in this case, "&u64arg" won't be used in PHI argument, so it seems ok for tail call optimization. (BTW, I tried current GCC trunk on the example code in PR 93487, but haven't encounter the ICE with that check removed, because the PHI arguments are "&y" and "&x" now.)