Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[asm goto] support outputs along indirect branches #53562

Closed
josephcsible opened this issue Feb 3, 2022 · 12 comments
Closed

[asm goto] support outputs along indirect branches #53562

josephcsible opened this issue Feb 3, 2022 · 12 comments
Labels
clang:codegen enhancement Improving things as opposed to bug fixing, e.g. new or missing feature

Comments

@josephcsible
Copy link

josephcsible commented Feb 3, 2022

Consider this C code:

int main(void) {
    int x = 123;
    asm goto("mov %1, %0\n\tjmp %l[label]" : "=r" (x) : "r" (45) : : label);
    x = 6;
    label:
    return x;
}

It's supposed to return 45. But when you compile it in Clang, it returns 123 instead. I tested this on both trunk (01b52f7) and 13.0.0, and both with -O3 and without optimizations, and the bug happens in all of those cases.

https://godbolt.org/z/vKeYrfYY5

@llvmbot
Copy link
Collaborator

llvmbot commented Feb 3, 2022

@llvm/issue-subscribers-clang-codegen

@efriedma-quic
Copy link
Collaborator

Outputs are only valid on the fallthrough codepath; on other paths, the output values are ignored. That's by design. Or at least, it's a practical consequence of the way asm goto is currently implemented.

This is documented at https://clang.llvm.org/docs/LanguageExtensions.html#asm-goto-with-output-constraints . -Wuninitialized prints a warning for your testcase. The warning could probably be improved. Not sure what else we can do here.

@josephcsible
Copy link
Author

Okay, I see what happened. This part of that documentation is no longer quite accurate:

In addition to the functionality provided by GCC’s extended assembly, clang supports output constraints with the goto form.

The goto form of GCC’s extended assembly allows the programmer to branch to a C label from within an inline assembly block. Clang extends this behavior by allowing the programmer to use output constraints:

Because as of version 11.1.0 (specifically, commit e3b3b59), GCC now supports asm goto with outputs, without a restriction to only the fallthrough codepath. So now we support only a subset of their functionality rather than an extension of it. In light of this, can this issue be reconsidered as a feature request to match that functionality?

@nickdesaulniers
Copy link
Member

cc @jyknight @gwelymernans @isanbard

can this issue be reconsidered as a feature request to match that functionality?

Yeah, we probably can't focus on this for a couple months, but this is surely a portability issue that folks will begin to notice more and more frequently.

We'll probably need to undo parts of https://reviews.llvm.org/D79794, making INLINEASM_BR a terminator again. We'll also probably need to split critical edges to insert COPYs for the indirect target. I forget now why we didn't; I think critical edge splitting is fallible.

Also, there is one undesirable side effect where address of label would no longer refer to the same label as the asm goto IIRC. But I'd say support for outputs along all edges is probably more worthwhile than such a minute detail.

@nickdesaulniers nickdesaulniers changed the title Wrong code with asm goto [asm goto] support outputs along indirect branches Feb 3, 2022
@nickdesaulniers nickdesaulniers added the enhancement Improving things as opposed to bug fixing, e.g. new or missing feature label Feb 3, 2022
@isanbard
Copy link
Contributor

isanbard commented Feb 3, 2022

If GCC's able to allow outputs on indirect branches, then they must not care about the label addresses like we did. (Segher mentioned something along those lines in our discussions with him before the implementation.) That would take care of the vast majority of issues we faced with splitting critical edges.

I don't know if it's worth making INLINEASM_BR a terminator again, since that has its own issues. We'll have to see though.

@nickdesaulniers
Copy link
Member

@nickdesaulniers
Copy link
Member

Updating docs to make note of this difference https://reviews.llvm.org/D135818. Will need to revisit those docs when this is implemented.

isanbard pushed a commit that referenced this issue Oct 13, 2022
…om GCC

That said, we are planning to add this support in the near future.

Link: #53562

Differential Revision: https://reviews.llvm.org/D135818
nickdesaulniers added a commit that referenced this issue Feb 17, 2023
Capstone of
https://discourse.llvm.org/t/rfc-syncing-asm-goto-with-outputs-with-gcc/65453/8

Clang changes are still necessary to enable the use of outputs along
indirect edges of asm goto statements.

Link: #53562

Reviewed By: void

Differential Revision: https://reviews.llvm.org/D140180
nickdesaulniers added a commit that referenced this issue Feb 17, 2023
Now that we support outputs from asm goto along indirect edges, we can
remove/revert some code that was added to help warn about the previous
limitation that outputs were not supported along indirect edges.

Reverts some code added in:
commit 72aa619 ("Warn of uninitialized variables on asm goto's indirect branch")
commit 3a604fd ("[Clang][CFG] check children statements of asm goto")
But keeps+updates the tests.

Link: #53562

Reviewed By: void

Differential Revision: https://reviews.llvm.org/D140508
@nickdesaulniers
Copy link
Member

nickdesaulniers commented Feb 17, 2023

