diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-24 19:17:53 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-24 19:17:53 +0000 |
commit | 02a336801959d4fc2ea0657d4489596e1ecbfee0 (patch) | |
tree | 776cc4ed9ad3080c3c6afbb0ffb73177c40292e8 | |
parent | 7c71d32ab52480cb7bfd9f951450060263a5b9e7 (diff) |
Notes
21 files changed, 673 insertions, 491 deletions
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index d9e249aad21d8..a46e49ccde83e 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -512,7 +512,7 @@ private: } Metadata *getFnMetadataByID(unsigned ID) { - return MDLoader->getMetadataFwdRef(ID); + return MDLoader->getMetadataFwdRefOrLoad(ID); } BasicBlock *getBasicBlock(unsigned ID) const { diff --git a/lib/Bitcode/Reader/MetadataLoader.cpp b/lib/Bitcode/Reader/MetadataLoader.cpp index b05ab4b1da853..a44b92effc7ed 100644 --- a/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/lib/Bitcode/Reader/MetadataLoader.cpp @@ -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 Pimpl->hasFwdRefs(); } /// 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) { diff --git a/lib/Bitcode/Reader/MetadataLoader.h b/lib/Bitcode/Reader/MetadataLoader.h index 753846c6eadfb..442dfc94e4e19 100644 --- a/lib/Bitcode/Reader/MetadataLoader.h +++ b/lib/Bitcode/Reader/MetadataLoader.h @@ -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); diff --git a/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp b/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp index 8a76c42b58986..a2887aa818953 100644 --- a/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp +++ b/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp @@ -687,9 +687,30 @@ AArch64LoadStoreOpt::mergePairedInsns(MachineBasicBlock::iterator I, 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)); diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 32b7c87e61bb9..fb4c689bcb598 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -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(const TargetMachine &TM, 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<RTLIB::Libcall>(LCID), + IsHFTarget ? CallingConv::ARM_AAPCS_VFP + : CallingConv::ARM_AAPCS); + } if (Subtarget->isTargetMachO()) { // Uses VFP for Thumb libfuncs if available. diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index 7a7f91f4d3c46..84c6eb845bb89 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -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); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 2f13b722eb3b1..da96040d99965 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -28788,10 +28788,12 @@ static SDValue combineExtractVectorElt(SDNode *N, SelectionDAG &DAG, 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 combineVSelectWithAllOnesOrZeros(SDNode *N, SelectionDAG &DAG, } } - 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, SelectionDAG &DAG, } } - 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 diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 9c4b417e35e1a..ffd518e52968a 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -600,6 +600,22 @@ private: void initializeCallbacks(Module &M); bool InstrumentGlobals(IRBuilder<> &IRB, Module &M); + void InstrumentGlobalsCOFF(IRBuilder<> &IRB, Module &M, + ArrayRef<GlobalVariable *> ExtendedGlobals, + ArrayRef<Constant *> MetadataInitializers); + void InstrumentGlobalsMachO(IRBuilder<> &IRB, Module &M, + ArrayRef<GlobalVariable *> ExtendedGlobals, + ArrayRef<Constant *> MetadataInitializers); + void + InstrumentGlobalsWithMetadataArray(IRBuilder<> &IRB, Module &M, + ArrayRef<GlobalVariable *> ExtendedGlobals, + ArrayRef<Constant *> 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::initializeCallbacks(Module &M) { // 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<GlobalVariable *> ExtendedGlobals, + ArrayRef<Constant *> 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<GlobalVariable *> ExtendedGlobals, + ArrayRef<Constant *> 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<GlobalValue *, 16> 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<GlobalVariable *> ExtendedGlobals, + ArrayRef<Constant *> 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::InstrumentGlobals(IRBuilder<> &IRB, Module &M) { 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::InstrumentGlobals(IRBuilder<> &IRB, Module &M) { 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<Constant *, 16> 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<GlobalValue *, 16> LivenessGlobals( - UseMachOGlobalsSection ? n : 0); + SmallVector<GlobalVariable *, 16> NewGlobals(n); + SmallVector<Constant *, 16> Initializers(n); bool HasDynamicallyInitializedGlobals = false; @@ -1681,25 +1839,7 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) { 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::InstrumentGlobals(IRBuilder<> &IRB, Module &M) { 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; } diff --git a/lib/Transforms/Scalar/NewGVN.cpp b/lib/Transforms/Scalar/NewGVN.cpp index 6043e04bb8c59..57e6e3ddad949 100644 --- a/lib/Transforms/Scalar/NewGVN.cpp +++ b/lib/Transforms/Scalar/NewGVN.cpp @@ -85,6 +85,8 @@ STATISTIC(NumGVNLeaderChanges, "Number of leader changes"); 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::moveValueToNewCongruenceClass(Instruction *I, 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<Instruction>(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<Instruction>(NewClass->RepLeader) && NewClass->RepLeader && + I != NewClass->RepLeader && + DT->properlyDominates( I->getParent(), - cast<Instruction>(NewClass->RepLeader)->getParent()) && - "New class for instruction should not be dominated by instruction"); + cast<Instruction>(NewClass->RepLeader)->getParent())) { + ++NumGVNNotMostDominatingLeader; + assert(!isa<PHINode>(I) && + "New class for instruction should not be dominated by instruction"); + } if (NewClass->RepLeader != I) { auto DFSNum = InstrDFS.lookup(I); diff --git a/test/CodeGen/AArch64/ldst-opt-dbg-limit.mir b/test/CodeGen/AArch64/ldst-opt-dbg-limit.mir deleted file mode 100644 index 45542cae98faf..0000000000000 --- a/test/CodeGen/AArch64/ldst-opt-dbg-limit.mir +++ /dev/null @@ -1,133 +0,0 @@ -# RUN: llc -run-pass=aarch64-ldst-opt %s -o - 2>&1 | FileCheck %s ---- | - target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" - target triple = "aarch64--linux-gnu" - - ; Function Attrs: nounwind - define i16 @promote-load-from-store(i32* %dst, i32 %x) #0 { - store i32 %x, i32* %dst - %dst16 = bitcast i32* %dst to i16* - %dst1 = getelementptr inbounds i16, i16* %dst16, i32 1 - %x16 = load i16, i16* %dst1 - ret i16 %x16 - } - - ; Function Attrs: nounwind - define void @store-pair(i32* %dst, i32 %x, i32 %y) #0 { - %dst01 = bitcast i32* %dst to i32* - %dst1 = getelementptr inbounds i32, i32* %dst, i32 1 - store i32 %x, i32* %dst01 - store i32 %x, i32* %dst1 - ret void - } - - attributes #0 = { nounwind } - -... ---- -name: promote-load-from-store -alignment: 2 -exposesReturnsTwice: false -tracksRegLiveness: true -liveins: - - { reg: '%x0' } - - { reg: '%w1' } -frameInfo: - isFrameAddressTaken: false - isReturnAddressTaken: false - hasStackMap: false - hasPatchPoint: false - stackSize: 0 - offsetAdjustment: 0 - maxAlignment: 0 - adjustsStack: false - hasCalls: false - maxCallFrameSize: 0 - hasOpaqueSPAdjustment: false - hasVAStart: false - hasMustTailInVarArgFunc: false -body: | - bb.0 (%ir-block.0): - liveins: %w1, %x0, %lr - - STRWui killed %w1, %x0, 0 :: (store 4 into %ir.dst) - 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 from %ir.dst1) - RET %lr, implicit %w0 - -... -# CHECK-LABEL: name: promote-load-from-store -# CHECK: STRWui %w1 -# CHECK: UBFMWri %w1 ---- -name: store-pair -alignment: 2 -exposesReturnsTwice: false -tracksRegLiveness: true -liveins: - - { reg: '%x0' } - - { reg: '%w1' } -frameInfo: - isFrameAddressTaken: false - isReturnAddressTaken: false - hasStackMap: false - hasPatchPoint: false - stackSize: 0 - offsetAdjustment: 0 - maxAlignment: 0 - adjustsStack: false - hasCalls: false - maxCallFrameSize: 0 - hasOpaqueSPAdjustment: false - hasVAStart: false - hasMustTailInVarArgFunc: false -body: | - bb.0 (%ir-block.0): - liveins: %w1, %x0, %lr - - STRWui %w1, %x0, 0 :: (store 4 into %ir.dst01) - 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 into %ir.dst1) - RET %lr - -... -# CHECK-LABEL: name: store-pair -# CHECK: STPWi diff --git a/test/CodeGen/AArch64/ldst-opt.mir b/test/CodeGen/AArch64/ldst-opt.mir new file mode 100644 index 0000000000000..8f0b71be34830 --- /dev/null +++ b/test/CodeGen/AArch64/ldst-opt.mir @@ -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 diff --git a/test/CodeGen/Thumb2/float-intrinsics-double.ll b/test/CodeGen/Thumb2/float-intrinsics-double.ll index 9e94990838299..657d1b172da98 100644 --- a/test/CodeGen/Thumb2/float-intrinsics-double.ll +++ b/test/CodeGen/Thumb2/float-intrinsics-double.ll @@ -18,7 +18,7 @@ declare double @llvm.powi.f64(double %Val, i32 %power) 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 } diff --git a/test/CodeGen/Thumb2/float-intrinsics-float.ll b/test/CodeGen/Thumb2/float-intrinsics-float.ll index fda840d90f36f..847aeacd2f914 100644 --- a/test/CodeGen/Thumb2/float-intrinsics-float.ll +++ b/test/CodeGen/Thumb2/float-intrinsics-float.ll @@ -18,7 +18,7 @@ declare float @llvm.powi.f32(float %Val, i32 %power) 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 } diff --git a/test/CodeGen/Thumb2/intrinsics-cc.ll b/test/CodeGen/Thumb2/intrinsics-cc.ll new file mode 100644 index 0000000000000..ab5081e3ab923 --- /dev/null +++ b/test/CodeGen/Thumb2/intrinsics-cc.ll @@ -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 +; CHECK-TO-HARD: vmov r0, r1, d0 + diff --git a/test/CodeGen/X86/sse1.ll b/test/CodeGen/X86/sse1.ll index beedb1d246557..9488d6d26056c 100644 --- a/test/CodeGen/X86/sse1.ll +++ b/test/CodeGen/X86/sse1.ll @@ -215,3 +215,136 @@ define <4 x i32> @PR30512(<4 x i32> %x, <4 x i32> %y) nounwind { ret <4 x i32> %zext } +; Fragile test warning - we need to induce the generation of a vselect +; post-legalization to cause the crash seen in: +; https://llvm.org/bugs/show_bug.cgi?id=31672 +; Is there a way to do that without an unsafe/fast sqrt intrinsic call? +; Also, although the goal for adding this test is to prove that we +; don't crash, I have no idea what this code is doing, so I'm keeping +; the full codegen checks in case there's motivation to improve this. + +define <2 x float> @PR31672() #0 { +; X32-LABEL: PR31672: +; X32: # BB#0: +; X32-NEXT: pushl %ebp +; X32-NEXT: movl %esp, %ebp +; X32-NEXT: andl $-16, %esp +; X32-NEXT: subl $80, %esp +; X32-NEXT: xorps %xmm0, %xmm0 +; X32-NEXT: movaps {{.*#+}} xmm1 = <42,3,u,u> +; X32-NEXT: movaps %xmm1, %xmm2 +; X32-NEXT: cmpeqps %xmm0, %xmm2 +; X32-NEXT: movaps %xmm2, {{[0-9]+}}(%esp) +; X32-NEXT: movaps %xmm0, {{[0-9]+}}(%esp) +; X32-NEXT: rsqrtps %xmm1, %xmm0 +; X32-NEXT: mulps %xmm0, %xmm1 +; X32-NEXT: mulps %xmm0, %xmm1 +; X32-NEXT: addps {{\.LCPI.*}}, %xmm1 +; X32-NEXT: mulps {{\.LCPI.*}}, %xmm0 +; X32-NEXT: mulps %xmm1, %xmm0 +; X32-NEXT: movaps %xmm0, {{[0-9]+}}(%esp) +; X32-NEXT: movl {{[0-9]+}}(%esp), %eax +; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X32-NEXT: andl %eax, %ecx +; X32-NEXT: notl %eax +; X32-NEXT: andl {{[0-9]+}}(%esp), %eax +; X32-NEXT: orl %ecx, %eax +; X32-NEXT: movl %eax, (%esp) +; X32-NEXT: movl {{[0-9]+}}(%esp), %eax +; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X32-NEXT: movl {{[0-9]+}}(%esp), %edx +; X32-NEXT: andl %ecx, %edx +; X32-NEXT: notl %ecx +; X32-NEXT: andl {{[0-9]+}}(%esp), %ecx +; X32-NEXT: orl %edx, %ecx +; X32-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X32-NEXT: movl {{[0-9]+}}(%esp), %edx +; X32-NEXT: andl %ecx, %edx +; X32-NEXT: notl %ecx +; X32-NEXT: andl {{[0-9]+}}(%esp), %ecx +; X32-NEXT: orl %edx, %ecx +; X32-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X32-NEXT: andl %eax, %ecx +; X32-NEXT: notl %eax +; X32-NEXT: andl {{[0-9]+}}(%esp), %eax +; X32-NEXT: orl %ecx, %eax +; X32-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X32-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero +; X32-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero +; X32-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; X32-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero +; X32-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero +; X32-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] +; X32-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] +; X32-NEXT: movl %ebp, %esp +; X32-NEXT: popl %ebp +; X32-NEXT: retl +; +; X64-LABEL: PR31672: +; X64: # BB#0: +; X64-NEXT: xorps %xmm0, %xmm0 +; X64-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; X64-NEXT: movaps {{.*#+}} xmm1 = <42,3,u,u> +; X64-NEXT: cmpeqps %xmm1, %xmm0 +; X64-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; X64-NEXT: rsqrtps %xmm1, %xmm0 +; X64-NEXT: mulps %xmm0, %xmm1 +; X64-NEXT: mulps %xmm0, %xmm1 +; X64-NEXT: addps {{.*}}(%rip), %xmm1 +; X64-NEXT: mulps {{.*}}(%rip), %xmm0 +; X64-NEXT: mulps %xmm1, %xmm0 +; X64-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; X64-NEXT: movq -{{[0-9]+}}(%rsp), %r8 +; X64-NEXT: movq -{{[0-9]+}}(%rsp), %r9 +; X64-NEXT: movq -{{[0-9]+}}(%rsp), %r10 +; X64-NEXT: movq -{{[0-9]+}}(%rsp), %rdi +; X64-NEXT: movl %r9d, %esi +; X64-NEXT: andl %edi, %esi +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: notl %ecx +; X64-NEXT: movq -{{[0-9]+}}(%rsp), %rdx +; X64-NEXT: movq -{{[0-9]+}}(%rsp), %rax +; X64-NEXT: andl %eax, %ecx +; X64-NEXT: orl %esi, %ecx +; X64-NEXT: movl %ecx, -{{[0-9]+}}(%rsp) +; X64-NEXT: movl %r8d, %ecx +; X64-NEXT: andl %r10d, %ecx +; X64-NEXT: movl %r10d, %esi +; X64-NEXT: notl %esi +; X64-NEXT: andl %edx, %esi +; X64-NEXT: orl %ecx, %esi +; X64-NEXT: movl %esi, -{{[0-9]+}}(%rsp) +; X64-NEXT: shrq $32, %r9 +; X64-NEXT: shrq $32, %rdi +; X64-NEXT: andl %edi, %r9d +; X64-NEXT: notl %edi +; X64-NEXT: shrq $32, %rax +; X64-NEXT: andl %edi, %eax +; X64-NEXT: orl %r9d, %eax +; X64-NEXT: movl %eax, -{{[0-9]+}}(%rsp) +; X64-NEXT: shrq $32, %r8 +; X64-NEXT: shrq $32, %r10 +; X64-NEXT: andl %r10d, %r8d +; X64-NEXT: notl %r10d +; X64-NEXT: shrq $32, %rdx +; X64-NEXT: andl %r10d, %edx +; X64-NEXT: orl %r8d, %edx +; X64-NEXT: movl %edx, -{{[0-9]+}}(%rsp) +; X64-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero +; X64-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero +; X64-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] +; X64-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero +; X64-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero +; X64-NEXT: unpcklps {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1] +; X64-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] +; X64-NEXT: retq + %t0 = call fast <2 x float> @llvm.sqrt.v2f32(<2 x float> <float 42.0, float 3.0>) + ret <2 x float> %t0 +} + +declare <2 x float> @llvm.sqrt.v2f32(<2 x float>) #1 + +attributes #0 = { nounwind "unsafe-fp-math"="true" } + diff --git a/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll b/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll index 5d510014a12a9..a8fe6a9f62562 100644 --- a/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll +++ b/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll @@ -16,18 +16,17 @@ target triple = "x86_64-apple-macosx10.11.0" ; Find the metadata for @global: -; CHECK: [[METADATA:@.+]] = internal global {{.*}} @global {{.*}} section "__DATA,__asan_globals,regular", align 64 +; CHECK: [[METADATA:@.+]] = internal global {{.*}} @global {{.*}} section "__DATA,__asan_globals,regular" ; Find the liveness binder for @global and its metadata: ; CHECK: @__asan_binder_global = internal global {{.*}} @global {{.*}} [[METADATA]] {{.*}} section "__DATA,__asan_liveness,regular,live_support" -; Test that there is the flag global variable: -; CHECK: @__asan_globals_registered = common hidden global i64 0 - ; The binder has to be inserted to llvm.compiler.used to avoid being stripped ; during LTO. ; CHECK: @llvm.compiler.used {{.*}} @__asan_binder_global {{.*}} section "llvm.metadata" +; Test that there is the flag global variable: +; CHECK: @__asan_globals_registered = common hidden global i64 0 ; Test that __asan_register_image_globals is invoked from the constructor: ; CHECK-LABEL: define internal void @asan.module_ctor diff --git a/test/ThinLTO/X86/lazyload_metadata.ll b/test/ThinLTO/X86/lazyload_metadata.ll index 7bd3e641bc779..bddabcdf9e722 100644 --- a/test/ThinLTO/X86/lazyload_metadata.ll +++ b/test/ThinLTO/X86/lazyload_metadata.ll @@ -11,19 +11,20 @@ ; RUN: -o /dev/null -stats \ ; RUN: 2>&1 | FileCheck %s -check-prefix=LAZY ; LAZY: 49 bitcode-reader - Number of Metadata records loaded -; LAZY: 1 bitcode-reader - Number of MDStrings loaded +; LAZY: 2 bitcode-reader - Number of MDStrings loaded ; RUN: llvm-lto -thinlto-action=import %t2.bc -thinlto-index=%t3.bc \ ; RUN: -o /dev/null -disable-ondemand-mds-loading -stats \ ; RUN: 2>&1 | FileCheck %s -check-prefix=NOTLAZY ; NOTLAZY: 58 bitcode-reader - Number of Metadata records loaded -; NOTLAZY: 6 bitcode-reader - Number of MDStrings loaded +; NOTLAZY: 7 bitcode-reader - Number of MDStrings loaded target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.11.0" define void @globalfunc1(i32 %arg) { + %x = call i1 @llvm.type.test(i8* undef, metadata !"typeid1") %tmp = add i32 %arg, 0, !metadata !2 ret void } @@ -34,6 +35,7 @@ define void @globalfunc1(i32 %arg) { ; These function are not imported and so we don't want to load their metadata. define void @globalfunc2(i32 %arg) { + %x = call i1 @llvm.type.test(i8* undef, metadata !"typeid1") %tmp = add i32 %arg, 0, !metadata !1 ret void } @@ -43,6 +45,8 @@ define void @globalfunc3(i32 %arg) { ret void } +declare i1 @llvm.type.test(i8* %ptr, metadata %bitset) nounwind readnone + !1 = !{!2, !3, !4, !5, !6, !7, !8, !9} !2 = !{!"Hello World"} !3 = !{!"3"} @@ -51,4 +55,4 @@ define void @globalfunc3(i32 %arg) { !6 = !{!9} !7 = !{!"7"} !8 = !{!"8"} -!9 = !{!6} +!9 = !{!6}
\ No newline at end of file diff --git a/test/Transforms/NewGVN/pr31682.ll b/test/Transforms/NewGVN/pr31682.ll new file mode 100644 index 0000000000000..108e1e19afbd4 --- /dev/null +++ b/test/Transforms/NewGVN/pr31682.ll @@ -0,0 +1,42 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +%struct.foo = type { i32, i32, [2 x [4 x [6 x [6 x i16]]]] } + +@global = external global %struct.foo* + +define void @bar() { +; CHECK-LABEL: @bar( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP:%.*]] = load %struct.foo*, %struct.foo** @global +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb2: +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_FOO:%.*]], %struct.foo* [[TMP]], i64 0, i32 1 +; CHECK-NEXT: br i1 undef, label [[BB2]], label [[BB7:%.*]] +; CHECK: bb7: +; CHECK-NEXT: br label [[BB10:%.*]] +; CHECK: bb10: +; CHECK-NEXT: br label [[BB10]] +; +bb: + %tmp = load %struct.foo*, %struct.foo** @global + %tmp1 = getelementptr %struct.foo, %struct.foo* %tmp + br label %bb2 + +bb2: ; preds = %bb2, %bb + %tmp3 = phi %struct.foo* [ undef, %bb ], [ %tmp6, %bb2 ] + %tmp4 = getelementptr %struct.foo, %struct.foo* %tmp3, i64 0, i32 1 + %tmp5 = load i32, i32* %tmp4 + %tmp6 = load %struct.foo*, %struct.foo** @global + br i1 undef, label %bb2, label %bb7 + +bb7: ; preds = %bb2 + %tmp8 = phi %struct.foo* [ %tmp6, %bb2 ] + %tmp9 = getelementptr %struct.foo, %struct.foo* %tmp8, i64 0, i32 1 + br label %bb10 + +bb10: ; preds = %bb10, %bb7 + %tmp11 = load i32, i32* %tmp9 + br label %bb10 +} diff --git a/test/tools/llvm-cxxfilt/invalid.test b/test/tools/llvm-cxxfilt/invalid.test new file mode 100644 index 0000000000000..10f3b2e813236 --- /dev/null +++ b/test/tools/llvm-cxxfilt/invalid.test @@ -0,0 +1,6 @@ +RUN: llvm-cxxfilt _Z1fi __Z1fi f ___ZSt1ff_block_invoke | FileCheck %s + +CHECK: f(int) +CHECK-NEXT: __Z1fi +CHECK-NEXT: f +CHECK-NEXT: invocation function for block in std::f(float) diff --git a/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/tools/llvm-cxxfilt/llvm-cxxfilt.cpp index 80a54bbf63d80..1e2797ba33343 100644 --- a/tools/llvm-cxxfilt/llvm-cxxfilt.cpp +++ b/tools/llvm-cxxfilt/llvm-cxxfilt.cpp @@ -14,9 +14,12 @@ using namespace llvm; -static void demangle(llvm::raw_ostream &OS, const char *Mangled) { +static void demangle(llvm::raw_ostream &OS, const std::string &Mangled) { int Status; - char *Demangled = itaniumDemangle(Mangled, nullptr, nullptr, &Status); + char *Demangled = nullptr; + if ((Mangled.size() >= 2 && Mangled.compare(0, 2, "_Z")) || + (Mangled.size() >= 4 && Mangled.compare(0, 4, "___Z"))) + Demangled = itaniumDemangle(Mangled.c_str(), nullptr, nullptr, &Status); OS << (Demangled ? Demangled : Mangled) << '\n'; free(Demangled); } @@ -24,7 +27,7 @@ static void demangle(llvm::raw_ostream &OS, const char *Mangled) { int main(int argc, char **argv) { if (argc == 1) for (std::string Mangled; std::getline(std::cin, Mangled);) - demangle(llvm::outs(), Mangled.c_str()); + demangle(llvm::outs(), Mangled); else for (int I = 1; I < argc; ++I) demangle(llvm::outs(), argv[I]); diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh index 73e31d46d5197..642bb670e7e21 100755 --- a/utils/release/test-release.sh +++ b/utils/release/test-release.sh @@ -37,6 +37,7 @@ do_libunwind="yes" do_test_suite="yes" do_openmp="yes" do_lldb="no" +do_polly="no" BuildDir="`pwd`" ExtraConfigureFlags="" ExportBranch="" @@ -65,6 +66,8 @@ function usage() { echo " -no-openmp Disable check-out & build libomp" echo " -lldb Enable check-out & build lldb" echo " -no-lldb Disable check-out & build lldb (default)" + echo " -polly Enable check-out & build Polly" + echo " -no-polly Disable check-out & build Polly (default)" } while [ $# -gt 0 ]; do @@ -146,6 +149,12 @@ while [ $# -gt 0 ]; do -no-lldb ) do_lldb="no" ;; + -polly ) + do_polly="yes" + ;; + -no-polly ) + do_polly="no" + ;; -help | --help | -h | --h | -\? ) usage exit 0 @@ -219,6 +228,9 @@ fi if [ $do_lldb = "yes" ]; then projects="$projects lldb" fi +if [ $do_polly = "yes" ]; then + projects="$projects polly" +fi # Go to the build directory (may be different from CWD) BuildDir=$BuildDir/$RC @@ -285,7 +297,7 @@ function export_sources() { cfe) projsrc=llvm.src/tools/clang ;; - lldb) + lldb|polly) projsrc=llvm.src/tools/$proj ;; clang-tools-extra) |