[llvm-bugs] [Bug 50574] New: [coroutines] Incorrectly saving sp across suspension points in optimized builds on aarch64

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Jun 3 10:26:32 PDT 2021


https://bugs.llvm.org/show_bug.cgi?id=50574

            Bug ID: 50574
           Summary: [coroutines] Incorrectly saving sp across suspension
                    points in optimized builds on aarch64
           Product: clang
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: C++2a
          Assignee: unassignedclangbugs at nondot.org
          Reporter: bartde at microsoft.com
                CC: blitzrakete at gmail.com, erik.pilkington at gmail.com,
                    llvm-bugs at lists.llvm.org, richard-llvm at metafoo.co.uk

Created attachment 24907
  --> https://bugs.llvm.org/attachment.cgi?id=24907&action=edit
Repro (also shared in Godbolt)

A simple repro is at https://godbolt.org/z/z8ajGhvcx and attached as well.
Compile with "-std=c++2a -g0 -O3 -stdlib=libc++" using "armv8-a clang (trunk)"
and found to repro with clang 11 as well.

The essence is this, using fmtlib (version 7.1.3):

void check(int a)
{
  fmt::print("{}\n", a);
}

when writing:

int main()
{
    check(123);
    check(321);
}

compiled code executes correctly and prints 123, 321. In optimized builds, it
is noted that the compiler inlines fmt::print and deduplicates some common code
for the two calls to check.

When writing:

task<int> f(std::vector<int> v)
{
#if REPRO
    for (auto& x : v)
#endif
    {
        check(123);

        co_await std::experimental::suspend_always();

        check(321);
    }
    co_return 42;
}

the compiled code has an issue, and the executing code prints 123, garbage.
Looking at the assembly, it seems that the compiler spills "sp" into the
coroutine frame as part of the first call to check:

  mov w10, #1
  mov x11, sp               ; sp is here
  stp x10, x11, [x19, #32]  ; gets stored here (A)
  cmp x9, x8
  stp x10, x11, [x19, #48]  ; gets stored here (B)
  b.eq .LBB3_7
  ldr x8, [x19, #64]
.LBB3_5:
  ldp x2, x3, [x19, #32]    ; gets loaded here (A) into x3
  str x8, [x19, #80]
  mov w8, #123
  stp x8, xzr, [sp]
  adrp x0, .L.str
  add x0, x0, :lo12:.L.str
  mov w1, #3
  bl fmt::v7::vprint(fmt::v7::basic_string_view<char>, fmt::v7::format_args)

For the second call site of check, after the suspension point, the compiler
emits:

  ldp x2, x3, [x19, #48]    ; gets loaded here (B) into x3
  mov w8, #321
  stp x8, xzr, [sp]
  adrp x0, .L.str
  add x0, x0, :lo12:.L.str
  mov w1, #3
  bl fmt::v7::vprint(fmt::v7::basic_string_view<char>, fmt::v7::format_args)

where it is loading the former value of "sp" which gets consumed by vprint,
resulting in garbage.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210603/12bf759b/attachment-0001.html>


More information about the llvm-bugs mailing list