Description
The llvm::isSafeToSpeculativelyExecute
function seems to be only safe to use when not speculating the result of moving instructions, since it may consider attributes that will get discarded during moving it later (e.g. dereferenceable). However, it can be seen that SimplifyCFG:: dominatesMergePoint
tries to use it exactly in that way. Otherwise, like seen in the small snippet below, that can allow violating the semantics of attributes of the IR which, won't be valid after speculating is done (which is expected to discard those attributes).
The invalid speculation appears to happen here:
llvm-project/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
Lines 461 to 465 in b592917
This can be observed by running opt -passes=simplifycfg this.ll
and observing that it returns IR with only basic block, which violates the semantics of %4
being a conditional load in the original IR specification (%3 is not dereferencable after hoisting for foldTwoEntryPHINode
):
define i64 @julia_collect_81(i1 %0, ptr nonnull align 8 dereferenceable(8) %1) {
top:
br i1 %0, label %L82, label %L85
L82:
%2 = load ptr, ptr %1, align 8, !dereferenceable !1, !align !1
%3 = load i64, ptr %2, align 8
br label %L85
L85:
%4 = phi i64 [ %3, %L82 ], [ 0, %top ]
ret i64 %4
}
!0 = !{}
!1 = !{i64 8}
What seems the best course of action to fix this pass mis-speculation? I think LICM and LoopRotationUtils and SpeculativeExecution may share same issue but SpeculativeExecution has a private AllPrecedingUsesFromBlockHoisted
check that it appears to have been using to avoid this issue (present since that pass was introduced in 154eb5a)