
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.
74 lines
2.0 KiB
LLVM
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)
|