This is an archive of the discontinued LLVM Phabricator instance.

[SCEVExpander] Recompute poison-generating flags on hoisting. PR57187
ClosedPublic

Authored by mkazantsev on Aug 17 2022, 4:08 AM.

Details

Summary

Instruction being hoisted could have nuw/nsw flags inferred from the old
context, and we cannot simply move it to the new location keeping them
because we are going to introduce new uses to them that didn't exist before.

Example in https://github.com/llvm/llvm-project/issues/57187 shows how
this can produce branch by poison from initially well-defined program.

This patch forcefully recomputes poison-generating flag in the new context.

Diff Detail

Event Timeline

mkazantsev created this revision.Aug 17 2022, 4:08 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 17 2022, 4:08 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
mkazantsev requested review of this revision.Aug 17 2022, 4:08 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 17 2022, 4:08 AM

Added context

mkazantsev edited the summary of this revision. (Show Details)Aug 17 2022, 4:14 AM

Rebased (test moved to X86).

fhahn added inline comments.Aug 17 2022, 7:33 AM
llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
1057

This seems too pessimistic and unnecessarily drops flags that are not inferred based on the context instruction, e.g. because the original IV already had nuw/nsw.

Would it be possible to preserve the flags valid at entry of the loop when hoisting?

mkazantsev added inline comments.Aug 17 2022, 10:34 PM
llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
1057

We can't do it here. But I guess this is mostly used in IndVars, and we can further strengthen no-wrap flags after this hoisting, if it happened. Didn't try it and don't know the consequences. Can it go as separate patch?

fhahn added inline comments.Aug 18 2022, 10:55 AM
llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
1057

After another thought, shouldn't moving the IV be fine by itself? It might generate poison at the earlier location, but that is fine, as long as it is not used before the original location. in a context where poison triggers UB.

Isn't the real issue the code that later replaces uses of the original IV with the hoisted IV? When updating uses, whether all flags can be retained would depend on whether the UB-on-poison user may execute in cases where the original IV increment didn't?

fhahn added inline comments.Aug 18 2022, 10:57 AM
llvm/test/Transforms/IndVarSimplify/X86/pr57187.ll
39

using an addresspace(1) pointer here has the unfortunate side effect that Alive2 cannot handle the code. It would probably be good to remove at least addrspace(1) here and maybe even better to just use a function call as use.

mkazantsev added inline comments.Aug 18 2022, 10:44 PM
llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
1057

Yes, I agree that moving is fine. The bug appears when we introduce a new use (in this case a trunc) to the hoisted IV in a point where the old IV didn't have any uses. I'll try to make a more targeted fix.

llvm/test/Transforms/IndVarSimplify/X86/pr57187.ll
39

Ok, I will update the test.

mkazantsev added inline comments.Aug 18 2022, 11:40 PM
llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
1057

Unfortunately, in practice it's undoable. This function may hoist multiple instructions, and then the notion that their flags were context-dependent gets lost. If we dropt flags immediately, we can't figure it out later. I propose to stick to this fix and then try to restore flags when possible.

mkazantsev planned changes to this revision.Aug 19 2022, 12:39 AM
mkazantsev added inline comments.Aug 19 2022, 1:10 AM
llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
1057

Actually we have all API available here, so let's just heal the flags.

mkazantsev retitled this revision from [SCEVExpander] Drop poison-generating flags on hoisting. PR57187 to [SCEVExpander] Recompute poison-generating flags on hoisting. PR57187.
mkazantsev edited the summary of this revision. (Show Details)

Healed poison flags. It also happened to improve some of the tests. :)

mkazantsev added inline comments.Aug 19 2022, 1:14 AM
llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
1066

This piece of code replicates similar piece of code in IndVars, I propose refectoring as a separate patch. Now we just need a conceptual agreement on how we fix it.

nikic added a comment.Aug 29 2022, 2:53 AM

I'm confused. Why would the nuw be legal in the "old context"? Wouldn't we already branch on poison there as well, because %iv.next is used in %loop.exit.cond is used in br (unconditionally)?

fhahn added inline comments.Aug 30 2022, 5:11 AM
llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
1057

Unfortunately, in practice it's undoable. This function may hoist multiple instructions, and then the notion that their flags were context-dependent gets lost

Yeah this is unfortunate indeed! I still think the right place to fix the flags would be where we actually introduce uses that cause UB on poison, but given the difficulty I guess our best option is doing it here. Could you add a comment explaining why this needs to be done here, even though hoisting in itself isn't a problem.

nikic added a comment.Sep 2 2022, 5:35 AM

I'm confused. Why would the nuw be legal in the "old context"? Wouldn't we already branch on poison there as well, because %iv.next is used in %loop.exit.cond is used in br (unconditionally)?

Okay, the missing context here is that we create an additional IV with increment in the dead block and then perform a congruent IV replacement that hoists that increment and introduces uses in a live block.

mkazantsev planned changes to this revision.Sep 12 2022, 12:18 AM

Ok, let's drop the flags right before introducing a new use.

Made flag recomputation conditional to avoid unexpected impact. Because this logic may hoist multiple instruction, I don't think there is another place where it can easily done.

nikic accepted this revision.Sep 12 2022, 2:35 AM

LGTM

llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
2024

posion -> poison

This revision is now accepted and ready to land.Sep 12 2022, 2:35 AM
fhahn accepted this revision.Sep 12 2022, 2:32 PM

LGTM thanks!