From owner-svn-src-vendor@freebsd.org Tue Jan 24 19:17:56 2017 Return-Path: Delivered-To: svn-src-vendor@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 88C02CBF518; Tue, 24 Jan 2017 19:17:56 +0000 (UTC) (envelope-from dim@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 3F0FFA36; Tue, 24 Jan 2017 19:17:56 +0000 (UTC) (envelope-from dim@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v0OJHtRZ072190; Tue, 24 Jan 2017 19:17:55 GMT (envelope-from dim@FreeBSD.org) Received: (from dim@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v0OJHsaj072176; Tue, 24 Jan 2017 19:17:54 GMT (envelope-from dim@FreeBSD.org) Message-Id: <201701241917.v0OJHsaj072176@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: dim set sender to dim@FreeBSD.org using -f From: Dimitry Andric Date: Tue, 24 Jan 2017 19:17:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r312704 - in vendor/llvm/dist: lib/Bitcode/Reader lib/Target/AArch64 lib/Target/ARM lib/Target/X86 lib/Transforms/Instrumentation lib/Transforms/Scalar test/CodeGen/AArch64 test/CodeGen... X-SVN-Group: vendor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-vendor@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the vendor work area tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 24 Jan 2017 19:17:56 -0000 Author: dim Date: Tue Jan 24 19:17:53 2017 New Revision: 312704 URL: https://svnweb.freebsd.org/changeset/base/312704 Log: Vendor import of llvm release_40 branch r292951: https://llvm.org/svn/llvm-project/llvm/branches/release_40@292951 Added: vendor/llvm/dist/test/CodeGen/AArch64/ldst-opt.mir vendor/llvm/dist/test/CodeGen/Thumb2/intrinsics-cc.ll vendor/llvm/dist/test/Transforms/NewGVN/pr31682.ll vendor/llvm/dist/test/tools/llvm-cxxfilt/invalid.test Deleted: vendor/llvm/dist/test/CodeGen/AArch64/ldst-opt-dbg-limit.mir Modified: vendor/llvm/dist/lib/Bitcode/Reader/BitcodeReader.cpp vendor/llvm/dist/lib/Bitcode/Reader/MetadataLoader.cpp vendor/llvm/dist/lib/Bitcode/Reader/MetadataLoader.h vendor/llvm/dist/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp vendor/llvm/dist/lib/Target/ARM/ARMISelLowering.cpp vendor/llvm/dist/lib/Target/ARM/ARMISelLowering.h vendor/llvm/dist/lib/Target/X86/X86ISelLowering.cpp vendor/llvm/dist/lib/Transforms/Instrumentation/AddressSanitizer.cpp vendor/llvm/dist/lib/Transforms/Scalar/NewGVN.cpp vendor/llvm/dist/test/CodeGen/Thumb2/float-intrinsics-double.ll vendor/llvm/dist/test/CodeGen/Thumb2/float-intrinsics-float.ll vendor/llvm/dist/test/CodeGen/X86/sse1.ll vendor/llvm/dist/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll vendor/llvm/dist/test/ThinLTO/X86/lazyload_metadata.ll vendor/llvm/dist/tools/llvm-cxxfilt/llvm-cxxfilt.cpp vendor/llvm/dist/utils/release/test-release.sh Modified: vendor/llvm/dist/lib/Bitcode/Reader/BitcodeReader.cpp ============================================================================== --- vendor/llvm/dist/lib/Bitcode/Reader/BitcodeReader.cpp Tue Jan 24 18:56:09 2017 (r312703) +++ vendor/llvm/dist/lib/Bitcode/Reader/BitcodeReader.cpp Tue Jan 24 19:17:53 2017 (r312704) @@ -512,7 +512,7 @@ private: } Metadata *getFnMetadataByID(unsigned ID) { - return MDLoader->getMetadataFwdRef(ID); + return MDLoader->getMetadataFwdRefOrLoad(ID); } BasicBlock *getBasicBlock(unsigned ID) const { Modified: vendor/llvm/dist/lib/Bitcode/Reader/MetadataLoader.cpp ============================================================================== --- vendor/llvm/dist/lib/Bitcode/Reader/MetadataLoader.cpp Tue Jan 24 18:56:09 2017 (r312703) +++ vendor/llvm/dist/lib/Bitcode/Reader/MetadataLoader.cpp Tue Jan 24 19:17:53 2017 (r312704) @@ -485,8 +485,21 @@ public: Error parseMetadata(bool ModuleLevel); bool hasFwdRefs() const { return MetadataList.hasFwdRefs(); } - Metadata *getMetadataFwdRef(unsigned Idx) { - return MetadataList.getMetadataFwdRef(Idx); + + Metadata *getMetadataFwdRefOrLoad(unsigned ID) { + if (ID < MDStringRef.size()) + return lazyLoadOneMDString(ID); + if (auto *MD = MetadataList.lookup(ID)) + return MD; + // If lazy-loading is enabled, we try recursively to load the operand + // instead of creating a temporary. + if (ID < (MDStringRef.size() + GlobalMetadataBitPosIndex.size())) { + PlaceholderQueue Placeholders; + lazyLoadOneMetadata(ID, Placeholders); + resolveForwardRefsAndPlaceholders(Placeholders); + return MetadataList.lookup(ID); + } + return MetadataList.getMetadataFwdRef(ID); } MDNode *getMDNodeFwdRefOrNull(unsigned Idx) { @@ -1727,8 +1740,8 @@ bool MetadataLoader::hasFwdRefs() const /// Return the given metadata, creating a replaceable forward reference if /// necessary. -Metadata *MetadataLoader::getMetadataFwdRef(unsigned Idx) { - return Pimpl->getMetadataFwdRef(Idx); +Metadata *MetadataLoader::getMetadataFwdRefOrLoad(unsigned Idx) { + return Pimpl->getMetadataFwdRefOrLoad(Idx); } MDNode *MetadataLoader::getMDNodeFwdRefOrNull(unsigned Idx) { Modified: vendor/llvm/dist/lib/Bitcode/Reader/MetadataLoader.h ============================================================================== --- vendor/llvm/dist/lib/Bitcode/Reader/MetadataLoader.h Tue Jan 24 18:56:09 2017 (r312703) +++ vendor/llvm/dist/lib/Bitcode/Reader/MetadataLoader.h Tue Jan 24 19:17:53 2017 (r312704) @@ -63,7 +63,7 @@ public: /// Return the given metadata, creating a replaceable forward reference if /// necessary. - Metadata *getMetadataFwdRef(unsigned Idx); + Metadata *getMetadataFwdRefOrLoad(unsigned Idx); MDNode *getMDNodeFwdRefOrNull(unsigned Idx); Modified: vendor/llvm/dist/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp ============================================================================== --- vendor/llvm/dist/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp Tue Jan 24 18:56:09 2017 (r312703) +++ vendor/llvm/dist/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp Tue Jan 24 19:17:53 2017 (r312704) @@ -687,9 +687,30 @@ AArch64LoadStoreOpt::mergePairedInsns(Ma MachineInstrBuilder MIB; DebugLoc DL = I->getDebugLoc(); MachineBasicBlock *MBB = I->getParent(); + MachineOperand RegOp0 = getLdStRegOp(*RtMI); + MachineOperand RegOp1 = getLdStRegOp(*Rt2MI); + // Kill flags may become invalid when moving stores for pairing. + if (RegOp0.isUse()) { + if (!MergeForward) { + // Clear kill flags on store if moving upwards. Example: + // STRWui %w0, ... + // USE %w1 + // STRWui kill %w1 ; need to clear kill flag when moving STRWui upwards + RegOp0.setIsKill(false); + RegOp1.setIsKill(false); + } else { + // Clear kill flags of the first stores register. Example: + // STRWui %w1, ... + // USE kill %w1 ; need to clear kill flag when moving STRWui downwards + // STRW %w0 + unsigned Reg = getLdStRegOp(*I).getReg(); + for (MachineInstr &MI : make_range(std::next(I), Paired)) + MI.clearRegisterKills(Reg, TRI); + } + } MIB = BuildMI(*MBB, InsertionPoint, DL, TII->get(getMatchingPairOpcode(Opc))) - .addOperand(getLdStRegOp(*RtMI)) - .addOperand(getLdStRegOp(*Rt2MI)) + .addOperand(RegOp0) + .addOperand(RegOp1) .addOperand(BaseRegOp) .addImm(OffsetImm) .setMemRefs(I->mergeMemRefsWith(*Paired)); Modified: vendor/llvm/dist/lib/Target/ARM/ARMISelLowering.cpp ============================================================================== --- vendor/llvm/dist/lib/Target/ARM/ARMISelLowering.cpp Tue Jan 24 18:56:09 2017 (r312703) +++ vendor/llvm/dist/lib/Target/ARM/ARMISelLowering.cpp Tue Jan 24 19:17:53 2017 (r312704) @@ -97,171 +97,6 @@ namespace { }; } -void ARMTargetLowering::InitLibcallCallingConvs() { - // The builtins on ARM always use AAPCS, irrespective of wheter C is AAPCS or - // AAPCS_VFP. - for (const auto LC : { - RTLIB::SHL_I16, - RTLIB::SHL_I32, - RTLIB::SHL_I64, - RTLIB::SHL_I128, - RTLIB::SRL_I16, - RTLIB::SRL_I32, - RTLIB::SRL_I64, - RTLIB::SRL_I128, - RTLIB::SRA_I16, - RTLIB::SRA_I32, - RTLIB::SRA_I64, - RTLIB::SRA_I128, - RTLIB::MUL_I8, - RTLIB::MUL_I16, - RTLIB::MUL_I32, - RTLIB::MUL_I64, - RTLIB::MUL_I128, - RTLIB::MULO_I32, - RTLIB::MULO_I64, - RTLIB::MULO_I128, - RTLIB::SDIV_I8, - RTLIB::SDIV_I16, - RTLIB::SDIV_I32, - RTLIB::SDIV_I64, - RTLIB::SDIV_I128, - RTLIB::UDIV_I8, - RTLIB::UDIV_I16, - RTLIB::UDIV_I32, - RTLIB::UDIV_I64, - RTLIB::UDIV_I128, - RTLIB::SREM_I8, - RTLIB::SREM_I16, - RTLIB::SREM_I32, - RTLIB::SREM_I64, - RTLIB::SREM_I128, - RTLIB::UREM_I8, - RTLIB::UREM_I16, - RTLIB::UREM_I32, - RTLIB::UREM_I64, - RTLIB::UREM_I128, - RTLIB::SDIVREM_I8, - RTLIB::SDIVREM_I16, - RTLIB::SDIVREM_I32, - RTLIB::SDIVREM_I64, - RTLIB::SDIVREM_I128, - RTLIB::UDIVREM_I8, - RTLIB::UDIVREM_I16, - RTLIB::UDIVREM_I32, - RTLIB::UDIVREM_I64, - RTLIB::UDIVREM_I128, - RTLIB::NEG_I32, - RTLIB::NEG_I64, - RTLIB::ADD_F32, - RTLIB::ADD_F64, - RTLIB::ADD_F80, - RTLIB::ADD_F128, - RTLIB::SUB_F32, - RTLIB::SUB_F64, - RTLIB::SUB_F80, - RTLIB::SUB_F128, - RTLIB::MUL_F32, - RTLIB::MUL_F64, - RTLIB::MUL_F80, - RTLIB::MUL_F128, - RTLIB::DIV_F32, - RTLIB::DIV_F64, - RTLIB::DIV_F80, - RTLIB::DIV_F128, - RTLIB::POWI_F32, - RTLIB::POWI_F64, - RTLIB::POWI_F80, - RTLIB::POWI_F128, - RTLIB::FPEXT_F64_F128, - RTLIB::FPEXT_F32_F128, - RTLIB::FPEXT_F32_F64, - RTLIB::FPEXT_F16_F32, - RTLIB::FPROUND_F32_F16, - RTLIB::FPROUND_F64_F16, - RTLIB::FPROUND_F80_F16, - RTLIB::FPROUND_F128_F16, - RTLIB::FPROUND_F64_F32, - RTLIB::FPROUND_F80_F32, - RTLIB::FPROUND_F128_F32, - RTLIB::FPROUND_F80_F64, - RTLIB::FPROUND_F128_F64, - RTLIB::FPTOSINT_F32_I32, - RTLIB::FPTOSINT_F32_I64, - RTLIB::FPTOSINT_F32_I128, - RTLIB::FPTOSINT_F64_I32, - RTLIB::FPTOSINT_F64_I64, - RTLIB::FPTOSINT_F64_I128, - RTLIB::FPTOSINT_F80_I32, - RTLIB::FPTOSINT_F80_I64, - RTLIB::FPTOSINT_F80_I128, - RTLIB::FPTOSINT_F128_I32, - RTLIB::FPTOSINT_F128_I64, - RTLIB::FPTOSINT_F128_I128, - RTLIB::FPTOUINT_F32_I32, - RTLIB::FPTOUINT_F32_I64, - RTLIB::FPTOUINT_F32_I128, - RTLIB::FPTOUINT_F64_I32, - RTLIB::FPTOUINT_F64_I64, - RTLIB::FPTOUINT_F64_I128, - RTLIB::FPTOUINT_F80_I32, - RTLIB::FPTOUINT_F80_I64, - RTLIB::FPTOUINT_F80_I128, - RTLIB::FPTOUINT_F128_I32, - RTLIB::FPTOUINT_F128_I64, - RTLIB::FPTOUINT_F128_I128, - RTLIB::SINTTOFP_I32_F32, - RTLIB::SINTTOFP_I32_F64, - RTLIB::SINTTOFP_I32_F80, - RTLIB::SINTTOFP_I32_F128, - RTLIB::SINTTOFP_I64_F32, - RTLIB::SINTTOFP_I64_F64, - RTLIB::SINTTOFP_I64_F80, - RTLIB::SINTTOFP_I64_F128, - RTLIB::SINTTOFP_I128_F32, - RTLIB::SINTTOFP_I128_F64, - RTLIB::SINTTOFP_I128_F80, - RTLIB::SINTTOFP_I128_F128, - RTLIB::UINTTOFP_I32_F32, - RTLIB::UINTTOFP_I32_F64, - RTLIB::UINTTOFP_I32_F80, - RTLIB::UINTTOFP_I32_F128, - RTLIB::UINTTOFP_I64_F32, - RTLIB::UINTTOFP_I64_F64, - RTLIB::UINTTOFP_I64_F80, - RTLIB::UINTTOFP_I64_F128, - RTLIB::UINTTOFP_I128_F32, - RTLIB::UINTTOFP_I128_F64, - RTLIB::UINTTOFP_I128_F80, - RTLIB::UINTTOFP_I128_F128, - RTLIB::OEQ_F32, - RTLIB::OEQ_F64, - RTLIB::OEQ_F128, - RTLIB::UNE_F32, - RTLIB::UNE_F64, - RTLIB::UNE_F128, - RTLIB::OGE_F32, - RTLIB::OGE_F64, - RTLIB::OGE_F128, - RTLIB::OLT_F32, - RTLIB::OLT_F64, - RTLIB::OLT_F128, - RTLIB::OLE_F32, - RTLIB::OLE_F64, - RTLIB::OLE_F128, - RTLIB::OGT_F32, - RTLIB::OGT_F64, - RTLIB::OGT_F128, - RTLIB::UO_F32, - RTLIB::UO_F64, - RTLIB::UO_F128, - RTLIB::O_F32, - RTLIB::O_F64, - RTLIB::O_F128, - }) - setLibcallCallingConv(LC, CallingConv::ARM_AAPCS); -} - // The APCS parameter registers. static const MCPhysReg GPRArgRegs[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 @@ -349,7 +184,22 @@ ARMTargetLowering::ARMTargetLowering(con setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); - InitLibcallCallingConvs(); + if (!Subtarget->isTargetDarwin() && !Subtarget->isTargetIOS() && + !Subtarget->isTargetWatchOS()) { + const auto &E = Subtarget->getTargetTriple().getEnvironment(); + + bool IsHFTarget = E == Triple::EABIHF || E == Triple::GNUEABIHF || + E == Triple::MuslEABIHF; + // Windows is a special case. Technically, we will replace all of the "GNU" + // calls with calls to MSVCRT if appropriate and adjust the calling + // convention then. + IsHFTarget = IsHFTarget || Subtarget->isTargetWindows(); + + for (int LCID = 0; LCID < RTLIB::UNKNOWN_LIBCALL; ++LCID) + setLibcallCallingConv(static_cast(LCID), + IsHFTarget ? CallingConv::ARM_AAPCS_VFP + : CallingConv::ARM_AAPCS); + } if (Subtarget->isTargetMachO()) { // Uses VFP for Thumb libfuncs if available. Modified: vendor/llvm/dist/lib/Target/ARM/ARMISelLowering.h ============================================================================== --- vendor/llvm/dist/lib/Target/ARM/ARMISelLowering.h Tue Jan 24 18:56:09 2017 (r312703) +++ vendor/llvm/dist/lib/Target/ARM/ARMISelLowering.h Tue Jan 24 19:17:53 2017 (r312704) @@ -538,8 +538,6 @@ class InstrItineraryData; bool HasStandaloneRem = true; - void InitLibcallCallingConvs(); - void addTypeForNEON(MVT VT, MVT PromotedLdStVT, MVT PromotedBitwiseVT); void addDRTypeForNEON(MVT VT); void addQRTypeForNEON(MVT VT); Modified: vendor/llvm/dist/lib/Target/X86/X86ISelLowering.cpp ============================================================================== --- vendor/llvm/dist/lib/Target/X86/X86ISelLowering.cpp Tue Jan 24 18:56:09 2017 (r312703) +++ vendor/llvm/dist/lib/Target/X86/X86ISelLowering.cpp Tue Jan 24 19:17:53 2017 (r312704) @@ -28788,10 +28788,12 @@ static SDValue combineExtractVectorElt(S return SDValue(); } -/// If a vector select has an operand that is -1 or 0, simplify the select to a -/// bitwise logic operation. -static SDValue combineVSelectWithAllOnesOrZeros(SDNode *N, SelectionDAG &DAG, - const X86Subtarget &Subtarget) { +/// If a vector select has an operand that is -1 or 0, try to simplify the +/// select to a bitwise logic operation. +static SDValue +combineVSelectWithAllOnesOrZeros(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const X86Subtarget &Subtarget) { SDValue Cond = N->getOperand(0); SDValue LHS = N->getOperand(1); SDValue RHS = N->getOperand(2); @@ -28853,18 +28855,28 @@ static SDValue combineVSelectWithAllOnes } } - if (!TValIsAllOnes && !FValIsAllZeros) + // vselect Cond, 111..., 000... -> Cond + if (TValIsAllOnes && FValIsAllZeros) + return DAG.getBitcast(VT, Cond); + + if (!DCI.isBeforeLegalize() && !TLI.isTypeLegal(CondVT)) return SDValue(); - SDValue Ret; - if (TValIsAllOnes && FValIsAllZeros) - Ret = Cond; - else if (TValIsAllOnes) - Ret = DAG.getNode(ISD::OR, DL, CondVT, Cond, DAG.getBitcast(CondVT, RHS)); - else if (FValIsAllZeros) - Ret = DAG.getNode(ISD::AND, DL, CondVT, Cond, DAG.getBitcast(CondVT, LHS)); + // vselect Cond, 111..., X -> or Cond, X + if (TValIsAllOnes) { + SDValue CastRHS = DAG.getBitcast(CondVT, RHS); + SDValue Or = DAG.getNode(ISD::OR, DL, CondVT, Cond, CastRHS); + return DAG.getBitcast(VT, Or); + } - return DAG.getBitcast(VT, Ret); + // vselect Cond, X, 000... -> and Cond, X + if (FValIsAllZeros) { + SDValue CastLHS = DAG.getBitcast(CondVT, LHS); + SDValue And = DAG.getNode(ISD::AND, DL, CondVT, Cond, CastLHS); + return DAG.getBitcast(VT, And); + } + + return SDValue(); } static SDValue combineSelectOfTwoConstants(SDNode *N, SelectionDAG &DAG) { @@ -29353,7 +29365,7 @@ static SDValue combineSelect(SDNode *N, } } - if (SDValue V = combineVSelectWithAllOnesOrZeros(N, DAG, Subtarget)) + if (SDValue V = combineVSelectWithAllOnesOrZeros(N, DAG, DCI, Subtarget)) return V; // If this is a *dynamic* select (non-constant condition) and we can match Modified: vendor/llvm/dist/lib/Transforms/Instrumentation/AddressSanitizer.cpp ============================================================================== --- vendor/llvm/dist/lib/Transforms/Instrumentation/AddressSanitizer.cpp Tue Jan 24 18:56:09 2017 (r312703) +++ vendor/llvm/dist/lib/Transforms/Instrumentation/AddressSanitizer.cpp Tue Jan 24 19:17:53 2017 (r312704) @@ -600,6 +600,22 @@ private: void initializeCallbacks(Module &M); bool InstrumentGlobals(IRBuilder<> &IRB, Module &M); + void InstrumentGlobalsCOFF(IRBuilder<> &IRB, Module &M, + ArrayRef ExtendedGlobals, + ArrayRef MetadataInitializers); + void InstrumentGlobalsMachO(IRBuilder<> &IRB, Module &M, + ArrayRef ExtendedGlobals, + ArrayRef MetadataInitializers); + void + InstrumentGlobalsWithMetadataArray(IRBuilder<> &IRB, Module &M, + ArrayRef ExtendedGlobals, + ArrayRef MetadataInitializers); + + GlobalVariable *CreateMetadataGlobal(Module &M, Constant *Initializer, + StringRef OriginalName); + void SetComdatForGlobalMetadata(GlobalVariable *G, GlobalVariable *Metadata); + IRBuilder<> CreateAsanModuleDtor(Module &M); + bool ShouldInstrumentGlobal(GlobalVariable *G); bool ShouldUseMachOGlobalsSection() const; StringRef getGlobalMetadataSection() const; @@ -1553,17 +1569,173 @@ void AddressSanitizerModule::initializeC // Declare the functions that find globals in a shared object and then invoke // the (un)register function on them. - AsanRegisterImageGlobals = checkSanitizerInterfaceFunction( - M.getOrInsertFunction(kAsanRegisterImageGlobalsName, - IRB.getVoidTy(), IntptrTy, nullptr)); + AsanRegisterImageGlobals = + checkSanitizerInterfaceFunction(M.getOrInsertFunction( + kAsanRegisterImageGlobalsName, IRB.getVoidTy(), IntptrTy, nullptr)); AsanRegisterImageGlobals->setLinkage(Function::ExternalLinkage); - AsanUnregisterImageGlobals = checkSanitizerInterfaceFunction( - M.getOrInsertFunction(kAsanUnregisterImageGlobalsName, - IRB.getVoidTy(), IntptrTy, nullptr)); + AsanUnregisterImageGlobals = + checkSanitizerInterfaceFunction(M.getOrInsertFunction( + kAsanUnregisterImageGlobalsName, IRB.getVoidTy(), IntptrTy, nullptr)); AsanUnregisterImageGlobals->setLinkage(Function::ExternalLinkage); } +// Put the metadata and the instrumented global in the same group. This ensures +// that the metadata is discarded if the instrumented global is discarded. +void AddressSanitizerModule::SetComdatForGlobalMetadata( + GlobalVariable *G, GlobalVariable *Metadata) { + Module &M = *G->getParent(); + Comdat *C = G->getComdat(); + if (!C) { + if (!G->hasName()) { + // If G is unnamed, it must be internal. Give it an artificial name + // so we can put it in a comdat. + assert(G->hasLocalLinkage()); + G->setName(Twine(kAsanGenPrefix) + "_anon_global"); + } + C = M.getOrInsertComdat(G->getName()); + // Make this IMAGE_COMDAT_SELECT_NODUPLICATES on COFF. + if (TargetTriple.isOSBinFormatCOFF()) + C->setSelectionKind(Comdat::NoDuplicates); + G->setComdat(C); + } + + assert(G->hasComdat()); + Metadata->setComdat(G->getComdat()); +} + +// Create a separate metadata global and put it in the appropriate ASan +// global registration section. +GlobalVariable * +AddressSanitizerModule::CreateMetadataGlobal(Module &M, Constant *Initializer, + StringRef OriginalName) { + GlobalVariable *Metadata = + new GlobalVariable(M, Initializer->getType(), false, + GlobalVariable::InternalLinkage, Initializer, + Twine("__asan_global_") + + GlobalValue::getRealLinkageName(OriginalName)); + Metadata->setSection(getGlobalMetadataSection()); + return Metadata; +} + +IRBuilder<> AddressSanitizerModule::CreateAsanModuleDtor(Module &M) { + Function *AsanDtorFunction = + Function::Create(FunctionType::get(Type::getVoidTy(*C), false), + GlobalValue::InternalLinkage, kAsanModuleDtorName, &M); + BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction); + appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndDtorPriority); + + return IRBuilder<>(ReturnInst::Create(*C, AsanDtorBB)); +} + +void AddressSanitizerModule::InstrumentGlobalsCOFF( + IRBuilder<> &IRB, Module &M, ArrayRef ExtendedGlobals, + ArrayRef MetadataInitializers) { + assert(ExtendedGlobals.size() == MetadataInitializers.size()); + auto &DL = M.getDataLayout(); + + for (size_t i = 0; i < ExtendedGlobals.size(); i++) { + Constant *Initializer = MetadataInitializers[i]; + GlobalVariable *G = ExtendedGlobals[i]; + GlobalVariable *Metadata = + CreateMetadataGlobal(M, Initializer, G->getName()); + + // The MSVC linker always inserts padding when linking incrementally. We + // cope with that by aligning each struct to its size, which must be a power + // of two. + unsigned SizeOfGlobalStruct = DL.getTypeAllocSize(Initializer->getType()); + assert(isPowerOf2_32(SizeOfGlobalStruct) && + "global metadata will not be padded appropriately"); + Metadata->setAlignment(SizeOfGlobalStruct); + + SetComdatForGlobalMetadata(G, Metadata); + } +} + +void AddressSanitizerModule::InstrumentGlobalsMachO( + IRBuilder<> &IRB, Module &M, ArrayRef ExtendedGlobals, + ArrayRef MetadataInitializers) { + assert(ExtendedGlobals.size() == MetadataInitializers.size()); + + // On recent Mach-O platforms, use a structure which binds the liveness of + // the global variable to the metadata struct. Keep the list of "Liveness" GV + // created to be added to llvm.compiler.used + StructType *LivenessTy = StructType::get(IntptrTy, IntptrTy, nullptr); + SmallVector LivenessGlobals(ExtendedGlobals.size()); + + for (size_t i = 0; i < ExtendedGlobals.size(); i++) { + Constant *Initializer = MetadataInitializers[i]; + GlobalVariable *G = ExtendedGlobals[i]; + GlobalVariable *Metadata = + CreateMetadataGlobal(M, Initializer, G->getName()); + + // On recent Mach-O platforms, we emit the global metadata in a way that + // allows the linker to properly strip dead globals. + auto LivenessBinder = ConstantStruct::get( + LivenessTy, Initializer->getAggregateElement(0u), + ConstantExpr::getPointerCast(Metadata, IntptrTy), nullptr); + GlobalVariable *Liveness = new GlobalVariable( + M, LivenessTy, false, GlobalVariable::InternalLinkage, LivenessBinder, + Twine("__asan_binder_") + G->getName()); + Liveness->setSection("__DATA,__asan_liveness,regular,live_support"); + LivenessGlobals[i] = Liveness; + } + + // Update llvm.compiler.used, adding the new liveness globals. This is + // needed so that during LTO these variables stay alive. The alternative + // would be to have the linker handling the LTO symbols, but libLTO + // current API does not expose access to the section for each symbol. + if (!LivenessGlobals.empty()) + appendToCompilerUsed(M, LivenessGlobals); + + // RegisteredFlag serves two purposes. First, we can pass it to dladdr() + // to look up the loaded image that contains it. Second, we can store in it + // whether registration has already occurred, to prevent duplicate + // registration. + // + // common linkage ensures that there is only one global per shared library. + GlobalVariable *RegisteredFlag = new GlobalVariable( + M, IntptrTy, false, GlobalVariable::CommonLinkage, + ConstantInt::get(IntptrTy, 0), kAsanGlobalsRegisteredFlagName); + RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility); + + IRB.CreateCall(AsanRegisterImageGlobals, + {IRB.CreatePointerCast(RegisteredFlag, IntptrTy)}); + + // We also need to unregister globals at the end, e.g., when a shared library + // gets closed. + IRBuilder<> IRB_Dtor = CreateAsanModuleDtor(M); + IRB_Dtor.CreateCall(AsanUnregisterImageGlobals, + {IRB.CreatePointerCast(RegisteredFlag, IntptrTy)}); +} + +void AddressSanitizerModule::InstrumentGlobalsWithMetadataArray( + IRBuilder<> &IRB, Module &M, ArrayRef ExtendedGlobals, + ArrayRef MetadataInitializers) { + assert(ExtendedGlobals.size() == MetadataInitializers.size()); + unsigned N = ExtendedGlobals.size(); + assert(N > 0); + + // On platforms that don't have a custom metadata section, we emit an array + // of global metadata structures. + ArrayType *ArrayOfGlobalStructTy = + ArrayType::get(MetadataInitializers[0]->getType(), N); + auto AllGlobals = new GlobalVariable( + M, ArrayOfGlobalStructTy, false, GlobalVariable::InternalLinkage, + ConstantArray::get(ArrayOfGlobalStructTy, MetadataInitializers), ""); + + IRB.CreateCall(AsanRegisterGlobals, + {IRB.CreatePointerCast(AllGlobals, IntptrTy), + ConstantInt::get(IntptrTy, N)}); + + // We also need to unregister globals at the end, e.g., when a shared library + // gets closed. + IRBuilder<> IRB_Dtor = CreateAsanModuleDtor(M); + IRB_Dtor.CreateCall(AsanUnregisterGlobals, + {IRB.CreatePointerCast(AllGlobals, IntptrTy), + ConstantInt::get(IntptrTy, N)}); +} + // This function replaces all global variables with new variables that have // trailing redzones. It also creates a function that poisons // redzones and inserts this function into llvm.global_ctors. @@ -1580,9 +1752,6 @@ bool AddressSanitizerModule::InstrumentG if (n == 0) return false; auto &DL = M.getDataLayout(); - bool UseComdatMetadata = TargetTriple.isOSBinFormatCOFF(); - bool UseMachOGlobalsSection = ShouldUseMachOGlobalsSection(); - bool UseMetadataArray = !(UseComdatMetadata || UseMachOGlobalsSection); // A global is described by a structure // size_t beg; @@ -1597,19 +1766,8 @@ bool AddressSanitizerModule::InstrumentG StructType *GlobalStructTy = StructType::get(IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy, nullptr); - unsigned SizeOfGlobalStruct = DL.getTypeAllocSize(GlobalStructTy); - assert(isPowerOf2_32(SizeOfGlobalStruct) && - "global metadata will not be padded appropriately"); - SmallVector Initializers(UseMetadataArray ? n : 0); - - // On recent Mach-O platforms, use a structure which binds the liveness of - // the global variable to the metadata struct. Keep the list of "Liveness" GV - // created to be added to llvm.compiler.used - StructType *LivenessTy = nullptr; - if (UseMachOGlobalsSection) - LivenessTy = StructType::get(IntptrTy, IntptrTy, nullptr); - SmallVector LivenessGlobals( - UseMachOGlobalsSection ? n : 0); + SmallVector NewGlobals(n); + SmallVector Initializers(n); bool HasDynamicallyInitializedGlobals = false; @@ -1681,25 +1839,7 @@ bool AddressSanitizerModule::InstrumentG ConstantExpr::getGetElementPtr(NewTy, NewGlobal, Indices2, true)); NewGlobal->takeName(G); G->eraseFromParent(); - G = NewGlobal; - - if (UseComdatMetadata) { - // Get or create a COMDAT for G so that we can use it with our metadata. - Comdat *C = G->getComdat(); - if (!C) { - if (!G->hasName()) { - // If G is unnamed, it must be internal. Give it an artificial name - // so we can put it in a comdat. - assert(G->hasLocalLinkage()); - G->setName(Twine(kAsanGenPrefix) + "_anon_global"); - } - C = M.getOrInsertComdat(G->getName()); - // Make this IMAGE_COMDAT_SELECT_NODUPLICATES on COFF. - if (TargetTriple.isOSBinFormatCOFF()) - C->setSelectionKind(Comdat::NoDuplicates); - G->setComdat(C); - } - } + NewGlobals[i] = NewGlobal; Constant *SourceLoc; if (!MD.SourceLoc.empty()) { @@ -1750,117 +1890,21 @@ bool AddressSanitizerModule::InstrumentG DEBUG(dbgs() << "NEW GLOBAL: " << *NewGlobal << "\n"); - // If we aren't using separate metadata globals, add it to the initializer - // list and continue. - if (UseMetadataArray) { - Initializers[i] = Initializer; - continue; - } - - // Create a separate metadata global and put it in the appropriate ASan - // global registration section. - GlobalVariable *Metadata = new GlobalVariable( - M, GlobalStructTy, false, GlobalVariable::InternalLinkage, - Initializer, Twine("__asan_global_") + - GlobalValue::getRealLinkageName(G->getName())); - Metadata->setSection(getGlobalMetadataSection()); - - // We don't want any padding, but we also need a reasonable alignment. - // The MSVC linker always inserts padding when linking incrementally. We - // cope with that by aligning each struct to its size, which must be a power - // of two. - Metadata->setAlignment(SizeOfGlobalStruct); - - // On platforms that support comdats, put the metadata and the - // instrumented global in the same group. This ensures that the metadata - // is discarded if the instrumented global is discarded. - if (UseComdatMetadata) { - assert(G->hasComdat()); - Metadata->setComdat(G->getComdat()); - continue; - } - assert(UseMachOGlobalsSection); + Initializers[i] = Initializer; + } - // On recent Mach-O platforms, we emit the global metadata in a way that - // allows the linker to properly strip dead globals. - auto LivenessBinder = ConstantStruct::get( - LivenessTy, Initializer->getAggregateElement(0u), - ConstantExpr::getPointerCast(Metadata, IntptrTy), nullptr); - GlobalVariable *Liveness = new GlobalVariable( - M, LivenessTy, false, GlobalVariable::InternalLinkage, LivenessBinder, - Twine("__asan_binder_") + G->getName()); - Liveness->setSection("__DATA,__asan_liveness,regular,live_support"); - LivenessGlobals[i] = Liveness; + if (TargetTriple.isOSBinFormatCOFF()) { + InstrumentGlobalsCOFF(IRB, M, NewGlobals, Initializers); + } else if (ShouldUseMachOGlobalsSection()) { + InstrumentGlobalsMachO(IRB, M, NewGlobals, Initializers); + } else { + InstrumentGlobalsWithMetadataArray(IRB, M, NewGlobals, Initializers); } // Create calls for poisoning before initializers run and unpoisoning after. if (HasDynamicallyInitializedGlobals) createInitializerPoisonCalls(M, ModuleName); - // Platforms with a dedicated metadata section don't need to emit any more - // code. - if (UseComdatMetadata) - return true; - - GlobalVariable *AllGlobals = nullptr; - GlobalVariable *RegisteredFlag = nullptr; - - if (UseMachOGlobalsSection) { - // RegisteredFlag serves two purposes. First, we can pass it to dladdr() - // to look up the loaded image that contains it. Second, we can store in it - // whether registration has already occurred, to prevent duplicate - // registration. - // - // common linkage ensures that there is only one global per shared library. - RegisteredFlag = new GlobalVariable( - M, IntptrTy, false, GlobalVariable::CommonLinkage, - ConstantInt::get(IntptrTy, 0), kAsanGlobalsRegisteredFlagName); - RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility); - - // Update llvm.compiler.used, adding the new liveness globals. This is - // needed so that during LTO these variables stay alive. The alternative - // would be to have the linker handling the LTO symbols, but libLTO - // current API does not expose access to the section for each symbol. - if (!LivenessGlobals.empty()) - appendToCompilerUsed(M, LivenessGlobals); - } else if (UseMetadataArray) { - // On platforms that don't have a custom metadata section, we emit an array - // of global metadata structures. - ArrayType *ArrayOfGlobalStructTy = ArrayType::get(GlobalStructTy, n); - AllGlobals = new GlobalVariable( - M, ArrayOfGlobalStructTy, false, GlobalVariable::InternalLinkage, - ConstantArray::get(ArrayOfGlobalStructTy, Initializers), ""); - } - - // Create a call to register the globals with the runtime. - if (UseMachOGlobalsSection) { - IRB.CreateCall(AsanRegisterImageGlobals, - {IRB.CreatePointerCast(RegisteredFlag, IntptrTy)}); - } else { - IRB.CreateCall(AsanRegisterGlobals, - {IRB.CreatePointerCast(AllGlobals, IntptrTy), - ConstantInt::get(IntptrTy, n)}); - } - - // We also need to unregister globals at the end, e.g., when a shared library - // gets closed. - Function *AsanDtorFunction = - Function::Create(FunctionType::get(Type::getVoidTy(*C), false), - GlobalValue::InternalLinkage, kAsanModuleDtorName, &M); - BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction); - IRBuilder<> IRB_Dtor(ReturnInst::Create(*C, AsanDtorBB)); - - if (UseMachOGlobalsSection) { - IRB_Dtor.CreateCall(AsanUnregisterImageGlobals, - {IRB.CreatePointerCast(RegisteredFlag, IntptrTy)}); - } else { - IRB_Dtor.CreateCall(AsanUnregisterGlobals, - {IRB.CreatePointerCast(AllGlobals, IntptrTy), - ConstantInt::get(IntptrTy, n)}); - } - - appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndDtorPriority); - DEBUG(dbgs() << M); return true; } Modified: vendor/llvm/dist/lib/Transforms/Scalar/NewGVN.cpp ============================================================================== --- vendor/llvm/dist/lib/Transforms/Scalar/NewGVN.cpp Tue Jan 24 18:56:09 2017 (r312703) +++ vendor/llvm/dist/lib/Transforms/Scalar/NewGVN.cpp Tue Jan 24 19:17:53 2017 (r312704) @@ -85,6 +85,8 @@ STATISTIC(NumGVNLeaderChanges, "Number o STATISTIC(NumGVNSortedLeaderChanges, "Number of sorted leader changes"); STATISTIC(NumGVNAvoidedSortedLeaderChanges, "Number of avoided sorted leader changes"); +STATISTIC(NumGVNNotMostDominatingLeader, + "Number of times a member dominated it's new classes' leader"); //===----------------------------------------------------------------------===// // GVN Pass @@ -1073,17 +1075,20 @@ void NewGVN::moveValueToNewCongruenceCla if (I == OldClass->NextLeader.first) OldClass->NextLeader = {nullptr, ~0U}; - // The new instruction and new class leader may either be siblings in the - // dominator tree, or the new class leader should dominate the new member - // instruction. We simply check that the member instruction does not properly - // dominate the new class leader. - assert( - !isa(NewClass->RepLeader) || !NewClass->RepLeader || - I == NewClass->RepLeader || - !DT->properlyDominates( + // It's possible, though unlikely, for us to discover equivalences such + // that the current leader does not dominate the old one. + // This statistic tracks how often this happens. + // We assert on phi nodes when this happens, currently, for debugging, because + // we want to make sure we name phi node cycles properly. + if (isa(NewClass->RepLeader) && NewClass->RepLeader && + I != NewClass->RepLeader && + DT->properlyDominates( I->getParent(), - cast(NewClass->RepLeader)->getParent()) && - "New class for instruction should not be dominated by instruction"); + cast(NewClass->RepLeader)->getParent())) { + ++NumGVNNotMostDominatingLeader; + assert(!isa(I) && + "New class for instruction should not be dominated by instruction"); + } if (NewClass->RepLeader != I) { auto DFSNum = InstrDFS.lookup(I); Added: vendor/llvm/dist/test/CodeGen/AArch64/ldst-opt.mir ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/llvm/dist/test/CodeGen/AArch64/ldst-opt.mir Tue Jan 24 19:17:53 2017 (r312704) @@ -0,0 +1,132 @@ +# RUN: llc -mtriple=aarch64--linux-gnu -run-pass=aarch64-ldst-opt %s -verify-machineinstrs -o - 2>&1 | FileCheck %s +--- | + define void @promote-load-from-store() { ret void } + define void @store-pair() { ret void } + define void @store-pair-clearkill0() { ret void } + define void @store-pair-clearkill1() { ret void } +... +--- +name: promote-load-from-store +tracksRegLiveness: true +body: | + bb.0: + liveins: %w1, %x0, %lr + + STRWui killed %w1, %x0, 0 :: (store 4) + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + %w0 = LDRHHui killed %x0, 1 :: (load 2) + RET %lr, implicit %w0 + +... +# Don't count transient instructions towards search limits. +# CHECK-LABEL: name: promote-load-from-store +# CHECK: STRWui %w1 +# CHECK: UBFMWri %w1 +--- +name: store-pair +tracksRegLiveness: true +body: | + bb.0: + liveins: %w1, %x0, %lr + + STRWui %w1, %x0, 0 :: (store 4) + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + CFI_INSTRUCTION 0 + STRWui killed %w1, killed %x0, 1 :: (store 4) + RET %lr + +... +# CHECK-LABEL: name: store-pair +# CHECK: STPWi +--- +name: store-pair-clearkill0 +tracksRegLiveness: true +body: | + bb.0: + liveins: %w1, %x0, %lr + + STRWui %w1, %x0, 0 :: (store 4) + %w2 = COPY %w1 + %x3 = COPY %x0 + STRWui killed %w1, killed %x0, 1 :: (store 4) + RET %lr +... +# When merging a lower store with an upper one, we must clear kill flags on +# the lower store. +# CHECK-LABEL: store-pair-clearkill0 +# CHECK-NOT: STPWi %w1, killed %w1, %x0, 0 :: (store 4) +# CHECK: STPWi %w1, %w1, %x0, 0 :: (store 4) +# CHECK: %w2 = COPY %w1 +# CHECK: RET %lr +--- +name: store-pair-clearkill1 +tracksRegLiveness: true +body: | + bb.0: + liveins: %x0, %lr + + %w1 = MOVi32imm 13 + %w2 = MOVi32imm 7 + STRWui %w1, %x0, 1 :: (store 4) + %w2 = COPY killed %w1 + STRWui killed %w2, %x0, 0 :: (store 4) + + %w1 = MOVi32imm 42 + %w2 = MOVi32imm 7 + STRWui %w1, %x0, 0 :: (store 4) + %w2 = COPY killed %w1 + STRWui killed %w2, killed %x0, 1 :: (store 4) + + RET %lr +... +# When merging an upper store with a lower one, kill flags along the way need +# to be removed; In this case the kill flag on %w1. +# CHECK-LABEL: store-pair-clearkill1 +# CHECK: %w1 = MOVi32imm +# CHECK: %w2 = MOVi32imm +# CHECK-NOT: %w2 = COPY killed %w1 +# CHECK: %w2 = COPY %w1 +# CHECK: STPWi killed %w2, %w1, %x0, 0 + +# CHECK: %w1 = MOVi32imm +# CHECK: %w2 = MOVi32imm +# CHECK-NOT: %w2 = COPY killed %w1 +# CHECK: %w2 = COPY %w1 +# CHECK: STPWi %w1, killed %w2, killed %x0, 0 Modified: vendor/llvm/dist/test/CodeGen/Thumb2/float-intrinsics-double.ll ============================================================================== --- vendor/llvm/dist/test/CodeGen/Thumb2/float-intrinsics-double.ll Tue Jan 24 18:56:09 2017 (r312703) +++ vendor/llvm/dist/test/CodeGen/Thumb2/float-intrinsics-double.ll Tue Jan 24 19:17:53 2017 (r312704) @@ -18,7 +18,7 @@ declare double @llvm.powi.f64(double define double @powi_d(double %a, i32 %b) { ; CHECK-LABEL: powi_d: ; SOFT: {{(bl|b)}} __powidf2 -; HARD: bl __powidf2 +; HARD: b __powidf2 %1 = call double @llvm.powi.f64(double %a, i32 %b) ret double %1 } Modified: vendor/llvm/dist/test/CodeGen/Thumb2/float-intrinsics-float.ll ============================================================================== --- vendor/llvm/dist/test/CodeGen/Thumb2/float-intrinsics-float.ll Tue Jan 24 18:56:09 2017 (r312703) +++ vendor/llvm/dist/test/CodeGen/Thumb2/float-intrinsics-float.ll Tue Jan 24 19:17:53 2017 (r312704) @@ -18,7 +18,7 @@ declare float @llvm.powi.f32(float % define float @powi_f(float %a, i32 %b) { ; CHECK-LABEL: powi_f: ; SOFT: bl __powisf2 -; HARD: bl __powisf2 +; HARD: b __powisf2 %1 = call float @llvm.powi.f32(float %a, i32 %b) ret float %1 } Added: vendor/llvm/dist/test/CodeGen/Thumb2/intrinsics-cc.ll ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/llvm/dist/test/CodeGen/Thumb2/intrinsics-cc.ll Tue Jan 24 19:17:53 2017 (r312704) @@ -0,0 +1,41 @@ +; RUN: llc -mtriple thumbv7-unknown-none-eabi -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH +; RUN: llc -mtriple thumbv7-unknown-none-eabi -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-SOFT +; RUN: llc -mtriple thumbv7-unknown-none-eabihf -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-HARD +; RUN: llc -mtriple thumbv7-unknown-none-eabihf -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH + +; RUN: llc -mtriple thumbv7-unknown-none-gnueabi -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH +; RUN: llc -mtriple thumbv7-unknown-none-gnueabi -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-SOFT +; RUN: llc -mtriple thumbv7-unknown-none-gnueabihf -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-HARD +; RUN: llc -mtriple thumbv7-unknown-none-gnueabihf -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH + +; RUN: llc -mtriple thumbv7-unknown-none-musleabi -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH +; RUN: llc -mtriple thumbv7-unknown-none-musleabi -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-SOFT +; RUN: llc -mtriple thumbv7-unknown-none-musleabihf -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-HARD +; RUN: llc -mtriple thumbv7-unknown-none-musleabihf -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH + +declare float @llvm.powi.f32(float, i32) + +define float @f(float %f, i32 %i) { +entry: + %0 = call float @llvm.powi.f32(float %f, i32 %i) + ret float %0 +} + +; CHECK-MATCH: b __powisf2 +; CHECK-MISMATCH: bl __powisf2 +; CHECK-TO-SOFT: vmov s0, r0 +; CHECK-TO-HARD: vmov r0, s0 + +declare double @llvm.powi.f64(double, i32) + +define double @g(double %d, i32 %i) { +entry: + %0 = call double @llvm.powi.f64(double %d, i32 %i) + ret double %0 +} + +; CHECK-MATCH: b __powidf2 +; CHECK-MISMATCH: bl __powidf2 +; CHECK-TO-SOFT: vmov d0, r0, r1 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***