From 4e20bb0468b8d0db13287e666b482eb93689be99 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Tue, 8 Aug 2017 16:52:53 +0000 Subject: [PATCH 1/3] Vendor import of llvm release_50 branch r310316: https://llvm.org/svn/llvm-project/llvm/branches/release_50@310316 --- bindings/ocaml/llvm/llvm.ml | 4 + bindings/ocaml/llvm/llvm.mli | 2 + bindings/ocaml/llvm/llvm_ocaml.c | 5 + cmake/modules/AddOCaml.cmake | 7 +- docs/ReleaseNotes.rst | 17 ++- include/llvm/Analysis/ValueTracking.h | 6 + include/llvm/CodeGen/MachineFunction.h | 6 + include/llvm/CodeGen/MachineInstr.h | 3 + lib/Analysis/ValueTracking.cpp | 63 ++++++++ lib/CodeGen/BranchFolding.cpp | 5 +- lib/CodeGen/MachineFunction.cpp | 14 ++ lib/CodeGen/MachineInstr.cpp | 6 +- lib/CodeGen/ScheduleDAGInstrs.cpp | 63 +------- .../SelectionDAG/SelectionDAGBuilder.cpp | 39 +++-- lib/CodeGen/StackColoring.cpp | 58 +++++++- lib/IR/ConstantFold.cpp | 12 +- lib/Object/COFFImportFile.cpp | 13 +- .../AArch64/AArch64ExpandPseudoInsts.cpp | 12 ++ lib/Target/AArch64/AArch64FrameLowering.cpp | 52 ++++--- lib/Target/AArch64/AArch64ISelLowering.cpp | 4 +- lib/Target/AArch64/AArch64InstrInfo.td | 28 ++++ lib/Target/AArch64/AArch64MacroFusion.cpp | 4 +- lib/Target/X86/X86ISelLowering.cpp | 11 +- lib/Target/X86/X86InstrSSE.td | 3 +- lib/Transforms/IPO/ArgumentPromotion.cpp | 2 +- .../Instrumentation/AddressSanitizer.cpp | 3 +- lib/Transforms/Scalar/SCCP.cpp | 3 +- lib/Transforms/Utils/CloneModule.cpp | 3 +- .../CodeGen/AArch64/aarch64_win64cc_vararg.ll | 4 +- test/CodeGen/AArch64/misched-fusion-aes.ll | 130 ++++++---------- test/CodeGen/AArch64/tbi.ll | 11 ++ test/CodeGen/AArch64/win64_vararg.ll | 111 +++++++++++++- test/CodeGen/Mips/cconv/pr33883.ll | 12 ++ test/CodeGen/Mips/pr33978.ll | 20 +++ .../X86/conditional-tailcall-samedest.mir | 139 ++++++++++++++++++ test/CodeGen/X86/pause.ll | 15 ++ test/CodeGen/X86/tail-call-mutable-memarg.ll | 42 ++++++ test/DllTool/coff-weak-exports.def | 18 +-- .../AddressSanitizer/force-dynamic-shadow.ll | 22 +++ .../stack-poisoning-byval-args.ll | 4 + test/MC/AArch64/arm64-crypto.s | 1 + test/Transforms/ArgumentPromotion/byval.ll | 43 ++++-- test/Transforms/InstSimplify/pr33957.ll | 29 ++++ test/Transforms/SCCP/definite-initializer.ll | 11 ++ unittests/Transforms/Utils/Cloning.cpp | 59 ++++++++ 45 files changed, 872 insertions(+), 247 deletions(-) create mode 100644 test/CodeGen/Mips/cconv/pr33883.ll create mode 100644 test/CodeGen/Mips/pr33978.ll create mode 100644 test/CodeGen/X86/conditional-tailcall-samedest.mir create mode 100644 test/CodeGen/X86/pause.ll create mode 100644 test/CodeGen/X86/tail-call-mutable-memarg.ll create mode 100644 test/Instrumentation/AddressSanitizer/force-dynamic-shadow.ll create mode 100644 test/Transforms/InstSimplify/pr33957.ll create mode 100644 test/Transforms/SCCP/definite-initializer.ll diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml index 6e8ca662ef67..59f0f178c288 100644 --- a/bindings/ocaml/llvm/llvm.ml +++ b/bindings/ocaml/llvm/llvm.ml @@ -20,6 +20,10 @@ type llattribute type llmemorybuffer type llmdkind +exception FeatureDisabled of string + +let () = Callback.register_exception "Llvm.FeatureDisabled" (FeatureDisabled "") + module TypeKind = struct type t = | Void diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli index c422e78f5d2d..3387c1ec52fe 100644 --- a/bindings/ocaml/llvm/llvm.mli +++ b/bindings/ocaml/llvm/llvm.mli @@ -371,6 +371,8 @@ type ('a, 'b) llrev_pos = (** {6 Exceptions} *) +exception FeatureDisabled of string + exception IoError of string diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c index 4b6d1c5072bc..137b17f26bfb 100644 --- a/bindings/ocaml/llvm/llvm_ocaml.c +++ b/bindings/ocaml/llvm/llvm_ocaml.c @@ -336,7 +336,12 @@ CAMLprim LLVMContextRef llvm_type_context(LLVMTypeRef Ty) { /* lltype -> unit */ CAMLprim value llvm_dump_type(LLVMTypeRef Val) { +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVMDumpType(Val); +#else + caml_raise_with_arg(*caml_named_value("Llvm.FeatureDisabled"), + caml_copy_string("dump")); +#endif return Val_unit; } diff --git a/cmake/modules/AddOCaml.cmake b/cmake/modules/AddOCaml.cmake index 1b805c0710a3..1d8094cc505f 100644 --- a/cmake/modules/AddOCaml.cmake +++ b/cmake/modules/AddOCaml.cmake @@ -87,6 +87,11 @@ function(add_ocaml_library name) foreach( include_dir ${LLVM_INCLUDE_DIR} ${LLVM_MAIN_INCLUDE_DIR} ) set(c_flags "${c_flags} -I${include_dir}") endforeach() + # include -D/-UNDEBUG to match dump function visibility + # regex from HandleLLVMOptions.cmake + string(REGEX MATCH "(^| )[/-][UD] *NDEBUG($| )" flag_matches + "${CMAKE_C_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${CMAKE_C_FLAGS}") + set(c_flags "${c_flags} ${flag_matches}") foreach( ocaml_file ${ARG_OCAML} ) list(APPEND sources "${ocaml_file}.mli" "${ocaml_file}.ml") @@ -199,7 +204,7 @@ function(add_ocaml_library name) PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE - DESTINATION "${LLVM_OCAML_INSTALL_PATH}/llvm") + DESTINATION "${LLVM_OCAML_INSTALL_PATH}/stublibs") foreach( install_file ${install_files} ${install_shlibs} ) get_filename_component(filename "${install_file}" NAME) diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index 800a8ec115b3..dcd2ec7eb22b 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -125,7 +125,22 @@ Changes to the AMDGPU Target Changes to the AVR Target ----------------------------- - During this release ... +This release consists mainly of bugfixes and implementations of features +required for compiling basic Rust programs. + +* Enable the branch relaxation pass so that we don't crash on large + stack load/stores + +* Add support for lowering bit-rotations to the native `ror` and `rol` + instructions + +* Fix bug where function pointers were treated as pointers to RAM and not + pointers to program memory + +* Fix broken code generaton for shift-by-variable expressions + +* Support zero-sized types in argument lists; this is impossible in C, + but possible in Rust Changes to the OCaml bindings ----------------------------- diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index f4c57d4289fc..da058b1d3918 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -312,6 +312,12 @@ template class ArrayRef; const DataLayout &DL, LoopInfo *LI = nullptr, unsigned MaxLookup = 6); + /// This is a wrapper around GetUnderlyingObjects and adds support for basic + /// ptrtoint+arithmetic+inttoptr sequences. + void getUnderlyingObjectsForCodeGen(const Value *V, + SmallVectorImpl &Objects, + const DataLayout &DL); + /// Return true if the only users of this pointer are lifetime markers. bool onlyUsedByLifetimeMarkers(const Value *V); diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 19173fa39bdc..010d7032c516 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -661,6 +661,12 @@ class MachineFunction { MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, int64_t Offset, uint64_t Size); + /// Allocate a new MachineMemOperand by copying an existing one, + /// replacing only AliasAnalysis information. MachineMemOperands are owned + /// by the MachineFunction and need not be explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, + const AAMDNodes &AAInfo); + using OperandCapacity = ArrayRecycler::Capacity; /// Allocate an array of MachineOperands. This is only intended for use by diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 95401e98b297..b87aff102d47 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -379,6 +379,9 @@ class MachineInstr return NumMemRefs == 1; } + /// Return the number of memory operands. + unsigned getNumMemOperands() const { return NumMemRefs; } + /// API for querying MachineInstr properties. They are the same as MCInstrDesc /// queries but they are bundle aware. diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 9e042da8801d..439b21a81258 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -3277,6 +3277,69 @@ void llvm::GetUnderlyingObjects(Value *V, SmallVectorImpl &Objects, } while (!Worklist.empty()); } +/// This is the function that does the work of looking through basic +/// ptrtoint+arithmetic+inttoptr sequences. +static const Value *getUnderlyingObjectFromInt(const Value *V) { + do { + if (const Operator *U = dyn_cast(V)) { + // If we find a ptrtoint, we can transfer control back to the + // regular getUnderlyingObjectFromInt. + if (U->getOpcode() == Instruction::PtrToInt) + return U->getOperand(0); + // If we find an add of a constant, a multiplied value, or a phi, it's + // likely that the other operand will lead us to the base + // object. We don't have to worry about the case where the + // object address is somehow being computed by the multiply, + // because our callers only care when the result is an + // identifiable object. + if (U->getOpcode() != Instruction::Add || + (!isa(U->getOperand(1)) && + Operator::getOpcode(U->getOperand(1)) != Instruction::Mul && + !isa(U->getOperand(1)))) + return V; + V = U->getOperand(0); + } else { + return V; + } + assert(V->getType()->isIntegerTy() && "Unexpected operand type!"); + } while (true); +} + +/// This is a wrapper around GetUnderlyingObjects and adds support for basic +/// ptrtoint+arithmetic+inttoptr sequences. +void llvm::getUnderlyingObjectsForCodeGen(const Value *V, + SmallVectorImpl &Objects, + const DataLayout &DL) { + SmallPtrSet Visited; + SmallVector Working(1, V); + do { + V = Working.pop_back_val(); + + SmallVector Objs; + GetUnderlyingObjects(const_cast(V), Objs, DL); + + for (Value *V : Objs) { + if (!Visited.insert(V).second) + continue; + if (Operator::getOpcode(V) == Instruction::IntToPtr) { + const Value *O = + getUnderlyingObjectFromInt(cast(V)->getOperand(0)); + if (O->getType()->isPointerTy()) { + Working.push_back(O); + continue; + } + } + // If GetUnderlyingObjects fails to find an identifiable object, + // getUnderlyingObjectsForCodeGen also fails for safety. + if (!isIdentifiedObject(V)) { + Objects.clear(); + return; + } + Objects.push_back(const_cast(V)); + } + } while (!Working.empty()); +} + /// Return true if the only users of this pointer are lifetime markers. bool llvm::onlyUsedByLifetimeMarkers(const Value *V) { for (const User *U : V->users()) { diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp index 530954976292..3c439e66944b 100644 --- a/lib/CodeGen/BranchFolding.cpp +++ b/lib/CodeGen/BranchFolding.cpp @@ -1475,13 +1475,14 @@ bool BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) { bool PredAnalyzable = !TII->analyzeBranch(*Pred, PredTBB, PredFBB, PredCond, true); - if (PredAnalyzable && !PredCond.empty() && PredTBB == MBB) { + if (PredAnalyzable && !PredCond.empty() && PredTBB == MBB && + PredTBB != PredFBB) { // The predecessor has a conditional branch to this block which consists // of only a tail call. Try to fold the tail call into the conditional // branch. if (TII->canMakeTailCallConditional(PredCond, TailCall)) { // TODO: It would be nice if analyzeBranch() could provide a pointer - // to the branch insturction so replaceBranchWithTailCall() doesn't + // to the branch instruction so replaceBranchWithTailCall() doesn't // have to search for it. TII->replaceBranchWithTailCall(*Pred, PredCond, TailCall); ++NumTailCalls; diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index f88e175a9776..742b095d955e 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/lib/CodeGen/MachineFunction.cpp @@ -330,6 +330,20 @@ MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO, MMO->getOrdering(), MMO->getFailureOrdering()); } +MachineMemOperand * +MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO, + const AAMDNodes &AAInfo) { + MachinePointerInfo MPI = MMO->getValue() ? + MachinePointerInfo(MMO->getValue(), MMO->getOffset()) : + MachinePointerInfo(MMO->getPseudoValue(), MMO->getOffset()); + + return new (Allocator) + MachineMemOperand(MPI, MMO->getFlags(), MMO->getSize(), + MMO->getBaseAlignment(), AAInfo, + MMO->getRanges(), MMO->getSyncScopeID(), + MMO->getOrdering(), MMO->getFailureOrdering()); +} + MachineInstr::mmo_iterator MachineFunction::allocateMemRefsArray(unsigned long Num) { return Allocator.Allocate(Num); diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index afea5575a3ae..535757ed87c1 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -578,10 +578,8 @@ bool MachinePointerInfo::isDereferenceable(unsigned Size, LLVMContext &C, if (BasePtr == nullptr) return false; - return isDereferenceableAndAlignedPointer(BasePtr, 1, - APInt(DL.getPointerSize(), - Offset + Size), - DL); + return isDereferenceableAndAlignedPointer( + BasePtr, 1, APInt(DL.getPointerSizeInBits(), Offset + Size), DL); } /// getConstantPool - Return a MachinePointerInfo record that refers to the diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp index ccd937950a74..99baa07390eb 100644 --- a/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -121,63 +121,6 @@ ScheduleDAGInstrs::ScheduleDAGInstrs(MachineFunction &mf, SchedModel.init(ST.getSchedModel(), &ST, TII); } -/// This is the function that does the work of looking through basic -/// ptrtoint+arithmetic+inttoptr sequences. -static const Value *getUnderlyingObjectFromInt(const Value *V) { - do { - if (const Operator *U = dyn_cast(V)) { - // If we find a ptrtoint, we can transfer control back to the - // regular getUnderlyingObjectFromInt. - if (U->getOpcode() == Instruction::PtrToInt) - return U->getOperand(0); - // If we find an add of a constant, a multiplied value, or a phi, it's - // likely that the other operand will lead us to the base - // object. We don't have to worry about the case where the - // object address is somehow being computed by the multiply, - // because our callers only care when the result is an - // identifiable object. - if (U->getOpcode() != Instruction::Add || - (!isa(U->getOperand(1)) && - Operator::getOpcode(U->getOperand(1)) != Instruction::Mul && - !isa(U->getOperand(1)))) - return V; - V = U->getOperand(0); - } else { - return V; - } - assert(V->getType()->isIntegerTy() && "Unexpected operand type!"); - } while (true); -} - -/// This is a wrapper around GetUnderlyingObjects and adds support for basic -/// ptrtoint+arithmetic+inttoptr sequences. -static void getUnderlyingObjects(const Value *V, - SmallVectorImpl &Objects, - const DataLayout &DL) { - SmallPtrSet Visited; - SmallVector Working(1, V); - do { - V = Working.pop_back_val(); - - SmallVector Objs; - GetUnderlyingObjects(const_cast(V), Objs, DL); - - for (Value *V : Objs) { - if (!Visited.insert(V).second) - continue; - if (Operator::getOpcode(V) == Instruction::IntToPtr) { - const Value *O = - getUnderlyingObjectFromInt(cast(V)->getOperand(0)); - if (O->getType()->isPointerTy()) { - Working.push_back(O); - continue; - } - } - Objects.push_back(const_cast(V)); - } - } while (!Working.empty()); -} - /// If this machine instr has memory reference information and it can be tracked /// to a normal reference to a known object, return the Value for that object. static void getUnderlyingObjectsForInstr(const MachineInstr *MI, @@ -208,12 +151,10 @@ static void getUnderlyingObjectsForInstr(const MachineInstr *MI, Objects.push_back(UnderlyingObjectsVector::value_type(PSV, MayAlias)); } else if (const Value *V = MMO->getValue()) { SmallVector Objs; - getUnderlyingObjects(V, Objs, DL); + getUnderlyingObjectsForCodeGen(V, Objs, DL); for (Value *V : Objs) { - if (!isIdentifiedObject(V)) - return false; - + assert(isIdentifiedObject(V)); Objects.push_back(UnderlyingObjectsVector::value_type(V, true)); } } else diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 41c3f5f235ea..127312076207 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -99,6 +99,27 @@ LimitFPPrecision("limit-float-precision", // store [4096 x i8] %data, [4096 x i8]* %buffer static const unsigned MaxParallelChains = 64; +// True if the Value passed requires ABI mangling as it is a parameter to a +// function or a return value from a function which is not an intrinsic. +static bool isABIRegCopy(const Value * V) { + const bool IsRetInst = V && isa(V); + const bool IsCallInst = V && isa(V); + const bool IsInLineAsm = + IsCallInst && static_cast(V)->isInlineAsm(); + const bool IsIndirectFunctionCall = + IsCallInst && !IsInLineAsm && + !static_cast(V)->getCalledFunction(); + // It is possible that the call instruction is an inline asm statement or an + // indirect function call in which case the return value of + // getCalledFunction() would be nullptr. + const bool IsInstrinsicCall = + IsCallInst && !IsInLineAsm && !IsIndirectFunctionCall && + static_cast(V)->getCalledFunction()->getIntrinsicID() != + Intrinsic::not_intrinsic; + + return IsRetInst || (IsCallInst && (!IsInLineAsm && !IsInstrinsicCall)); +} + static SDValue getCopyFromPartsVector(SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts, MVT PartVT, EVT ValueVT, const Value *V, @@ -1026,13 +1047,9 @@ SDValue SelectionDAGBuilder::getCopyFromRegs(const Value *V, Type *Ty) { if (It != FuncInfo.ValueMap.end()) { unsigned InReg = It->second; - bool IsABIRegCopy = - V && ((isa(V) && - !(static_cast(V))->isInlineAsm()) || - isa(V)); RegsForValue RFV(*DAG.getContext(), DAG.getTargetLoweringInfo(), - DAG.getDataLayout(), InReg, Ty, IsABIRegCopy); + DAG.getDataLayout(), InReg, Ty, isABIRegCopy(V)); SDValue Chain = DAG.getEntryNode(); Result = RFV.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(), Chain, nullptr, V); @@ -1221,13 +1238,9 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) { // If this is an instruction which fast-isel has deferred, select it now. if (const Instruction *Inst = dyn_cast(V)) { unsigned InReg = FuncInfo.InitializeRegForValue(Inst); - bool IsABIRegCopy = - V && ((isa(V) && - !(static_cast(V))->isInlineAsm()) || - isa(V)); RegsForValue RFV(*DAG.getContext(), TLI, DAG.getDataLayout(), InReg, - Inst->getType(), IsABIRegCopy); + Inst->getType(), isABIRegCopy(V)); SDValue Chain = DAG.getEntryNode(); return RFV.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(), Chain, nullptr, V); } @@ -8281,13 +8294,9 @@ SelectionDAGBuilder::CopyValueToVirtualRegister(const Value *V, unsigned Reg) { const TargetLowering &TLI = DAG.getTargetLoweringInfo(); // If this is an InlineAsm we have to match the registers required, not the // notional registers required by the type. - bool IsABIRegCopy = - V && ((isa(V) && - !(static_cast(V))->isInlineAsm()) || - isa(V)); RegsForValue RFV(V->getContext(), TLI, DAG.getDataLayout(), Reg, - V->getType(), IsABIRegCopy); + V->getType(), isABIRegCopy(V)); SDValue Chain = DAG.getEntryNode(); ISD::NodeType ExtendType = (FuncInfo.PreferredExtendType.find(V) == diff --git a/lib/CodeGen/StackColoring.cpp b/lib/CodeGen/StackColoring.cpp index 6bac39c7ee77..e5fc5402cb41 100644 --- a/lib/CodeGen/StackColoring.cpp +++ b/lib/CodeGen/StackColoring.cpp @@ -37,6 +37,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/CodeGen/StackProtector.h" #include "llvm/CodeGen/WinEHFuncInfo.h" @@ -889,6 +890,10 @@ void StackColoring::remapInstructions(DenseMap &SlotRemap) { // Keep a list of *allocas* which need to be remapped. DenseMap Allocas; + + // Keep a list of allocas which has been affected by the remap. + SmallPtrSet MergedAllocas; + for (const std::pair &SI : SlotRemap) { const AllocaInst *From = MFI->getObjectAllocation(SI.first); const AllocaInst *To = MFI->getObjectAllocation(SI.second); @@ -908,6 +913,10 @@ void StackColoring::remapInstructions(DenseMap &SlotRemap) { Inst = Cast; } + // We keep both slots to maintain AliasAnalysis metadata later. + MergedAllocas.insert(From); + MergedAllocas.insert(To); + // Allow the stack protector to adjust its value map to account for the // upcoming replacement. SP->adjustForColoring(From, To); @@ -939,13 +948,6 @@ void StackColoring::remapInstructions(DenseMap &SlotRemap) { // Update the MachineMemOperand to use the new alloca. for (MachineMemOperand *MMO : I.memoperands()) { - // FIXME: In order to enable the use of TBAA when using AA in CodeGen, - // we'll also need to update the TBAA nodes in MMOs with values - // derived from the merged allocas. When doing this, we'll need to use - // the same variant of GetUnderlyingObjects that is used by the - // instruction scheduler (that can look through ptrtoint/inttoptr - // pairs). - // We've replaced IR-level uses of the remapped allocas, so we only // need to replace direct uses here. const AllocaInst *AI = dyn_cast_or_null(MMO->getValue()); @@ -997,6 +999,48 @@ void StackColoring::remapInstructions(DenseMap &SlotRemap) { MO.setIndex(ToSlot); FixedInstr++; } + + // We adjust AliasAnalysis information for merged stack slots. + MachineSDNode::mmo_iterator NewMemOps = + MF->allocateMemRefsArray(I.getNumMemOperands()); + unsigned MemOpIdx = 0; + bool ReplaceMemOps = false; + for (MachineMemOperand *MMO : I.memoperands()) { + // If this memory location can be a slot remapped here, + // we remove AA information. + bool MayHaveConflictingAAMD = false; + if (MMO->getAAInfo()) { + if (const Value *MMOV = MMO->getValue()) { + SmallVector Objs; + getUnderlyingObjectsForCodeGen(MMOV, Objs, MF->getDataLayout()); + + if (Objs.empty()) + MayHaveConflictingAAMD = true; + else + for (Value *V : Objs) { + // If this memory location comes from a known stack slot + // that is not remapped, we continue checking. + // Otherwise, we need to invalidate AA infomation. + const AllocaInst *AI = dyn_cast_or_null(V); + if (AI && MergedAllocas.count(AI)) { + MayHaveConflictingAAMD = true; + break; + } + } + } + } + if (MayHaveConflictingAAMD) { + NewMemOps[MemOpIdx++] = MF->getMachineMemOperand(MMO, AAMDNodes()); + ReplaceMemOps = true; + } + else + NewMemOps[MemOpIdx++] = MMO; + } + + // If any memory operand is updated, set memory references of + // this instruction. + if (ReplaceMemOps) + I.setMemRefs(std::make_pair(NewMemOps, I.getNumMemOperands())); } // Update the location of C++ catch objects for the MSVC personality routine. diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index 23ccd8d4cf42..311b0a76ce8a 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -2097,15 +2097,19 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C, // Subsequent evaluation would get confused and produce erroneous results. // // The following prohibits such a GEP from being formed by checking to see - // if the index is in-range with respect to an array or vector. + // if the index is in-range with respect to an array. + // TODO: This code may be extended to handle vectors as well. bool PerformFold = false; if (Idx0->isNullValue()) PerformFold = true; else if (LastI.isSequential()) if (ConstantInt *CI = dyn_cast(Idx0)) - PerformFold = - !LastI.isBoundedSequential() || - isIndexInRangeOfArrayType(LastI.getSequentialNumElements(), CI); + PerformFold = (!LastI.isBoundedSequential() || + isIndexInRangeOfArrayType( + LastI.getSequentialNumElements(), CI)) && + !CE->getOperand(CE->getNumOperands() - 1) + ->getType() + ->isVectorTy(); if (PerformFold) { SmallVector NewIndices; diff --git a/lib/Object/COFFImportFile.cpp b/lib/Object/COFFImportFile.cpp index d1f46fdfa292..a515bc8ad16d 100644 --- a/lib/Object/COFFImportFile.cpp +++ b/lib/Object/COFFImportFile.cpp @@ -542,15 +542,12 @@ NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym, SymbolTable[2].Name.Offset.Offset = sizeof(uint32_t); //__imp_ String Table - if (Imp) { - SymbolTable[3].Name.Offset.Offset = sizeof(uint32_t) + Sym.size() + 7; - writeStringTable(Buffer, {std::string("__imp_").append(Sym), - std::string("__imp_").append(Weak)}); - } else { - SymbolTable[3].Name.Offset.Offset = sizeof(uint32_t) + Sym.size() + 1; - writeStringTable(Buffer, {Sym, Weak}); - } + StringRef Prefix = Imp ? "__imp_" : ""; + SymbolTable[3].Name.Offset.Offset = + sizeof(uint32_t) + Sym.size() + Prefix.size() + 1; append(Buffer, SymbolTable); + writeStringTable(Buffer, {(Prefix + Sym).str(), + (Prefix + Weak).str()}); // Copied here so we can still use writeStringTable char *Buf = Alloc.Allocate(Buffer.size()); diff --git a/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp index 160107cd7e2b..d52cd84246a1 100644 --- a/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ b/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -946,6 +946,18 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB, case AArch64::CMP_SWAP_128: return expandCMP_SWAP_128(MBB, MBBI, NextMBBI); + case AArch64::AESMCrrTied: + case AArch64::AESIMCrrTied: { + MachineInstrBuilder MIB = + BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr : + AArch64::AESIMCrr)) + .add(MI.getOperand(0)) + .add(MI.getOperand(1)); + transferImpOps(MI, MIB, MIB); + MI.eraseFromParent(); + return true; + } } return false; } diff --git a/lib/Target/AArch64/AArch64FrameLowering.cpp b/lib/Target/AArch64/AArch64FrameLowering.cpp index 4907d082eda0..7c6a99990406 100644 --- a/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -506,19 +506,23 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, return; } - auto CSStackSize = AFI->getCalleeSavedStackSize(); + bool IsWin64 = + Subtarget.isCallingConvWin64(MF.getFunction()->getCallingConv()); + unsigned FixedObject = IsWin64 ? alignTo(AFI->getVarArgsGPRSize(), 16) : 0; + + auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject; // All of the remaining stack allocations are for locals. - AFI->setLocalStackSize(NumBytes - CSStackSize); + AFI->setLocalStackSize(NumBytes - PrologueSaveSize); bool CombineSPBump = shouldCombineCSRLocalStackBump(MF, NumBytes); if (CombineSPBump) { emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP, -NumBytes, TII, MachineInstr::FrameSetup); NumBytes = 0; - } else if (CSStackSize != 0) { + } else if (PrologueSaveSize != 0) { MBBI = convertCalleeSaveRestoreToSPPrePostIncDec(MBB, MBBI, DL, TII, - -CSStackSize); - NumBytes -= CSStackSize; + -PrologueSaveSize); + NumBytes -= PrologueSaveSize; } assert(NumBytes >= 0 && "Negative stack allocation size!?"); @@ -532,8 +536,9 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, ++MBBI; } if (HasFP) { - // Only set up FP if we actually need to. Frame pointer is fp = sp - 16. - int FPOffset = CSStackSize - 16; + // Only set up FP if we actually need to. Frame pointer is fp = + // sp - fixedobject - 16. + int FPOffset = AFI->getCalleeSavedStackSize() - 16; if (CombineSPBump) FPOffset += AFI->getLocalStackSize(); @@ -672,8 +677,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, if (HasFP) { // Define the current CFA rule to use the provided FP. unsigned Reg = RegInfo->getDwarfRegNum(FramePtr, true); - unsigned CFIIndex = MF.addFrameInst( - MCCFIInstruction::createDefCfa(nullptr, Reg, 2 * StackGrowth)); + unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa( + nullptr, Reg, 2 * StackGrowth - FixedObject)); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); @@ -759,12 +764,16 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, // AArch64TargetLowering::LowerCall figures out ArgumentPopSize and keeps // it as the 2nd argument of AArch64ISD::TC_RETURN. - auto CSStackSize = AFI->getCalleeSavedStackSize(); + bool IsWin64 = + Subtarget.isCallingConvWin64(MF.getFunction()->getCallingConv()); + unsigned FixedObject = IsWin64 ? alignTo(AFI->getVarArgsGPRSize(), 16) : 0; + + auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject; bool CombineSPBump = shouldCombineCSRLocalStackBump(MF, NumBytes); - if (!CombineSPBump && CSStackSize != 0) + if (!CombineSPBump && PrologueSaveSize != 0) convertCalleeSaveRestoreToSPPrePostIncDec( - MBB, std::prev(MBB.getFirstTerminator()), DL, TII, CSStackSize); + MBB, std::prev(MBB.getFirstTerminator()), DL, TII, PrologueSaveSize); // Move past the restores of the callee-saved registers. MachineBasicBlock::iterator LastPopI = MBB.getFirstTerminator(); @@ -786,7 +795,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, return; } - NumBytes -= CSStackSize; + NumBytes -= PrologueSaveSize; assert(NumBytes >= 0 && "Negative stack allocation size!?"); if (!hasFP(MF)) { @@ -796,7 +805,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, if (RedZone && ArgumentPopSize == 0) return; - bool NoCalleeSaveRestore = CSStackSize == 0; + bool NoCalleeSaveRestore = PrologueSaveSize == 0; int StackRestoreBytes = RedZone ? 0 : NumBytes; if (NoCalleeSaveRestore) StackRestoreBytes += ArgumentPopSize; @@ -815,7 +824,8 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, // be able to save any instructions. if (MFI.hasVarSizedObjects() || AFI->isStackRealigned()) emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::FP, - -CSStackSize + 16, TII, MachineInstr::FrameDestroy); + -AFI->getCalleeSavedStackSize() + 16, TII, + MachineInstr::FrameDestroy); else if (NumBytes) emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::SP, NumBytes, TII, MachineInstr::FrameDestroy); @@ -845,7 +855,11 @@ int AArch64FrameLowering::resolveFrameIndexReference(const MachineFunction &MF, const AArch64RegisterInfo *RegInfo = static_cast( MF.getSubtarget().getRegisterInfo()); const AArch64FunctionInfo *AFI = MF.getInfo(); - int FPOffset = MFI.getObjectOffset(FI) + 16; + const AArch64Subtarget &Subtarget = MF.getSubtarget(); + bool IsWin64 = + Subtarget.isCallingConvWin64(MF.getFunction()->getCallingConv()); + unsigned FixedObject = IsWin64 ? alignTo(AFI->getVarArgsGPRSize(), 16) : 0; + int FPOffset = MFI.getObjectOffset(FI) + FixedObject + 16; int Offset = MFI.getObjectOffset(FI) + MFI.getStackSize(); bool isFixed = MFI.isFixedObjectIndex(FI); @@ -956,12 +970,6 @@ static void computeCalleeSaveRegisterPairs( "Odd number of callee-saved regs to spill!"); int Offset = AFI->getCalleeSavedStackSize(); - unsigned GPRSaveSize = AFI->getVarArgsGPRSize(); - const AArch64Subtarget &Subtarget = MF.getSubtarget(); - bool IsWin64 = Subtarget.isCallingConvWin64(MF.getFunction()->getCallingConv()); - if (IsWin64) - Offset -= alignTo(GPRSaveSize, 16); - for (unsigned i = 0; i < Count; ++i) { RegPairInfo RPI; RPI.Reg1 = CSI[i].getReg(); diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp index 8c30c4410c09..9d879886d39d 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -9586,8 +9586,8 @@ static bool performTBISimplification(SDValue Addr, SelectionDAG &DAG) { APInt DemandedMask = APInt::getLowBitsSet(64, 56); KnownBits Known; - TargetLowering::TargetLoweringOpt TLO(DAG, DCI.isBeforeLegalize(), - DCI.isBeforeLegalizeOps()); + TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(), + !DCI.isBeforeLegalizeOps()); const TargetLowering &TLI = DAG.getTargetLoweringInfo(); if (TLI.SimplifyDemandedBits(Addr, DemandedMask, Known, TLO)) { DCI.CommitTargetLoweringOpt(TLO); diff --git a/lib/Target/AArch64/AArch64InstrInfo.td b/lib/Target/AArch64/AArch64InstrInfo.td index 0dcf07f98412..5049a39814f1 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.td +++ b/lib/Target/AArch64/AArch64InstrInfo.td @@ -37,6 +37,9 @@ def HasFullFP16 : Predicate<"Subtarget->hasFullFP16()">, AssemblerPredicate<"FeatureFullFP16", "fullfp16">; def HasSPE : Predicate<"Subtarget->hasSPE()">, AssemblerPredicate<"FeatureSPE", "spe">; +def HasFuseAES : Predicate<"Subtarget->hasFuseAES()">, + AssemblerPredicate<"FeatureFuseAES", + "fuse-aes">; def HasSVE : Predicate<"Subtarget->hasSVE()">, AssemblerPredicate<"FeatureSVE", "sve">; @@ -5304,6 +5307,31 @@ def AESDrr : AESTiedInst<0b0101, "aesd", int_aarch64_crypto_aesd>; def AESMCrr : AESInst< 0b0110, "aesmc", int_aarch64_crypto_aesmc>; def AESIMCrr : AESInst< 0b0111, "aesimc", int_aarch64_crypto_aesimc>; +// Pseudo instructions for AESMCrr/AESIMCrr with a register constraint required +// for AES fusion on some CPUs. +let hasSideEffects = 0, mayStore = 0, mayLoad = 0 in { +def AESMCrrTied: Pseudo<(outs V128:$Rd), (ins V128:$Rn), [], "$Rn = $Rd">, + Sched<[WriteV]>; +def AESIMCrrTied: Pseudo<(outs V128:$Rd), (ins V128:$Rn), [], "$Rn = $Rd">, + Sched<[WriteV]>; +} + +// Only use constrained versions of AES(I)MC instructions if they are paired with +// AESE/AESD. +def : Pat<(v16i8 (int_aarch64_crypto_aesmc + (v16i8 (int_aarch64_crypto_aese (v16i8 V128:$src1), + (v16i8 V128:$src2))))), + (v16i8 (AESMCrrTied (v16i8 (AESErr (v16i8 V128:$src1), + (v16i8 V128:$src2)))))>, + Requires<[HasFuseAES]>; + +def : Pat<(v16i8 (int_aarch64_crypto_aesimc + (v16i8 (int_aarch64_crypto_aesd (v16i8 V128:$src1), + (v16i8 V128:$src2))))), + (v16i8 (AESIMCrrTied (v16i8 (AESDrr (v16i8 V128:$src1), + (v16i8 V128:$src2)))))>, + Requires<[HasFuseAES]>; + def SHA1Crrr : SHATiedInstQSV<0b000, "sha1c", int_aarch64_crypto_sha1c>; def SHA1Prrr : SHATiedInstQSV<0b001, "sha1p", int_aarch64_crypto_sha1p>; def SHA1Mrrr : SHATiedInstQSV<0b010, "sha1m", int_aarch64_crypto_sha1m>; diff --git a/lib/Target/AArch64/AArch64MacroFusion.cpp b/lib/Target/AArch64/AArch64MacroFusion.cpp index ccc9d2ad1b48..963cfadc54fd 100644 --- a/lib/Target/AArch64/AArch64MacroFusion.cpp +++ b/lib/Target/AArch64/AArch64MacroFusion.cpp @@ -118,11 +118,13 @@ static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, // Fuse AES crypto operations. switch(SecondOpcode) { // AES encode. - case AArch64::AESMCrr : + case AArch64::AESMCrr: + case AArch64::AESMCrrTied: return FirstOpcode == AArch64::AESErr || FirstOpcode == AArch64::INSTRUCTION_LIST_END; // AES decode. case AArch64::AESIMCrr: + case AArch64::AESIMCrrTied: return FirstOpcode == AArch64::AESDrr || FirstOpcode == AArch64::INSTRUCTION_LIST_END; } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index ba8eb8656585..7563bffd8f87 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -3984,6 +3984,13 @@ bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags, if (Offset != MFI.getObjectOffset(FI)) return false; + // If this is not byval, check that the argument stack object is immutable. + // inalloca and argument copy elision can create mutable argument stack + // objects. Byval objects can be mutated, but a byval call intends to pass the + // mutated memory. + if (!Flags.isByVal() && !MFI.isImmutableObjectIndex(FI)) + return false; + if (VA.getLocVT().getSizeInBits() > Arg.getValueSizeInBits()) { // If the argument location is wider than the argument type, check that any // extension flags match. @@ -30605,8 +30612,8 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG, assert(BitWidth >= 8 && BitWidth <= 64 && "Invalid mask size"); APInt DemandedMask(APInt::getSignMask(BitWidth)); KnownBits Known; - TargetLowering::TargetLoweringOpt TLO(DAG, DCI.isBeforeLegalize(), - DCI.isBeforeLegalizeOps()); + TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(), + !DCI.isBeforeLegalizeOps()); if (TLI.ShrinkDemandedConstant(Cond, DemandedMask, TLO) || TLI.SimplifyDemandedBits(Cond, DemandedMask, Known, TLO)) { // If we changed the computation somewhere in the DAG, this change will diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index fe87bbd99473..650e4fc8716c 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -3697,8 +3697,7 @@ let SchedRW = [WriteNop] in { // Pause. This "instruction" is encoded as "rep; nop", so even though it // was introduced with SSE2, it's backward compatible. def PAUSE : I<0x90, RawFrm, (outs), (ins), - "pause", [(int_x86_sse2_pause)], IIC_SSE_PAUSE>, - OBXS, Requires<[HasSSE2]>; + "pause", [(int_x86_sse2_pause)], IIC_SSE_PAUSE>, OBXS; } let SchedRW = [WriteFence] in { diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp index 53223ab44316..72bae203ee94 100644 --- a/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -356,7 +356,7 @@ doPromotion(Function *F, SmallPtrSetImpl &ArgsToPromote, // Just add all the struct element types. Type *AgTy = cast(I->getType())->getElementType(); Value *TheAlloca = new AllocaInst(AgTy, DL.getAllocaAddrSpace(), nullptr, - "", InsertPt); + I->getParamAlignment(), "", InsertPt); StructType *STy = cast(AgTy); Value *Idxs[2] = {ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), nullptr}; diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 057f746e052d..f8d255273b2a 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -756,7 +756,8 @@ struct FunctionStackPoisoner : public InstVisitor { bool runOnFunction() { if (!ClStack) return false; - if (ClRedzoneByvalArgs) copyArgsPassedByValToAllocas(); + if (ClRedzoneByvalArgs && Mapping.Offset != kDynamicShadowSentinel) + copyArgsPassedByValToAllocas(); // Collect alloca, ret, lifetime instructions etc. for (BasicBlock *BB : depth_first(&F.getEntryBlock())) visit(*BB); diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index a738ebb4607e..4822cf7cce0f 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -1790,7 +1790,8 @@ static bool runIPSCCP(Module &M, const DataLayout &DL, // variables that do not have their 'addresses taken'. If they don't have // their addresses taken, we can propagate constants through them. for (GlobalVariable &G : M.globals()) - if (!G.isConstant() && G.hasLocalLinkage() && !AddressIsTaken(&G)) + if (!G.isConstant() && G.hasLocalLinkage() && + G.hasDefinitiveInitializer() && !AddressIsTaken(&G)) Solver.TrackValueOfGlobalVariable(&G); // Solve for constants. diff --git a/lib/Transforms/Utils/CloneModule.cpp b/lib/Transforms/Utils/CloneModule.cpp index d27cb45c7d7f..e5392b53050d 100644 --- a/lib/Transforms/Utils/CloneModule.cpp +++ b/lib/Transforms/Utils/CloneModule.cpp @@ -132,7 +132,8 @@ std::unique_ptr llvm::CloneModule( SmallVector, 1> MDs; I->getAllMetadata(MDs); for (auto MD : MDs) - GV->addMetadata(MD.first, *MapMetadata(MD.second, VMap)); + GV->addMetadata(MD.first, + *MapMetadata(MD.second, VMap, RF_MoveDistinctMDs)); copyComdat(GV, &*I); } diff --git a/test/CodeGen/AArch64/aarch64_win64cc_vararg.ll b/test/CodeGen/AArch64/aarch64_win64cc_vararg.ll index 89efe335e329..43b821fa37c8 100644 --- a/test/CodeGen/AArch64/aarch64_win64cc_vararg.ll +++ b/test/CodeGen/AArch64/aarch64_win64cc_vararg.ll @@ -2,14 +2,14 @@ define win64cc void @pass_va(i32 %count, ...) nounwind { entry: -; CHECK: sub sp, sp, #80 +; CHECK: str x30, [sp, #-80]! ; CHECK: add x8, sp, #24 ; CHECK: add x0, sp, #24 ; CHECK: stp x6, x7, [sp, #64] ; CHECK: stp x4, x5, [sp, #48] ; CHECK: stp x2, x3, [sp, #32] ; CHECK: str x1, [sp, #24] -; CHECK: stp x30, x8, [sp] +; CHECK: str x8, [sp, #8] ; CHECK: bl other_func ; CHECK: ldr x30, [sp], #80 ; CHECK: ret diff --git a/test/CodeGen/AArch64/misched-fusion-aes.ll b/test/CodeGen/AArch64/misched-fusion-aes.ll index 8ee4dbcee52b..9c3af6dae300 100644 --- a/test/CodeGen/AArch64/misched-fusion-aes.ll +++ b/test/CodeGen/AArch64/misched-fusion-aes.ll @@ -1,10 +1,10 @@ -; RUN: llc %s -o - -mtriple=aarch64-unknown -mattr=+fuse-aes,+crypto | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS -; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=generic -mattr=+crypto | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS -; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a53 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS -; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a57 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS -; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a72 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS -; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a73 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS -; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=exynos-m1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKM1 +; RUN: llc %s -o - -mtriple=aarch64-unknown -mattr=+fuse-aes,+crypto | FileCheck %s +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=generic -mattr=+crypto | FileCheck %s +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a53 | FileCheck %s +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a57 | FileCheck %s +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a72 | FileCheck %s +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a73 | FileCheck %s +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=exynos-m1 | FileCheck %s declare <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %d, <16 x i8> %k) declare <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %d) @@ -76,41 +76,23 @@ define void @aesea(<16 x i8>* %a0, <16 x i8>* %b0, <16 x i8>* %c0, <16 x i8> %d, ret void ; CHECK-LABEL: aesea: -; CHECKFUSEALLPAIRS: aese [[VA:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VA]] -; CHECKFUSEALLPAIRS: aese [[VB:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VB]] -; CHECKFUSEALLPAIRS: aese [[VC:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VC]] -; CHECKFUSEALLPAIRS: aese [[VD:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VD]] -; CHECKFUSEALLPAIRS: aese [[VE:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VE]] -; CHECKFUSEALLPAIRS: aese [[VF:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VF]] -; CHECKFUSEALLPAIRS: aese [[VG:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VG]] -; CHECKFUSEALLPAIRS: aese [[VH:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VH]] -; CHECKFUSEALLPAIRS-NOT: aesmc - -; CHECKM1: aese [[VA:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VA]] -; CHECKM1: aese [[VH:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1: aese [[VB:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VB]] -; CHECKM1: aese {{v[0-7].16b}}, {{v[0-7].16b}} -; CHECKM1: aese [[VC:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VC]] -; CHECKM1: aese [[VD:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VD]] -; CHECKM1: aesmc {{v[0-7].16b}}, [[VH]] -; CHECKM1: aese [[VE:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VE]] -; CHECKM1: aese [[VF:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VF]] -; CHECKM1: aese [[VG:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VG]] +; CHECK: aese [[VA:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesmc [[VA]], [[VA]] +; CHECK: aese [[VB:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesmc [[VB]], [[VB]] +; CHECK: aese [[VC:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesmc [[VC]], [[VC]] +; CHECK: aese [[VD:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesmc [[VD]], [[VD]] +; CHECK: aese [[VE:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesmc [[VE]], [[VE]] +; CHECK: aese [[VF:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesmc [[VF]], [[VF]] +; CHECK: aese [[VG:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesmc [[VG]], [[VG]] +; CHECK: aese [[VH:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesmc [[VH]], [[VH]] +; CHECK-NOT: aesmc } define void @aesda(<16 x i8>* %a0, <16 x i8>* %b0, <16 x i8>* %c0, <16 x i8> %d, <16 x i8> %e) { @@ -178,41 +160,23 @@ define void @aesda(<16 x i8>* %a0, <16 x i8>* %b0, <16 x i8>* %c0, <16 x i8> %d, ret void ; CHECK-LABEL: aesda: -; CHECKFUSEALLPAIRS: aesd [[VA:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VA]] -; CHECKFUSEALLPAIRS: aesd [[VB:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VB]] -; CHECKFUSEALLPAIRS: aesd [[VC:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VC]] -; CHECKFUSEALLPAIRS: aesd [[VD:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VD]] -; CHECKFUSEALLPAIRS: aesd [[VE:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VE]] -; CHECKFUSEALLPAIRS: aesd [[VF:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VF]] -; CHECKFUSEALLPAIRS: aesd [[VG:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VG]] -; CHECKFUSEALLPAIRS: aesd [[VH:v[0-7].16b]], {{v[0-7].16b}} -; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VH]] -; CHECKFUSEALLPAIRS-NOT: aesimc - -; CHECKM1: aesd [[VA:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VA]] -; CHECKM1: aesd [[VH:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1: aesd [[VB:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VB]] -; CHECKM1: aesd {{v[0-7].16b}}, {{v[0-7].16b}} -; CHECKM1: aesd [[VC:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VC]] -; CHECKM1: aesd [[VD:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VD]] -; CHECKM1: aesimc {{v[0-7].16b}}, [[VH]] -; CHECKM1: aesd [[VE:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VE]] -; CHECKM1: aesd [[VF:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VF]] -; CHECKM1: aesd [[VG:v[0-7].16b]], {{v[0-7].16b}} -; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VG]] +; CHECK: aesd [[VA:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesimc [[VA]], [[VA]] +; CHECK: aesd [[VB:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesimc [[VB]], [[VB]] +; CHECK: aesd [[VC:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesimc [[VC]], [[VC]] +; CHECK: aesd [[VD:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesimc [[VD]], [[VD]] +; CHECK: aesd [[VE:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesimc [[VE]], [[VE]] +; CHECK: aesd [[VF:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesimc [[VF]], [[VF]] +; CHECK: aesd [[VG:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesimc [[VG]], [[VG]] +; CHECK: aesd [[VH:v[0-7].16b]], {{v[0-7].16b}} +; CHECK-NEXT: aesimc [[VH]], [[VH]] +; CHECK-NOT: aesimc } define void @aes_load_store(<16 x i8> *%p1, <16 x i8> *%p2 , <16 x i8> *%p3) { @@ -225,20 +189,20 @@ entry: %in1 = load <16 x i8>, <16 x i8>* %p1, align 16 store <16 x i8> %in1, <16 x i8>* %x1, align 16 %aese1 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %in1, <16 x i8> %in1) #2 - store <16 x i8> %aese1, <16 x i8>* %x2, align 16 %in2 = load <16 x i8>, <16 x i8>* %p2, align 16 %aesmc1= call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %aese1) #2 - store <16 x i8> %aesmc1, <16 x i8>* %x3, align 16 %aese2 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %in1, <16 x i8> %in2) #2 - store <16 x i8> %aese2, <16 x i8>* %x4, align 16 + store <16 x i8> %aesmc1, <16 x i8>* %x3, align 16 + %in3 = load <16 x i8>, <16 x i8>* %p3, align 16 %aesmc2= call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %aese2) #2 - store <16 x i8> %aesmc2, <16 x i8>* %x5, align 16 + %aese3 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %aesmc2, <16 x i8> %in3) #2 + store <16 x i8> %aese3, <16 x i8>* %x5, align 16 ret void ; CHECK-LABEL: aes_load_store: ; CHECK: aese [[VA:v[0-7].16b]], {{v[0-7].16b}} -; CHECK-NEXT: aesmc {{v[0-7].16b}}, [[VA]] +; CHECK-NEXT: aesmc [[VA]], [[VA]] ; CHECK: aese [[VB:v[0-7].16b]], {{v[0-7].16b}} -; CHECK-NEXT: aesmc {{v[0-7].16b}}, [[VB]] +; CHECK-NEXT: aesmc [[VB]], [[VB]] ; CHECK-NOT: aesmc } diff --git a/test/CodeGen/AArch64/tbi.ll b/test/CodeGen/AArch64/tbi.ll index ab2d31b7cacc..153bd4e6438d 100644 --- a/test/CodeGen/AArch64/tbi.ll +++ b/test/CodeGen/AArch64/tbi.ll @@ -100,3 +100,14 @@ define i32 @ld_and32_narrower(i64 %p) { %load = load i32, i32* %cast ret i32 %load } + +; BOTH-LABEL:ld_and8: +; BOTH: and x +define i32 @ld_and8(i64 %base, i8 %off) { + %off_masked = and i8 %off, 63 + %off_64 = zext i8 %off_masked to i64 + %p = add i64 %base, %off_64 + %cast = inttoptr i64 %p to i32* + %load = load i32, i32* %cast + ret i32 %load +} diff --git a/test/CodeGen/AArch64/win64_vararg.ll b/test/CodeGen/AArch64/win64_vararg.ll index 3acc7e520c96..7e28c9f79ec8 100644 --- a/test/CodeGen/AArch64/win64_vararg.ll +++ b/test/CodeGen/AArch64/win64_vararg.ll @@ -2,14 +2,14 @@ define void @pass_va(i32 %count, ...) nounwind { entry: -; CHECK: sub sp, sp, #80 +; CHECK: str x30, [sp, #-80]! ; CHECK: add x8, sp, #24 ; CHECK: add x0, sp, #24 ; CHECK: stp x6, x7, [sp, #64] ; CHECK: stp x4, x5, [sp, #48] ; CHECK: stp x2, x3, [sp, #32] ; CHECK: str x1, [sp, #24] -; CHECK: stp x30, x8, [sp] +; CHECK: str x8, [sp, #8] ; CHECK: bl other_func ; CHECK: ldr x30, [sp], #80 ; CHECK: ret @@ -102,6 +102,113 @@ declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1 declare i32 @__stdio_common_vsprintf(i64, i8*, i64, i8*, i8*, i8*) local_unnamed_addr #3 declare i64* @__local_stdio_printf_options() local_unnamed_addr #4 +; CHECK-LABEL: fp +; CHECK: str x21, [sp, #-96]! +; CHECK: stp x20, x19, [sp, #16] +; CHECK: stp x29, x30, [sp, #32] +; CHECK: add x29, sp, #32 +; CHECK: add x8, x29, #24 +; CHECK: mov x19, x2 +; CHECK: mov x20, x1 +; CHECK: mov x21, x0 +; CHECK: stp x6, x7, [x29, #48] +; CHECK: stp x4, x5, [x29, #32] +; CHECK: str x3, [x29, #24] +; CHECK: str x8, [sp, #8] +; CHECK: bl __local_stdio_printf_options +; CHECK: ldr x8, [x0] +; CHECK: add x5, x29, #24 +; CHECK: mov x1, x21 +; CHECK: mov x2, x20 +; CHECK: orr x0, x8, #0x2 +; CHECK: mov x3, x19 +; CHECK: mov x4, xzr +; CHECK: bl __stdio_common_vsprintf +; CHECK: ldp x29, x30, [sp, #32] +; CHECK: ldp x20, x19, [sp, #16] +; CHECK: cmp w0, #0 +; CHECK: csinv w0, w0, wzr, ge +; CHECK: ldr x21, [sp], #96 +; CHECK: ret +define i32 @fp(i8*, i64, i8*, ...) local_unnamed_addr #6 { + %4 = alloca i8*, align 8 + %5 = bitcast i8** %4 to i8* + call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %5) #2 + call void @llvm.va_start(i8* nonnull %5) + %6 = load i8*, i8** %4, align 8 + %7 = call i64* @__local_stdio_printf_options() #2 + %8 = load i64, i64* %7, align 8 + %9 = or i64 %8, 2 + %10 = call i32 @__stdio_common_vsprintf(i64 %9, i8* %0, i64 %1, i8* %2, i8* null, i8* %6) #2 + %11 = icmp sgt i32 %10, -1 + %12 = select i1 %11, i32 %10, i32 -1 + call void @llvm.va_end(i8* nonnull %5) + call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %5) #2 + ret i32 %12 +} + +attributes #6 = { "no-frame-pointer-elim"="true" } + +; CHECK-LABEL: vla +; CHECK: str x23, [sp, #-112]! +; CHECK: stp x22, x21, [sp, #16] +; CHECK: stp x20, x19, [sp, #32] +; CHECK: stp x29, x30, [sp, #48] +; CHECK: add x29, sp, #48 +; CHECK: add x8, x29, #16 +; CHECK: stur x8, [x29, #-40] +; CHECK: mov w8, w0 +; CHECK: add x8, x8, #15 +; CHECK: mov x9, sp +; CHECK: and x8, x8, #0x1fffffff0 +; CHECK: sub x20, x9, x8 +; CHECK: mov x19, x1 +; CHECK: mov x23, sp +; CHECK: stp x6, x7, [x29, #48] +; CHECK: stp x4, x5, [x29, #32] +; CHECK: stp x2, x3, [x29, #16] +; CHECK: mov sp, x20 +; CHECK: ldur x21, [x29, #-40] +; CHECK: sxtw x22, w0 +; CHECK: bl __local_stdio_printf_options +; CHECK: ldr x8, [x0] +; CHECK: mov x1, x20 +; CHECK: mov x2, x22 +; CHECK: mov x3, x19 +; CHECK: orr x0, x8, #0x2 +; CHECK: mov x4, xzr +; CHECK: mov x5, x21 +; CHECK: bl __stdio_common_vsprintf +; CHECK: mov sp, x23 +; CHECK: sub sp, x29, #48 +; CHECK: ldp x29, x30, [sp, #48] +; CHECK: ldp x20, x19, [sp, #32] +; CHECK: ldp x22, x21, [sp, #16] +; CHECK: ldr x23, [sp], #112 +; CHECK: ret +define void @vla(i32, i8*, ...) local_unnamed_addr { + %3 = alloca i8*, align 8 + %4 = bitcast i8** %3 to i8* + call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %4) #5 + call void @llvm.va_start(i8* nonnull %4) + %5 = zext i32 %0 to i64 + %6 = call i8* @llvm.stacksave() + %7 = alloca i8, i64 %5, align 1 + %8 = load i8*, i8** %3, align 8 + %9 = sext i32 %0 to i64 + %10 = call i64* @__local_stdio_printf_options() + %11 = load i64, i64* %10, align 8 + %12 = or i64 %11, 2 + %13 = call i32 @__stdio_common_vsprintf(i64 %12, i8* nonnull %7, i64 %9, i8* %1, i8* null, i8* %8) + call void @llvm.va_end(i8* nonnull %4) + call void @llvm.stackrestore(i8* %6) + call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %4) #5 + ret void +} + +declare i8* @llvm.stacksave() +declare void @llvm.stackrestore(i8*) + ; CHECK-LABEL: snprintf ; CHECK: sub sp, sp, #96 ; CHECK: stp x21, x20, [sp, #16] diff --git a/test/CodeGen/Mips/cconv/pr33883.ll b/test/CodeGen/Mips/cconv/pr33883.ll new file mode 100644 index 000000000000..54d7286ab8ff --- /dev/null +++ b/test/CodeGen/Mips/cconv/pr33883.ll @@ -0,0 +1,12 @@ +; RUN: llc -march=mips -mcpu=mips32 < %s -o /dev/null + +; Test that calls to vector intrinsics do not crash SelectionDAGBuilder. + +define <4 x float> @_ZN4simd3foo17hebb969c5fb39a194E(<4 x float>) { +start: + %1 = call <4 x float> @llvm.sqrt.v4f32(<4 x float> %0) + + ret <4 x float> %1 +} + +declare <4 x float> @llvm.sqrt.v4f32(<4 x float>) diff --git a/test/CodeGen/Mips/pr33978.ll b/test/CodeGen/Mips/pr33978.ll new file mode 100644 index 000000000000..19fa1715baab --- /dev/null +++ b/test/CodeGen/Mips/pr33978.ll @@ -0,0 +1,20 @@ +; RUN: llc -march=mips -mcpu=mips32r2 < %s -o /dev/null + +; Test that SelectionDAG does not crash during DAGCombine when two pointers +; to the stack match with differing bases and offsets when expanding memcpy. +; This could result in one of the pointers being considered dereferenceable +; and other not. + +define void @foo(i8*) { +start: + %a = alloca [22 x i8] + %b = alloca [22 x i8] + %c = bitcast [22 x i8]* %a to i8* + %d = getelementptr inbounds [22 x i8], [22 x i8]* %b, i32 0, i32 2 + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %c, i8* %d, i32 20, i32 1, i1 false) + %e = getelementptr inbounds [22 x i8], [22 x i8]* %b, i32 0, i32 6 + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* %e, i32 12, i32 1, i1 false) + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) diff --git a/test/CodeGen/X86/conditional-tailcall-samedest.mir b/test/CodeGen/X86/conditional-tailcall-samedest.mir new file mode 100644 index 000000000000..c18a98be53f3 --- /dev/null +++ b/test/CodeGen/X86/conditional-tailcall-samedest.mir @@ -0,0 +1,139 @@ +# RUN: llc -run-pass=branch-folder %s -o - | FileCheck %s + +# PR33980 + +# Don't form conditional tail calls when the original conditional branch has +# the same true and false destination. Otherwise, when we remove the tail call +# successor we will also remove the fallthrough successor from the CFG. + +# CHECK: body: | +# CHECK: bb.0.entry: +# CHECK: successors: %bb.1.sw.bb(0x40000000) +# CHECK: liveins: %edi +# CHECK: CMP32ri8 killed %edi, 2, implicit-def %eflags +# CHECK: TCRETURNdi64cc @mergeable_conditional_tailcall + +# This was the unconditional branch to a dead MBB that we left behind before +# this bug was fixed. +# CHECK-NOT: JMP_1 %bb.-1 + +--- | + ; ModuleID = 't.ll' + source_filename = "t.ll" + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64--linux" + + @static_local_guard = external global i64, align 8 + + ; Function Attrs: optsize + define void @f(i32 %arg) #0 { + entry: + switch i32 %arg, label %sw.epilog [ + i32 0, label %sw.bb + i32 1, label %sw.bb + i32 2, label %sw.bb2 + ] + + sw.bb: ; preds = %entry, %entry + %tmp = load atomic i8, i8* bitcast (i64* @static_local_guard to i8*) acquire, align 8 + %guard.uninitialized.i = icmp eq i8 %tmp, 0 + br i1 %guard.uninitialized.i, label %init.check.i, label %return, !prof !0 + + init.check.i: ; preds = %sw.bb + tail call void @initialize_static_local(i64* nonnull @static_local_guard) + ret void + + sw.bb2: ; preds = %entry + tail call void @mergeable_conditional_tailcall() + ret void + + sw.epilog: ; preds = %entry + tail call void @mergeable_conditional_tailcall() + ret void + + return: ; preds = %sw.bb + ret void + } + + declare void @mergeable_conditional_tailcall() + + declare void @initialize_static_local(i64*) + + ; Function Attrs: nounwind + declare void @llvm.stackprotector(i8*, i8**) #1 + + attributes #0 = { optsize } + attributes #1 = { nounwind } + + !0 = !{!"branch_weights", i32 1, i32 1048575} + +... +--- +name: f +alignment: 0 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: +liveins: + - { reg: '%edi', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: +body: | + bb.0.entry: + successors: %bb.2.sw.bb(0x40000000), %bb.1.entry(0x40000000) + liveins: %edi + + CMP32ri8 killed %edi, 2, implicit-def %eflags + JB_1 %bb.2.sw.bb, implicit %eflags + JMP_1 %bb.1.entry + + bb.1.entry: + successors: %bb.4.sw.bb2(0x40000000), %bb.5.sw.epilog(0x40000000) + liveins: %eflags + + JE_1 %bb.4.sw.bb2, implicit killed %eflags + JMP_1 %bb.5.sw.epilog + + bb.2.sw.bb: + successors: %bb.3.init.check.i(0x00000800), %bb.6.return(0x7ffff800) + + %al = ACQUIRE_MOV8rm %rip, 1, _, @static_local_guard, _ :: (volatile load acquire 1 from `i8* bitcast (i64* @static_local_guard to i8*)`, align 8) + TEST8rr killed %al, %al, implicit-def %eflags + JNE_1 %bb.6.return, implicit killed %eflags + JMP_1 %bb.3.init.check.i + + bb.3.init.check.i: + dead %edi = MOV32ri64 @static_local_guard, implicit-def %rdi + TCRETURNdi64 @initialize_static_local, 0, csr_64, implicit %rsp, implicit %rdi + + bb.4.sw.bb2: + TCRETURNdi64 @mergeable_conditional_tailcall, 0, csr_64, implicit %rsp + + bb.5.sw.epilog: + TCRETURNdi64 @mergeable_conditional_tailcall, 0, csr_64, implicit %rsp + + bb.6.return: + RET 0 + +... diff --git a/test/CodeGen/X86/pause.ll b/test/CodeGen/X86/pause.ll new file mode 100644 index 000000000000..70ac79f78f6e --- /dev/null +++ b/test/CodeGen/X86/pause.ll @@ -0,0 +1,15 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -disable-peephole -mtriple=i386-apple-darwin -mattr=-sse -show-mc-encoding | FileCheck %s +; RUN: llc < %s -disable-peephole -mtriple=i386-apple-darwin -mattr=-avx,+sse2 -show-mc-encoding | FileCheck %s +; RUN: llc < %s -disable-peephole -mtriple=i386-apple-darwin -mattr=+avx2 -show-mc-encoding | FileCheck %s +; RUN: llc < %s -disable-peephole -mtriple=i386-apple-darwin -mcpu=skx -show-mc-encoding | FileCheck %s + +define void @test_x86_sse2_pause() { +; CHECK-LABEL: test_x86_sse2_pause: +; CHECK: ## BB#0: +; CHECK-NEXT: pause ## encoding: [0xf3,0x90] +; CHECK-NEXT: retl ## encoding: [0xc3] + tail call void @llvm.x86.sse2.pause() + ret void +} +declare void @llvm.x86.sse2.pause() nounwind diff --git a/test/CodeGen/X86/tail-call-mutable-memarg.ll b/test/CodeGen/X86/tail-call-mutable-memarg.ll new file mode 100644 index 000000000000..491bbba8c2fc --- /dev/null +++ b/test/CodeGen/X86/tail-call-mutable-memarg.ll @@ -0,0 +1,42 @@ +; RUN: llc < %s | FileCheck %s + +; Make sure we check that forwarded memory arguments are not modified when tail +; calling. inalloca and copy arg elimination make argument slots mutable. + +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i386-pc-windows-msvc19.0.24215" + +declare x86_stdcallcc void @tail_std(i32) +declare void @capture(i32*) + +define x86_thiscallcc void @inalloca(i32* %this, i32* inalloca %args) { +entry: + %val = load i32, i32* %args + store i32 0, i32* %args + tail call x86_stdcallcc void @tail_std(i32 %val) + ret void +} + +; CHECK-LABEL: _inalloca: # @inalloca +; CHECK: movl 4(%esp), %[[reg:[^ ]*]] +; CHECK: movl $0, 4(%esp) +; CHECK: pushl %[[reg]] +; CHECK: calll _tail_std@4 +; CHECK: retl $4 + +define x86_stdcallcc void @copy_elide(i32 %arg) { +entry: + %arg.ptr = alloca i32 + store i32 %arg, i32* %arg.ptr + call void @capture(i32* %arg.ptr) + tail call x86_stdcallcc void @tail_std(i32 %arg) + ret void +} + +; CHECK-LABEL: _copy_elide@4: # @copy_elide +; CHECK: leal {{[0-9]+}}(%esp), %[[reg:[^ ]*]] +; CHECK: pushl %[[reg]] +; CHECK: calll _capture +; ... +; CHECK: calll _tail_std@4 +; CHECK: retl $4 diff --git a/test/DllTool/coff-weak-exports.def b/test/DllTool/coff-weak-exports.def index 511d947d8395..b4709e972645 100644 --- a/test/DllTool/coff-weak-exports.def +++ b/test/DllTool/coff-weak-exports.def @@ -1,19 +1,11 @@ ; RUN: llvm-dlltool -m i386:x86-64 --input-def %s --output-lib %t.a -; RUN: llvm-readobj -coff-exports %t.a | FileCheck %s +; RUN: llvm-nm %t.a | FileCheck %s LIBRARY test.dll EXPORTS TestFunction==AltTestFunction -; CHECK: File: test.dll -; CHECK: Format: COFF-x86-64 -; CHECK: Arch: x86_64 -; CHECK: AddressSize: 64bit -; CHECK: File: test.dll -; CHECK: Format: COFF-x86-64 -; CHECK: Arch: x86_64 -; CHECK: AddressSize: 64bit -; CHECK: File: test.dll -; CHECK: Format: COFF-x86-64 -; CHECK: Arch: x86_64 -; CHECK: AddressSize: 64bit +; CHECK: U AltTestFunction +; CHECK-NEXT: w TestFunction +; CHECK: U __imp_AltTestFunction +; CHECK-NEXT: w __imp_TestFunction diff --git a/test/Instrumentation/AddressSanitizer/force-dynamic-shadow.ll b/test/Instrumentation/AddressSanitizer/force-dynamic-shadow.ll new file mode 100644 index 000000000000..d0152d278adc --- /dev/null +++ b/test/Instrumentation/AddressSanitizer/force-dynamic-shadow.ll @@ -0,0 +1,22 @@ +; Test -asan-force-dynamic-shadow flag. +; +; RUN: opt -asan -asan-module -S -asan-force-dynamic-shadow=1 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-FDS +; RUN: opt -asan -asan-module -S -asan-force-dynamic-shadow=0 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-NDS + +target triple = "x86_64-unknown-linux-gnu" + +define i32 @test_load(i32* %a) sanitize_address { +; First instrumentation in the function must be to load the dynamic shadow +; address into a local variable. +; CHECK-LABEL: @test_load +; CHECK: entry: +; CHECK-FDS-NEXT: %[[SHADOW:[^ ]*]] = load i64, i64* @__asan_shadow_memory_dynamic_address +; CHECK-NDS-NOT: __asan_shadow_memory_dynamic_address + +; Shadow address is loaded and added into the whole offset computation. +; CHECK-FDS add i64 %{{.*}}, %[[SHADOW] ] + +entry: + %tmp1 = load i32, i32* %a, align 4 + ret i32 %tmp1 +} diff --git a/test/Instrumentation/AddressSanitizer/stack-poisoning-byval-args.ll b/test/Instrumentation/AddressSanitizer/stack-poisoning-byval-args.ll index 32610ce3b815..8531cb963248 100644 --- a/test/Instrumentation/AddressSanitizer/stack-poisoning-byval-args.ll +++ b/test/Instrumentation/AddressSanitizer/stack-poisoning-byval-args.ll @@ -1,5 +1,7 @@ ; This check verifies that arguments passed by value get redzones. ; RUN: opt < %s -asan -asan-realign-stack=32 -S | FileCheck %s +; RUN: opt < %s -asan -asan-realign-stack=32 -asan-force-dynamic-shadow -S | FileCheck %s --check-prefixes=CHECK-FDS + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" @@ -8,6 +10,8 @@ target triple = "x86_64-unknown-linux-gnu" declare i32 @bar(%struct.A*) +; CHECK-FDS-NOT: {{\.byval}} + ; Test behavior for named argument with explicit alignment. The memcpy and ; alloca alignments should match the explicit alignment of 64. define void @foo(%struct.A* byval align 64 %a) sanitize_address { diff --git a/test/MC/AArch64/arm64-crypto.s b/test/MC/AArch64/arm64-crypto.s index 51efd2132a78..468a720276c0 100644 --- a/test/MC/AArch64/arm64-crypto.s +++ b/test/MC/AArch64/arm64-crypto.s @@ -1,4 +1,5 @@ ; RUN: llvm-mc -triple arm64-apple-darwin -mattr=crypto -show-encoding -output-asm-variant=1 < %s | FileCheck %s +; RUN: llvm-mc -triple arm64-apple-darwin -mattr='+crypto,+fuse-aes' -show-encoding -output-asm-variant=1 < %s | FileCheck %s foo: aese.16b v0, v1 diff --git a/test/Transforms/ArgumentPromotion/byval.ll b/test/Transforms/ArgumentPromotion/byval.ll index 58475fc89607..00542e3ec244 100644 --- a/test/Transforms/ArgumentPromotion/byval.ll +++ b/test/Transforms/ArgumentPromotion/byval.ll @@ -6,24 +6,45 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:1 %struct.ss = type { i32, i64 } define internal void @f(%struct.ss* byval %b) nounwind { -; CHECK-LABEL: define internal void @f(i32 %b.0, i64 %b.1) entry: - %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 ; [#uses=2] - %tmp1 = load i32, i32* %tmp, align 4 ; [#uses=1] - %tmp2 = add i32 %tmp1, 1 ; [#uses=1] + %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 + %tmp1 = load i32, i32* %tmp, align 4 + %tmp2 = add i32 %tmp1, 1 store i32 %tmp2, i32* %tmp, align 4 ret void } -define i32 @main() nounwind { -; CHECK-LABEL: define i32 @main +; CHECK-LABEL: define internal void @f(i32 %b.0, i64 %b.1) +; CHECK: alloca %struct.ss{{$}} +; CHECK: store i32 %b.0 +; CHECK: store i64 %b.1 + +define internal void @g(%struct.ss* byval align 32 %b) nounwind { entry: - %S = alloca %struct.ss ; <%struct.ss*> [#uses=4] - %tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0 ; [#uses=1] + %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 + %tmp1 = load i32, i32* %tmp, align 4 + %tmp2 = add i32 %tmp1, 1 + store i32 %tmp2, i32* %tmp, align 4 + ret void +} + +; CHECK-LABEL: define internal void @g(i32 %b.0, i64 %b.1) +; CHECK: alloca %struct.ss, align 32 +; CHECK: store i32 %b.0 +; CHECK: store i64 %b.1 + +define i32 @main() nounwind { +entry: + %S = alloca %struct.ss + %tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0 store i32 1, i32* %tmp1, align 8 - %tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1 ; [#uses=1] + %tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1 store i64 2, i64* %tmp4, align 4 - call void @f( %struct.ss* byval %S ) nounwind -; CHECK: call void @f(i32 %{{.*}}, i64 %{{.*}}) + call void @f(%struct.ss* byval %S) nounwind + call void @g(%struct.ss* byval %S) nounwind ret i32 0 } + +; CHECK-LABEL: define i32 @main +; CHECK: call void @f(i32 %{{.*}}, i64 %{{.*}}) +; CHECK: call void @g(i32 %{{.*}}, i64 %{{.*}}) diff --git a/test/Transforms/InstSimplify/pr33957.ll b/test/Transforms/InstSimplify/pr33957.ll new file mode 100644 index 000000000000..256bb89e7861 --- /dev/null +++ b/test/Transforms/InstSimplify/pr33957.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -loop-unroll -S %s | FileCheck %s + +%struct.bar = type { i32 } + +@global = external constant [78 x %struct.bar], align 4 + +define void @patatino(i32 %x) { +; CHECK-LABEL: @patatino( +; CHECK-NEXT: bb: +; CHECK-NEXT: br i1 true, label [[BB1_PREHEADER:%.*]], label [[BB3:%.*]] +; CHECK: bb1.preheader: +; CHECK-NEXT: br label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: br label [[BB3]] +; CHECK: bb3: +; CHECK-NEXT: ret void +; +bb: + br i1 true, label %bb1, label %bb3 + +bb1: + %tmp = getelementptr inbounds [78 x %struct.bar], [78 x %struct.bar]* @global, i32 0, <4 x i32> undef + %tmp2 = getelementptr inbounds %struct.bar, <4 x %struct.bar*> %tmp, i32 1 + br i1 true, label %bb3, label %bb1 + +bb3: + ret void +} diff --git a/test/Transforms/SCCP/definite-initializer.ll b/test/Transforms/SCCP/definite-initializer.ll new file mode 100644 index 000000000000..a2c4521e07ca --- /dev/null +++ b/test/Transforms/SCCP/definite-initializer.ll @@ -0,0 +1,11 @@ +; RUN: opt -S -ipsccp < %s | FileCheck %s +@d = internal externally_initialized global i32 0, section ".openbsd.randomdata", align 4 + +; CHECK-LABEL: @test1( +define i32 @test1() { +entry: + %load = load i32, i32* @d, align 4 + ret i32 %load +; CHECK: %[[load:.*]] = load i32, i32* @d, align 4 +; CHECK: ret i32 %[[load]] +} diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index 72a91d144174..beb50455f012 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -507,6 +507,19 @@ class CloneModule : public ::testing::Test { DINode::FlagZero, false); F->setSubprogram(Subprogram); + // Create and assign DIGlobalVariableExpression to gv + auto GVExpression = DBuilder.createGlobalVariableExpression( + Subprogram, "gv", "gv", File, 1, DBuilder.createNullPtrType(), false); + GV->addDebugInfo(GVExpression); + + // DIGlobalVariableExpression not attached to any global variable + auto Expr = DBuilder.createExpression( + ArrayRef{dwarf::DW_OP_constu, 42U, dwarf::DW_OP_stack_value}); + + DBuilder.createGlobalVariableExpression( + Subprogram, "unattached", "unattached", File, 1, + DBuilder.createNullPtrType(), false, Expr); + auto *Entry = BasicBlock::Create(C, "", F); IBuilder.SetInsertPoint(Entry); IBuilder.CreateRetVoid(); @@ -546,6 +559,52 @@ TEST_F(CloneModule, GlobalMetadata) { EXPECT_NE(nullptr, NewGV->getMetadata(LLVMContext::MD_type)); } +TEST_F(CloneModule, GlobalDebugInfo) { + GlobalVariable *NewGV = NewM->getGlobalVariable("gv"); + EXPECT_TRUE(NewGV != nullptr); + + // Find debug info expression assigned to global + SmallVector GVs; + NewGV->getDebugInfo(GVs); + EXPECT_EQ(GVs.size(), 1U); + + DIGlobalVariableExpression *GVExpr = GVs[0]; + DIGlobalVariable *GV = GVExpr->getVariable(); + EXPECT_TRUE(GV != nullptr); + + EXPECT_EQ(GV->getName(), "gv"); + EXPECT_EQ(GV->getLine(), 1U); + + // Assert that the scope of the debug info attached to + // global variable matches the cloned function. + DISubprogram *SP = NewM->getFunction("f")->getSubprogram(); + EXPECT_TRUE(SP != nullptr); + EXPECT_EQ(GV->getScope(), SP); +} + +TEST_F(CloneModule, CompileUnit) { + // Find DICompileUnit listed in llvm.dbg.cu + auto *NMD = NewM->getNamedMetadata("llvm.dbg.cu"); + EXPECT_TRUE(NMD != nullptr); + EXPECT_EQ(NMD->getNumOperands(), 1U); + + DICompileUnit *CU = dyn_cast(NMD->getOperand(0)); + EXPECT_TRUE(CU != nullptr); + + // Assert this CU is consistent with the cloned function debug info + DISubprogram *SP = NewM->getFunction("f")->getSubprogram(); + EXPECT_TRUE(SP != nullptr); + EXPECT_EQ(SP->getUnit(), CU); + + // Check globals listed in CU have the correct scope + DIGlobalVariableExpressionArray GlobalArray = CU->getGlobalVariables(); + EXPECT_EQ(GlobalArray.size(), 2U); + for (DIGlobalVariableExpression *GVExpr : GlobalArray) { + DIGlobalVariable *GV = GVExpr->getVariable(); + EXPECT_EQ(GV->getScope(), SP); + } +} + TEST_F(CloneModule, Comdat) { GlobalVariable *NewGV = NewM->getGlobalVariable("gv"); auto *CD = NewGV->getComdat(); From ffe56ea4c355b82c6fdbed4befc7fe3b956e35a2 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Tue, 8 Aug 2017 16:53:22 +0000 Subject: [PATCH 2/3] Vendor import of clang release_50 branch r310316: https://llvm.org/svn/llvm-project/cfe/branches/release_50@310316 --- include/clang/AST/StmtCXX.h | 5 + include/clang/Basic/BuiltinsX86.def | 4 +- include/clang/Driver/Options.td | 4 - include/clang/Serialization/ASTBitCodes.h | 9 +- lib/AST/ODRHash.cpp | 8 +- lib/AST/StmtCXX.cpp | 14 +++ lib/Basic/Targets.cpp | 8 +- lib/Driver/ToolChains/Arch/Mips.cpp | 2 - lib/Driver/ToolChains/OpenBSD.cpp | 2 + lib/Headers/avx2intrin.h | 3 +- lib/Headers/avx512fintrin.h | 72 +++++++------- lib/Headers/avxintrin.h | 9 +- lib/Headers/float.h | 9 ++ lib/Lex/ScratchBuffer.cpp | 8 ++ lib/Sema/Sema.cpp | 3 + lib/Sema/SemaExpr.cpp | 2 +- lib/Serialization/ASTReaderStmt.cpp | 66 ++++++++++--- lib/Serialization/ASTWriterStmt.cpp | 49 +++++++--- test/CodeGen/mips-madd4.c | 87 ----------------- test/CodeGen/pause.c | 11 +++ test/CodeGen/x86-nontemporal.c | 93 +++++++++++++++++++ test/Driver/openbsd.c | 5 +- test/Misc/caret-diags-multiline.cpp | 5 + test/PCH/coroutines.cpp | 77 +++++++++++++++ test/Preprocessor/init.c | 10 -- test/Sema/vector-cast.c | 8 ++ ...xx1z-class-template-argument-deduction.cpp | 25 ++++- 27 files changed, 413 insertions(+), 185 deletions(-) delete mode 100644 test/CodeGen/mips-madd4.c create mode 100644 test/CodeGen/pause.c create mode 100644 test/CodeGen/x86-nontemporal.c create mode 100644 test/PCH/coroutines.cpp diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index d6c9654fefa4..77f81838e5eb 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -317,6 +317,7 @@ class CoroutineBodyStmt final unsigned NumParams; friend class ASTStmtReader; + friend class ASTReader; friend TrailingObjects; Stmt **getStoredStmts() { return getTrailingObjects(); } @@ -347,6 +348,8 @@ class CoroutineBodyStmt final public: static CoroutineBodyStmt *Create(const ASTContext &C, CtorArgs const &Args); + static CoroutineBodyStmt *Create(const ASTContext &C, EmptyShell, + unsigned NumParams); bool hasDependentPromiseType() const { return getPromiseDecl()->getType()->isDependentType(); @@ -444,6 +447,8 @@ class CoreturnStmt : public Stmt { SubStmts[SubStmt::PromiseCall] = PromiseCall; } + CoreturnStmt(EmptyShell) : CoreturnStmt({}, {}, {}) {} + SourceLocation getKeywordLoc() const { return CoreturnLoc; } /// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index a516bf6bf06c..6d3a478ac360 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -338,8 +338,8 @@ TARGET_BUILTIN(__builtin_ia32_lfence, "v", "", "sse2") TARGET_HEADER_BUILTIN(_mm_lfence, "v", "h", "emmintrin.h", ALL_LANGUAGES, "sse2") TARGET_BUILTIN(__builtin_ia32_mfence, "v", "", "sse2") TARGET_HEADER_BUILTIN(_mm_mfence, "v", "h", "emmintrin.h", ALL_LANGUAGES, "sse2") -TARGET_BUILTIN(__builtin_ia32_pause, "v", "", "sse2") -TARGET_HEADER_BUILTIN(_mm_pause, "v", "h", "emmintrin.h", ALL_LANGUAGES, "sse2") +TARGET_BUILTIN(__builtin_ia32_pause, "v", "", "") +TARGET_HEADER_BUILTIN(_mm_pause, "v", "h", "emmintrin.h", ALL_LANGUAGES, "") TARGET_BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "", "sse2") TARGET_BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "", "sse2") TARGET_BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "", "sse2") diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 753c178eec6a..3c0674f598d1 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -2019,10 +2019,6 @@ def mdspr2 : Flag<["-"], "mdspr2">, Group; def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group; def msingle_float : Flag<["-"], "msingle-float">, Group; def mdouble_float : Flag<["-"], "mdouble-float">, Group; -def mmadd4 : Flag<["-"], "mmadd4">, Group, - HelpText<"Enable the generation of 4-operand madd.s, madd.d and related instructions.">; -def mno_madd4 : Flag<["-"], "mno-madd4">, Group, - HelpText<"Disable the generation of 4-operand madd.s, madd.d and related instructions.">; def mmsa : Flag<["-"], "mmsa">, Group, HelpText<"Enable MSA ASE (MIPS only)">; def mno_msa : Flag<["-"], "mno-msa">, Group, diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 6b40781a1239..9227b33d2c53 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -1545,9 +1545,14 @@ namespace clang { // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr - + STMT_MS_DEPENDENT_EXISTS, // MSDependentExistsStmt - EXPR_LAMBDA // LambdaExpr + EXPR_LAMBDA, // LambdaExpr + STMT_COROUTINE_BODY, + STMT_CORETURN, + EXPR_COAWAIT, + EXPR_COYIELD, + EXPR_DEPENDENT_COAWAIT, }; /// \brief The kinds of designators that can occur in a diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index b19135384cfd..121724a73152 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -378,8 +378,12 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) { assert(Record && Record->hasDefinition() && "Expected non-null record to be a definition."); - if (isa(Record)) { - return; + const DeclContext *DC = Record; + while (DC) { + if (isa(DC)) { + return; + } + DC = DC->getParent(); } AddDecl(Record); diff --git a/lib/AST/StmtCXX.cpp b/lib/AST/StmtCXX.cpp index 8466cd61f055..666f5dcc9d97 100644 --- a/lib/AST/StmtCXX.cpp +++ b/lib/AST/StmtCXX.cpp @@ -96,6 +96,20 @@ CoroutineBodyStmt *CoroutineBodyStmt::Create( return new (Mem) CoroutineBodyStmt(Args); } +CoroutineBodyStmt *CoroutineBodyStmt::Create(const ASTContext &C, EmptyShell, + unsigned NumParams) { + std::size_t Size = totalSizeToAlloc( + CoroutineBodyStmt::FirstParamMove + NumParams); + + void *Mem = C.Allocate(Size, alignof(CoroutineBodyStmt)); + auto *Result = new (Mem) CoroutineBodyStmt(CtorArgs()); + Result->NumParams = NumParams; + auto *ParamBegin = Result->getStoredStmts() + SubStmt::FirstParamMove; + std::uninitialized_fill(ParamBegin, ParamBegin + NumParams, + static_cast(nullptr)); + return Result; +} + CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) : Stmt(CoroutineBodyStmtClass), NumParams(Args.ParamMoves.size()) { Stmt **SubStmts = getStoredStmts(); diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 5d75aa5a7528..73be2e173fda 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -8050,7 +8050,6 @@ class MipsTargetInfo : public TargetInfo { NoDSP, DSP1, DSP2 } DspRev; bool HasMSA; - bool DisableMadd4; protected: bool HasFP64; @@ -8061,7 +8060,7 @@ class MipsTargetInfo : public TargetInfo { : TargetInfo(Triple), IsMips16(false), IsMicromips(false), IsNan2008(false), IsSingleFloat(false), IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat), DspRev(NoDSP), - HasMSA(false), DisableMadd4(false), HasFP64(false) { + HasMSA(false), HasFP64(false) { TheCXXABI.set(TargetCXXABI::GenericMIPS); setABI((getTriple().getArch() == llvm::Triple::mips || @@ -8307,9 +8306,6 @@ class MipsTargetInfo : public TargetInfo { if (HasMSA) Builder.defineMacro("__mips_msa", Twine(1)); - if (DisableMadd4) - Builder.defineMacro("__mips_no_madd4", Twine(1)); - Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(0))); Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth())); Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth())); @@ -8472,8 +8468,6 @@ class MipsTargetInfo : public TargetInfo { DspRev = std::max(DspRev, DSP2); else if (Feature == "+msa") HasMSA = true; - else if (Feature == "+nomadd4") - DisableMadd4 = true; else if (Feature == "+fp64") HasFP64 = true; else if (Feature == "-fp64") diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp index b45dcd6db678..1da90d1dc7ba 100644 --- a/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/lib/Driver/ToolChains/Arch/Mips.cpp @@ -297,8 +297,6 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, options::OPT_modd_spreg, "nooddspreg"); - AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4, - "nomadd4"); AddTargetFeature(Args, Features, options::OPT_mlong_calls, options::OPT_mno_long_calls, "long-calls"); AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt,"mt"); diff --git a/lib/Driver/ToolChains/OpenBSD.cpp b/lib/Driver/ToolChains/OpenBSD.cpp index c5f266ec8fdc..1d54a1e9cbb0 100644 --- a/lib/Driver/ToolChains/OpenBSD.cpp +++ b/lib/Driver/ToolChains/OpenBSD.cpp @@ -133,6 +133,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } + if (Args.hasArg(options::OPT_pie)) + CmdArgs.push_back("-pie"); if (Args.hasArg(options::OPT_nopie)) CmdArgs.push_back("-nopie"); diff --git a/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h index 5d83a8db484b..576f761b2542 100644 --- a/lib/Headers/avx2intrin.h +++ b/lib/Headers/avx2intrin.h @@ -832,7 +832,8 @@ _mm256_xor_si256(__m256i __a, __m256i __b) static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_stream_load_si256(__m256i const *__V) { - return (__m256i)__builtin_nontemporal_load((const __v4di *)__V); + typedef __v4di __v4di_aligned __attribute__((aligned(32))); + return (__m256i)__builtin_nontemporal_load((const __v4di_aligned *)__V); } static __inline__ __m128 __DEFAULT_FN_ATTRS diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index b556d04efbb7..4ce694531100 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -4289,7 +4289,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_cvtps_epu32 ( __mmask16 __U, __m512 __A) { return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A, - (__v16si) + (__v16si) _mm512_setzero_si512 (), (__mmask16) __U , _MM_FROUND_CUR_DIRECTION); @@ -9035,25 +9035,29 @@ _mm512_kxor (__mmask16 __A, __mmask16 __B) static __inline__ void __DEFAULT_FN_ATTRS _mm512_stream_si512 (__m512i * __P, __m512i __A) { - __builtin_nontemporal_store((__v8di)__A, (__v8di*)__P); + typedef __v8di __v8di_aligned __attribute__((aligned(64))); + __builtin_nontemporal_store((__v8di_aligned)__A, (__v8di_aligned*)__P); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_stream_load_si512 (void *__P) { - return (__m512i) __builtin_nontemporal_load((const __v8di *)__P); + typedef __v8di __v8di_aligned __attribute__((aligned(64))); + return (__m512i) __builtin_nontemporal_load((const __v8di_aligned *)__P); } static __inline__ void __DEFAULT_FN_ATTRS _mm512_stream_pd (double *__P, __m512d __A) { - __builtin_nontemporal_store((__v8df)__A, (__v8df*)__P); + typedef __v8df __v8df_aligned __attribute__((aligned(64))); + __builtin_nontemporal_store((__v8df_aligned)__A, (__v8df_aligned*)__P); } static __inline__ void __DEFAULT_FN_ATTRS _mm512_stream_ps (float *__P, __m512 __A) { - __builtin_nontemporal_store((__v16sf)__A, (__v16sf*)__P); + typedef __v16sf __v16sf_aligned __attribute__((aligned(64))); + __builtin_nontemporal_store((__v16sf_aligned)__A, (__v16sf_aligned*)__P); } static __inline__ __m512d __DEFAULT_FN_ATTRS @@ -9217,39 +9221,39 @@ _mm512_maskz_moveldup_ps (__mmask16 __U, __m512 __A) static __inline__ __m128 __DEFAULT_FN_ATTRS _mm_mask_move_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { - __m128 res = __A; + __m128 res = __A; res[0] = (__U & 1) ? __B[0] : __W[0]; - return res; + return res; } static __inline__ __m128 __DEFAULT_FN_ATTRS _mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B) { - __m128 res = __A; - res[0] = (__U & 1) ? __B[0] : 0; - return res; + __m128 res = __A; + res[0] = (__U & 1) ? __B[0] : 0; + return res; } static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_mask_move_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { - __m128d res = __A; + __m128d res = __A; res[0] = (__U & 1) ? __B[0] : __W[0]; - return res; + return res; } static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B) { - __m128d res = __A; - res[0] = (__U & 1) ? __B[0] : 0; - return res; + __m128d res = __A; + res[0] = (__U & 1) ? __B[0] : 0; + return res; } static __inline__ void __DEFAULT_FN_ATTRS _mm_mask_store_ss (float * __W, __mmask8 __U, __m128 __A) { - __builtin_ia32_storess128_mask ((__v16sf *)__W, + __builtin_ia32_storess128_mask ((__v16sf *)__W, (__v16sf) _mm512_castps128_ps512(__A), (__mmask16) __U & (__mmask16)1); } @@ -9257,7 +9261,7 @@ _mm_mask_store_ss (float * __W, __mmask8 __U, __m128 __A) static __inline__ void __DEFAULT_FN_ATTRS _mm_mask_store_sd (double * __W, __mmask8 __U, __m128d __A) { - __builtin_ia32_storesd128_mask ((__v8df *)__W, + __builtin_ia32_storesd128_mask ((__v8df *)__W, (__v8df) _mm512_castpd128_pd512(__A), (__mmask8) __U & 1); } @@ -9606,7 +9610,7 @@ _mm_mask_cvtsd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128d __B) { return __builtin_ia32_cvtsd2ss_round_mask ((__v4sf)(__A), (__v2df)(__B), - (__v4sf)(__W), + (__v4sf)(__W), (__mmask8)(__U), _MM_FROUND_CUR_DIRECTION); } @@ -9615,7 +9619,7 @@ _mm_maskz_cvtsd_ss (__mmask8 __U, __m128 __A, __m128d __B) { return __builtin_ia32_cvtsd2ss_round_mask ((__v4sf)(__A), (__v2df)(__B), - (__v4sf)_mm_setzero_ps(), + (__v4sf)_mm_setzero_ps(), (__mmask8)(__U), _MM_FROUND_CUR_DIRECTION); } @@ -9680,7 +9684,7 @@ _mm_mask_cvtss_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128 __B) return __builtin_ia32_cvtss2sd_round_mask((__v2df)(__A), (__v4sf)(__B), (__v2df)(__W), - (__mmask8)(__U), _MM_FROUND_CUR_DIRECTION); + (__mmask8)(__U), _MM_FROUND_CUR_DIRECTION); } static __inline__ __m128d __DEFAULT_FN_ATTRS @@ -9688,8 +9692,8 @@ _mm_maskz_cvtss_sd (__mmask8 __U, __m128d __A, __m128 __B) { return __builtin_ia32_cvtss2sd_round_mask((__v2df)(__A), (__v4sf)(__B), - (__v2df)_mm_setzero_pd(), - (__mmask8)(__U), _MM_FROUND_CUR_DIRECTION); + (__v2df)_mm_setzero_pd(), + (__mmask8)(__U), _MM_FROUND_CUR_DIRECTION); } static __inline__ __m128d __DEFAULT_FN_ATTRS @@ -9935,7 +9939,7 @@ static __inline__ double __DEFAULT_FN_ATTRS _mm512_reduce_mul_pd(__m512d __W) { } // Vec512 - Vector with size 512. -// Vec512Neutral - All vector elements set to the identity element. +// Vec512Neutral - All vector elements set to the identity element. // Identity element: {+,0},{*,1},{&,0xFFFFFFFFFFFFFFFF},{|,0} // Operator - Can be one of following: +,*,&,| // Mask - Intrinsic Mask @@ -9965,19 +9969,19 @@ _mm512_mask_reduce_mul_epi64(__mmask8 __M, __m512i __W) { static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_and_epi64(__mmask8 __M, __m512i __W) { - _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0xFFFFFFFFFFFFFFFF), + _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0xFFFFFFFFFFFFFFFF), &, __M, i, i, q); } static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W) { - _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0), |, __M, + _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0), |, __M, i, i, q); } static __inline__ double __DEFAULT_FN_ATTRS _mm512_mask_reduce_add_pd(__mmask8 __M, __m512d __W) { - _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_pd(0), +, __M, + _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_pd(0), +, __M, f, d, pd); } @@ -10039,17 +10043,17 @@ _mm512_reduce_add_epi32(__m512i __W) { _mm512_reduce_operator_32bit(__W, +, i, i); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_mul_epi32(__m512i __W) { _mm512_reduce_operator_32bit(__W, *, i, i); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_and_epi32(__m512i __W) { _mm512_reduce_operator_32bit(__W, &, i, i); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_or_epi32(__m512i __W) { _mm512_reduce_operator_32bit(__W, |, i, i); } @@ -10065,7 +10069,7 @@ _mm512_reduce_mul_ps(__m512 __W) { } // Vec512 - Vector with size 512. -// Vec512Neutral - All vector elements set to the identity element. +// Vec512Neutral - All vector elements set to the identity element. // Identity element: {+,0},{*,1},{&,0xFFFFFFFF},{|,0} // Operator - Can be one of following: +,*,&,| // Mask - Intrinsic Mask @@ -10095,7 +10099,7 @@ _mm512_mask_reduce_mul_epi32( __mmask16 __M, __m512i __W) { static __inline__ int __DEFAULT_FN_ATTRS _mm512_mask_reduce_and_epi32( __mmask16 __M, __m512i __W) { - _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(0xFFFFFFFF), &, __M, + _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(0xFFFFFFFF), &, __M, i, i, d); } @@ -10158,7 +10162,7 @@ _mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W) { return Vec512[0]; \ }) -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_max_epi64(__m512i __V) { _mm512_reduce_maxMin_64bit(__V, max_epi64, i, i); } @@ -10168,7 +10172,7 @@ _mm512_reduce_max_epu64(__m512i __V) { _mm512_reduce_maxMin_64bit(__V, max_epu64, i, i); } -static __inline__ double __DEFAULT_FN_ATTRS +static __inline__ double __DEFAULT_FN_ATTRS _mm512_reduce_max_pd(__m512d __V) { _mm512_reduce_maxMin_64bit(__V, max_pd, d, f); } @@ -10183,7 +10187,7 @@ _mm512_reduce_min_epu64(__m512i __V) { _mm512_reduce_maxMin_64bit(__V, min_epu64, i, i); } -static __inline__ double __DEFAULT_FN_ATTRS +static __inline__ double __DEFAULT_FN_ATTRS _mm512_reduce_min_pd(__m512d __V) { _mm512_reduce_maxMin_64bit(__V, min_pd, d, f); } diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 78bb70740bbf..dff5897b6bb6 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -3590,7 +3590,8 @@ _mm_maskstore_ps(float *__p, __m128i __m, __m128 __a) static __inline void __DEFAULT_FN_ATTRS _mm256_stream_si256(__m256i *__a, __m256i __b) { - __builtin_nontemporal_store((__v4di)__b, (__v4di*)__a); + typedef __v4di __v4di_aligned __attribute__((aligned(32))); + __builtin_nontemporal_store((__v4di_aligned)__b, (__v4di_aligned*)__a); } /// \brief Moves double-precision values from a 256-bit vector of [4 x double] @@ -3609,7 +3610,8 @@ _mm256_stream_si256(__m256i *__a, __m256i __b) static __inline void __DEFAULT_FN_ATTRS _mm256_stream_pd(double *__a, __m256d __b) { - __builtin_nontemporal_store((__v4df)__b, (__v4df*)__a); + typedef __v4df __v4df_aligned __attribute__((aligned(32))); + __builtin_nontemporal_store((__v4df_aligned)__b, (__v4df_aligned*)__a); } /// \brief Moves single-precision floating point values from a 256-bit vector @@ -3629,7 +3631,8 @@ _mm256_stream_pd(double *__a, __m256d __b) static __inline void __DEFAULT_FN_ATTRS _mm256_stream_ps(float *__p, __m256 __a) { - __builtin_nontemporal_store((__v8sf)__a, (__v8sf*)__p); + typedef __v8sf __v8sf_aligned __attribute__((aligned(32))); + __builtin_nontemporal_store((__v8sf_aligned)__a, (__v8sf_aligned*)__p); } /* Create vectors */ diff --git a/lib/Headers/float.h b/lib/Headers/float.h index 0f453d87cbcb..502143d4e481 100644 --- a/lib/Headers/float.h +++ b/lib/Headers/float.h @@ -33,6 +33,15 @@ */ #if (defined(__APPLE__) || (defined(__MINGW32__) || defined(_MSC_VER))) && \ __STDC_HOSTED__ && __has_include_next() + +/* Prior to Apple's 10.7 SDK, float.h SDK header used to apply an extra level + * of #include_next to keep Metrowerks compilers happy. Avoid this + * extra indirection. + */ +#ifdef __APPLE__ +#define _FLOAT_H_ +#endif + # include_next /* Undefine anything that we'll be redefining below. */ diff --git a/lib/Lex/ScratchBuffer.cpp b/lib/Lex/ScratchBuffer.cpp index cd8a27e76c28..e0f3966fce48 100644 --- a/lib/Lex/ScratchBuffer.cpp +++ b/lib/Lex/ScratchBuffer.cpp @@ -35,6 +35,14 @@ SourceLocation ScratchBuffer::getToken(const char *Buf, unsigned Len, const char *&DestPtr) { if (BytesUsed+Len+2 > ScratchBufSize) AllocScratchBuffer(Len+2); + else { + // Clear out the source line cache if it's already been computed. + // FIXME: Allow this to be incrementally extended. + auto *ContentCache = const_cast( + SourceMgr.getSLocEntry(SourceMgr.getFileID(BufferStartLoc)) + .getFile().getContentCache()); + ContentCache->SourceLineCache = nullptr; + } // Prefix the token with a \n, so that it looks like it is the first thing on // its own virtual line in caret diagnostics. diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 6f0db6ce1c6a..a18f71422fde 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -542,6 +542,9 @@ void Sema::getUndefinedButUsed( // __attribute__((weakref)) is basically a definition. if (ND->hasAttr()) continue; + if (isa(ND)) + continue; + if (FunctionDecl *FD = dyn_cast(ND)) { if (FD->isDefined()) continue; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index ead80b61586a..d3d7d8b67c70 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -8288,7 +8288,7 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, // type. Note that this is already done by non-compound assignments in // CheckAssignmentConstraints. If it's a scalar type, only bitcast for // <1 x T> -> T. The result is also a vector type. - } else if (OtherType->isExtVectorType() || + } else if (OtherType->isExtVectorType() || OtherType->isVectorType() || (OtherType->isScalarType() && VT->getNumElements() == 1)) { ExprResult *RHSExpr = &RHS; *RHSExpr = ImpCastExprToType(RHSExpr->get(), LHSType, CK_BitCast); diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 21adcddd3a4a..3f5da029947c 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -367,28 +367,45 @@ void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) { } void ASTStmtReader::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) { - // FIXME: Implement coroutine serialization. - llvm_unreachable("unimplemented"); + VisitStmt(S); + assert(Record.peekInt() == S->NumParams); + Record.skipInts(1); + auto *StoredStmts = S->getStoredStmts(); + for (unsigned i = 0; + i < CoroutineBodyStmt::SubStmt::FirstParamMove + S->NumParams; ++i) + StoredStmts[i] = Record.readSubStmt(); } void ASTStmtReader::VisitCoreturnStmt(CoreturnStmt *S) { - // FIXME: Implement coroutine serialization. - llvm_unreachable("unimplemented"); + VisitStmt(S); + S->CoreturnLoc = Record.readSourceLocation(); + for (auto &SubStmt: S->SubStmts) + SubStmt = Record.readSubStmt(); + S->IsImplicit = Record.readInt() != 0; } -void ASTStmtReader::VisitCoawaitExpr(CoawaitExpr *S) { - // FIXME: Implement coroutine serialization. - llvm_unreachable("unimplemented"); +void ASTStmtReader::VisitCoawaitExpr(CoawaitExpr *E) { + VisitExpr(E); + E->KeywordLoc = ReadSourceLocation(); + for (auto &SubExpr: E->SubExprs) + SubExpr = Record.readSubStmt(); + E->OpaqueValue = cast_or_null(Record.readSubStmt()); + E->setIsImplicit(Record.readInt() != 0); } -void ASTStmtReader::VisitDependentCoawaitExpr(DependentCoawaitExpr *S) { - // FIXME: Implement coroutine serialization. - llvm_unreachable("unimplemented"); +void ASTStmtReader::VisitCoyieldExpr(CoyieldExpr *E) { + VisitExpr(E); + E->KeywordLoc = ReadSourceLocation(); + for (auto &SubExpr: E->SubExprs) + SubExpr = Record.readSubStmt(); + E->OpaqueValue = cast_or_null(Record.readSubStmt()); } -void ASTStmtReader::VisitCoyieldExpr(CoyieldExpr *S) { - // FIXME: Implement coroutine serialization. - llvm_unreachable("unimplemented"); +void ASTStmtReader::VisitDependentCoawaitExpr(DependentCoawaitExpr *E) { + VisitExpr(E); + E->KeywordLoc = ReadSourceLocation(); + for (auto &SubExpr: E->SubExprs) + SubExpr = Record.readSubStmt(); } void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) { @@ -3947,6 +3964,29 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = LambdaExpr::CreateDeserialized(Context, NumCaptures); break; } + + case STMT_COROUTINE_BODY: { + unsigned NumParams = Record[ASTStmtReader::NumStmtFields]; + S = CoroutineBodyStmt::Create(Context, Empty, NumParams); + break; + } + + case STMT_CORETURN: + S = new (Context) CoreturnStmt(Empty); + break; + + case EXPR_COAWAIT: + S = new (Context) CoawaitExpr(Empty); + break; + + case EXPR_COYIELD: + S = new (Context) CoyieldExpr(Empty); + break; + + case EXPR_DEPENDENT_COAWAIT: + S = new (Context) DependentCoawaitExpr(Empty); + break; + } // We hit a STMT_STOP, so we're done with this expression. diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index ae2e0b88c311..6971339663f0 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -286,7 +286,7 @@ void ASTStmtWriter::VisitMSAsmStmt(MSAsmStmt *S) { } // Outputs - for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) { + for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) { Record.AddStmt(S->getOutputExpr(I)); Record.AddString(S->getOutputConstraint(I)); } @@ -300,29 +300,48 @@ void ASTStmtWriter::VisitMSAsmStmt(MSAsmStmt *S) { Code = serialization::STMT_MSASM; } -void ASTStmtWriter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) { - // FIXME: Implement coroutine serialization. - llvm_unreachable("unimplemented"); +void ASTStmtWriter::VisitCoroutineBodyStmt(CoroutineBodyStmt *CoroStmt) { + VisitStmt(CoroStmt); + Record.push_back(CoroStmt->getParamMoves().size()); + for (Stmt *S : CoroStmt->children()) + Record.AddStmt(S); + Code = serialization::STMT_COROUTINE_BODY; } void ASTStmtWriter::VisitCoreturnStmt(CoreturnStmt *S) { - // FIXME: Implement coroutine serialization. - llvm_unreachable("unimplemented"); + VisitStmt(S); + Record.AddSourceLocation(S->getKeywordLoc()); + Record.AddStmt(S->getOperand()); + Record.AddStmt(S->getPromiseCall()); + Record.push_back(S->isImplicit()); + Code = serialization::STMT_CORETURN; } -void ASTStmtWriter::VisitCoawaitExpr(CoawaitExpr *S) { - // FIXME: Implement coroutine serialization. - llvm_unreachable("unimplemented"); +void ASTStmtWriter::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E) { + VisitExpr(E); + Record.AddSourceLocation(E->getKeywordLoc()); + for (Stmt *S : E->children()) + Record.AddStmt(S); + Record.AddStmt(E->getOpaqueValue()); } -void ASTStmtWriter::VisitDependentCoawaitExpr(DependentCoawaitExpr *S) { - // FIXME: Implement coroutine serialization. - llvm_unreachable("unimplemented"); +void ASTStmtWriter::VisitCoawaitExpr(CoawaitExpr *E) { + VisitCoroutineSuspendExpr(E); + Record.push_back(E->isImplicit()); + Code = serialization::EXPR_COAWAIT; } -void ASTStmtWriter::VisitCoyieldExpr(CoyieldExpr *S) { - // FIXME: Implement coroutine serialization. - llvm_unreachable("unimplemented"); +void ASTStmtWriter::VisitCoyieldExpr(CoyieldExpr *E) { + VisitCoroutineSuspendExpr(E); + Code = serialization::EXPR_COYIELD; +} + +void ASTStmtWriter::VisitDependentCoawaitExpr(DependentCoawaitExpr *E) { + VisitExpr(E); + Record.AddSourceLocation(E->getKeywordLoc()); + for (Stmt *S : E->children()) + Record.AddStmt(S); + Code = serialization::EXPR_DEPENDENT_COAWAIT; } void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) { diff --git a/test/CodeGen/mips-madd4.c b/test/CodeGen/mips-madd4.c deleted file mode 100644 index bc7bb593f95d..000000000000 --- a/test/CodeGen/mips-madd4.c +++ /dev/null @@ -1,87 +0,0 @@ -// REQUIRES: mips-registered-target -// RUN: %clang --target=mips64-unknown-linux -S -mmadd4 %s -o -| FileCheck %s -check-prefix=MADD4 -// RUN: %clang --target=mips64-unknown-linux -S -mno-madd4 %s -o -| FileCheck %s -check-prefix=NOMADD4 -// RUN: %clang --target=mips64-unknown-linux -S -mmadd4 -fno-honor-nans %s -o -| FileCheck %s -check-prefix=MADD4-NONAN -// RUN: %clang --target=mips64-unknown-linux -S -mno-madd4 -fno-honor-nans %s -o -| FileCheck %s -check-prefix=NOMADD4-NONAN - -float madd_s (float f, float g, float h) -{ - return (f * g) + h; -} -// MADD4: madd.s -// NOMADD4: mul.s -// NOMADD4: add.s - -float msub_s (float f, float g, float h) -{ - return (f * g) - h; -} -// MADD4: msub.s -// NOMADD4: mul.s -// NOMADD4: sub.s - -double madd_d (double f, double g, double h) -{ - return (f * g) + h; -} -// MADD4: madd.d -// NOMADD4: mul.d -// NOMADD4: add.d - -double msub_d (double f, double g, double h) -{ - return (f * g) - h; -} -// MADD4: msub.d -// NOMADD4: mul.d -// NOMADD4: sub.d - - -float nmadd_s (float f, float g, float h) -{ - // FIXME: Zero has been explicitly placed to force generation of a positive - // zero in IR until pattern used to match this instruction is changed to - // comply with negative zero as well. - return 0-((f * g) + h); -} -// MADD4-NONAN: nmadd.s -// NOMADD4-NONAN: mul.s -// NOMADD4-NONAN: add.s -// NOMADD4-NONAN: sub.s - -float nmsub_s (float f, float g, float h) -{ - // FIXME: Zero has been explicitly placed to force generation of a positive - // zero in IR until pattern used to match this instruction is changed to - // comply with negative zero as well. - return 0-((f * g) - h); -} -// MADD4-NONAN: nmsub.s -// NOMADD4-NONAN: mul.s -// NOMADD4-NONAN: sub.s -// NOMADD4-NONAN: sub.s - -double nmadd_d (double f, double g, double h) -{ - // FIXME: Zero has been explicitly placed to force generation of a positive - // zero in IR until pattern used to match this instruction is changed to - // comply with negative zero as well. - return 0-((f * g) + h); -} -// MADD4-NONAN: nmadd.d -// NOMADD4-NONAN: mul.d -// NOMADD4-NONAN: add.d -// NOMADD4-NONAN: sub.d - -double nmsub_d (double f, double g, double h) -{ - // FIXME: Zero has been explicitly placed to force generation of a positive - // zero in IR until pattern used to match this instruction is changed to - // comply with negative zero as well. - return 0-((f * g) - h); -} -// MADD4-NONAN: nmsub.d -// NOMADD4-NONAN: mul.d -// NOMADD4-NONAN: sub.d -// NOMADD4-NONAN: sub.d - diff --git a/test/CodeGen/pause.c b/test/CodeGen/pause.c new file mode 100644 index 000000000000..1a8e10aec043 --- /dev/null +++ b/test/CodeGen/pause.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -ffreestanding %s -triple=i386-pc-win32 -target-feature -sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s +// RUN: %clang_cc1 -ffreestanding %s -triple=i386-pc-win32 -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s + + +#include + +void test_mm_pause() { + // CHECK-LABEL: test_mm_pause + // CHECK: call void @llvm.x86.sse2.pause() + return _mm_pause(); +} diff --git a/test/CodeGen/x86-nontemporal.c b/test/CodeGen/x86-nontemporal.c new file mode 100644 index 000000000000..5e9e42c9f204 --- /dev/null +++ b/test/CodeGen/x86-nontemporal.c @@ -0,0 +1,93 @@ +// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.1 -target-feature +avx -target-feature +avx2 -target-feature +avx512f -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=CHECK +// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.1 -target-feature +avx -target-feature +avx2 -target-feature +avx512f -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=CHECK + +// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.1 -target-feature +avx -target-feature +avx2 -target-feature +avx512f -emit-llvm -o - -Wall -Werror -fmax-type-align=16 | FileCheck %s --check-prefix=CHECK +// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.1 -target-feature +avx -target-feature +avx2 -target-feature +avx512f -fno-signed-char -emit-llvm -o - -Wall -Werror -fmax-type-align=16 | FileCheck %s --check-prefix=CHECK + +#include + +// (PR33830) Tests ensure the correct alignment of non-temporal load/stores on darwin targets where fmax-type-align is set to 16. + +// +// 128-bit vectors +// + +void test_mm_stream_pd(double* A, __m128d B) { + // CHECK-LABEL: test_mm_stream_pd + // CHECK: store <2 x double> %{{.*}}, <2 x double>* %{{.*}}, align 16, !nontemporal + _mm_stream_pd(A, B); +} + +void test_mm_stream_ps(float* A, __m128 B) { + // CHECK16-LABEL: test_mm_stream_ps + // CHECK16: store <4 x float> %{{.*}}, <4 x float>* %{{.*}}, align 16, !nontemporal + _mm_stream_ps(A, B); +} + +void test_mm_stream_si128(__m128i* A, __m128i B) { + // CHECK-LABEL: test_mm_stream_si128 + // CHECK: store <2 x i64> %{{.*}}, <2 x i64>* %{{.*}}, align 16, !nontemporal + _mm_stream_si128(A, B); +} + +__m128i test_mm_stream_load_si128(__m128i const *A) { + // CHECK-LABEL: test_mm_stream_load_si128 + // CHECK: load <2 x i64>, <2 x i64>* %{{.*}}, align 16, !nontemporal + return _mm_stream_load_si128(A); +} + +// +// 256-bit vectors +// + +void test_mm256_stream_pd(double* A, __m256d B) { + // CHECK-LABEL: test_mm256_stream_pd + // CHECK: store <4 x double> %{{.*}}, <4 x double>* %{{.*}}, align 32, !nontemporal + _mm256_stream_pd(A, B); +} + +void test_mm256_stream_ps(float* A, __m256 B) { + // CHECK-LABEL: test_mm256_stream_ps + // CHECK: store <8 x float> %{{.*}}, <8 x float>* %{{.*}}, align 32, !nontemporal + _mm256_stream_ps(A, B); +} + +void test_mm256_stream_si256(__m256i* A, __m256i B) { + // CHECK-LABEL: test_mm256_stream_si256 + // CHECK: store <4 x i64> %{{.*}}, <4 x i64>* %{{.*}}, align 32, !nontemporal + _mm256_stream_si256(A, B); +} + +__m256i test_mm256_stream_load_si256(__m256i const *A) { + // CHECK-LABEL: test_mm256_stream_load_si256 + // CHECK: load <4 x i64>, <4 x i64>* %{{.*}}, align 32, !nontemporal + return _mm256_stream_load_si256(A); +} + +// +// 512-bit vectors +// + +void test_mm512_stream_pd(double* A, __m512d B) { + // CHECK-LABEL: test_mm512_stream_pd + // CHECK: store <8 x double> %{{.*}}, <8 x double>* %{{.*}}, align 64, !nontemporal + _mm512_stream_pd(A, B); +} + +void test_mm512_stream_ps(float* A, __m512 B) { + // CHECK-LABEL: test_mm512_stream_ps + // CHECK: store <16 x float> %{{.*}}, <16 x float>* %{{.*}}, align 64, !nontemporal + _mm512_stream_ps(A, B); +} + +void test_mm512_stream_si512(__m512i* A, __m512i B) { + // CHECK-LABEL: test_mm512_stream_si512 + // CHECK: store <8 x i64> %{{.*}}, <8 x i64>* %{{.*}}, align 64, !nontemporal + _mm512_stream_si512(A, B); +} + +__m512i test_mm512_stream_load_si512(void *A) { + // CHECK-LABEL: test_mm512_stream_load_si512 + // CHECK: load <8 x i64>, <8 x i64>* %{{.*}}, align 64, !nontemporal + return _mm512_stream_load_si512(A); +} diff --git a/test/Driver/openbsd.c b/test/Driver/openbsd.c index b4e2796c5d24..2bcd70377033 100644 --- a/test/Driver/openbsd.c +++ b/test/Driver/openbsd.c @@ -77,7 +77,9 @@ // Check linking against correct startup code when (not) using PIE // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-PIE %s -// RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd %s -fno-pie %s -### 2>&1 \ +// RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -pie %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-PIE-FLAG %s +// RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -fno-pie %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-PIE %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -static %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-STATIC-PIE %s @@ -93,6 +95,7 @@ // RUN: | FileCheck -check-prefix=CHECK-NOPIE %s // CHECK-PIE: "{{.*}}crt0.o" // CHECK-PIE-NOT: "-nopie" +// CHECK-PIE-FLAG: "-pie" // CHECK-STATIC-PIE: "{{.*}}rcrt0.o" // CHECK-STATIC-PIE-NOT: "-nopie" // CHECK-NOPIE: "-nopie" "{{.*}}crt0.o" diff --git a/test/Misc/caret-diags-multiline.cpp b/test/Misc/caret-diags-multiline.cpp index 4826d9beaa3f..90b50ff398ac 100644 --- a/test/Misc/caret-diags-multiline.cpp +++ b/test/Misc/caret-diags-multiline.cpp @@ -232,3 +232,8 @@ void multiple_ranges(int a, int b) { b ); } + +#define pr33902_a(b) #b +#define pr33902_c(d) _Pragma(pr33902_a(d)) +#define pr33902_e(f) pr33902_c(GCC warning #f) +pr33902_e() pr33902_e() diff --git a/test/PCH/coroutines.cpp b/test/PCH/coroutines.cpp new file mode 100644 index 000000000000..46a2872420bf --- /dev/null +++ b/test/PCH/coroutines.cpp @@ -0,0 +1,77 @@ +// Test this without pch. +// RUN: %clang_cc1 -include %s -verify -std=c++1z -fcoroutines-ts %s + +// Test with pch. +// RUN: %clang_cc1 -std=c++1z -fcoroutines-ts -emit-pch -o %t %s +// RUN: %clang_cc1 -include-pch %t -verify -std=c++1z -fcoroutines-ts %s + +#ifndef HEADER +#define HEADER + +namespace std::experimental { +template struct coroutine_traits; + +template struct coroutine_handle { + coroutine_handle() = default; + static coroutine_handle from_address(void *) noexcept; +}; +template <> struct coroutine_handle { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template + coroutine_handle(coroutine_handle) noexcept; +}; +} + +struct suspend_always { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +template struct std::experimental::coroutine_traits { + struct promise_type { + void get_return_object() noexcept; + suspend_always initial_suspend() noexcept; + suspend_always final_suspend() noexcept; + void return_void() noexcept; + suspend_always yield_value(int) noexcept; + promise_type(); + ~promise_type() noexcept; + void unhandled_exception() noexcept; + }; +}; + +template struct std::experimental::coroutine_traits { + struct promise_type { + int get_return_object() noexcept; + suspend_always initial_suspend() noexcept; + suspend_always final_suspend() noexcept; + void return_value(int) noexcept; + promise_type(); + ~promise_type() noexcept; + void unhandled_exception() noexcept; + }; +}; + +template +void f(T x) { // checks coawait_expr and coroutine_body_stmt + co_yield 42; // checks coyield_expr + co_await x; // checks dependent_coawait + co_return; // checks coreturn_stmt +} + +template +int f2(T x) { // checks coawait_expr and coroutine_body_stmt + co_return x; // checks coreturn_stmt with expr +} + +#else + +// expected-no-diagnostics +void g() { + f(suspend_always{}); + f2(42); +} + +#endif diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c index 5a77d06d2403..3a8e5dbd3fd8 100644 --- a/test/Preprocessor/init.c +++ b/test/Preprocessor/init.c @@ -4686,16 +4686,6 @@ // RUN: | FileCheck -match-full-lines -check-prefix MIPS-MSA %s // MIPS-MSA:#define __mips_msa 1 // -// RUN: %clang_cc1 -target-feature +nomadd4 \ -// RUN: -E -dM -triple=mips-none-none < /dev/null \ -// RUN: | FileCheck -match-full-lines -check-prefix MIPS-NOMADD4 %s -// MIPS-NOMADD4:#define __mips_no_madd4 1 -// -// RUN: %clang_cc1 \ -// RUN: -E -dM -triple=mips-none-none < /dev/null \ -// RUN: | FileCheck -match-full-lines -check-prefix MIPS-MADD4 %s -// MIPS-MADD4-NOT:#define __mips_no_madd4 1 -// // RUN: %clang_cc1 -target-cpu mips32r3 -target-feature +nan2008 \ // RUN: -E -dM -triple=mips-none-none < /dev/null \ // RUN: | FileCheck -match-full-lines -check-prefix MIPS-NAN2008 %s diff --git a/test/Sema/vector-cast.c b/test/Sema/vector-cast.c index cf23eb2742c4..2bdc00707d4c 100644 --- a/test/Sema/vector-cast.c +++ b/test/Sema/vector-cast.c @@ -48,6 +48,9 @@ typedef float float2 __attribute__ ((vector_size (8))); typedef __attribute__((vector_size(8))) double float64x1_t; typedef __attribute__((vector_size(16))) double float64x2_t; float64x1_t vget_low_f64(float64x2_t __p0); +typedef float float16 __attribute__((__vector_size__(16))); +typedef signed int vSInt32 __attribute__((__vector_size__(16))); +typedef unsigned int vUInt32 __attribute__((__vector_size__(16))); void f4() { float2 f2; @@ -73,3 +76,8 @@ void f5() { v = ptr; // expected-error-re {{assigning to 'short_sizeof_pointer' (vector of {{[0-9]+}} 'short' values) from incompatible type 'void *'}} ptr = v; // expected-error {{assigning to 'void *' from incompatible type 'short_sizeof_pointer'}} } + +void f6(vSInt32 a0) { + vUInt32 counter = (float16){0.0f, 0.0f, 0.0f, 0.0f}; // expected-warning {{incompatible vector types initializing 'vUInt32' (vector of 4 'unsigned int' values) with an expression of type 'float16' (vector of 4 'float' values)}} + counter -= a0; +} diff --git a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp index 159b7072e61e..668c24280258 100644 --- a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp +++ b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp @@ -1,4 +1,9 @@ -// RUN: %clang_cc1 -std=c++1z -verify %s +// RUN: %clang_cc1 -std=c++1z -verify %s -DERRORS +// RUN: %clang_cc1 -std=c++1z -verify %s -UERRORS + +// This test is split into two because we only produce "undefined internal" +// warnings if we didn't produce any errors. +#if ERRORS namespace std { using size_t = decltype(sizeof(0)); @@ -280,3 +285,21 @@ namespace tuple_tests { scoped_lock l = {}; } } + +#else + +// expected-no-diagnostics +namespace undefined_warnings { + // Make sure we don't get an "undefined but used internal symbol" warning for the deduction guide here. + namespace { + template + struct TemplDObj { + explicit TemplDObj(T func) noexcept {} + }; + auto test1 = TemplDObj(0); + + TemplDObj(float) -> TemplDObj; + auto test2 = TemplDObj(.0f); + } +} +#endif From 2297469e56abc8e8842c838f8bb5451e8a62570f Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Tue, 8 Aug 2017 16:53:40 +0000 Subject: [PATCH 3/3] Vendor import of libc++ release_50 branch r310316: https://llvm.org/svn/llvm-project/libcxx/branches/release_50@310316 --- include/__bsd_locale_defaults.h | 4 ++++ include/__bsd_locale_fallbacks.h | 4 ++++ include/__locale | 2 +- include/mutex | 6 +++--- include/sstream | 3 ++- .../stringstream.cons/string.pass.cpp | 19 +++++++++++++++++++ .../thread.lock.scoped/adopt_lock.pass.cpp | 8 ++++---- .../variant.ctor/copy.pass.cpp | 9 +++++++++ www/cxx1z_status.html | 6 ++++-- www/cxx2a_status.html | 2 ++ 10 files changed, 52 insertions(+), 11 deletions(-) diff --git a/include/__bsd_locale_defaults.h b/include/__bsd_locale_defaults.h index f315ca2949e3..cbc407d10305 100644 --- a/include/__bsd_locale_defaults.h +++ b/include/__bsd_locale_defaults.h @@ -15,6 +15,10 @@ #ifndef _LIBCPP_BSD_LOCALE_DEFAULTS_H #define _LIBCPP_BSD_LOCALE_DEFAULTS_H +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + #define __libcpp_mb_cur_max_l(loc) MB_CUR_MAX_L(loc) #define __libcpp_btowc_l(ch, loc) btowc_l(ch, loc) #define __libcpp_wctob_l(wch, loc) wctob_l(wch, loc) diff --git a/include/__bsd_locale_fallbacks.h b/include/__bsd_locale_fallbacks.h index 9489452905c1..5e9e09483072 100644 --- a/include/__bsd_locale_fallbacks.h +++ b/include/__bsd_locale_fallbacks.h @@ -18,6 +18,10 @@ #include #include +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + _LIBCPP_BEGIN_NAMESPACE_STD inline _LIBCPP_ALWAYS_INLINE diff --git a/include/__locale b/include/__locale index 766842294ca3..91ed9e709ee3 100644 --- a/include/__locale +++ b/include/__locale @@ -34,7 +34,7 @@ # include #elif defined(_NEWLIB_VERSION) # include -#elif (defined(__GLIBC__) || defined(__APPLE__) || defined(__FreeBSD__) \ +#elif (defined(__APPLE__) || defined(__FreeBSD__) \ || defined(__EMSCRIPTEN__) || defined(__IBMCPP__)) # include #elif defined(__Fuchsia__) diff --git a/include/mutex b/include/mutex index 1557ed8770d7..fbcc0989fa98 100644 --- a/include/mutex +++ b/include/mutex @@ -116,7 +116,7 @@ public: using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex explicit scoped_lock(MutexTypes&... m); - scoped_lock(MutexTypes&... m, adopt_lock_t); + scoped_lock(adopt_lock_t, MutexTypes&... m); ~scoped_lock(); scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; @@ -500,7 +500,7 @@ public: ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} _LIBCPP_INLINE_VISIBILITY - explicit scoped_lock(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) + explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) : __m_(__m) {} scoped_lock(scoped_lock const&) = delete; @@ -522,7 +522,7 @@ public: } _LIBCPP_INLINE_VISIBILITY - scoped_lock(_MArgs&... __margs, adopt_lock_t) + scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) { } diff --git a/include/sstream b/include/sstream index b9903f961823..fe65fd7db53d 100644 --- a/include/sstream +++ b/include/sstream @@ -249,7 +249,8 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::basic_stringbuf(ios_base::openmode template basic_stringbuf<_CharT, _Traits, _Allocator>::basic_stringbuf(const string_type& __s, ios_base::openmode __wch) - : __hm_(0), + : __str_(__s.get_allocator()), + __hm_(0), __mode_(__wch) { str(__s); diff --git a/test/std/input.output/string.streams/stringstream.cons/string.pass.cpp b/test/std/input.output/string.streams/stringstream.cons/string.pass.cpp index 3776f17f5304..f808bcd14dea 100644 --- a/test/std/input.output/string.streams/stringstream.cons/string.pass.cpp +++ b/test/std/input.output/string.streams/stringstream.cons/string.pass.cpp @@ -18,6 +18,16 @@ #include #include +template +struct NoDefaultAllocator : std::allocator +{ + template struct rebind { using other = NoDefaultAllocator; }; + NoDefaultAllocator(int id_) : id(id_) { } + template NoDefaultAllocator(const NoDefaultAllocator& a) : id(a.id) { } + int id; +}; + + int main() { { @@ -46,4 +56,13 @@ int main() ss << i << ' ' << 123; assert(ss.str() == L"456 1236 "); } + { // This is https://bugs.llvm.org/show_bug.cgi?id=33727 + typedef std::basic_string , NoDefaultAllocator > S; + typedef std::basic_stringbuf, NoDefaultAllocator > SB; + + S s(NoDefaultAllocator(1)); + SB sb(s); + // This test is not required by the standard, but *where else* could it get the allocator? + assert(sb.str().get_allocator() == s.get_allocator()); + } } diff --git a/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/adopt_lock.pass.cpp b/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/adopt_lock.pass.cpp index 78165383a158..d49ba8d1139b 100644 --- a/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/adopt_lock.pass.cpp +++ b/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/adopt_lock.pass.cpp @@ -14,7 +14,7 @@ // template class scoped_lock; -// scoped_lock(Mutex&..., adopt_lock_t); +// scoped_lock(adopt_lock_t, Mutex&...); #include #include @@ -43,7 +43,7 @@ int main() using LG = std::scoped_lock; m1.lock(); { - LG lg(m1, std::adopt_lock); + LG lg(std::adopt_lock, m1); assert(m1.locked); } assert(!m1.locked); @@ -53,7 +53,7 @@ int main() using LG = std::scoped_lock; m1.lock(); m2.lock(); { - LG lg(m1, m2, std::adopt_lock); + LG lg(std::adopt_lock, m1, m2); assert(m1.locked && m2.locked); } assert(!m1.locked && !m2.locked); @@ -63,7 +63,7 @@ int main() using LG = std::scoped_lock; m1.lock(); m2.lock(); m3.lock(); { - LG lg(m1, m2, m3, std::adopt_lock); + LG lg(std::adopt_lock, m1, m2, m3); assert(m1.locked && m2.locked && m3.locked); } assert(!m1.locked && !m2.locked && !m3.locked); diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp index f3113435f3ce..1696f9cc2320 100644 --- a/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp +++ b/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp @@ -261,4 +261,13 @@ int main() { test_copy_ctor_valueless_by_exception(); test_copy_ctor_sfinae(); test_constexpr_copy_ctor_extension(); +#if 0 +// disable this for the moment; it fails on older compilers. +// Need to figure out which compilers will support it. +{ // This is the motivating example from P0739R0 + std::variant v1(3); + std::variant v2 = v1; + (void) v2; +} +#endif } diff --git a/www/cxx1z_status.html b/www/cxx1z_status.html index d9c44fc297ac..601c6e7d2f46 100644 --- a/www/cxx1z_status.html +++ b/www/cxx1z_status.html @@ -39,6 +39,8 @@

