diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp index 70ccecf7752a..09eb1ed5e186 100644 --- a/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -379,10 +379,10 @@ static bool compareFnAttributes(const CodeGenIntrinsic *L, return TieL < TieR; // Try to order by readonly/readnone attribute. - uint32_t LK = L->ME.toIntValue(); - uint32_t RK = R->ME.toIntValue(); - if (LK != RK) - return LK > RK; + uint32_t LME = L->ME.toIntValue(); + uint32_t RME = R->ME.toIntValue(); + if (LME != RME) + return LME > RME; return Default; } @@ -404,6 +404,54 @@ struct AttributeComparator { }; } // End anonymous namespace +/// Returns the effective MemoryEffects for intrinsic \p Int. +static MemoryEffects getEffectiveME(const CodeGenIntrinsic &Int) { + MemoryEffects ME = Int.ME; + // TODO: IntrHasSideEffects should affect not only readnone intrinsics. + if (ME.doesNotAccessMemory() && Int.hasSideEffects) + ME = MemoryEffects::unknown(); + return ME; +} + +/// Returns true if \p Int has a non-empty set of function attributes. Note that +/// NoUnwind = !canThrow, so we need to negate it's sense to test if the +// intrinsic has NoUnwind attribute. +static bool hasFnAttributes(const CodeGenIntrinsic &Int) { + return !Int.canThrow || Int.isNoReturn || Int.isNoCallback || Int.isNoSync || + Int.isNoFree || Int.isWillReturn || Int.isCold || Int.isNoDuplicate || + Int.isNoMerge || Int.isConvergent || Int.isSpeculatable || + Int.isStrictFP || getEffectiveME(Int) != MemoryEffects::unknown(); +} + +/// Returns the name of the IR enum for argument attribute kind \p Kind. +static StringRef getArgAttrEnumName(CodeGenIntrinsic::ArgAttrKind Kind) { + switch (Kind) { + case CodeGenIntrinsic::NoCapture: + return "NoCapture"; + case CodeGenIntrinsic::NoAlias: + return "NoAlias"; + case CodeGenIntrinsic::NoUndef: + return "NoUndef"; + case CodeGenIntrinsic::NonNull: + return "NonNull"; + case CodeGenIntrinsic::Returned: + return "Returned"; + case CodeGenIntrinsic::ReadOnly: + return "ReadOnly"; + case CodeGenIntrinsic::WriteOnly: + return "WriteOnly"; + case CodeGenIntrinsic::ReadNone: + return "ReadNone"; + case CodeGenIntrinsic::ImmArg: + return "ImmArg"; + case CodeGenIntrinsic::Alignment: + return "Alignment"; + case CodeGenIntrinsic::Dereferenceable: + return "Dereferenceable"; + } + llvm_unreachable("Unknown CodeGenIntrinsic::ArgAttrKind enum"); +} + /// EmitAttributes - This emits the Intrinsic::getAttributes method. void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints, raw_ostream &OS) { @@ -425,34 +473,6 @@ static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) { continue; assert(is_sorted(Attrs) && "Argument attributes are not sorted"); - auto getAttrEnumName = - [](CodeGenIntrinsic::ArgAttrKind Kind) -> StringRef { - switch (Kind) { - case CodeGenIntrinsic::NoCapture: - return "NoCapture"; - case CodeGenIntrinsic::NoAlias: - return "NoAlias"; - case CodeGenIntrinsic::NoUndef: - return "NoUndef"; - case CodeGenIntrinsic::NonNull: - return "NonNull"; - case CodeGenIntrinsic::Returned: - return "Returned"; - case CodeGenIntrinsic::ReadOnly: - return "ReadOnly"; - case CodeGenIntrinsic::WriteOnly: - return "WriteOnly"; - case CodeGenIntrinsic::ReadNone: - return "ReadNone"; - case CodeGenIntrinsic::ImmArg: - return "ImmArg"; - case CodeGenIntrinsic::Alignment: - return "Alignment"; - case CodeGenIntrinsic::Dereferenceable: - return "Dereferenceable"; - } - llvm_unreachable("Unknown CodeGenIntrinsic::ArgAttrKind enum"); - }; OS << formatv(R"( case {0}: @@ -460,7 +480,7 @@ static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) { )", ID); for (const CodeGenIntrinsic::ArgAttribute &Attr : Attrs) { - StringRef AttrName = getAttrEnumName(Attr.Kind); + StringRef AttrName = getArgAttrEnumName(Attr.Kind); if (Attr.Kind == CodeGenIntrinsic::Alignment || Attr.Kind == CodeGenIntrinsic::Dereferenceable) OS << formatv(" Attribute::get(C, Attribute::{0}, {1}),\n", @@ -473,7 +493,8 @@ static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) { } OS << R"( } -} // getIntrinsicArgAttributeSet)"; +} // getIntrinsicArgAttributeSet +)"; // Compute unique function attribute sets. std::map @@ -482,9 +503,12 @@ static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) { static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) { switch (ID) { default: llvm_unreachable("Invalid attribute set number");)"; - for (const CodeGenIntrinsic &Intrinsic : Ints) { + + for (const CodeGenIntrinsic &Int : Ints) { + if (!hasFnAttributes(Int)) + continue; unsigned ID = UniqFnAttributes.size(); - if (!UniqFnAttributes.try_emplace(&Intrinsic, ID).second) + if (!UniqFnAttributes.try_emplace(&Int, ID).second) continue; OS << formatv(R"( case {0}: @@ -494,44 +518,42 @@ static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) { auto addAttribute = [&OS](StringRef Attr) { OS << formatv(" Attribute::get(C, Attribute::{0}),\n", Attr); }; - if (!Intrinsic.canThrow) + if (!Int.canThrow) addAttribute("NoUnwind"); - if (Intrinsic.isNoReturn) + if (Int.isNoReturn) addAttribute("NoReturn"); - if (Intrinsic.isNoCallback) + if (Int.isNoCallback) addAttribute("NoCallback"); - if (Intrinsic.isNoSync) + if (Int.isNoSync) addAttribute("NoSync"); - if (Intrinsic.isNoFree) + if (Int.isNoFree) addAttribute("NoFree"); - if (Intrinsic.isWillReturn) + if (Int.isWillReturn) addAttribute("WillReturn"); - if (Intrinsic.isCold) + if (Int.isCold) addAttribute("Cold"); - if (Intrinsic.isNoDuplicate) + if (Int.isNoDuplicate) addAttribute("NoDuplicate"); - if (Intrinsic.isNoMerge) + if (Int.isNoMerge) addAttribute("NoMerge"); - if (Intrinsic.isConvergent) + if (Int.isConvergent) addAttribute("Convergent"); - if (Intrinsic.isSpeculatable) + if (Int.isSpeculatable) addAttribute("Speculatable"); - if (Intrinsic.isStrictFP) + if (Int.isStrictFP) addAttribute("StrictFP"); - MemoryEffects ME = Intrinsic.ME; - // TODO: IntrHasSideEffects should affect not only readnone intrinsics. - if (ME.doesNotAccessMemory() && Intrinsic.hasSideEffects) - ME = MemoryEffects::unknown(); + const MemoryEffects ME = getEffectiveME(Int); if (ME != MemoryEffects::unknown()) { OS << formatv(" // {0}\n", ME); OS << formatv(" Attribute::getWithMemoryEffects(C, " "MemoryEffects::createFromIntValue({0})),\n", ME.toIntValue()); } - OS << " });\n"; + OS << " });"; + } + OS << R"( } - OS << R"( } } // getIntrinsicFnAttributeSet AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) { @@ -586,11 +608,7 @@ AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) { NumAttrs++, AttrIdx, ArgAttrID); } - if (!Int.canThrow || - (Int.ME != MemoryEffects::unknown() && !Int.hasSideEffects) || - Int.isNoReturn || Int.isNoCallback || Int.isNoSync || Int.isNoFree || - Int.isWillReturn || Int.isCold || Int.isNoDuplicate || Int.isNoMerge || - Int.isConvergent || Int.isSpeculatable || Int.isStrictFP) { + if (hasFnAttributes(Int)) { unsigned FnAttrID = UniqFnAttributes.find(&Int)->second; OS << formatv(" AS[{0}] = {{AttributeList::FunctionIndex, " "getIntrinsicFnAttributeSet(C, {1})};\n",