Landed as:

  1. commit 45a291b ("[Dominators] check indirect branches of callbr")
  2. commit fb47115 ("[llvm] boilerplate for new callbrprepare codegen IR pass")
  3. commit 0a39af0 ("[llvm][CallBrPrepare] split critical edges")
  4. commit 094190c ("[llvm][CallBrPrepare] add llvm.callbr.landingpad intrinsic")
  5. commit 28d45c8 ("[llvm][CallBrPrepare] use SSAUpdater to use intrinsic value")
  6. commit 5cc1016 ("[llvm][SelectionDAGBuilder] codegen callbr.landingpad intrinsic")
  7. commit a3a84c9 ("[llvm] add CallBrPrepare pass to pipelines")
  8. commit b1bc723 ("[Clang] refactor CodeGenFunction::EmitAsmStmt NFC")
  9. commit 329ef60 ("[Clang] support for outputs along indirect edges of asm goto")
  10. commit af66563 ("[clang] fix -Wuninitialized for asm goto outputs on indirect edges.")
  11. commit 54186d3 ("[clang] add __has_extension(gnu_asm_goto_with_outputs_full)")
  12. commit 39811e2 ("[llvm][test] enable/disable -verify-machineinstrs where possible for callbr")
  13. commit cf86855 ("[M68k] fix test regression introduced by D140180")

This is intentionally going to ship in clang-17; I want it to miss the clang-16 train so that it gets maximal soak time. @josephcsible please help test using ToT. @nathanchance is going to help me keep an eye on this in case we need to revert/back it out (hence the above list, in case it's needed). Please file new bugs and assign to me for issues found with this feature.

CarlosAlbertoEnciso pushed a commit to SNSystems/llvm-debuginfo-analyzer that referenced this issue Feb 17, 2023
Capstone of
https://discourse.llvm.org/t/rfc-syncing-asm-goto-with-outputs-with-gcc/65453/8

Clang changes are still necessary to enable the use of outputs along
indirect edges of asm goto statements.

Link: llvm/llvm-project#53562

Reviewed By: void

Differential Revision: https://reviews.llvm.org/D140180
CarlosAlbertoEnciso pushed a commit to SNSystems/llvm-debuginfo-analyzer that referenced this issue Feb 17, 2023
Initial support for asm goto w/ outputs (D69876) only supported outputs
along the "default" (aka "fallthrough") edge.

We can support outputs along all edges by repeating the same pattern of
stores along the indirect edges that we allready do for the default
edge.  One complication is that these indirect edges may be critical
edges which would need to be split. Another issue is that mid-codgen of
LLVM IR, the control flow graph might not reflect the control flow of
the final function.

To avoid this "chicken and the egg" problem assume that any given
indirect edge may become a critical edge, and pro-actively split it.
This is unnecessary if the edge does not become critical, but LLVM will
optimize such cases via tail duplication.

Fixes: llvm/llvm-project#53562

Reviewed By: void

Differential Revision: https://reviews.llvm.org/D136497
CarlosAlbertoEnciso pushed a commit to SNSystems/llvm-debuginfo-analyzer that referenced this issue Feb 17, 2023
Now that we support outputs from asm goto along indirect edges, we can
remove/revert some code that was added to help warn about the previous
limitation that outputs were not supported along indirect edges.

Reverts some code added in:
commit 72aa619 ("Warn of uninitialized variables on asm goto's indirect branch")
commit 3a604fd ("[Clang][CFG] check children statements of asm goto")
But keeps+updates the tests.

Link: llvm/llvm-project#53562

Reviewed By: void

Differential Revision: https://reviews.llvm.org/D140508
@bwendling
Copy link
Collaborator

Huzzah!!! Great job. :-)

@josephcsible
Copy link
Author

@josephcsible please help test using ToT.

I broke it with the exact same code as in my first post here ☹️ #60855

@nickdesaulniers
Copy link
Member

Another follow up reported issue: #61023

nickdesaulniers added a commit that referenced this issue Mar 1, 2023
…EASM_BR

When generating spills (stores) for values produced by INLINEASM_BR
instructions, make sure to insert one spill per indirect target.
Otherwise the reload generated may load from a stack slot that has not
yet been stored to (resulting in a load of an uninitialized stack slot).

Link: #53562
Fixes: #60855

Reviewed By: MatzeB

Differential Revision: https://reviews.llvm.org/D144907
nickdesaulniers added a commit that referenced this issue Mar 13, 2023
This isn't safe to do.

Link: #53562
Fixes: #61023

Reviewed By: efriedma, nikic

Differential Revision: https://reviews.llvm.org/D144927
CarlosAlbertoEnciso pushed a commit to SNSystems/llvm-debuginfo-analyzer that referenced this issue Mar 17, 2023
agozillon pushed a commit to ROCm-Developer-Tools/llvm-project that referenced this issue Mar 17, 2023
eymay pushed a commit to eymay/llvm-project that referenced this issue Mar 21, 2023
This isn't safe to do.

Link: llvm#53562
Fixes: llvm#61023

Reviewed By: efriedma, nikic

Differential Revision: https://reviews.llvm.org/D144927
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen enhancement Improving things as opposed to bug fixing, e.g. new or missing feature
Projects
None yet
Development

No branches or pull requests

7 participants