diff options
author | Ayke van Laethem <aykevanlaethem@gmail.com> | 2019-06-09 10:20:33 +0000 |
---|---|---|
committer | Ayke van Laethem <aykevanlaethem@gmail.com> | 2019-06-09 10:20:33 +0000 |
commit | f18cf230e4e2a78fd575a5a1d260653b452f4d9d (patch) | |
tree | 36d5f91fc1a187144e9c2a9548fba745a854493a /llvm/test | |
parent | de329e511606b73d0b06f1afeef8689f84f54102 (diff) | |
download | bcm5719-llvm-f18cf230e4e2a78fd575a5a1d260653b452f4d9d.tar.gz bcm5719-llvm-f18cf230e4e2a78fd575a5a1d260653b452f4d9d.zip |
[CaptureTracking] Don't let comparisons against null escape inbounds pointers
Pointers that are in-bounds (either through dereferenceable_or_null or
thorough a getelementptr inbounds) cannot be captured with a comparison
against null. There is no way to construct a pointer that is still in
bounds but also NULL.
This helps safe languages that insert null checks before load/store
instructions. Without this patch, almost all pointers would be
considered captured even for simple loads. With this patch, an icmp with
null will not be seen as escaping as long as certain conditions are met.
There was a lot of discussion about this patch. See the Phabricator
thread for detals.
Differential Revision: https://reviews.llvm.org/D60047
llvm-svn: 362900
Diffstat (limited to 'llvm/test')
-rw-r--r-- | llvm/test/Transforms/FunctionAttrs/nocapture.ll | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/llvm/test/Transforms/FunctionAttrs/nocapture.ll b/llvm/test/Transforms/FunctionAttrs/nocapture.ll index 0c3fc0af725..b109249674b 100644 --- a/llvm/test/Transforms/FunctionAttrs/nocapture.ll +++ b/llvm/test/Transforms/FunctionAttrs/nocapture.ll @@ -253,5 +253,33 @@ define void @captureStrip(i8* %p) { ret void } +; CHECK: define i1 @captureICmp(i32* readnone %x) +define i1 @captureICmp(i32* %x) { + %1 = icmp eq i32* %x, null + ret i1 %1 +} + +; CHECK: define i1 @nocaptureInboundsGEPICmp(i32* nocapture readnone %x) +define i1 @nocaptureInboundsGEPICmp(i32* %x) { + %1 = getelementptr inbounds i32, i32* %x, i32 5 + %2 = bitcast i32* %1 to i8* + %3 = icmp eq i8* %2, null + ret i1 %3 +} + +; CHECK: define i1 @nocaptureDereferenceableOrNullICmp(i32* nocapture readnone dereferenceable_or_null(4) %x) +define i1 @nocaptureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x) { + %1 = bitcast i32* %x to i8* + %2 = icmp eq i8* %1, null + ret i1 %2 +} + +; CHECK: define i1 @captureDereferenceableOrNullICmp(i32* readnone dereferenceable_or_null(4) %x) +define i1 @captureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x) "null-pointer-is-valid"="true" { + %1 = bitcast i32* %x to i8* + %2 = icmp eq i8* %1, null + ret i1 %2 +} + declare i8* @llvm.launder.invariant.group.p0i8(i8*) declare i8* @llvm.strip.invariant.group.p0i8(i8*) |