Index: cfe/trunk/include/clang/AST/GlobalDecl.h =================================================================== --- cfe/trunk/include/clang/AST/GlobalDecl.h +++ cfe/trunk/include/clang/AST/GlobalDecl.h @@ -34,6 +34,7 @@ /// a VarDecl, a FunctionDecl or a BlockDecl. class GlobalDecl { llvm::PointerIntPair Value; + unsigned MultiVersionIndex = 0; void Init(const Decl *D) { assert(!isa(D) && "Use other ctor with ctor decls!"); @@ -45,7 +46,10 @@ public: GlobalDecl() = default; GlobalDecl(const VarDecl *D) { Init(D);} - GlobalDecl(const FunctionDecl *D) { Init(D); } + GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0) + : MultiVersionIndex(MVIndex) { + Init(D); + } GlobalDecl(const BlockDecl *D) { Init(D); } GlobalDecl(const CapturedDecl *D) { Init(D); } GlobalDecl(const ObjCMethodDecl *D) { Init(D); } @@ -57,6 +61,7 @@ GlobalDecl CanonGD; CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl()); CanonGD.Value.setInt(Value.getInt()); + CanonGD.MultiVersionIndex = MultiVersionIndex; return CanonGD; } @@ -73,8 +78,17 @@ return static_cast(Value.getInt()); } + unsigned getMultiVersionIndex() const { + assert(isa(getDecl()) && + !isa(getDecl()) && + !isa(getDecl()) && + "Decl is not a plain FunctionDecl!"); + return MultiVersionIndex; + } + friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) { - return LHS.Value == RHS.Value; + return LHS.Value == RHS.Value && + LHS.MultiVersionIndex == RHS.MultiVersionIndex; } void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } @@ -90,6 +104,16 @@ Result.Value.setPointer(D); return Result; } + + GlobalDecl getWithMultiVersionIndex(unsigned Index) { + assert(isa(getDecl()) && + !isa(getDecl()) && + !isa(getDecl()) && + "Decl is not a plain FunctionDecl!"); + GlobalDecl Result(*this); + Result.MultiVersionIndex = Index; + return Result; + } }; } // namespace clang Index: cfe/trunk/include/clang/Basic/Attr.td =================================================================== --- cfe/trunk/include/clang/Basic/Attr.td +++ cfe/trunk/include/clang/Basic/Attr.td @@ -864,10 +864,8 @@ let Subjects = SubjectList<[Function]>; let Documentation = [CPUSpecificCPUDispatchDocs]; let AdditionalMembers = [{ - unsigned ActiveArgIndex = 0; - - IdentifierInfo *getCurCPUName() const { - return *(cpus_begin() + ActiveArgIndex); + IdentifierInfo *getCPUName(unsigned Index) const { + return *(cpus_begin() + Index); } }]; } Index: cfe/trunk/lib/CodeGen/CGBlocks.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGBlocks.cpp +++ cfe/trunk/lib/CodeGen/CGBlocks.cpp @@ -1983,7 +1983,7 @@ } else { Fn->setVisibility(llvm::GlobalValue::HiddenVisibility); Fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.SetLLVMFunctionAttributes(nullptr, FI, Fn); + CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn); CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn); } } Index: cfe/trunk/lib/CodeGen/CGBuiltin.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp @@ -385,7 +385,7 @@ static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *FD, const CallExpr *E, llvm::Constant *calleeValue) { - CGCallee callee = CGCallee::forDirect(calleeValue, FD); + CGCallee callee = CGCallee::forDirect(calleeValue, GlobalDecl(FD)); return CGF.EmitCall(E->getCallee()->getType(), callee, E, ReturnValueSlot()); } @@ -1103,7 +1103,7 @@ llvm::Function *Fn = llvm::Function::Create( FuncTy, llvm::GlobalValue::LinkOnceODRLinkage, Name, &CGM.getModule()); Fn->setVisibility(llvm::GlobalValue::HiddenVisibility); - CGM.SetLLVMFunctionAttributes(nullptr, FI, Fn); + CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn); CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn); // Attach 'noinline' at -Oz. @@ -1424,9 +1424,10 @@ return RValue::get(Builder.CreateCall(F, { Src, Src, ShiftAmt })); } -RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, - unsigned BuiltinID, const CallExpr *E, +RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, + const CallExpr *E, ReturnValueSlot ReturnValue) { + const FunctionDecl *FD = GD.getDecl()->getAsFunction(); // See if we can constant fold this builtin. If so, don't emit it at all. Expr::EvalResult Result; if (E->EvaluateAsRValue(Result, CGM.getContext()) && Index: cfe/trunk/lib/CodeGen/CGCXX.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGCXX.cpp +++ cfe/trunk/lib/CodeGen/CGCXX.cpp @@ -276,7 +276,7 @@ CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); llvm::Value *VFunc = CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.PointerAlignInBytes); - CGCallee Callee(GD.getDecl()->getCanonicalDecl(), VFunc); + CGCallee Callee(GD, VFunc); return Callee; } Index: cfe/trunk/lib/CodeGen/CGCall.h =================================================================== --- cfe/trunk/lib/CodeGen/CGCall.h +++ cfe/trunk/lib/CodeGen/CGCall.h @@ -46,21 +46,21 @@ /// The function prototype of the callee. const FunctionProtoType *CalleeProtoTy; /// The function declaration of the callee. - const Decl *CalleeDecl; + GlobalDecl CalleeDecl; public: - explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl(nullptr) {} - CGCalleeInfo(const FunctionProtoType *calleeProtoTy, const Decl *calleeDecl) + explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl() {} + CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl) : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {} CGCalleeInfo(const FunctionProtoType *calleeProtoTy) - : CalleeProtoTy(calleeProtoTy), CalleeDecl(nullptr) {} - CGCalleeInfo(const Decl *calleeDecl) + : CalleeProtoTy(calleeProtoTy), CalleeDecl() {} + CGCalleeInfo(GlobalDecl calleeDecl) : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {} const FunctionProtoType *getCalleeFunctionProtoType() const { return CalleeProtoTy; } - const Decl *getCalleeDecl() const { return CalleeDecl; } + const GlobalDecl getCalleeDecl() const { return CalleeDecl; } }; /// All available information about a concrete callee. @@ -171,7 +171,7 @@ } CGCalleeInfo getAbstractInfo() const { if (isVirtual()) - return VirtualInfo.MD.getDecl(); + return VirtualInfo.MD; assert(isOrdinary()); return AbstractInfo; } Index: cfe/trunk/lib/CodeGen/CGCall.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGCall.cpp +++ cfe/trunk/lib/CodeGen/CGCall.cpp @@ -1833,7 +1833,7 @@ AddAttributesFromFunctionProtoType(getContext(), FuncAttrs, CalleeInfo.getCalleeFunctionProtoType()); - const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); + const Decl *TargetDecl = CalleeInfo.getCalleeDecl().getDecl(); bool HasOptnone = false; // FIXME: handle sseregparm someday... @@ -1941,7 +1941,7 @@ FuncAttrs.addAttribute("disable-tail-calls", llvm::toStringRef(DisableTailCalls)); - GetCPUAndFeaturesAttributes(TargetDecl, FuncAttrs); + GetCPUAndFeaturesAttributes(CalleeInfo.getCalleeDecl(), FuncAttrs); } ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI); @@ -4260,8 +4260,11 @@ // Apply always_inline to all calls within flatten functions. // FIXME: should this really take priority over __try, below? if (CurCodeDecl && CurCodeDecl->hasAttr() && - !(Callee.getAbstractInfo().getCalleeDecl() && - Callee.getAbstractInfo().getCalleeDecl()->hasAttr())) { + !(Callee.getAbstractInfo().getCalleeDecl().getDecl() && + Callee.getAbstractInfo() + .getCalleeDecl() + .getDecl() + ->hasAttr())) { Attrs = Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex, llvm::Attribute::AlwaysInline); @@ -4346,7 +4349,7 @@ // Suppress tail calls if requested. if (llvm::CallInst *Call = dyn_cast(CI)) { - const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl(); + const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl(); if (TargetDecl && TargetDecl->hasAttr()) Call->setTailCallKind(llvm::CallInst::TCK_NoTail); } @@ -4493,7 +4496,7 @@ } (); // Emit the assume_aligned check on the return value. - const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl(); + const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl(); if (Ret.isScalar() && TargetDecl) { if (const auto *AA = TargetDecl->getAttr()) { llvm::Value *OffsetValue = nullptr; Index: cfe/trunk/lib/CodeGen/CGClass.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGClass.cpp +++ cfe/trunk/lib/CodeGen/CGClass.cpp @@ -2122,7 +2122,7 @@ CGM.getAddrOfCXXStructor(D, getFromCtorType(Type)); const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall( Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix, PassPrototypeArgs); - CGCallee Callee = CGCallee::forDirect(CalleePtr, D); + CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(D, Type)); EmitCall(Info, Callee, ReturnValueSlot(), Args); // Generate vtable assumptions if we're constructing a complete object @@ -2808,7 +2808,7 @@ // variadic arguments. // Now emit our call. - auto callee = CGCallee::forDirect(calleePtr, callOperator); + auto callee = CGCallee::forDirect(calleePtr, GlobalDecl(callOperator)); RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs); // If necessary, copy the returned value into the slot. Index: cfe/trunk/lib/CodeGen/CGException.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGException.cpp +++ cfe/trunk/lib/CodeGen/CGException.cpp @@ -1878,7 +1878,7 @@ OutlinedStmt->getBeginLoc(), OutlinedStmt->getBeginLoc()); CurSEHParent = ParentCGF.CurSEHParent; - CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn); + CGM.SetLLVMFunctionAttributes(GlobalDecl(), FnInfo, CurFn); EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter); } Index: cfe/trunk/lib/CodeGen/CGExpr.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGExpr.cpp +++ cfe/trunk/lib/CodeGen/CGExpr.cpp @@ -4375,7 +4375,7 @@ } llvm::Constant *calleePtr = EmitFunctionDeclPointer(CGF.CGM, FD); - return CGCallee::forDirect(calleePtr, FD); + return CGCallee::forDirect(calleePtr, GlobalDecl(FD)); } CGCallee CodeGenFunction::EmitCallee(const Expr *E) { @@ -4419,8 +4419,13 @@ calleePtr = EmitLValue(E).getPointer(); } assert(functionType->isFunctionType()); - CGCalleeInfo calleeInfo(functionType->getAs(), - E->getReferencedDeclOfCallee()); + + GlobalDecl GD; + if (const auto *VD = + dyn_cast_or_null(E->getReferencedDeclOfCallee())) + GD = GlobalDecl(VD); + + CGCalleeInfo calleeInfo(functionType->getAs(), GD); CGCallee callee(calleeInfo, calleePtr); return callee; } @@ -4605,7 +4610,8 @@ assert(CalleeType->isFunctionPointerType() && "Call must have function pointer type!"); - const Decl *TargetDecl = OrigCallee.getAbstractInfo().getCalleeDecl(); + const Decl *TargetDecl = + OrigCallee.getAbstractInfo().getCalleeDecl().getDecl(); if (const FunctionDecl *FD = dyn_cast_or_null(TargetDecl)) // We can only guarantee that a function is called from the correct Index: cfe/trunk/lib/CodeGen/CGExprCXX.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp @@ -177,7 +177,8 @@ if (MD->isStatic()) { // The method is static, emit it as we would a regular call. - CGCallee callee = CGCallee::forDirect(CGM.GetAddrOfFunction(MD), MD); + CGCallee callee = + CGCallee::forDirect(CGM.GetAddrOfFunction(MD), GlobalDecl(MD)); return EmitCall(getContext().getPointerType(MD->getType()), callee, CE, ReturnValue); } @@ -353,13 +354,13 @@ else if (!DevirtualizedMethod) Callee = CGCallee::forDirect( CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete, FInfo, Ty), - Dtor); + GlobalDecl(Dtor, Dtor_Complete)); else { const CXXDestructorDecl *DDtor = cast(DevirtualizedMethod); Callee = CGCallee::forDirect( - CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty), - DDtor); + CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty), + GlobalDecl(DDtor, Dtor_Complete)); } EmitCXXMemberOrOperatorCall( CalleeDecl, Callee, ReturnValue, This.getPointer(), @@ -371,8 +372,8 @@ CGCallee Callee; if (const CXXConstructorDecl *Ctor = dyn_cast(MD)) { Callee = CGCallee::forDirect( - CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty), - Ctor); + CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty), + GlobalDecl(Ctor, Ctor_Complete)); } else if (UseVirtualCall) { Callee = CGCallee::forVirtual(CE, MD, This.getAddress(), Ty); } else { @@ -389,11 +390,12 @@ if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier) Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty); else if (!DevirtualizedMethod) - Callee = CGCallee::forDirect(CGM.GetAddrOfFunction(MD, Ty), MD); + Callee = + CGCallee::forDirect(CGM.GetAddrOfFunction(MD, Ty), GlobalDecl(MD)); else { - Callee = CGCallee::forDirect( - CGM.GetAddrOfFunction(DevirtualizedMethod, Ty), - DevirtualizedMethod); + Callee = + CGCallee::forDirect(CGM.GetAddrOfFunction(DevirtualizedMethod, Ty), + GlobalDecl(DevirtualizedMethod)); } } @@ -1293,7 +1295,7 @@ const CallArgList &Args) { llvm::Instruction *CallOrInvoke; llvm::Constant *CalleePtr = CGF.CGM.GetAddrOfFunction(CalleeDecl); - CGCallee Callee = CGCallee::forDirect(CalleePtr, CalleeDecl); + CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(CalleeDecl)); RValue RV = CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall( Args, CalleeType, /*chainCall=*/false), Index: cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp +++ cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp @@ -458,7 +458,7 @@ llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage, FuncName, &CGM.getModule()); F->setVisibility(llvm::GlobalValue::HiddenVisibility); - CGM.SetLLVMFunctionAttributes(nullptr, FI, F); + CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F); CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F); IdentifierInfo *II = &Ctx.Idents.get(FuncName); FunctionDecl *FD = FunctionDecl::Create( Index: cfe/trunk/lib/CodeGen/CGVTables.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGVTables.cpp +++ cfe/trunk/lib/CodeGen/CGVTables.cpp @@ -304,7 +304,7 @@ CGM.ErrorUnsupported( MD, "non-trivial argument copy for return-adjusting thunk"); } - EmitMustTailThunk(MD, AdjustedThisPtr, CalleePtr); + EmitMustTailThunk(CurGD, AdjustedThisPtr, CalleePtr); return; } @@ -356,7 +356,7 @@ // Now emit our call. llvm::Instruction *CallOrInvoke; - CGCallee Callee = CGCallee::forDirect(CalleePtr, MD); + CGCallee Callee = CGCallee::forDirect(CalleePtr, CurGD); RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, &CallOrInvoke); // Consider return adjustment if we have ThunkInfo. @@ -375,7 +375,7 @@ FinishThunk(); } -void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD, +void CodeGenFunction::EmitMustTailThunk(GlobalDecl GD, llvm::Value *AdjustedThisPtr, llvm::Value *CalleePtr) { // Emitting a musttail call thunk doesn't use any of the CGCall.cpp machinery @@ -412,7 +412,7 @@ // Apply the standard set of call attributes. unsigned CallingConv; llvm::AttributeList Attrs; - CGM.ConstructAttributeList(CalleePtr->getName(), *CurFnInfo, MD, Attrs, + CGM.ConstructAttributeList(CalleePtr->getName(), *CurFnInfo, GD, Attrs, CallingConv, /*AttrOnCallSite=*/true); Call->setAttributes(Attrs); Call->setCallingConv(static_cast(CallingConv)); Index: cfe/trunk/lib/CodeGen/CodeGenFunction.h =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h @@ -1856,7 +1856,7 @@ void FinishThunk(); /// Emit a musttail call for a thunk with a potentially adjusted this pointer. - void EmitMustTailThunk(const CXXMethodDecl *MD, llvm::Value *AdjustedThisPtr, + void EmitMustTailThunk(GlobalDecl GD, llvm::Value *AdjustedThisPtr, llvm::Value *Callee); /// Generate a thunk for the given method. @@ -3681,9 +3681,8 @@ RValue EmitNVPTXDevicePrintfCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue); - RValue EmitBuiltinExpr(const FunctionDecl *FD, - unsigned BuiltinID, const CallExpr *E, - ReturnValueSlot ReturnValue); + RValue EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, + const CallExpr *E, ReturnValueSlot ReturnValue); RValue emitRotate(const CallExpr *E, bool IsRotateRight); Index: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp @@ -2291,7 +2291,7 @@ // Now build up the set of caller features and verify that all the required // features are there. llvm::StringMap CallerFeatureMap; - CGM.getFunctionFeatureMap(CallerFeatureMap, FD); + CGM.getFunctionFeatureMap(CallerFeatureMap, GlobalDecl().getWithDecl(FD)); // If we have at least one of the features in the feature list return // true, otherwise return false. Index: cfe/trunk/lib/CodeGen/CodeGenModule.h =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.h +++ cfe/trunk/lib/CodeGen/CodeGenModule.h @@ -1043,8 +1043,7 @@ const CGFunctionInfo &FI); /// Set the LLVM function attributes (sext, zext, etc). - void SetLLVMFunctionAttributes(const Decl *D, - const CGFunctionInfo &Info, + void SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info, llvm::Function *F); /// Set the LLVM function attributes which only apply to a function @@ -1104,8 +1103,7 @@ // Fills in the supplied string map with the set of target features for the // passed in function. - void getFunctionFeatureMap(llvm::StringMap &FeatureMap, - const FunctionDecl *FD); + void getFunctionFeatureMap(llvm::StringMap &FeatureMap, GlobalDecl GD); StringRef getMangledName(GlobalDecl GD); StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD); @@ -1304,7 +1302,7 @@ ForDefinition_t IsForDefinition = NotForDefinition); - bool GetCPUAndFeaturesAttributes(const Decl *D, + bool GetCPUAndFeaturesAttributes(GlobalDecl GD, llvm::AttrBuilder &AttrBuilder); void setNonAliasAttributes(GlobalDecl GD, llvm::GlobalObject *GO); @@ -1315,6 +1313,8 @@ void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = nullptr); void EmitGlobalFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV); + void EmitMultiVersionFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV); + void EmitGlobalVarDefinition(const VarDecl *D, bool IsTentative = false); void EmitAliasDefinition(GlobalDecl GD); void emitIFuncDefinition(GlobalDecl GD); Index: cfe/trunk/lib/CodeGen/CodeGenModule.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp @@ -891,11 +891,12 @@ static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM, const CPUSpecificAttr *Attr, + unsigned CPUIndex, raw_ostream &Out) { // cpu_specific gets the current name, dispatch gets the resolver if IFunc is // supported. if (Attr) - Out << getCPUSpecificMangling(CGM, Attr->getCurCPUName()->getName()); + Out << getCPUSpecificMangling(CGM, Attr->getCPUName(CPUIndex)->getName()); else if (CGM.getTarget().supportsIFunc()) Out << ".resolver"; } @@ -963,8 +964,9 @@ if (const auto *FD = dyn_cast(ND)) if (FD->isMultiVersion() && !OmitMultiVersionMangling) { if (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion()) - AppendCPUSpecificCPUDispatchMangling( - CGM, FD->getAttr(), Out); + AppendCPUSpecificCPUDispatchMangling(CGM, + FD->getAttr(), + GD.getMultiVersionIndex(), Out); else AppendTargetMangling(CGM, FD->getAttr(), Out); } @@ -1024,26 +1026,6 @@ } } - const auto *FD = dyn_cast(GD.getDecl()); - // Since CPUSpecific can require multiple emits per decl, store the manglings - // separately. - if (FD && - (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion())) { - const auto *SD = FD->getAttr(); - - std::pair SpecCanonicalGD{ - CanonicalGD, - SD ? SD->ActiveArgIndex : std::numeric_limits::max()}; - - auto FoundName = CPUSpecificMangledDeclNames.find(SpecCanonicalGD); - if (FoundName != CPUSpecificMangledDeclNames.end()) - return FoundName->second; - - auto Result = CPUSpecificManglings.insert( - std::make_pair(getMangledNameImpl(*this, GD, FD), SpecCanonicalGD)); - return CPUSpecificMangledDeclNames[SpecCanonicalGD] = Result.first->first(); - } - auto FoundName = MangledDeclNames.find(CanonicalGD); if (FoundName != MangledDeclNames.end()) return FoundName->second; @@ -1166,12 +1148,12 @@ return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString())); } -void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D, +void CodeGenModule::SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info, llvm::Function *F) { unsigned CallingConv; llvm::AttributeList PAL; - ConstructAttributeList(F->getName(), Info, D, PAL, CallingConv, false); + ConstructAttributeList(F->getName(), Info, GD, PAL, CallingConv, false); F->setAttributes(PAL); F->setCallingConv(static_cast(CallingConv)); } @@ -1393,21 +1375,21 @@ } } -bool CodeGenModule::GetCPUAndFeaturesAttributes(const Decl *D, +bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD, llvm::AttrBuilder &Attrs) { // Add target-cpu and target-features attributes to functions. If // we have a decl for the function and it has a target attribute then // parse that and add it to the feature set. StringRef TargetCPU = getTarget().getTargetOpts().CPU; std::vector Features; - const auto *FD = dyn_cast_or_null(D); + const auto *FD = dyn_cast_or_null(GD.getDecl()); FD = FD ? FD->getMostRecentDecl() : FD; const auto *TD = FD ? FD->getAttr() : nullptr; const auto *SD = FD ? FD->getAttr() : nullptr; bool AddedAttr = false; if (TD || SD) { llvm::StringMap FeatureMap; - getFunctionFeatureMap(FeatureMap, FD); + getFunctionFeatureMap(FeatureMap, GD); // Produce the canonical string for this set of features. for (const llvm::StringMap::value_type &Entry : FeatureMap) @@ -1463,7 +1445,7 @@ F->addFnAttr("implicit-section-name", SA->getName()); llvm::AttrBuilder Attrs; - if (GetCPUAndFeaturesAttributes(D, Attrs)) { + if (GetCPUAndFeaturesAttributes(GD, Attrs)) { // We know that GetCPUAndFeaturesAttributes will always have the // newest set, since it has the newest possible FunctionDecl, so the // new ones should replace the old. @@ -1486,7 +1468,7 @@ llvm::Function *F, const CGFunctionInfo &FI) { const Decl *D = GD.getDecl(); - SetLLVMFunctionAttributes(D, FI, F); + SetLLVMFunctionAttributes(GD, FI, F); SetLLVMFunctionAttributesForDefinition(D, F); F->setLinkage(llvm::Function::InternalLinkage); @@ -1548,7 +1530,7 @@ const auto *FD = cast(GD.getDecl()); if (!IsIncompleteFunction) { - SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F); + SetLLVMFunctionAttributes(GD, getTypes().arrangeGlobalDeclaration(GD), F); // Setup target-specific attributes. if (F->isDeclaration()) getTargetCodeGenInfo().setTargetAttributes(FD, F, *this); @@ -2424,6 +2406,19 @@ return CodeGenOpts.OptimizationLevel > 0; } +void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD, + llvm::GlobalValue *GV) { + const auto *FD = cast(GD.getDecl()); + + if (FD->isCPUSpecificMultiVersion()) { + auto *Spec = FD->getAttr(); + for (unsigned I = 0; I < Spec->cpus_size(); ++I) + EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr); + // Requires multiple emits. + } else + EmitGlobalFunctionDefinition(GD, GV); +} + void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) { const auto *D = cast(GD.getDecl()); @@ -2431,7 +2426,7 @@ Context.getSourceManager(), "Generating code for declaration"); - if (isa(D)) { + if (const auto *FD = dyn_cast(D)) { // At -O0, don't generate IR for functions with available_externally // linkage. if (!shouldEmitFunction(GD)) @@ -2444,6 +2439,8 @@ ABI->emitCXXStructor(CD, getFromCtorType(GD.getCtorType())); else if (const auto *DD = dyn_cast(Method)) ABI->emitCXXStructor(DD, getFromDtorType(GD.getDtorType())); + else if (FD->isMultiVersion()) + EmitMultiVersionFunctionDefinition(GD, GV); else EmitGlobalFunctionDefinition(GD, GV); @@ -2453,6 +2450,8 @@ return; } + if (FD->isMultiVersion()) + return EmitMultiVersionFunctionDefinition(GD, GV); return EmitGlobalFunctionDefinition(GD, GV); } @@ -2566,13 +2565,20 @@ SmallVector Options; const TargetInfo &Target = getTarget(); + unsigned Index = 0; for (const IdentifierInfo *II : DD->cpus()) { // Get the name of the target function so we can look it up/create it. std::string MangledName = getMangledNameImpl(*this, GD, FD, true) + getCPUSpecificMangling(*this, II->getName()); - llvm::Constant *Func = GetOrCreateLLVMFunction( - MangledName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/true, - /*IsThunk=*/false, llvm::AttributeList(), ForDefinition); + + llvm::Constant *Func = GetGlobalValue(MangledName); + + if (!Func) + Func = GetOrCreateLLVMFunction( + MangledName, DeclTy, GD.getWithMultiVersionIndex(Index), + /*ForVTable=*/false, /*DontDefer=*/true, + /*IsThunk=*/false, llvm::AttributeList(), ForDefinition); + llvm::SmallVector Features; Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features); llvm::transform(Features, Features.begin(), @@ -2582,6 +2588,7 @@ return !Target.validateCpuSupports(Feat); }), Features.end()); Options.emplace_back(cast(Func), StringRef{}, Features); + ++Index; } llvm::sort( @@ -3974,15 +3981,6 @@ AddGlobalDtor(Fn, DA->getPriority()); if (D->hasAttr()) AddGlobalAnnotations(D, Fn); - - if (D->isCPUSpecificMultiVersion()) { - auto *Spec = D->getAttr(); - // If there is another specific version we need to emit, do so here. - if (Spec->ActiveArgIndex + 1 < Spec->cpus_size()) { - ++Spec->ActiveArgIndex; - EmitGlobalFunctionDefinition(GD, nullptr); - } - } } void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { @@ -5404,8 +5402,9 @@ // Fills in the supplied string map with the set of target features for the // passed in function. void CodeGenModule::getFunctionFeatureMap(llvm::StringMap &FeatureMap, - const FunctionDecl *FD) { + GlobalDecl GD) { StringRef TargetCPU = Target.getTargetOpts().CPU; + const FunctionDecl *FD = GD.getDecl()->getAsFunction(); if (const auto *TD = FD->getAttr()) { TargetAttr::ParsedTargetAttr ParsedAttr = filterFunctionTargetAttrs(TD); @@ -5427,8 +5426,8 @@ ParsedAttr.Features); } else if (const auto *SD = FD->getAttr()) { llvm::SmallVector FeaturesTmp; - Target.getCPUSpecificCPUDispatchFeatures(SD->getCurCPUName()->getName(), - FeaturesTmp); + Target.getCPUSpecificCPUDispatchFeatures( + SD->getCPUName(GD.getMultiVersionIndex())->getName(), FeaturesTmp); std::vector Features(FeaturesTmp.begin(), FeaturesTmp.end()); Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, Features); } else { Index: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp @@ -1562,9 +1562,8 @@ Type != Dtor_Base && DD->isVirtual()) Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent()); else - Callee = - CGCallee::forDirect(CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)), - DD); + Callee = CGCallee::forDirect( + CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)), GD); CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(), This.getPointer(), VTT, VTTTy, @@ -1750,7 +1749,7 @@ VFunc = VFuncLoad; } - CGCallee Callee(MethodDecl->getCanonicalDecl(), VFunc); + CGCallee Callee(GD, VFunc); return Callee; } @@ -2420,7 +2419,7 @@ llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM), WrapperName.str(), &CGM.getModule()); - CGM.SetLLVMFunctionAttributes(nullptr, FI, Wrapper); + CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper); if (VD->hasDefinition()) CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Wrapper); @@ -2527,7 +2526,8 @@ llvm::GlobalVariable::ExternalWeakLinkage, InitFnName.str(), &CGM.getModule()); const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); - CGM.SetLLVMFunctionAttributes(nullptr, FI, cast(Init)); + CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, + cast(Init)); } if (Init) { Index: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp =================================================================== --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1552,9 +1552,9 @@ if (Type == Dtor_Complete && DD->getParent()->getNumVBases() == 0) Type = Dtor_Base; - CGCallee Callee = CGCallee::forDirect( - CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)), - DD); + CGCallee Callee = + CGCallee::forDirect(CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)), + GlobalDecl(DD, Type)); if (DD->isVirtual()) { assert(Type != CXXDtorType::Dtor_Deleting && @@ -1872,7 +1872,7 @@ VFunc = Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); } - CGCallee Callee(MethodDecl->getCanonicalDecl(), VFunc); + CGCallee Callee(GD, VFunc); return Callee; } @@ -3956,7 +3956,8 @@ // Call the destructor with our arguments. llvm::Constant *CalleePtr = CGM.getAddrOfCXXStructor(CD, StructorType::Complete); - CGCallee Callee = CGCallee::forDirect(CalleePtr, CD); + CGCallee Callee = + CGCallee::forDirect(CalleePtr, GlobalDecl(CD, Ctor_Complete)); const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall( Args, CD, Ctor_Complete, ExtraArgs.Prefix, ExtraArgs.Suffix); CGF.EmitCall(CalleeInfo, Callee, ReturnValueSlot(), Args); Index: cfe/trunk/lib/Parse/ParseDeclCXX.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp @@ -39,13 +39,15 @@ /// nested-namespace-definition /// /// named-namespace-definition: -/// 'inline'[opt] 'namespace' attributes[opt] identifier '{' namespace-body '}' +/// 'inline'[opt] 'namespace' attributes[opt] identifier '{' +/// namespace-body '}' /// /// unnamed-namespace-definition: /// 'inline'[opt] 'namespace' attributes[opt] '{' namespace-body '}' /// /// nested-namespace-definition: -/// 'namespace' enclosing-namespace-specifier '::' 'inline'[opt] identifier '{' namespace-body '}' +/// 'namespace' enclosing-namespace-specifier '::' 'inline'[opt] +/// identifier '{' namespace-body '}' /// /// enclosing-namespace-specifier: /// identifier @@ -264,8 +266,7 @@ assert(!ImplicitUsingDirectiveDecl && "nested namespace definition cannot define anonymous namespace"); - ParseInnerNamespace(InnerNSs, ++index, InlineLoc, - attrs, Tracker); + ParseInnerNamespace(InnerNSs, ++index, InlineLoc, attrs, Tracker); NamespaceScope.Exit(); Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation()); Index: cfe/trunk/test/CodeGen/attr-cpuspecific.c =================================================================== --- cfe/trunk/test/CodeGen/attr-cpuspecific.c +++ cfe/trunk/test/CodeGen/attr-cpuspecific.c @@ -223,6 +223,34 @@ // WINDOWS-NOT: call i32 @GenericAndPentium.A // WINDOWS-NOT: call void @llvm.trap +ATTR(cpu_dispatch(atom, pentium)) +int DispatchFirst(void); +// LINUX: define i32 ()* @DispatchFirst.resolver +// LINUX: ret i32 ()* @DispatchFirst.O +// LINUX: ret i32 ()* @DispatchFirst.B + +// WINDOWS: define dso_local i32 @DispatchFirst() +// WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.O() +// WINDOWS-NEXT: ret i32 %[[RET]] +// WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.B() +// WINDOWS-NEXT: ret i32 %[[RET]] + +ATTR(cpu_specific(atom)) +int DispatchFirst(void) {return 0;} +// LINUX: define i32 @DispatchFirst.O +// LINUX: ret i32 0 + +// WINDOWS: define dso_local i32 @DispatchFirst.O() +// WINDOWS: ret i32 0 + +ATTR(cpu_specific(pentium)) +int DispatchFirst(void) {return 1;} +// LINUX: define i32 @DispatchFirst.B +// LINUX: ret i32 1 + +// WINDOWS: define dso_local i32 @DispatchFirst.B +// WINDOWS: ret i32 1 + // CHECK: attributes #[[S]] = {{.*}}"target-features"="+avx,+cmov,+f16c,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave" // CHECK: attributes #[[K]] = {{.*}}"target-features"="+adx,+avx,+avx2,+avx512cd,+avx512er,+avx512f,+avx512pf,+bmi,+cmov,+f16c,+fma,+lzcnt,+mmx,+movbe,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave" // CHECK: attributes #[[O]] = {{.*}}"target-features"="+cmov,+mmx,+movbe,+sse,+sse2,+sse3,+ssse3,+x87"