In February 2017, the C++ standard committee approved this draft, and sent it to ISO for approval as C++17

This page shows the status of libc++; the status of clang's support of the language features is here.

+

Reminder: Features in unreleased drafts of the standard are subject to change.

+

The groups that have contributed papers:

  • LWG - Library working group
  • @@ -163,7 +165,7 @@ P0623R0LWGFinal C++17 Parallel Algorithms FixesKona P0682R1LWGRepairing elementary string conversionsToronto - P0739R0LWGSome improvements to class template argument deduction integration into the standard libraryToronto + P0739R0LWGSome improvements to class template argument deduction integration into the standard libraryTorontoComplete5.0 @@ -497,7 +499,7 @@ -

    Last Updated: 25-May-2017

    +

    Last Updated: 27-Jul-2017

    diff --git a/www/cxx2a_status.html b/www/cxx2a_status.html index 2c9f878b623f..7a17b784af98 100644 --- a/www/cxx2a_status.html +++ b/www/cxx2a_status.html @@ -38,6 +38,8 @@

    In July 2017, the C++ standard committee created a draft for the next version of the C++ standard, known here as "C++2a" (probably to be C++20).

    This page shows the status of libc++; the status of clang's support of the language features is here.

    +

    Reminder: Features in unreleased drafts of the standard are subject to change.

    +

    The groups that have contributed papers:

    • LWG - Library working group