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

[SR-3016] Infinite recursion without side-effects can be optimized to undef #45606

Open
huonw mannequin opened this issue Oct 21, 2016 · 3 comments
Open

[SR-3016] Infinite recursion without side-effects can be optimized to undef #45606

huonw mannequin opened this issue Oct 21, 2016 · 3 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@huonw
Copy link
Mannequin

huonw mannequin commented Oct 21, 2016

Previous ID SR-3016
Radar rdar://problem/30529068
Original Reporter @huonw
Type Bug
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: 424b71570cfa0cd2d4dab65ecb9ca00f

relates to:

  • SR-626 No diagnostic for unconditional recursion

Issue Description:

Compiling the following code with `-O` can sometimes result in `foo` just returning `undef`, that is, LLVM removes the infinite recursion because there's no side-effects.

public func foo() -> String {
    return foo()
}

The IR is:

; Function Attrs: nounwind
define { i64, i64, i64 } @_TF8infinite3fooFT_SS() #​1 {
entry:
  ret { i64, i64, i64 } undef
}

This is a safety hole: any manipulations of the return value could be working with random data (if the function isn't inlined), or LLVM inlines the function and propagates the undef deeper through the program.

This behavior is somewhat inconsistent across compilers, e.g. it doesn't seem to happen with my local 3.0 compiler (it has the recursive call), but it does with my current development build which is a week or two old, I think.

Notably this transformation is valid in C (more specifically, this sort of recursion is UB), and it may be hard for LLVM to avoid doing this without inhibiting its ability to delete finite side-effect free loops. https://llvm.org/bugs/show_bug.cgi?id=965 is possibly a relevant LLVM bug. Other languages have encountered this problem too, e.g. Rust, which "solved" it by introducing a warning for obvious cases of infinite recursion.

(Certain phrasings of infinite loops are possibly problematic too.)

@jckarter
Copy link
Member

If we were to optimize away a loop like this at the SIL level, I think we would turn it into a trap, since Swift's runtime failure semantics allow still allow for undef-like propagation of the trap condition. From past discussion about this issue in the LLVM sphere, it sounds like LLVM might benefit from being able to represent a similar non-strict trap concept, so that cases like this can be folded away to traps instead of UB without interfering with optimization.

@huonw
Copy link
Mannequin Author

huonw mannequin commented Feb 14, 2017

@swift-ci create

@huonw
Copy link
Mannequin Author

huonw mannequin commented Sep 28, 2017

https://reviews.llvm.org/D38336 may allow us to fix this on the LLVM side.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

1 participant