2019-11-02 02:48:05 -05:00
|
|
|
; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 < %s | FileCheck %s
|
2019-08-29 05:52:00 +00:00
|
|
|
|
|
|
|
define dso_local i32 @visible(i32* noalias %A, i32* noalias %B) #0 {
|
|
|
|
entry:
|
|
|
|
%call1 = call i32 @noalias_args(i32* %A, i32* %B)
|
|
|
|
%call2 = call i32 @noalias_args_argmem(i32* %A, i32* %B)
|
|
|
|
%add = add nsw i32 %call1, %call2
|
|
|
|
ret i32 %add
|
|
|
|
}
|
|
|
|
|
2019-11-12 06:36:49 +00:00
|
|
|
; CHECK: define private i32 @noalias_args(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %A, i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) %B)
|
2019-08-29 05:52:00 +00:00
|
|
|
|
2019-10-07 23:21:52 +00:00
|
|
|
define private i32 @noalias_args(i32* %A, i32* %B) #0 {
|
2019-08-29 05:52:00 +00:00
|
|
|
entry:
|
|
|
|
%0 = load i32, i32* %A, align 4
|
|
|
|
%1 = load i32, i32* %B, align 4
|
|
|
|
%add = add nsw i32 %0, %1
|
|
|
|
%call = call i32 @noalias_args_argmem(i32* %A, i32* %B)
|
|
|
|
%add2 = add nsw i32 %add, %call
|
|
|
|
ret i32 %add2
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
; FIXME: Should be something like this.
|
|
|
|
; define internal i32 @noalias_args_argmem(i32* noalias nocapture readonly %A, i32* noalias nocapture readonly %B)
|
2019-11-12 06:36:49 +00:00
|
|
|
; CHECK: define internal i32 @noalias_args_argmem(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %A, i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %B)
|
[Attributor][MustExec] Deduce dereferenceable and nonnull attribute using MustBeExecutedContextExplorer
Summary:
In D65186 and related patches, MustBeExecutedContextExplorer is introduced. This enables us to traverse instructions guaranteed to execute from function entry. If we can know the argument is used as `dereferenceable` or `nonnull` in these instructions, we can mark `dereferenceable` or `nonnull` in the argument definition:
1. Memory instruction (similar to D64258)
Trace memory instruction pointer operand. Currently, only inbounds GEPs are traced.
```
define i64* @f(i64* %a) {
entry:
%add.ptr = getelementptr inbounds i64, i64* %a, i64 1
; (because of inbounds GEP we can know that %a is at least dereferenceable(16))
store i64 1, i64* %add.ptr, align 8
ret i64* %add.ptr ; dereferenceable 8 (because above instruction stores into it)
}
```
2. Propagation from callsite (similar to D27855)
If `deref` or `nonnull` are known in call site parameter attributes we can also say that argument also that attribute.
```
declare void @use3(i8* %x, i8* %y, i8* %z);
declare void @use3nonnull(i8* nonnull %x, i8* nonnull %y, i8* nonnull %z);
define void @parent1(i8* %a, i8* %b, i8* %c) {
call void @use3nonnull(i8* %b, i8* %c, i8* %a)
; Above instruction is always executed so we can say that@parent1(i8* nonnnull %a, i8* nonnull %b, i8* nonnull %c)
call void @use3(i8* %c, i8* %a, i8* %b)
ret void
}
```
Reviewers: jdoerfert, sstefan1, spatel, reames
Reviewed By: jdoerfert
Subscribers: xbolva00, hiraditya, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65402
llvm-svn: 374063
2019-10-08 15:25:56 +00:00
|
|
|
|
2019-08-29 05:52:00 +00:00
|
|
|
;
|
|
|
|
define internal i32 @noalias_args_argmem(i32* %A, i32* %B) #1 {
|
|
|
|
entry:
|
|
|
|
%0 = load i32, i32* %A, align 4
|
|
|
|
%1 = load i32, i32* %B, align 4
|
|
|
|
%add = add nsw i32 %0, %1
|
|
|
|
ret i32 %add
|
|
|
|
}
|
|
|
|
|
|
|
|
define dso_local i32 @visible_local(i32* %A) #0 {
|
|
|
|
entry:
|
|
|
|
%B = alloca i32, align 4
|
|
|
|
store i32 5, i32* %B, align 4
|
|
|
|
%call1 = call i32 @noalias_args(i32* %A, i32* nonnull %B)
|
|
|
|
%call2 = call i32 @noalias_args_argmem(i32* %A, i32* nonnull %B)
|
|
|
|
%add = add nsw i32 %call1, %call2
|
|
|
|
ret i32 %add
|
|
|
|
}
|
|
|
|
|
|
|
|
attributes #0 = { noinline nounwind uwtable willreturn }
|
|
|
|
attributes #1 = { argmemonly noinline nounwind uwtable willreturn}
|