1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt < %s -passes='function-attrs' -S | FileCheck %s 3 4@g_var = external global [0 x i8] 5 6define i32 @test_ret_constant() { 7; CHECK-LABEL: define noundef i32 @test_ret_constant( 8; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { 9; CHECK-NEXT: ret i32 0 10; 11 ret i32 0 12} 13 14define i32 @test_ret_poison() { 15; CHECK-LABEL: define i32 @test_ret_poison( 16; CHECK-SAME: ) #[[ATTR0]] { 17; CHECK-NEXT: ret i32 poison 18; 19 ret i32 poison 20} 21 22define i32 @test_ret_undef() { 23; CHECK-LABEL: define i32 @test_ret_undef( 24; CHECK-SAME: ) #[[ATTR0]] { 25; CHECK-NEXT: ret i32 undef 26; 27 ret i32 undef 28} 29 30define i32 @test_ret_param(i32 %x) { 31; CHECK-LABEL: define i32 @test_ret_param( 32; CHECK-SAME: i32 returned [[X:%.*]]) #[[ATTR0]] { 33; CHECK-NEXT: ret i32 [[X]] 34; 35 ret i32 %x 36} 37 38define i32 @test_ret_noundef_param(i32 noundef %x) { 39; CHECK-LABEL: define noundef i32 @test_ret_noundef_param( 40; CHECK-SAME: i32 noundef returned [[X:%.*]]) #[[ATTR0]] { 41; CHECK-NEXT: ret i32 [[X]] 42; 43 ret i32 %x 44} 45 46define i32 @test_ret_noundef_expr(i32 noundef %x) { 47; CHECK-LABEL: define noundef i32 @test_ret_noundef_expr( 48; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] { 49; CHECK-NEXT: [[Y:%.*]] = add i32 [[X]], 1 50; CHECK-NEXT: ret i32 [[Y]] 51; 52 %y = add i32 %x, 1 53 ret i32 %y 54} 55 56define i32 @test_ret_create_poison_expr(i32 noundef %x) { 57; CHECK-LABEL: define i32 @test_ret_create_poison_expr( 58; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] { 59; CHECK-NEXT: [[Y:%.*]] = add nsw i32 [[X]], 1 60; CHECK-NEXT: ret i32 [[Y]] 61; 62 %y = add nsw i32 %x, 1 63 ret i32 %y 64} 65 66define i32 @test_ret_freezed(i32 noundef %x) { 67; CHECK-LABEL: define noundef i32 @test_ret_freezed( 68; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] { 69; CHECK-NEXT: [[Y:%.*]] = add nsw i32 [[X]], 1 70; CHECK-NEXT: [[Z:%.*]] = freeze i32 [[Y]] 71; CHECK-NEXT: ret i32 [[Z]] 72; 73 %y = add nsw i32 %x, 1 74 %z = freeze i32 %y 75 ret i32 %z 76} 77 78define i32 @test_ret_control_flow(i32 noundef %x) { 79; CHECK-LABEL: define noundef i32 @test_ret_control_flow( 80; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] { 81; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X]], 0 82; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 83; CHECK: if.then: 84; CHECK-NEXT: ret i32 2 85; CHECK: if.else: 86; CHECK-NEXT: [[RET:%.*]] = add i32 [[X]], 1 87; CHECK-NEXT: ret i32 [[RET]] 88; 89 %cond = icmp eq i32 %x, 0 90 br i1 %cond, label %if.then, label %if.else 91if.then: 92 ret i32 2 93if.else: 94 %ret = add i32 %x, 1 95 ret i32 %ret 96} 97 98define i32 @test_ret_control_flow_may_poison(i32 noundef %x) { 99; CHECK-LABEL: define i32 @test_ret_control_flow_may_poison( 100; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] { 101; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X]], 0 102; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 103; CHECK: if.then: 104; CHECK-NEXT: ret i32 2 105; CHECK: if.else: 106; CHECK-NEXT: [[RET:%.*]] = add nsw i32 [[X]], 1 107; CHECK-NEXT: ret i32 [[RET]] 108; 109 %cond = icmp eq i32 %x, 0 110 br i1 %cond, label %if.then, label %if.else 111if.then: 112 ret i32 2 113if.else: 114 %ret = add nsw i32 %x, 1 115 ret i32 %ret 116} 117 118; TODO: use context-sensitive analysis 119define i32 @test_ret_control_flow_never_poison(i32 noundef %x) { 120; CHECK-LABEL: define i32 @test_ret_control_flow_never_poison( 121; CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] { 122; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X]], 2147483647 123; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 124; CHECK: if.then: 125; CHECK-NEXT: ret i32 2 126; CHECK: if.else: 127; CHECK-NEXT: [[RET:%.*]] = add nsw i32 [[X]], 1 128; CHECK-NEXT: ret i32 [[RET]] 129; 130 %cond = icmp eq i32 %x, 2147483647 131 br i1 %cond, label %if.then, label %if.else 132if.then: 133 ret i32 2 134if.else: 135 %ret = add nsw i32 %x, 1 136 ret i32 %ret 137} 138 139define i32 @test_noundef_prop() { 140; CHECK-LABEL: define noundef i32 @test_noundef_prop( 141; CHECK-SAME: ) #[[ATTR0]] { 142; CHECK-NEXT: [[RET:%.*]] = call i32 @test_ret_constant() 143; CHECK-NEXT: ret i32 [[RET]] 144; 145 %ret = call i32 @test_ret_constant() 146 ret i32 %ret 147} 148 149; Don't deduce noundef for functions with sanitize_memory. 150define i32 @test_ret_constant_msan() sanitize_memory { 151; CHECK-LABEL: define i32 @test_ret_constant_msan( 152; CHECK-SAME: ) #[[ATTR1:[0-9]+]] { 153; CHECK-NEXT: ret i32 0 154; 155 ret i32 0 156} 157 158define i64 @test_trunc_with_constexpr() { 159; CHECK-LABEL: define noundef i64 @test_trunc_with_constexpr( 160; CHECK-SAME: ) #[[ATTR0]] { 161; CHECK-NEXT: [[ADD:%.*]] = add i32 trunc (i64 sub (i64 0, i64 ptrtoint (ptr @g_var to i64)) to i32), 1 162; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ADD]] to i64 163; CHECK-NEXT: ret i64 [[CONV]] 164; 165 %add = add i32 trunc (i64 sub (i64 0, i64 ptrtoint (ptr @g_var to i64)) to i32), 1 166 %conv = sext i32 %add to i64 167 ret i64 %conv 168} 169 170define align 4 ptr @maybe_not_aligned(ptr noundef %p) { 171; CHECK-LABEL: define align 4 ptr @maybe_not_aligned( 172; CHECK-SAME: ptr noundef readnone returned [[P:%.*]]) #[[ATTR0]] { 173; CHECK-NEXT: ret ptr [[P]] 174; 175 ret ptr %p 176} 177 178define align 4 ptr @definitely_aligned(ptr noundef align 4 %p) { 179; CHECK-LABEL: define noundef align 4 ptr @definitely_aligned( 180; CHECK-SAME: ptr noundef readnone returned align 4 [[P:%.*]]) #[[ATTR0]] { 181; CHECK-NEXT: ret ptr [[P]] 182; 183 ret ptr %p 184} 185 186define nonnull ptr @maybe_not_nonnull(ptr noundef %p) { 187; CHECK-LABEL: define nonnull ptr @maybe_not_nonnull( 188; CHECK-SAME: ptr noundef readnone returned [[P:%.*]]) #[[ATTR0]] { 189; CHECK-NEXT: ret ptr [[P]] 190; 191 ret ptr %p 192} 193 194define nonnull ptr @definitely_nonnull(ptr noundef nonnull %p) { 195; CHECK-LABEL: define noundef nonnull ptr @definitely_nonnull( 196; CHECK-SAME: ptr noundef nonnull readnone returned [[P:%.*]]) #[[ATTR0]] { 197; CHECK-NEXT: ret ptr [[P]] 198; 199 ret ptr %p 200} 201 202define range(i8 0, 10) i8 @maybe_not_in_range(i8 noundef %v) { 203; CHECK-LABEL: define range(i8 0, 10) i8 @maybe_not_in_range( 204; CHECK-SAME: i8 noundef returned [[V:%.*]]) #[[ATTR0]] { 205; CHECK-NEXT: ret i8 [[V]] 206; 207 ret i8 %v 208} 209 210define range(i8 0, 10) i8 @definitely_in_range(i8 noundef range(i8 0, 10) %v) { 211; CHECK-LABEL: define noundef range(i8 0, 10) i8 @definitely_in_range( 212; CHECK-SAME: i8 noundef returned range(i8 0, 10) [[V:%.*]]) #[[ATTR0]] { 213; CHECK-NEXT: ret i8 [[V]] 214; 215 ret i8 %v 216} 217