cc @Nikita Popov
To anybody reading along, see this first
@Nikita Popov what happens is that once you have
%0 = call i32 @foo(); ret i32 %0
that gets optimised out in following steps:
call void @foo() ret i32 undef ; because foo never terminates
; foo call removed because it is readnone and its results are never used and it has no side-effects ret i32 undef ; because foo never terminates
At some point (does not matter whether it happens before or after the call removal) the return instruction also becomes
and that is why you end with a function that contains a single
unreachable rather than an infinite loop.
making sure that such
@foo is never marked as side-effect-free (which any of
writeonly imply) resolves this issue in my testing
Seems simple enough, right?
First thing I proposed to LLVM people is to just consider
noreturn attribute as a "this has side-effects" but apparently it is possible that this is not always inferred right.
That seems like something that should be the case regardless of whether it covers all cases...
That’s how I felt as well. Then we can also somehow make sure that analysis for noreturn always runs as a dependency for the analysis for readnone and (read|write)only
For that purpose you're not interested in noreturn though, but in maybe noreturn. Basically pretty much any function that has a loop without known tripcount.
Indeed, and that was the part that I had trouble with :slight_smile:
I’m fairly unfamiliar with how that area of code works.