[PATCH] D28276: [JumpThreading] Fix a bug affecting guards and assumes
Philip Reames via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 3 19:53:34 PST 2017
reames created this revision.
reames added reviewers: sanjoy, hfinkel, apilipenko.
reames added a subscriber: llvm-commits.
Herald added a subscriber: mcrosier.
This patch fixes an issue in jump threading where we'd sometimes use circular logic to fold the condition assumed or guarded to true. The code had an implicit assumption that a fact true at the end of a block must be true for all uses within the block. This is blatantly false. The net effect for guards was that we could remove a guard on a condition which wasn't actual true at runtime and miscompile.
I noticed this while working on another optimization patch. I'm a little terrified that we never noticed this previously.
https://reviews.llvm.org/D28276
Files:
lib/Transforms/Scalar/JumpThreading.cpp
test/Transforms/JumpThreading/assume.ll
Index: test/Transforms/JumpThreading/assume.ll
===================================================================
--- test/Transforms/JumpThreading/assume.ll
+++ test/Transforms/JumpThreading/assume.ll
@@ -56,8 +56,50 @@
ret i32 %retval.0
}
+ at g = external global i32
+
+; Check that we do prove a fact using an assume within the block and
+; that we *don't* use circular logic to remove the assume.
+; CHECK-LABEL: @local_assume
+; CHECK: %notnull = icmp ne i32* %array, null
+; CHECK-NEXT: call void @llvm.assume(i1 %notnull)
+; CHECK-NEXT: ret void
+define void @local_assume(i32* %array) {
+ %notnull = icmp ne i32* %array, null
+ call void @llvm.assume(i1 %notnull)
+ br i1 %notnull, label %normal, label %error
+
+normal:
+ ret void
+
+error:
+ store atomic i32 0, i32* @g unordered, align 4
+ ret void
+}
+
+; Check that we do prove a fact using an assume within the block and
+; that we *don't* use circular logic to remove the guard.
+; CHECK-LABEL: @local_guard
+; CHECK: %notnull = icmp ne i32* %array, null
+; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %notnull) [ "deopt"(i32 0) ]
+; CHECK-NEXT: ret void
+
+define void @local_guard(i32* %array) {
+ %notnull = icmp ne i32* %array, null
+ call void (i1, ...) @llvm.experimental.guard(i1 %notnull) ["deopt" (i32 0)]
+ br i1 %notnull, label %normal, label %error
+
+normal:
+ ret void
+
+error:
+ store atomic i32 0, i32* @g unordered, align 4
+ ret void
+}
+
; Function Attrs: nounwind
declare void @llvm.assume(i1) #1
+declare void @llvm.experimental.guard(i1 %cnd, ...)
declare void @bar(...)
Index: lib/Transforms/Scalar/JumpThreading.cpp
===================================================================
--- lib/Transforms/Scalar/JumpThreading.cpp
+++ lib/Transforms/Scalar/JumpThreading.cpp
@@ -822,17 +822,24 @@
CondBr->getSuccessor(ToRemove)->removePredecessor(BB, true);
BranchInst::Create(CondBr->getSuccessor(ToKeep), CondBr);
CondBr->eraseFromParent();
- if (CondCmp->use_empty())
- CondCmp->eraseFromParent();
- else if (CondCmp->getParent() == BB) {
- // If the fact we just learned is true for all uses of the
- // condition, replace it with a constant value
+
+ // Now, see if we can eagerly update any other uses. WARNING: we used a
+ // context instruction at the end of the current basic block, so the
+ // facts LVI returned may not be true before that point. (i.e. we may
+ // have a guard or assume part way through the block.) Thus, we can
+ // not reason about any use which is not dominated by the context
+ // instruction. Given we don't have dom-tree here, we're restricted to
+ // only handling cases where dominance can be trivially established
+ // from the definition of SSA.
+ if (!CondCmp->use_empty() &&
+ CondCmp->getParent() == BB) {
auto *CI = Ret == LazyValueInfo::True ?
ConstantInt::getTrue(CondCmp->getType()) :
ConstantInt::getFalse(CondCmp->getType());
- CondCmp->replaceAllUsesWith(CI);
- CondCmp->eraseFromParent();
+ replaceNonLocalUsesWith(CondCmp, CI);
}
+ if (CondCmp->use_empty())
+ CondCmp->eraseFromParent();
return true;
}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D28276.82995.patch
Type: text/x-patch
Size: 3338 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170104/058749ec/attachment.bin>
More information about the llvm-commits
mailing list