
Update LangRef and code using `Dereferenceable` in assume bundles to only use the information if it is safe at the point of use. `Dereferenceable` in an assume bundle is only guaranteed at the point of the assumption, but may not be guaranteed at later points, because the pointer may have been freed. Update code using `Dereferenceable` to only use it if the pointer cannot be freed. This can further be refined to check if the pointer could be freed between assume and use. This follows up on https://github.com/llvm/llvm-project/pull/123196. With that change, it should be safe to expose dereferenceable assumptions more widely as in https://github.com/llvm/llvm-project/pull/121789 PR: https://github.com/llvm/llvm-project/pull/126117
113 lines
4.2 KiB
LLVM
113 lines
4.2 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; REQUIRES: asserts
|
|
|
|
; RUN: opt < %s -passes=instcombine --debug-counter=assume-queries-counter=0 -S | FileCheck %s --check-prefixes=COUNTER1
|
|
; RUN: opt < %s -passes=instcombine --debug-counter=assume-queries-counter=1-2 -S | FileCheck %s --check-prefixes=COUNTER2
|
|
; RUN: opt < %s -passes=instcombine --debug-counter=assume-queries-counter=2-6 -S | FileCheck %s --check-prefixes=COUNTER3
|
|
|
|
declare i1 @get_val()
|
|
declare void @llvm.assume(i1)
|
|
|
|
define dso_local i1 @test1(ptr readonly %0) {
|
|
; COUNTER1-LABEL: @test1(
|
|
; COUNTER1-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0:%.*]]) ]
|
|
; COUNTER1-NEXT: ret i1 false
|
|
;
|
|
; COUNTER2-LABEL: @test1(
|
|
; COUNTER2-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0:%.*]]) ]
|
|
; COUNTER2-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
|
|
; COUNTER2-NEXT: ret i1 [[TMP2]]
|
|
;
|
|
; COUNTER3-LABEL: @test1(
|
|
; COUNTER3-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0:%.*]]) ]
|
|
; COUNTER3-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
|
|
; COUNTER3-NEXT: ret i1 [[TMP2]]
|
|
;
|
|
call void @llvm.assume(i1 true) ["nonnull"(ptr %0)]
|
|
%2 = icmp eq ptr %0, null
|
|
ret i1 %2
|
|
}
|
|
|
|
define dso_local i1 @test2(ptr readonly %0) {
|
|
; COUNTER1-LABEL: @test2(
|
|
; COUNTER1-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0:%.*]], null
|
|
; COUNTER1-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0]]) ]
|
|
; COUNTER1-NEXT: ret i1 [[TMP2]]
|
|
;
|
|
; COUNTER2-LABEL: @test2(
|
|
; COUNTER2-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0:%.*]]) ]
|
|
; COUNTER2-NEXT: ret i1 false
|
|
;
|
|
; COUNTER3-LABEL: @test2(
|
|
; COUNTER3-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0:%.*]]) ]
|
|
; COUNTER3-NEXT: ret i1 false
|
|
;
|
|
%2 = icmp eq ptr %0, null
|
|
call void @llvm.assume(i1 true) ["nonnull"(ptr %0)]
|
|
ret i1 %2
|
|
}
|
|
|
|
define dso_local i32 @test4(ptr readonly %0, i1 %cond) nofree nosync {
|
|
; COUNTER1-LABEL: @test4(
|
|
; COUNTER1-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0:%.*]], i32 4) ]
|
|
; COUNTER1-NEXT: br i1 [[COND:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
; COUNTER1: B:
|
|
; COUNTER1-NEXT: br label [[A]]
|
|
; COUNTER1: A:
|
|
; COUNTER1-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
|
|
; COUNTER1-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]]
|
|
; COUNTER1: 3:
|
|
; COUNTER1-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP0]], align 4
|
|
; COUNTER1-NEXT: br label [[TMP5]]
|
|
; COUNTER1: 5:
|
|
; COUNTER1-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP4]], [[TMP3]] ], [ 0, [[A]] ]
|
|
; COUNTER1-NEXT: ret i32 [[TMP6]]
|
|
;
|
|
; COUNTER2-LABEL: @test4(
|
|
; COUNTER2-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0:%.*]], i32 4) ]
|
|
; COUNTER2-NEXT: br i1 [[COND:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
; COUNTER2: B:
|
|
; COUNTER2-NEXT: br label [[A]]
|
|
; COUNTER2: A:
|
|
; COUNTER2-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
|
|
; COUNTER2-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]]
|
|
; COUNTER2: 3:
|
|
; COUNTER2-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP0]], align 4
|
|
; COUNTER2-NEXT: br label [[TMP5]]
|
|
; COUNTER2: 5:
|
|
; COUNTER2-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP4]], [[TMP3]] ], [ 0, [[A]] ]
|
|
; COUNTER2-NEXT: ret i32 [[TMP6]]
|
|
;
|
|
; COUNTER3-LABEL: @test4(
|
|
; COUNTER3-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0:%.*]], i32 4) ]
|
|
; COUNTER3-NEXT: br i1 [[COND:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
; COUNTER3: B:
|
|
; COUNTER3-NEXT: br label [[A]]
|
|
; COUNTER3: A:
|
|
; COUNTER3-NEXT: br i1 false, label [[TMP4:%.*]], label [[TMP2:%.*]]
|
|
; COUNTER3: 2:
|
|
; COUNTER3-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP0]], align 4
|
|
; COUNTER3-NEXT: br label [[TMP4]]
|
|
; COUNTER3: 4:
|
|
; COUNTER3-NEXT: [[TMP5:%.*]] = phi i32 [ [[TMP3]], [[TMP2]] ], [ poison, [[A]] ]
|
|
; COUNTER3-NEXT: ret i32 [[TMP5]]
|
|
;
|
|
call void @llvm.assume(i1 true) ["dereferenceable"(ptr %0, i32 4)]
|
|
br i1 %cond, label %A, label %B
|
|
|
|
B:
|
|
br label %A
|
|
|
|
A:
|
|
%2 = icmp eq ptr %0, null
|
|
br i1 %2, label %5, label %3
|
|
|
|
3: ; preds = %1
|
|
%4 = load i32, ptr %0, align 4
|
|
br label %5
|
|
|
|
5: ; preds = %1, %3
|
|
%6 = phi i32 [ %4, %3 ], [ 0, %A ]
|
|
ret i32 %6
|
|
}
|