diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def index 5f6af3514fc24902b1f27e86324cba6fa72e1144..f9f7524686db61556958e9d0b8c976977e7eb4ae 100644 --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def @@ -151,6 +151,16 @@ TLI_DEFINE_ENUM_INTERNAL(under_IO_putc) TLI_DEFINE_STRING_INTERNAL("_IO_putc") TLI_DEFINE_SIG_INTERNAL(Int, Int, Ptr) +/// void _Unwind_Resume(_Unwind_Exception *); +TLI_DEFINE_ENUM_INTERNAL(_Unwind_Resume) +TLI_DEFINE_STRING_INTERNAL("_Unwind_Resume") +TLI_DEFINE_SIG_INTERNAL(Void, Ptr) + +/// void std::terminate(); +TLI_DEFINE_ENUM_INTERNAL(terminate) +TLI_DEFINE_STRING_INTERNAL("_ZSt9terminatev") +TLI_DEFINE_SIG_INTERNAL(Void) + /// void operator delete[](void*); TLI_DEFINE_ENUM_INTERNAL(ZdaPv) TLI_DEFINE_STRING_INTERNAL("_ZdaPv") @@ -421,11 +431,21 @@ TLI_DEFINE_ENUM_INTERNAL(cospif) TLI_DEFINE_STRING_INTERNAL("__cospif") TLI_DEFINE_SIG_INTERNAL(Flt, Flt) +/// void * __cxa_allocate_exception(size_t thrown_size) +TLI_DEFINE_ENUM_INTERNAL(__cxa_allocate_exception) +TLI_DEFINE_STRING_INTERNAL("__cxa_allocate_exception") +TLI_DEFINE_SIG_INTERNAL(Ptr, SizeT) + /// int __cxa_atexit(void (*f)(void *), void *p, void *d); TLI_DEFINE_ENUM_INTERNAL(cxa_atexit) TLI_DEFINE_STRING_INTERNAL("__cxa_atexit") TLI_DEFINE_SIG_INTERNAL(Int, Ptr, Ptr, Ptr) +/// void *__cxa_begin_catch(void *e) +TLI_DEFINE_ENUM_INTERNAL(__cxa_begin_catch) +TLI_DEFINE_STRING_INTERNAL("__cxa_begin_catch") +TLI_DEFINE_SIG_INTERNAL(Ptr, Ptr) + /// void __cxa_guard_abort(guard_t *guard); /// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi. TLI_DEFINE_ENUM_INTERNAL(cxa_guard_abort) @@ -442,6 +462,11 @@ TLI_DEFINE_ENUM_INTERNAL(cxa_guard_release) TLI_DEFINE_STRING_INTERNAL("__cxa_guard_release") TLI_DEFINE_SIG_INTERNAL(Void, Ptr) +/// void __cxa_throw(void *, void *, void (*)(void *)); +TLI_DEFINE_ENUM_INTERNAL(cxa_throw) +TLI_DEFINE_STRING_INTERNAL("__cxa_throw") +TLI_DEFINE_SIG_INTERNAL(Void, Ptr, Ptr, Ptr) + /// double __exp10_finite(double x); TLI_DEFINE_ENUM_INTERNAL(exp10_finite) TLI_DEFINE_STRING_INTERNAL("__exp10_finite") diff --git a/llvm/lib/CodeGen/DwarfEHPrepare.cpp b/llvm/lib/CodeGen/DwarfEHPrepare.cpp index aa81f618dc59f4b0f2299b40291a76a325aefce7..a11327f88956b9bc1f29359c1e02ac9a1d25cfa6 100644 --- a/llvm/lib/CodeGen/DwarfEHPrepare.cpp +++ b/llvm/lib/CodeGen/DwarfEHPrepare.cpp @@ -234,6 +234,10 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls() { } RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy); + // If -fno-plt is enabled, add NonLazyBind for this library call. + if (F.getParent()->getRtLibUseGOT()) + (cast(RewindFunction.getCallee()))->addFnAttr(Attribute::NonLazyBind); + // Create the basic block where the _Unwind_Resume call will live. if (ResumesLeft == 1) { // Instead of creating a new BB and PHI node, just append the call to diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp index 89872259cfcaf30e82a782a91bcfbb6f2a4218f8..9728c89ed263a7c18ef898656b80ccbce60c2be4 100644 --- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -142,9 +142,20 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB, // Try looking through a bitcast from one function type to another. // Commonly happens with calls to objc_msgSend(). const Value *CalleeV = CB.getCalledOperand()->stripPointerCasts(); - if (const Function *F = dyn_cast(CalleeV)) - Info.Callee = MachineOperand::CreateGA(F, 0); - else + if (const Function *F = dyn_cast(CalleeV)) { + if (F->hasFnAttribute(Attribute::NonLazyBind)) { + LLT Ty = getLLTForType(*F->getType(), DL); + Register Reg = MIRBuilder.buildGlobalValue(Ty, F).getReg(0); + Info.Callee = MachineOperand::CreateReg(Reg, false); + } else { + Info.Callee = MachineOperand::CreateGA(F, 0); + } + } else if (isa(CalleeV) || isa(CalleeV)) { + // IR IFuncs and Aliases can't be forward declared (only defined), so the + // callee must be in the same TU and therefore we can direct-call it without + // worrying about it being out of range. + Info.Callee = MachineOperand::CreateGA(cast(CalleeV), 0); + } else Info.Callee = MachineOperand::CreateReg(GetCalleeReg(), false); Register ReturnHintAlignReg; diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index 41f9303da1bf5048fb60c70fb5e81b990e29ec4e..6174fa478bae94f584be2c311c1f9d396e2747a2 100644 --- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp +++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp @@ -3181,6 +3181,11 @@ bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) { if (CM == CodeModel::Large && !Subtarget->isTargetMachO()) return false; + // ELF -fno-plt compiled intrinsic calls do not have the nonlazybind + // attribute. Check "RtLibUseGOT" instead. + if (MF->getFunction().getParent()->getRtLibUseGOT()) + return false; + // Let SDISel handle vararg functions. if (IsVarArg) return false; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 6f2058c721577c72ad8f7a91cf6692da08902e49..7803a91c1c8ff8dfab746f8313031289ca59ef78 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -7567,13 +7567,14 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0); } } else if (auto *S = dyn_cast(Callee)) { - if (getTargetMachine().getCodeModel() == CodeModel::Large && - Subtarget->isTargetMachO()) { - const char *Sym = S->getSymbol(); + bool UseGot = (getTargetMachine().getCodeModel() == CodeModel::Large && + Subtarget->isTargetMachO()) || + MF.getFunction().getParent()->getRtLibUseGOT(); + const char *Sym = S->getSymbol(); + if (UseGot) { Callee = DAG.getTargetExternalSymbol(Sym, PtrVT, AArch64II::MO_GOT); Callee = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, Callee); } else { - const char *Sym = S->getSymbol(); Callee = DAG.getTargetExternalSymbol(Sym, PtrVT, 0); } } diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp index 245ed812ae9e4052b61cef7c2c8e67aa6e547b1a..3282791c69275a6759f0d56fe4071ed12c5d547a 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp @@ -26,6 +26,8 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/Support/AArch64TargetParser.h" #include "llvm/Support/TargetParser.h" +#include "llvm/IR/Module.h" +#include "llvm/TargetParser/AArch64TargetParser.h" using namespace llvm; @@ -44,10 +46,10 @@ static cl::opt UseAddressTopByteIgnored("aarch64-use-tbi", cl::desc("Assume that top byte of " "an address is ignored"), cl::init(false), cl::Hidden); -static cl::opt - UseNonLazyBind("aarch64-enable-nonlazybind", - cl::desc("Call nonlazybind functions via direct GOT load"), - cl::init(false), cl::Hidden); +static cl::opt MachOUseNonLazyBind( + "aarch64-macho-enable-nonlazybind", + cl::desc("Call nonlazybind functions via direct GOT load for Mach-O"), + cl::Hidden); static cl::opt UseAA("aarch64-use-aa", cl::init(true), cl::desc("Enable the use of AA during codegen.")); @@ -401,8 +403,14 @@ unsigned AArch64Subtarget::classifyGlobalFunctionReference( // NonLazyBind goes via GOT unless we know it's available locally. auto *F = dyn_cast(GV); - if (UseNonLazyBind && F && F->hasFnAttribute(Attribute::NonLazyBind) && - !TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) +// Check if NonLazyBind should go via GOT: +// 1. The target is not MachO, or MachO uses NonLazyBind. +// 2. The function's parent module requires GOT for runtime library calls. +// 3. The symbol is not assumed to be DSO-local. +// 4. The symbol does not have local linkage. + if ((!isTargetMachO() || MachOUseNonLazyBind) && F && + F->getParent()->getRtLibUseGOT() && + !(TM.shouldAssumeDSOLocal(*GV->getParent(), GV) || GV->hasLocalLinkage())) return AArch64II::MO_GOT; if (getTargetTriple().isOSWindows()) { diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp index e20b0f4a9e3f410e199ef483223b41be60dd3e85..9fcae88b794fdc37cd1f80c27e3907c83b19002f 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp @@ -1181,8 +1181,17 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, !Subtarget.noBTIAtReturnTwice() && MF.getInfo()->branchTargetEnforcement()) Opc = AArch64::BLR_BTI; - else + else { + // For an intrinsic call (e.g. memset), use GOT if "RtLibUseGOT" (-fno-plt) + // is set. + if (Info.Callee.isSymbol() && F.getParent()->getRtLibUseGOT()) { + auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_GLOBAL_VALUE); + DstOp(getLLTForType(*F.getType(), DL)).addDefToMIB(MRI, MIB); + MIB.addExternalSymbol(Info.Callee.getSymbolName(), AArch64II::MO_GOT); + Info.Callee = MachineOperand::CreateReg(MIB.getReg(0), false); + } Opc = getCallOpcode(MF, Info.Callee.isReg(), false); + } auto MIB = MIRBuilder.buildInstrNoInsert(Opc); unsigned CalleeOpNo = 0; diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index 58e89010c1390c77531bd6dbffb10573868ff46f..e6efb8f9722c2f29d9bfc28ec0dd5c28ebbb9b30 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -2781,11 +2781,19 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { } case TargetOpcode::G_GLOBAL_VALUE: { - auto GV = I.getOperand(1).getGlobal(); - if (GV->isThreadLocal()) - return selectTLSGlobalValue(I, MRI); + const GlobalValue *GV = nullptr; + unsigned OpFlags; + if (I.getOperand(1).isSymbol()) { + OpFlags = I.getOperand(1).getTargetFlags(); + // Currently only used by "RtLibUseGOT". + assert(OpFlags == AArch64II::MO_GOT); + } else { + GV = I.getOperand(1).getGlobal(); + if (GV->isThreadLocal()) + return selectTLSGlobalValue(I, MRI); + OpFlags = STI.ClassifyGlobalReference(GV, TM); + } - unsigned OpFlags = STI.ClassifyGlobalReference(GV, TM); if (OpFlags & AArch64II::MO_GOT) { I.setDesc(TII.get(AArch64::LOADgot)); I.getOperand(1).setTargetFlags(OpFlags); diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp index 186d0ed35d56f2d3e4e9ec192f47e463a92df14f..5f728b997dcb36227785b10976128ffbbcdea2e5 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -997,6 +997,9 @@ bool AArch64LegalizerInfo::legalizeSmallCMGlobalValue( // By splitting this here, we can optimize accesses in the small code model by // folding in the G_ADD_LOW into the load/store offset. auto &GlobalOp = MI.getOperand(1); + // Don't modify an intrinsic call. + if (GlobalOp.isSymbol()) + return true; const auto* GV = GlobalOp.getGlobal(); if (GV->isThreadLocal()) return true; // Don't want to modify TLS vars. diff --git a/llvm/test/CodeGen/AArch64/call-rv-marker.ll b/llvm/test/CodeGen/AArch64/call-rv-marker.ll index fc06809ad09fb670c4aafe8bb54b4bbb47e6c835..3579d2c9f2a594db21330764eef80a45574e7a44 100644 --- a/llvm/test/CodeGen/AArch64/call-rv-marker.ll +++ b/llvm/test/CodeGen/AArch64/call-rv-marker.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -o - %s | FileCheck --check-prefix=SELDAG --check-prefix=CHECK %s ; RUN: llc -global-isel -o - %s | FileCheck --check-prefix=GISEL --check-prefix=CHECK %s @@ -25,37 +26,93 @@ declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) @fptr = dso_local global ptr null, align 8 define dso_local ptr @rv_marker_1_retain() { -; CHECK-LABEL: _rv_marker_1_retain: -; CHECK: bl _foo1 -; CHECK-NEXT: mov x29, x29 -; CHECK-NEXT: bl _objc_retainAutoreleasedReturnValue +; SELDAG-LABEL: rv_marker_1_retain: +; SELDAG: ; %bb.0: ; %entry +; SELDAG-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill +; SELDAG-NEXT: .cfi_def_cfa_offset 16 +; SELDAG-NEXT: .cfi_offset w30, -8 +; SELDAG-NEXT: .cfi_offset w29, -16 +; SELDAG-NEXT: bl _foo1 +; SELDAG-NEXT: mov x29, x29 +; SELDAG-NEXT: bl _objc_retainAutoreleasedReturnValue +; SELDAG-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload +; SELDAG-NEXT: ret ; +; GISEL-LABEL: rv_marker_1_retain: +; GISEL: ; %bb.0: ; %entry +; GISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 16 +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset w29, -16 +; GISEL-NEXT: bl _foo1 +; GISEL-NEXT: mov x29, x29 +; GISEL-NEXT: bl _objc_retainAutoreleasedReturnValue +; GISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload +; GISEL-NEXT: ret entry: %call = call ptr @foo1() [ "clang.arc.attachedcall"(ptr @objc_retainAutoreleasedReturnValue) ] ret ptr %call } define dso_local ptr @rv_marker_1_unsafeClaim() { -; CHECK-LABEL: _rv_marker_1_unsafeClaim: -; CHECK: bl _foo1 -; CHECK-NEXT: mov x29, x29 -; CHECK-NEXT: bl _objc_unsafeClaimAutoreleasedReturnValue +; SELDAG-LABEL: rv_marker_1_unsafeClaim: +; SELDAG: ; %bb.0: ; %entry +; SELDAG-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill +; SELDAG-NEXT: .cfi_def_cfa_offset 16 +; SELDAG-NEXT: .cfi_offset w30, -8 +; SELDAG-NEXT: .cfi_offset w29, -16 +; SELDAG-NEXT: bl _foo1 +; SELDAG-NEXT: mov x29, x29 +; SELDAG-NEXT: bl _objc_unsafeClaimAutoreleasedReturnValue +; SELDAG-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload +; SELDAG-NEXT: ret ; +; GISEL-LABEL: rv_marker_1_unsafeClaim: +; GISEL: ; %bb.0: ; %entry +; GISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 16 +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset w29, -16 +; GISEL-NEXT: bl _foo1 +; GISEL-NEXT: mov x29, x29 +; GISEL-NEXT: bl _objc_unsafeClaimAutoreleasedReturnValue +; GISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload +; GISEL-NEXT: ret entry: %call = call ptr @foo1() [ "clang.arc.attachedcall"(ptr @objc_unsafeClaimAutoreleasedReturnValue) ] ret ptr %call } define dso_local void @rv_marker_2_select(i32 %c) { -; CHECK-LABEL: _rv_marker_2_select: -; SELDAG: cinc w0, w8, eq -; GISEL: csinc w0, w8, wzr, eq -; CHECK-NEXT: bl _foo0 -; CHECK-NEXT: mov x29, x29 -; CHECK-NEXT: bl _objc_retainAutoreleasedReturnValue -; CHECK-NEXT: ldp x29, x30, [sp], #16 -; CHECK-NEXT: b _foo2 +; SELDAG-LABEL: rv_marker_2_select: +; SELDAG: ; %bb.0: ; %entry +; SELDAG-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill +; SELDAG-NEXT: .cfi_def_cfa_offset 16 +; SELDAG-NEXT: .cfi_offset w30, -8 +; SELDAG-NEXT: .cfi_offset w29, -16 +; SELDAG-NEXT: mov w8, #1 +; SELDAG-NEXT: cmp w0, #0 +; SELDAG-NEXT: cinc w0, w8, eq +; SELDAG-NEXT: bl _foo0 +; SELDAG-NEXT: mov x29, x29 +; SELDAG-NEXT: bl _objc_retainAutoreleasedReturnValue +; SELDAG-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload +; SELDAG-NEXT: b _foo2 ; +; GISEL-LABEL: rv_marker_2_select: +; GISEL: ; %bb.0: ; %entry +; GISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 16 +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset w29, -16 +; GISEL-NEXT: mov w8, #2 +; GISEL-NEXT: cmp w0, #0 +; GISEL-NEXT: csinc w0, w8, wzr, eq +; GISEL-NEXT: bl _foo0 +; GISEL-NEXT: mov x29, x29 +; GISEL-NEXT: bl _objc_retainAutoreleasedReturnValue +; GISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload +; GISEL-NEXT: b _foo2 entry: %tobool.not = icmp eq i32 %c, 0 %.sink = select i1 %tobool.not, i32 2, i32 1 @@ -65,11 +122,131 @@ entry: } define dso_local void @rv_marker_3() personality ptr @__gxx_personality_v0 { -; CHECK-LABEL: _rv_marker_3: -; CHECK: bl _foo1 -; CHECK-NEXT: mov x29, x29 -; CHECK-NEXT: bl _objc_retainAutoreleasedReturnValue +; SELDAG-LABEL: rv_marker_3: +; SELDAG: Lfunc_begin0: +; SELDAG-NEXT: .cfi_startproc +; SELDAG-NEXT: .cfi_personality 155, ___gxx_personality_v0 +; SELDAG-NEXT: .cfi_lsda 16, Lexception0 +; SELDAG-NEXT: ; %bb.0: ; %entry +; SELDAG-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill +; SELDAG-NEXT: .cfi_def_cfa_offset 32 +; SELDAG-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill +; SELDAG-NEXT: .cfi_offset w30, -8 +; SELDAG-NEXT: .cfi_offset w29, -16 +; SELDAG-NEXT: .cfi_offset w19, -24 +; SELDAG-NEXT: .cfi_offset w20, -32 +; SELDAG-NEXT: bl _foo1 +; SELDAG-NEXT: mov x29, x29 +; SELDAG-NEXT: bl _objc_retainAutoreleasedReturnValue +; SELDAG-NEXT: mov x19, x0 +; SELDAG-NEXT: Ltmp0: +; SELDAG-NEXT: bl _objc_object +; SELDAG-NEXT: Ltmp1: +; SELDAG-NEXT: ; %bb.1: ; %invoke.cont +; SELDAG-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload +; SELDAG-NEXT: mov x0, x19 +; SELDAG-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload +; SELDAG-NEXT: b _objc_release +; SELDAG-NEXT: LBB3_2: ; %lpad +; SELDAG-NEXT: Ltmp2: +; SELDAG-NEXT: mov x20, x0 +; SELDAG-NEXT: mov x0, x19 +; SELDAG-NEXT: bl _objc_release +; SELDAG-NEXT: mov x0, x20 +; SELDAG-NEXT: bl __Unwind_Resume +; SELDAG-NEXT: Lfunc_end0: +; SELDAG-NEXT: .cfi_endproc +; SELDAG-NEXT: .section __TEXT,__gcc_except_tab +; SELDAG-NEXT: .p2align 2, 0x0 +; SELDAG-NEXT: GCC_except_table3: +; SELDAG-NEXT: Lexception0: +; SELDAG-NEXT: .byte 255 ; @LPStart Encoding = omit +; SELDAG-NEXT: .byte 255 ; @TType Encoding = omit +; SELDAG-NEXT: .byte 1 ; Call site Encoding = uleb128 +; SELDAG-NEXT: .uleb128 Lcst_end0-Lcst_begin0 +; SELDAG-NEXT: Lcst_begin0: +; SELDAG-NEXT: .uleb128 Lfunc_begin0-Lfunc_begin0 ; >> Call Site 1 << +; SELDAG-NEXT: .uleb128 Ltmp0-Lfunc_begin0 ; Call between Lfunc_begin0 and Ltmp0 +; SELDAG-NEXT: .byte 0 ; has no landing pad +; SELDAG-NEXT: .byte 0 ; On action: cleanup +; SELDAG-NEXT: .uleb128 Ltmp0-Lfunc_begin0 ; >> Call Site 2 << +; SELDAG-NEXT: .uleb128 Ltmp1-Ltmp0 ; Call between Ltmp0 and Ltmp1 +; SELDAG-NEXT: .uleb128 Ltmp2-Lfunc_begin0 ; jumps to Ltmp2 +; SELDAG-NEXT: .byte 0 ; On action: cleanup +; SELDAG-NEXT: .uleb128 Ltmp1-Lfunc_begin0 ; >> Call Site 3 << +; SELDAG-NEXT: .uleb128 Lfunc_end0-Ltmp1 ; Call between Ltmp1 and Lfunc_end0 +; SELDAG-NEXT: .byte 0 ; has no landing pad +; SELDAG-NEXT: .byte 0 ; On action: cleanup +; SELDAG-NEXT: Lcst_end0: +; SELDAG-NEXT: .p2align 2, 0x0 ; +; GISEL-LABEL: rv_marker_3: +; GISEL: Lfunc_begin0: +; GISEL-NEXT: .cfi_startproc +; GISEL-NEXT: .cfi_personality 155, ___gxx_personality_v0 +; GISEL-NEXT: .cfi_lsda 16, Lexception0 +; GISEL-NEXT: ; %bb.0: ; %entry +; GISEL-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 32 +; GISEL-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset w29, -16 +; GISEL-NEXT: .cfi_offset w19, -24 +; GISEL-NEXT: .cfi_offset w20, -32 +; GISEL-NEXT: bl _foo1 +; GISEL-NEXT: mov x29, x29 +; GISEL-NEXT: bl _objc_retainAutoreleasedReturnValue +; GISEL-NEXT: mov x19, x0 +; GISEL-NEXT: Ltmp0: +; GISEL-NEXT: bl _objc_object +; GISEL-NEXT: Ltmp1: +; GISEL-NEXT: ; %bb.1: ; %invoke.cont +; GISEL-NEXT: Lloh0: +; GISEL-NEXT: adrp x1, _objc_release@GOTPAGE +; GISEL-NEXT: mov x0, x19 +; GISEL-NEXT: Lloh1: +; GISEL-NEXT: ldr x1, [x1, _objc_release@GOTPAGEOFF] +; GISEL-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload +; GISEL-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload +; GISEL-NEXT: br x1 +; GISEL-NEXT: LBB3_2: ; %lpad +; GISEL-NEXT: Ltmp2: +; GISEL-NEXT: Lloh2: +; GISEL-NEXT: adrp x8, _objc_release@GOTPAGE +; GISEL-NEXT: mov x20, x0 +; GISEL-NEXT: mov x0, x19 +; GISEL-NEXT: Lloh3: +; GISEL-NEXT: ldr x8, [x8, _objc_release@GOTPAGEOFF] +; GISEL-NEXT: blr x8 +; GISEL-NEXT: mov x0, x20 +; GISEL-NEXT: bl __Unwind_Resume +; GISEL-NEXT: .loh AdrpLdrGot Lloh0, Lloh1 +; GISEL-NEXT: .loh AdrpLdrGot Lloh2, Lloh3 +; GISEL-NEXT: Lfunc_end0: +; GISEL-NEXT: .cfi_endproc +; GISEL-NEXT: .section __TEXT,__gcc_except_tab +; GISEL-NEXT: .p2align 2, 0x0 +; GISEL-NEXT: GCC_except_table3: +; GISEL-NEXT: Lexception0: +; GISEL-NEXT: .byte 255 ; @LPStart Encoding = omit +; GISEL-NEXT: .byte 255 ; @TType Encoding = omit +; GISEL-NEXT: .byte 1 ; Call site Encoding = uleb128 +; GISEL-NEXT: .uleb128 Lcst_end0-Lcst_begin0 +; GISEL-NEXT: Lcst_begin0: +; GISEL-NEXT: .uleb128 Lfunc_begin0-Lfunc_begin0 ; >> Call Site 1 << +; GISEL-NEXT: .uleb128 Ltmp0-Lfunc_begin0 ; Call between Lfunc_begin0 and Ltmp0 +; GISEL-NEXT: .byte 0 ; has no landing pad +; GISEL-NEXT: .byte 0 ; On action: cleanup +; GISEL-NEXT: .uleb128 Ltmp0-Lfunc_begin0 ; >> Call Site 2 << +; GISEL-NEXT: .uleb128 Ltmp1-Ltmp0 ; Call between Ltmp0 and Ltmp1 +; GISEL-NEXT: .uleb128 Ltmp2-Lfunc_begin0 ; jumps to Ltmp2 +; GISEL-NEXT: .byte 0 ; On action: cleanup +; GISEL-NEXT: .uleb128 Ltmp1-Lfunc_begin0 ; >> Call Site 3 << +; GISEL-NEXT: .uleb128 Lfunc_end0-Ltmp1 ; Call between Ltmp1 and Lfunc_end0 +; GISEL-NEXT: .byte 0 ; has no landing pad +; GISEL-NEXT: .byte 0 ; On action: cleanup +; GISEL-NEXT: Lcst_end0: +; GISEL-NEXT: .p2align 2, 0x0 entry: %call = call ptr @foo1() [ "clang.arc.attachedcall"(ptr @objc_retainAutoreleasedReturnValue) ] invoke void @objc_object(ptr %call) #5 @@ -87,13 +264,161 @@ lpad: ; preds = %entry } define dso_local void @rv_marker_4() personality ptr @__gxx_personality_v0 { -; CHECK-LABEL: _rv_marker_4: -; CHECK: Ltmp3: -; CHECK-NEXT: bl _foo1 -; CHECK-NEXT: mov x29, x29 -; CHECK-NEXT: bl _objc_retainAutoreleasedReturnValue -; CHECK-NEXT: Ltmp4: +; SELDAG-LABEL: rv_marker_4: +; SELDAG: Lfunc_begin1: +; SELDAG-NEXT: .cfi_startproc +; SELDAG-NEXT: .cfi_personality 155, ___gxx_personality_v0 +; SELDAG-NEXT: .cfi_lsda 16, Lexception1 +; SELDAG-NEXT: ; %bb.0: ; %entry +; SELDAG-NEXT: sub sp, sp, #48 +; SELDAG-NEXT: .cfi_def_cfa_offset 48 +; SELDAG-NEXT: stp x20, x19, [sp, #16] ; 16-byte Folded Spill +; SELDAG-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill +; SELDAG-NEXT: .cfi_offset w30, -8 +; SELDAG-NEXT: .cfi_offset w29, -16 +; SELDAG-NEXT: .cfi_offset w19, -24 +; SELDAG-NEXT: .cfi_offset w20, -32 +; SELDAG-NEXT: Ltmp3: +; SELDAG-NEXT: bl _foo1 +; SELDAG-NEXT: mov x29, x29 +; SELDAG-NEXT: bl _objc_retainAutoreleasedReturnValue +; SELDAG-NEXT: Ltmp4: +; SELDAG-NEXT: ; %bb.1: ; %invoke.cont +; SELDAG-NEXT: Ltmp6: +; SELDAG-NEXT: mov x19, x0 +; SELDAG-NEXT: bl _objc_object +; SELDAG-NEXT: Ltmp7: +; SELDAG-NEXT: ; %bb.2: ; %invoke.cont2 +; SELDAG-NEXT: mov x0, x19 +; SELDAG-NEXT: bl _objc_release +; SELDAG-NEXT: add x0, sp, #8 +; SELDAG-NEXT: bl __ZN1SD1Ev +; SELDAG-NEXT: ldp x29, x30, [sp, #32] ; 16-byte Folded Reload +; SELDAG-NEXT: ldp x20, x19, [sp, #16] ; 16-byte Folded Reload +; SELDAG-NEXT: add sp, sp, #48 +; SELDAG-NEXT: ret +; SELDAG-NEXT: LBB4_3: ; %lpad1 +; SELDAG-NEXT: Ltmp8: +; SELDAG-NEXT: mov x20, x0 +; SELDAG-NEXT: mov x0, x19 +; SELDAG-NEXT: bl _objc_release +; SELDAG-NEXT: b LBB4_5 +; SELDAG-NEXT: LBB4_4: ; %lpad +; SELDAG-NEXT: Ltmp5: +; SELDAG-NEXT: mov x20, x0 +; SELDAG-NEXT: LBB4_5: ; %ehcleanup +; SELDAG-NEXT: add x0, sp, #8 +; SELDAG-NEXT: bl __ZN1SD1Ev +; SELDAG-NEXT: mov x0, x20 +; SELDAG-NEXT: bl __Unwind_Resume +; SELDAG-NEXT: Lfunc_end1: +; SELDAG-NEXT: .cfi_endproc +; SELDAG-NEXT: .section __TEXT,__gcc_except_tab +; SELDAG-NEXT: .p2align 2, 0x0 +; SELDAG-NEXT: GCC_except_table4: +; SELDAG-NEXT: Lexception1: +; SELDAG-NEXT: .byte 255 ; @LPStart Encoding = omit +; SELDAG-NEXT: .byte 255 ; @TType Encoding = omit +; SELDAG-NEXT: .byte 1 ; Call site Encoding = uleb128 +; SELDAG-NEXT: .uleb128 Lcst_end1-Lcst_begin1 +; SELDAG-NEXT: Lcst_begin1: +; SELDAG-NEXT: .uleb128 Ltmp3-Lfunc_begin1 ; >> Call Site 1 << +; SELDAG-NEXT: .uleb128 Ltmp4-Ltmp3 ; Call between Ltmp3 and Ltmp4 +; SELDAG-NEXT: .uleb128 Ltmp5-Lfunc_begin1 ; jumps to Ltmp5 +; SELDAG-NEXT: .byte 0 ; On action: cleanup +; SELDAG-NEXT: .uleb128 Ltmp6-Lfunc_begin1 ; >> Call Site 2 << +; SELDAG-NEXT: .uleb128 Ltmp7-Ltmp6 ; Call between Ltmp6 and Ltmp7 +; SELDAG-NEXT: .uleb128 Ltmp8-Lfunc_begin1 ; jumps to Ltmp8 +; SELDAG-NEXT: .byte 0 ; On action: cleanup +; SELDAG-NEXT: .uleb128 Ltmp7-Lfunc_begin1 ; >> Call Site 3 << +; SELDAG-NEXT: .uleb128 Lfunc_end1-Ltmp7 ; Call between Ltmp7 and Lfunc_end1 +; SELDAG-NEXT: .byte 0 ; has no landing pad +; SELDAG-NEXT: .byte 0 ; On action: cleanup +; SELDAG-NEXT: Lcst_end1: +; SELDAG-NEXT: .p2align 2, 0x0 ; +; GISEL-LABEL: rv_marker_4: +; GISEL: Lfunc_begin1: +; GISEL-NEXT: .cfi_startproc +; GISEL-NEXT: .cfi_personality 155, ___gxx_personality_v0 +; GISEL-NEXT: .cfi_lsda 16, Lexception1 +; GISEL-NEXT: ; %bb.0: ; %entry +; GISEL-NEXT: sub sp, sp, #48 +; GISEL-NEXT: .cfi_def_cfa_offset 48 +; GISEL-NEXT: stp x20, x19, [sp, #16] ; 16-byte Folded Spill +; GISEL-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset w29, -16 +; GISEL-NEXT: .cfi_offset w19, -24 +; GISEL-NEXT: .cfi_offset w20, -32 +; GISEL-NEXT: Ltmp3: +; GISEL-NEXT: bl _foo1 +; GISEL-NEXT: mov x29, x29 +; GISEL-NEXT: bl _objc_retainAutoreleasedReturnValue +; GISEL-NEXT: Ltmp4: +; GISEL-NEXT: ; %bb.1: ; %invoke.cont +; GISEL-NEXT: Ltmp6: +; GISEL-NEXT: mov x19, x0 +; GISEL-NEXT: bl _objc_object +; GISEL-NEXT: Ltmp7: +; GISEL-NEXT: ; %bb.2: ; %invoke.cont2 +; GISEL-NEXT: Lloh4: +; GISEL-NEXT: adrp x8, _objc_release@GOTPAGE +; GISEL-NEXT: mov x0, x19 +; GISEL-NEXT: Lloh5: +; GISEL-NEXT: ldr x8, [x8, _objc_release@GOTPAGEOFF] +; GISEL-NEXT: blr x8 +; GISEL-NEXT: add x0, sp, #15 +; GISEL-NEXT: bl __ZN1SD1Ev +; GISEL-NEXT: ldp x29, x30, [sp, #32] ; 16-byte Folded Reload +; GISEL-NEXT: ldp x20, x19, [sp, #16] ; 16-byte Folded Reload +; GISEL-NEXT: add sp, sp, #48 +; GISEL-NEXT: ret +; GISEL-NEXT: LBB4_3: ; %lpad1 +; GISEL-NEXT: Ltmp8: +; GISEL-NEXT: Lloh6: +; GISEL-NEXT: adrp x8, _objc_release@GOTPAGE +; GISEL-NEXT: mov x20, x0 +; GISEL-NEXT: mov x0, x19 +; GISEL-NEXT: Lloh7: +; GISEL-NEXT: ldr x8, [x8, _objc_release@GOTPAGEOFF] +; GISEL-NEXT: blr x8 +; GISEL-NEXT: b LBB4_5 +; GISEL-NEXT: LBB4_4: ; %lpad +; GISEL-NEXT: Ltmp5: +; GISEL-NEXT: mov x20, x0 +; GISEL-NEXT: LBB4_5: ; %ehcleanup +; GISEL-NEXT: add x0, sp, #15 +; GISEL-NEXT: bl __ZN1SD1Ev +; GISEL-NEXT: mov x0, x20 +; GISEL-NEXT: bl __Unwind_Resume +; GISEL-NEXT: .loh AdrpLdrGot Lloh4, Lloh5 +; GISEL-NEXT: .loh AdrpLdrGot Lloh6, Lloh7 +; GISEL-NEXT: Lfunc_end1: +; GISEL-NEXT: .cfi_endproc +; GISEL-NEXT: .section __TEXT,__gcc_except_tab +; GISEL-NEXT: .p2align 2, 0x0 +; GISEL-NEXT: GCC_except_table4: +; GISEL-NEXT: Lexception1: +; GISEL-NEXT: .byte 255 ; @LPStart Encoding = omit +; GISEL-NEXT: .byte 255 ; @TType Encoding = omit +; GISEL-NEXT: .byte 1 ; Call site Encoding = uleb128 +; GISEL-NEXT: .uleb128 Lcst_end1-Lcst_begin1 +; GISEL-NEXT: Lcst_begin1: +; GISEL-NEXT: .uleb128 Ltmp3-Lfunc_begin1 ; >> Call Site 1 << +; GISEL-NEXT: .uleb128 Ltmp4-Ltmp3 ; Call between Ltmp3 and Ltmp4 +; GISEL-NEXT: .uleb128 Ltmp5-Lfunc_begin1 ; jumps to Ltmp5 +; GISEL-NEXT: .byte 0 ; On action: cleanup +; GISEL-NEXT: .uleb128 Ltmp6-Lfunc_begin1 ; >> Call Site 2 << +; GISEL-NEXT: .uleb128 Ltmp7-Ltmp6 ; Call between Ltmp6 and Ltmp7 +; GISEL-NEXT: .uleb128 Ltmp8-Lfunc_begin1 ; jumps to Ltmp8 +; GISEL-NEXT: .byte 0 ; On action: cleanup +; GISEL-NEXT: .uleb128 Ltmp7-Lfunc_begin1 ; >> Call Site 3 << +; GISEL-NEXT: .uleb128 Lfunc_end1-Ltmp7 ; Call between Ltmp7 and Lfunc_end1 +; GISEL-NEXT: .byte 0 ; has no landing pad +; GISEL-NEXT: .byte 0 ; On action: cleanup +; GISEL-NEXT: Lcst_end1: +; GISEL-NEXT: .p2align 2, 0x0 entry: %s = alloca %struct.S, align 1 call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %s) #2 @@ -129,11 +454,53 @@ ehcleanup: ; preds = %lpad1, %lpad } define dso_local ptr @rv_marker_5_indirect_call() { -; CHECK-LABEL: _rv_marker_5_indirect_call: -; CHECK: ldr [[ADDR:x[0-9]+]], [ -; CHECK-NEXT: blr [[ADDR]] -; CHECK-NEXT: mov x29, x29 -; CHECK-NEXT: bl _objc_retainAutoreleasedReturnValue +; SELDAG-LABEL: rv_marker_5_indirect_call: +; SELDAG: ; %bb.0: ; %entry +; SELDAG-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill +; SELDAG-NEXT: .cfi_def_cfa_offset 32 +; SELDAG-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill +; SELDAG-NEXT: .cfi_offset w30, -8 +; SELDAG-NEXT: .cfi_offset w29, -16 +; SELDAG-NEXT: .cfi_offset w19, -24 +; SELDAG-NEXT: .cfi_offset w20, -32 +; SELDAG-NEXT: Lloh0: +; SELDAG-NEXT: adrp x8, _fptr@PAGE +; SELDAG-NEXT: Lloh1: +; SELDAG-NEXT: ldr x8, [x8, _fptr@PAGEOFF] +; SELDAG-NEXT: blr x8 +; SELDAG-NEXT: mov x29, x29 +; SELDAG-NEXT: bl _objc_retainAutoreleasedReturnValue +; SELDAG-NEXT: mov x19, x0 +; SELDAG-NEXT: bl _foo2 +; SELDAG-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload +; SELDAG-NEXT: mov x0, x19 +; SELDAG-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload +; SELDAG-NEXT: ret +; SELDAG-NEXT: .loh AdrpLdr Lloh0, Lloh1 +; +; GISEL-LABEL: rv_marker_5_indirect_call: +; GISEL: ; %bb.0: ; %entry +; GISEL-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 32 +; GISEL-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset w29, -16 +; GISEL-NEXT: .cfi_offset w19, -24 +; GISEL-NEXT: .cfi_offset w20, -32 +; GISEL-NEXT: Lloh8: +; GISEL-NEXT: adrp x8, _fptr@PAGE +; GISEL-NEXT: Lloh9: +; GISEL-NEXT: ldr x8, [x8, _fptr@PAGEOFF] +; GISEL-NEXT: blr x8 +; GISEL-NEXT: mov x29, x29 +; GISEL-NEXT: bl _objc_retainAutoreleasedReturnValue +; GISEL-NEXT: mov x19, x0 +; GISEL-NEXT: bl _foo2 +; GISEL-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload +; GISEL-NEXT: mov x0, x19 +; GISEL-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload +; GISEL-NEXT: ret +; GISEL-NEXT: .loh AdrpLdr Lloh8, Lloh9 entry: %0 = load ptr, ptr @fptr, align 8 %call = call ptr %0() [ "clang.arc.attachedcall"(ptr @objc_retainAutoreleasedReturnValue) ] @@ -144,13 +511,35 @@ entry: declare ptr @foo(i64, i64, i64) define dso_local void @rv_marker_multiarg(i64 %a, i64 %b, i64 %c) { -; CHECK-LABEL: _rv_marker_multiarg: -; CHECK: mov [[TMP:x[0-9]+]], x0 -; CHECK-NEXT: mov x0, x2 -; CHECK-NEXT: mov x2, [[TMP]] -; CHECK-NEXT: bl _foo -; CHECK-NEXT: mov x29, x29 -; CHECK-NEXT: bl _objc_retainAutoreleasedReturnValue +; SELDAG-LABEL: rv_marker_multiarg: +; SELDAG: ; %bb.0: +; SELDAG-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill +; SELDAG-NEXT: .cfi_def_cfa_offset 16 +; SELDAG-NEXT: .cfi_offset w30, -8 +; SELDAG-NEXT: .cfi_offset w29, -16 +; SELDAG-NEXT: mov x8, x0 +; SELDAG-NEXT: mov x0, x2 +; SELDAG-NEXT: mov x2, x8 +; SELDAG-NEXT: bl _foo +; SELDAG-NEXT: mov x29, x29 +; SELDAG-NEXT: bl _objc_retainAutoreleasedReturnValue +; SELDAG-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload +; SELDAG-NEXT: ret +; +; GISEL-LABEL: rv_marker_multiarg: +; GISEL: ; %bb.0: +; GISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 16 +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset w29, -16 +; GISEL-NEXT: mov x3, x0 +; GISEL-NEXT: mov x0, x2 +; GISEL-NEXT: mov x2, x3 +; GISEL-NEXT: bl _foo +; GISEL-NEXT: mov x29, x29 +; GISEL-NEXT: bl _objc_retainAutoreleasedReturnValue +; GISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload +; GISEL-NEXT: ret call ptr @foo(i64 %c, i64 %b, i64 %a) [ "clang.arc.attachedcall"(ptr @objc_retainAutoreleasedReturnValue) ] ret void } @@ -158,3 +547,5 @@ define dso_local void @rv_marker_multiarg(i64 %a, i64 %b, i64 %c) { declare ptr @objc_retainAutoreleasedReturnValue(ptr) declare ptr @objc_unsafeClaimAutoreleasedReturnValue(ptr) declare i32 @__gxx_personality_v0(...) +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; CHECK: {{.*}} diff --git a/llvm/test/CodeGen/AArch64/fno-plt.c b/llvm/test/CodeGen/AArch64/fno-plt.c new file mode 100644 index 0000000000000000000000000000000000000000..81ed912ce927e1b3dd3e2071e53efca78b84dc58 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/fno-plt.c @@ -0,0 +1,32 @@ +// RUN: clang %s -shared -fno-plt -O2 -fno-inline -fPIC -o noplt.so +// RUN: llvm-objdump -d noplt.so | FileCheck %s --check-prefix=CHECK-NO-PLT + +// RUN: clang %s -shared -O2 -fno-inline -fPIC -o plt.so +// RUN: llvm-objdump -d plt.so | FileCheck %s --check-prefix=CHECK-PLT + +// CHECK-PLT: bar@plt +// CHECK-PLT: bar1@plt +// CHECK-NO-PLT-NOT: bar@plt +// CHECK-NO-PLT-NOT: bar1@plt +// CHECK-NO-PLT-NOT: bar2@plt + +__attribute__((optnone)) +void bar(int a) { + return; +} + +__attribute__((optnone)) +extern void bar1(int); + +__attribute__((optnone)) +static void bar2(int a) { + return; +} + +void foo(int a) { + bar(a); + bar1(a); + bar2(a); + return; +} + diff --git a/llvm/test/CodeGen/AArch64/fno-plt.cpp b/llvm/test/CodeGen/AArch64/fno-plt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5a1f2f24b376fc59f4fd4197c7f085a1b7ce867 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/fno-plt.cpp @@ -0,0 +1,35 @@ +// RUN: clang -x c++ %s -shared -fno-plt -O2 -fno-inline -fPIC -o noplt.so +// RUN: llvm-objdump -d noplt.so | FileCheck %s --check-prefix=CHECK-NO-PLT + +// RUN: clang -x c++ %s -shared -O0 -fPIC -o plt.so +// RUN: llvm-objdump -d plt.so | FileCheck %s --check-prefix=CHECK-PLT + +// RUN: clang -x c++ %s -shared -O2 -fno-inline -fPIC -o plt.so +// RUN: llvm-objdump -d plt.so | FileCheck %s --check-prefix=CHECK-PLT + +// CHECK-PLT: bar@plt +// CHECK-PLT: bar1@plt +// CHECK-NO-PLT-NOT: bar@plt +// CHECK-NO-PLT-NOT: bar1@plt +// CHECK-NO-PLT-NOT: bar2@plt + +__attribute__((optnone)) +void bar(int a) { + return; +} + +__attribute__((optnone)) +extern void bar1(int); + +__attribute__((optnone)) +static void bar2(int a) { + return; +} + +void foo(int a) { + bar(a); + bar1(a); + bar2(a); + return; +} + diff --git a/llvm/test/CodeGen/AArch64/nonlazybind.ll b/llvm/test/CodeGen/AArch64/nonlazybind.ll index 7f5701495ef9204e5dd18bb35d03fa87b6f39fd4..c5d5b10d64504c610595e393705cd7c03bb6cfae 100644 --- a/llvm/test/CodeGen/AArch64/nonlazybind.ll +++ b/llvm/test/CodeGen/AArch64/nonlazybind.ll @@ -1,40 +1,104 @@ -; RUN: llc -mtriple=aarch64-apple-ios %s -o - -aarch64-enable-nonlazybind | FileCheck %s -; RUN: llc -mtriple=aarch64-apple-ios %s -o - | FileCheck %s --check-prefix=CHECK-NORMAL +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64-apple-ios %s -o - -aarch64-macho-enable-nonlazybind | FileCheck %s --check-prefix=MACHO +; RUN: llc -mtriple=aarch64-apple-ios %s -o - | FileCheck %s --check-prefix=MACHO-NORMAL +; RUN: llc -mtriple=aarch64 -fast-isel %s -o - | FileCheck %s --check-prefixes=ELF,ELF-FI +; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s --check-prefixes=ELF,ELF-SDAG -define void @local() nonlazybind { +declare void @external() nonlazybind + +define void @test_laziness(ptr %a) nounwind { +; +; MACHO-LABEL: test_laziness: +; MACHO: ; %bb.0: +; MACHO-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill +; MACHO-NEXT: Lloh0: +; MACHO-NEXT: adrp x8, _external@GOTPAGE +; MACHO-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill +; MACHO-NEXT: mov x19, x0 +; MACHO-NEXT: Lloh1: +; MACHO-NEXT: ldr x8, [x8, _external@GOTPAGEOFF] +; MACHO-NEXT: blr x8 +; MACHO-NEXT: Lloh2: +; MACHO-NEXT: adrp x8, _memset@GOTPAGE +; MACHO-NEXT: mov x0, x19 +; MACHO-NEXT: mov w1, #1 +; MACHO-NEXT: mov w2, #1000 +; MACHO-NEXT: Lloh3: +; MACHO-NEXT: ldr x8, [x8, _memset@GOTPAGEOFF] +; MACHO-NEXT: blr x8 +; MACHO-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload +; MACHO-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload +; MACHO-NEXT: ret +; MACHO-NEXT: .loh AdrpLdrGot Lloh2, Lloh3 +; MACHO-NEXT: .loh AdrpLdrGot Lloh0, Lloh1 +; +; MACHO-NORMAL-LABEL: test_laziness: +; MACHO-NORMAL: ; %bb.0: +; MACHO-NORMAL-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill +; MACHO-NORMAL-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill +; MACHO-NORMAL-NEXT: mov x19, x0 +; MACHO-NORMAL-NEXT: bl _external +; MACHO-NORMAL-NEXT: Lloh0: +; MACHO-NORMAL-NEXT: adrp x8, _memset@GOTPAGE +; MACHO-NORMAL-NEXT: mov x0, x19 +; MACHO-NORMAL-NEXT: mov w1, #1 +; MACHO-NORMAL-NEXT: mov w2, #1000 +; MACHO-NORMAL-NEXT: Lloh1: +; MACHO-NORMAL-NEXT: ldr x8, [x8, _memset@GOTPAGEOFF] +; MACHO-NORMAL-NEXT: blr x8 +; MACHO-NORMAL-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload +; MACHO-NORMAL-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload +; MACHO-NORMAL-NEXT: ret +; MACHO-NORMAL-NEXT: .loh AdrpLdrGot Lloh0, Lloh1 +; +; ELF-LABEL: test_laziness: +; ELF: // %bb.0: +; ELF-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill +; ELF-NEXT: adrp x8, :got:external +; ELF-NEXT: mov x19, x0 +; ELF-NEXT: ldr x8, [x8, :got_lo12:external] +; ELF-NEXT: blr x8 +; ELF-NEXT: adrp x8, :got:memset +; ELF-NEXT: mov x0, x19 +; ELF-NEXT: mov w1, #1 +; ELF-NEXT: mov w2, #1000 +; ELF-NEXT: ldr x8, [x8, :got_lo12:memset] +; ELF-NEXT: blr x8 +; ELF-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload +; ELF-NEXT: ret + call void @external() + call void @llvm.memset.p0.i64(ptr align 1 %a, i8 1, i64 1000, i1 false) ret void } -declare void @nonlocal() nonlazybind - -define void @test_laziness() { -; CHECK-LABEL: test_laziness: - -; CHECK: bl _local - -; CHECK: adrp x[[TMP:[0-9]+]], _nonlocal@GOTPAGE -; CHECK: ldr [[FUNC:x[0-9]+]], [x[[TMP]], _nonlocal@GOTPAGEOFF] -; CHECK: blr [[FUNC]] - -; CHECK-NORMAL-LABEL: test_laziness: -; CHECK-NORMAL: bl _local -; CHECK-NORMAL: bl _nonlocal - - call void @local() - call void @nonlocal() +define void @test_laziness_tail() nounwind { +; MACHO-LABEL: test_laziness_tail: +; MACHO: ; %bb.0: +; MACHO-NEXT: Lloh4: +; MACHO-NEXT: adrp x0, _external@GOTPAGE +; MACHO-NEXT: Lloh5: +; MACHO-NEXT: ldr x0, [x0, _external@GOTPAGEOFF] +; MACHO-NEXT: br x0 +; MACHO-NEXT: .loh AdrpLdrGot Lloh4, Lloh5 +; +; MACHO-NORMAL-LABEL: test_laziness_tail: +; MACHO-NORMAL: ; %bb.0: +; MACHO-NORMAL-NEXT: b _external +; +; ELF-LABEL: test_laziness_tail: +; ELF: // %bb.0: +; ELF-NEXT: adrp x0, :got:external +; ELF-NEXT: ldr x0, [x0, :got_lo12:external] +; ELF-NEXT: br x0 + tail call void @external() ret void } -define void @test_laziness_tail() { -; CHECK-LABEL: test_laziness_tail: - -; CHECK: adrp x[[TMP:[0-9]+]], _nonlocal@GOTPAGE -; CHECK: ldr [[FUNC:x[0-9]+]], [x[[TMP]], _nonlocal@GOTPAGEOFF] -; CHECK: br [[FUNC]] - -; CHECK-NORMAL-LABEL: test_laziness_tail: -; CHECK-NORMAL: b _nonlocal +declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) - tail call void @nonlocal() - ret void -} +!llvm.module.flags = !{!0} +!0 = !{i32 7, !"RtLibUseGOT", i32 1} +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; ELF-FI: {{.*}} +; ELF-GI: {{.*}} +; ELF-SDAG: {{.*}} diff --git a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml index 06e3794ded09ecc8c24c9de26b97c7e9d785c143..f7ee5a588ba43f02d57d9b3e00ab4a2fea63c7dd 100644 --- a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml +++ b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml @@ -32,13 +32,18 @@ # RUN: FileCheck %s --check-prefix=AVAIL --input-file %t3.txt # RUN: FileCheck %s --check-prefix=UNAVAIL --input-file %t3.txt # -# CHECK: << Total TLI yes SDK no: 0 +# CHECK: << Total TLI yes SDK no: 5 # CHECK: >> Total TLI no SDK yes: 0 # CHECK: == Total TLI yes SDK yes: 235 # +# WRONG_DETAIL: << TLI yes SDK no : '_Unwind_Resume' +# WRONG_DETAIL: << TLI yes SDK no : '_ZSt9terminatev' aka std::terminate() # WRONG_DETAIL: << TLI yes SDK no : '_ZdaPv' aka operator delete[](void*) # WRONG_DETAIL: >> TLI no SDK yes: '_ZdaPvj' aka operator delete[](void*, unsigned int) -# WRONG_SUMMARY: << Total TLI yes SDK no: 1{{$}} +# WRONG_DETAIL: << TLI yes SDK no : '__cxa_allocate_exception' +# WRONG_DETAIL: << TLI yes SDK no : '__cxa_begin_catch' +# WRONG_DETAIL: << TLI yes SDK no : '__cxa_throw' +# WRONG_SUMMARY: << Total TLI yes SDK no: 6 # WRONG_SUMMARY: >> Total TLI no SDK yes: 1{{$}} # WRONG_SUMMARY: == Total TLI yes SDK yes: 234 # @@ -46,11 +51,9 @@ ## the exact count first; the two directives should add up to that. ## Yes, this means additions to TLI will fail this test, but the argument ## to -COUNT can't be an expression. -# AVAIL: TLI knows 468 symbols, 235 available -# AVAIL-COUNT-235: {{^}} available -# AVAIL-NOT: {{^}} available +# AVAIL: TLI knows 473 symbols, 240 available +# AVAIL-COUNT-240: {{^}} available # UNAVAIL-COUNT-233: not available -# UNAVAIL-NOT: not available ## This is a large file so it's worth telling lit to stop here. # END. diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp index 261786b3046113cf0a89802c928a54ab631a8a14..5c093f2ac160f2df51e366b6bc0d4eea31253cad 100644 --- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp +++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp @@ -412,6 +412,8 @@ TEST_F(TargetLibraryInfoTest, ValidProto) { "declare i32 @fseeko64(%struct*, i64, i32)\n" "declare i64 @ftello64(%struct*)\n" + "declare void @_Unwind_Resume(%struct*)\n" + "declare void @_ZSt9terminatev()\n" "declare void @_ZdaPv(i8*)\n" "declare void @_ZdaPvRKSt9nothrow_t(i8*, %struct*)\n" "declare void @_ZdaPvSt11align_val_t(i8*, i64)\n" @@ -468,7 +470,9 @@ TEST_F(TargetLibraryInfoTest, ValidProto) { "declare void @\"??_V@YAXPAXI@Z\"(i8*, i32)\n" // These other functions were derived from the .def C declaration. + "declare i8* @__cxa_allocate_exception(i64)\n" "declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)\n" + "declare i8* @__cxa_begin_catch(i8*)\n" "declare void @__cxa_guard_abort(%struct*)\n" "declare i32 @__cxa_guard_acquire(%struct*)\n" "declare void @__cxa_guard_release(%struct*)\n" @@ -559,6 +563,7 @@ TEST_F(TargetLibraryInfoTest, ValidProto) { "declare double @__cosh_finite(double)\n" "declare float @__coshf_finite(float)\n" "declare x86_fp80 @__coshl_finite(x86_fp80)\n" + "declare void @__cxa_throw(i8*, i8*, i8*)\n" "declare double @__exp10_finite(double)\n" "declare float @__exp10f_finite(float)\n" "declare x86_fp80 @__exp10l_finite(x86_fp80)\n"