1; For instructions explicitly defined as mayThrow, make sure they prevent nounwind propagation 2; RUN: split-file %s %t 3; RUN: opt -thinlto-bc %t/main.ll -thin-link-bitcode-file=%t1.thinlink.bc -o %t1.bc 4; RUN: opt -thinlto-bc %t/callees.ll -thin-link-bitcode-file=%t2.thinlink.bc -o %t2.bc 5; RUN: llvm-lto2 run -disable-thinlto-funcattrs=0 %t1.bc %t2.bc -o %t.o -r %t1.bc,caller,px -r %t1.bc,caller1,px -r %t1.bc,caller2,px -r %t1.bc,caller_nounwind,px \ 6; RUN: -r %t1.bc,cleanupret,l -r %t1.bc,catchret,l -r %t1.bc,resume,l -r %t1.bc,cleanupret_nounwind,l \ 7; RUN: -r %t2.bc,cleanupret,px -r %t2.bc,catchret,px -r %t2.bc,resume,px -r %t2.bc,cleanupret_nounwind,px -r %t2.bc,nonThrowing,px -r %t2.bc,__gxx_personality_v0,px -save-temps 8; RUN: llvm-dis -o - %t2.bc | FileCheck %s --check-prefix=SUMMARY 9; RUN: llvm-dis -o - %t.o.1.3.import.bc | FileCheck %s 10 11;--- main.ll 12target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 13target triple = "x86_64-unknown-linux-gnu" 14 15declare void @cleanupret() 16declare void @catchret() 17declare void @resume() 18 19; Functions can have mayThrow instructions but also be marked noUnwind 20; if they have terminate semantics (e.g. noexcept). In such cases 21; propagation trusts the original noUnwind value in the function summary 22declare void @cleanupret_nounwind() 23 24; CHECK: define void @caller() [[ATTR_MAYTHROW:#[0-9]+]] 25define void @caller() { 26 call void @cleanupret() 27 ret void 28} 29 30; CHECK: define void @caller1() [[ATTR_MAYTHROW:#[0-9]+]] 31define void @caller1() { 32 call void @catchret() 33 ret void 34} 35 36; CHECK: define void @caller2() [[ATTR_MAYTHROW:#[0-9]+]] 37define void @caller2() { 38 call void @resume() 39 ret void 40} 41 42; CHECK: define void @caller_nounwind() [[ATTR_NOUNWIND:#[0-9]+]] 43define void @caller_nounwind() { 44 call void @cleanupret_nounwind() 45 ret void 46} 47 48; CHECK-DAG: attributes [[ATTR_NOUNWIND]] = { norecurse nounwind } 49; CHECK-DAG: attributes [[ATTR_MAYTHROW]] = { norecurse } 50 51; SUMMARY-DAG: = gv: (name: "cleanupret", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) 52; SUMMARY-DAG: = gv: (name: "resume", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) 53; SUMMARY-DAG: = gv: (name: "catchret", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) 54 55;--- callees.ll 56target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 57target triple = "x86_64-unknown-linux-gnu" 58attributes #0 = { nounwind } 59 60define void @nonThrowing() #0 { 61 ret void 62} 63 64declare i32 @__gxx_personality_v0(...) 65 66define void @cleanupret() personality ptr @__gxx_personality_v0 { 67entry: 68 invoke void @nonThrowing() 69 to label %exit unwind label %pad 70pad: 71 %cp = cleanuppad within none [i7 4] 72 cleanupret from %cp unwind to caller 73exit: 74 ret void 75} 76 77define void @catchret() personality ptr @__gxx_personality_v0 { 78entry: 79 invoke void @nonThrowing() 80 to label %exit unwind label %pad 81pad: 82 %cs1 = catchswitch within none [label %catch] unwind to caller 83catch: 84 %cp = catchpad within %cs1 [i7 4] 85 catchret from %cp to label %exit 86exit: 87 ret void 88} 89 90define void @resume() uwtable optsize ssp personality ptr @__gxx_personality_v0 { 91entry: 92 invoke void @nonThrowing() 93 to label %try.cont unwind label %lpad 94 95try.cont: ; preds = %entry, %invoke.cont4 96 ret void 97 98lpad: ; preds = %entry 99 %exn = landingpad {ptr, i32} 100 cleanup 101 resume { ptr, i32 } %exn 102} 103 104define void @cleanupret_nounwind() #0 personality ptr @__gxx_personality_v0 { 105entry: 106 invoke void @nonThrowing() 107 to label %exit unwind label %pad 108pad: 109 %cp = cleanuppad within none [i7 4] 110 cleanupret from %cp unwind to caller 111exit: 112 ret void 113} 114 115attributes #0 = { nounwind } 116