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

            Bug ID: 92474
           Summary: Sanitizer breaks tail-recursion optimization
           Product: gcc
           Version: 9.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: sanitizer
          Assignee: unassigned at gcc dot gnu.org
          Reporter: Hi-Angel at yandex dot ru
                CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
                    jakub at gcc dot gnu.org, kcc at gcc dot gnu.org, marxin at 
gcc dot gnu.org
  Target Milestone: ---

When `-fsanitize=address` applied, tail-call optimization does not kick in.

I made a testcase below. Simplest way to demonstrate it would be to try to run
executable built from the testcase with and without the option: it either
crashes or not. But since it's an arguable demonstration (because how does one
know if non-crashing version didn't simply did not consume enough stack), I
demonstrate it with a different approach: I grep the assembly for `callq
foo()`, and while the case with optimization applied has just one call to it,
the case where it wasn't applied has 2 of them.

# Steps to reproduce (in terms of terminal commands):

    $ cat test.cpp
    struct MyStruct {
        unsigned  n_recurses;
    };

    MyStruct foo(MyStruct m) {
        return (m.n_recurses == 0)? m : foo(MyStruct{m.n_recurses - 1});
    }

    int main() {
        foo(MyStruct{999999});
    }
    $ g++ test.cpp -o a -O3 -g
    $ objdump -d a | grep -E "callq.*foo"
        1029:       e8 12 01 00 00          callq  1140 <_Z3foo8MyStruct>
    $ g++ test.cpp -o a -O3 -g -fsanitize=address
    $ objdump -d a | grep -E "callq.*foo"

## Expected:

One line with the call:
        1089:       e8 32 01 00 00          callq  11c0 <_Z3foo8MyStruct>

## Actual:

Two lines with the call:
        1089:       e8 32 01 00 00          callq  11c0 <_Z3foo8MyStruct>
        1293:       e8 28 ff ff ff          callq  11c0 <_Z3foo8MyStruct>

Reply via email to