1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature 2; RUN: opt -inline -S < %s | FileCheck --check-prefixes=CHECK,NO_ASSUME %s 3; RUN: opt -inline -S --enable-knowledge-retention < %s | FileCheck %s --check-prefixes=CHECK,USE_ASSUME 4 5; The callee guarantees that the pointer argument is nonnull and dereferenceable. 6; That information should transfer to the caller. 7 8define i32 @callee(i32* dereferenceable(32) %t1) { 9; CHECK-LABEL: define {{[^@]+}}@callee 10; CHECK-SAME: (i32* dereferenceable(32) [[T1:%.*]]) { 11; CHECK-NEXT: [[T2:%.*]] = load i32, i32* [[T1]], align 4 12; CHECK-NEXT: ret i32 [[T2]] 13; 14 %t2 = load i32, i32* %t1 15 ret i32 %t2 16} 17 18define i32 @callee2(i32* dereferenceable(32) %t1, i32 noundef %t2) { 19; CHECK-LABEL: define {{[^@]+}}@callee2 20; CHECK-SAME: (i32* dereferenceable(32) [[T1:%.*]], i32 noundef [[T2:%.*]]) { 21; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[T1]], align 4 22; CHECK-NEXT: ret i32 [[V]] 23; 24 %v = load i32, i32* %t1 25 ret i32 %v 26} 27 28; FIXME: All dereferenceability information is lost. 29; The caller argument could be known nonnull and dereferenceable(32). 30 31define i32 @caller1(i32* %t1, i32 %t2) { 32; NO_ASSUME-LABEL: define {{[^@]+}}@caller1 33; NO_ASSUME-SAME: (i32* [[T1:%.*]], i32 [[T2:%.*]]) { 34; NO_ASSUME-NEXT: [[V_I:%.*]] = load i32, i32* [[T1]], align 4 35; NO_ASSUME-NEXT: ret i32 [[V_I]] 36; 37; USE_ASSUME-LABEL: define {{[^@]+}}@caller1 38; USE_ASSUME-SAME: (i32* [[T1:%.*]], i32 [[T2:%.*]]) { 39; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[T1]], i64 32), "noundef"(i32 [[T2]]) ] 40; USE_ASSUME-NEXT: [[V_I:%.*]] = load i32, i32* [[T1]], align 4 41; USE_ASSUME-NEXT: ret i32 [[V_I]] 42; 43 %v = tail call i32 @callee2(i32* dereferenceable(32) %t1, i32 noundef %t2) 44 ret i32 %v 45} 46 47; The caller argument is nonnull, but that can be explicit. 48; The dereferenceable amount could be increased. 49 50define i32 @caller2(i32* dereferenceable(31) %t1) { 51; NO_ASSUME-LABEL: define {{[^@]+}}@caller2 52; NO_ASSUME-SAME: (i32* dereferenceable(31) [[T1:%.*]]) 53; NO_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]] 54; NO_ASSUME-NEXT: ret i32 [[T2_I]] 55; 56; USE_ASSUME-LABEL: define {{[^@]+}}@caller2 57; USE_ASSUME-SAME: (i32* dereferenceable(31) [[T1:%.*]]) 58; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[T1]], i64 32) ] 59; USE_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]] 60; USE_ASSUME-NEXT: ret i32 [[T2_I]] 61; 62 %t2 = tail call i32 @callee(i32* dereferenceable(32) %t1) 63 ret i32 %t2 64} 65 66; The caller argument is nonnull, but that can be explicit. 67; Make sure that we don't propagate a smaller dereferenceable amount. 68 69define i32 @caller3(i32* dereferenceable(33) %t1) { 70; CHECK-LABEL: define {{[^@]+}}@caller3 71; CHECK-SAME: (i32* dereferenceable(33) [[T1:%.*]]) 72; CHECK-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]] 73; CHECK-NEXT: ret i32 [[T2_I]] 74; 75 %t2 = tail call i32 @callee(i32* dereferenceable(32) %t1) 76 ret i32 %t2 77} 78 79