1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes 2; RUN: opt < %s -function-attrs -S | FileCheck %s 3; RUN: opt < %s -passes=function-attrs -S | FileCheck %s 4 5target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 6target triple = "x86_64-unknown-linux-gnu" 7 8define void @_Z4foo1Pi(i32* nocapture readnone %a) local_unnamed_addr #0 { 9; CHECK: Function Attrs: uwtable 10; CHECK-LABEL: @_Z4foo1Pi( 11; CHECK-NEXT: entry: 12; CHECK-NEXT: tail call void @_Z3extv() 13; CHECK-NEXT: ret void 14; 15entry: 16 tail call void @_Z3extv() 17 ret void 18} 19 20declare void @_Z3extv() local_unnamed_addr 21 22define void @_Z4foo2Pi(i32* nocapture %a) local_unnamed_addr #1 { 23; CHECK: Function Attrs: nounwind uwtable 24; CHECK-LABEL: @_Z4foo2Pi( 25; CHECK-NEXT: entry: 26; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[A:%.*]] to i8* 27; CHECK-NEXT: tail call void @free(i8* [[TMP0]]) #[[ATTR2:[0-9]+]] 28; CHECK-NEXT: ret void 29; 30entry: 31 %0 = bitcast i32* %a to i8* 32 tail call void @free(i8* %0) #2 33 ret void 34} 35 36declare void @free(i8* nocapture) local_unnamed_addr #2 37 38define i32 @_Z4foo3Pi(i32* nocapture readonly %a) local_unnamed_addr #3 { 39; CHECK: Function Attrs: nofree norecurse nosync nounwind readonly uwtable willreturn 40; CHECK-LABEL: @_Z4foo3Pi( 41; CHECK-NEXT: entry: 42; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4 43; CHECK-NEXT: ret i32 [[TMP0]] 44; 45entry: 46 %0 = load i32, i32* %a, align 4 47 ret i32 %0 48} 49 50define double @_Z4foo4Pd(double* nocapture readonly %a) local_unnamed_addr #1 { 51; CHECK: Function Attrs: nounwind uwtable 52; CHECK-LABEL: @_Z4foo4Pd( 53; CHECK-NEXT: entry: 54; CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[A:%.*]], align 8 55; CHECK-NEXT: [[CALL:%.*]] = tail call double @cos(double [[TMP0]]) #[[ATTR2]] 56; CHECK-NEXT: ret double [[CALL]] 57; 58entry: 59 %0 = load double, double* %a, align 8 60 %call = tail call double @cos(double %0) #2 61 ret double %call 62} 63 64declare double @cos(double) local_unnamed_addr #2 65 66define noalias i32* @_Z4foo5Pm(i64* nocapture readonly %a) local_unnamed_addr #1 { 67; CHECK: Function Attrs: nounwind uwtable 68; CHECK-LABEL: @_Z4foo5Pm( 69; CHECK-NEXT: entry: 70; CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[A:%.*]], align 8 71; CHECK-NEXT: [[CALL:%.*]] = tail call noalias i8* @malloc(i64 [[TMP0]]) #[[ATTR2]] 72; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8* [[CALL]] to i32* 73; CHECK-NEXT: ret i32* [[TMP1]] 74; 75entry: 76 %0 = load i64, i64* %a, align 8 77 %call = tail call noalias i8* @malloc(i64 %0) #2 78 %1 = bitcast i8* %call to i32* 79 ret i32* %1 80} 81 82declare noalias i8* @malloc(i64) local_unnamed_addr #2 83 84define noalias i64* @_Z4foo6Pm(i64* nocapture %a) local_unnamed_addr #1 { 85; CHECK: Function Attrs: nounwind uwtable 86; CHECK-LABEL: @_Z4foo6Pm( 87; CHECK-NEXT: entry: 88; CHECK-NEXT: [[TMP0:%.*]] = bitcast i64* [[A:%.*]] to i8* 89; CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[A]], align 8 90; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @realloc(i8* [[TMP0]], i64 [[TMP1]]) #[[ATTR2]] 91; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[CALL]] to i64* 92; CHECK-NEXT: ret i64* [[TMP2]] 93; 94entry: 95 %0 = bitcast i64* %a to i8* 96 %1 = load i64, i64* %a, align 8 97 %call = tail call i8* @realloc(i8* %0, i64 %1) #2 98 %2 = bitcast i8* %call to i64* 99 ret i64* %2 100} 101 102declare noalias i8* @realloc(i8* nocapture, i64) local_unnamed_addr #2 103 104define void @_Z4foo7Pi(i32* %a) local_unnamed_addr #1 { 105; CHECK: Function Attrs: nounwind uwtable 106; CHECK-LABEL: @_Z4foo7Pi( 107; CHECK-NEXT: entry: 108; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq i32* [[A:%.*]], null 109; CHECK-NEXT: br i1 [[ISNULL]], label [[DELETE_END:%.*]], label [[DELETE_NOTNULL:%.*]] 110; CHECK: delete.notnull: 111; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[A]] to i8* 112; CHECK-NEXT: tail call void @_ZdlPv(i8* [[TMP0]]) #[[ATTR6:[0-9]+]] 113; CHECK-NEXT: br label [[DELETE_END]] 114; CHECK: delete.end: 115; CHECK-NEXT: ret void 116; 117entry: 118 %isnull = icmp eq i32* %a, null 119 br i1 %isnull, label %delete.end, label %delete.notnull 120 121delete.notnull: ; preds = %entry 122 %0 = bitcast i32* %a to i8* 123 tail call void @_ZdlPv(i8* %0) #5 124 br label %delete.end 125 126delete.end: ; preds = %delete.notnull, %entry 127 ret void 128} 129 130declare void @_ZdlPv(i8*) local_unnamed_addr #4 131 132define void @_Z4foo8Pi(i32* %a) local_unnamed_addr #1 { 133; CHECK: Function Attrs: nounwind uwtable 134; CHECK-LABEL: @_Z4foo8Pi( 135; CHECK-NEXT: entry: 136; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq i32* [[A:%.*]], null 137; CHECK-NEXT: br i1 [[ISNULL]], label [[DELETE_END:%.*]], label [[DELETE_NOTNULL:%.*]] 138; CHECK: delete.notnull: 139; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[A]] to i8* 140; CHECK-NEXT: tail call void @_ZdaPv(i8* [[TMP0]]) #[[ATTR6]] 141; CHECK-NEXT: br label [[DELETE_END]] 142; CHECK: delete.end: 143; CHECK-NEXT: ret void 144; 145entry: 146 %isnull = icmp eq i32* %a, null 147 br i1 %isnull, label %delete.end, label %delete.notnull 148 149delete.notnull: ; preds = %entry 150 %0 = bitcast i32* %a to i8* 151 tail call void @_ZdaPv(i8* %0) #5 152 br label %delete.end 153 154delete.end: ; preds = %delete.notnull, %entry 155 ret void 156} 157 158declare void @may_free() 159 160define void @nofree_callsite_attr(i32* %a) { 161; CHECK: Function Attrs: nofree 162; CHECK-LABEL: @nofree_callsite_attr( 163; CHECK-NEXT: entry: 164; CHECK-NEXT: call void @may_free() #[[ATTR5:[0-9]+]] 165; CHECK-NEXT: ret void 166; 167entry: 168 call void @may_free() nofree 169 ret void 170} 171 172declare void @_ZdaPv(i8*) local_unnamed_addr #4 173 174attributes #0 = { uwtable } 175attributes #1 = { nounwind uwtable } 176attributes #2 = { nounwind } 177attributes #3 = { norecurse nounwind readonly uwtable } 178attributes #4 = { nobuiltin nounwind } 179attributes #5 = { builtin nounwind } 180