llvm-project/llvm/test/Transforms/PhaseOrdering/gep-null-compare-in-loop.ll
Yingwei Zheng 1228becf7d
[FuncAttrs] Deduce noundef attributes for return values (#76553)
This patch deduces `noundef` attributes for return values.
IIUC, a function returns `noundef` values iff all of its return values
are guaranteed not to be `undef` or `poison`.
Definition of `noundef` from LangRef:
```
noundef
This attribute applies to parameters and return values. If the value representation contains any 
undefined or poison bits, the behavior is undefined. Note that this does not refer to padding 
introduced by the type’s storage representation.
```
Alive2: https://alive2.llvm.org/ce/z/g8Eis6

Compile-time impact: http://llvm-compile-time-tracker.com/compare.php?from=30dcc33c4ea3ab50397a7adbe85fe977d4a400bd&to=c5e8738d4bfbf1e97e3f455fded90b791f223d74&stat=instructions:u
|stage1-O3|stage1-ReleaseThinLTO|stage1-ReleaseLTO-g|stage1-O0-g|stage2-O3|stage2-O0-g|stage2-clang|
|--|--|--|--|--|--|--|
|+0.01%|+0.01%|-0.01%|+0.01%|+0.03%|-0.04%|+0.01%|

The motivation of this patch is to reduce the number of `freeze` insts
and enable more optimizations.
2023-12-31 20:44:48 +08:00

74 lines
2.0 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
; RUN: opt -O3 -S < %s | FileCheck %s
define internal i32 @loop(ptr %arg, ptr %arg1) {
bb:
br label %bb2
bb2:
%phi = phi ptr [ %arg, %bb ], [ %phi8, %bb11 ]
%phi3 = phi i32 [ 0, %bb ], [ %add, %bb11 ]
%icmp = icmp ne ptr %arg1, null
%icmp4 = icmp eq ptr %phi, %arg1
br i1 %icmp4, label %bb7, label %bb5
bb5:
%getelementptr = getelementptr inbounds i32, ptr %phi, i64 1
br label %bb7
bb7:
%phi8 = phi ptr [ %phi, %bb2 ], [ %getelementptr, %bb5 ]
%phi9 = phi ptr [ null, %bb2 ], [ %phi, %bb5 ]
%icmp10 = icmp eq ptr %phi9, null
br i1 %icmp10, label %bb12, label %bb11
bb11:
%load = load i32, ptr %phi9, align 4
%add = add i32 %load, %phi3
br label %bb2
bb12:
ret i32 %phi3
}
define i32 @using_alloca() {
; CHECK-LABEL: define noundef i32 @using_alloca
; CHECK-SAME: () local_unnamed_addr #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: bb:
; CHECK-NEXT: ret i32 6
;
bb:
%alloca = alloca [3 x i32], align 4
store i32 1, ptr %alloca, align 4
%getelementptr = getelementptr i32, ptr %alloca, i32 1
store i32 2, ptr %getelementptr, align 4
%getelementptr1 = getelementptr i32, ptr %alloca, i32 2
store i32 3, ptr %getelementptr1, align 4
%getelementptr2 = getelementptr i32, ptr %alloca, i32 3
%call = call i32 @loop(ptr %alloca, ptr %getelementptr2)
ret i32 %call
}
define i32 @using_malloc() {
; CHECK-LABEL: define noundef i32 @using_malloc
; CHECK-SAME: () local_unnamed_addr #[[ATTR0]] {
; CHECK-NEXT: bb:
; CHECK-NEXT: ret i32 6
;
bb:
%alloc = call dereferenceable_or_null(64) ptr @malloc(i64 64)
store i32 1, ptr %alloc, align 4
%getelementptr = getelementptr i32, ptr %alloc, i64 1
store i32 2, ptr %getelementptr, align 4
%getelementptr1 = getelementptr i32, ptr %alloc, i64 2
store i32 3, ptr %getelementptr1, align 4
%getelementptr2 = getelementptr i32, ptr %alloc, i64 3
%call = call i32 @loop(ptr %alloc, ptr %getelementptr2)
ret i32 %call
}
declare ptr @malloc(i64)
declare void @free(ptr)