diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -100,6 +100,10 @@ def IntrNoReturn : IntrinsicProperty; +def IntrNoSync : IntrinsicProperty; + +def IntrNoFree : IntrinsicProperty; + def IntrWillReturn : IntrinsicProperty; // IntrCold - Calls to this intrinsic are cold. @@ -306,13 +310,15 @@ list param_types = [], list intr_properties = [], string name = "", - list sd_properties = []> : SDPatternOperator { + list sd_properties = [], + list optout_intr_properties = []> : SDPatternOperator { string LLVMName = name; string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics. list RetTypes = ret_types; list ParamTypes = param_types; list IntrProperties = intr_properties; let Properties = sd_properties; + list OptOutIntrProperties = optout_intr_properties; bit isTarget = 0; } @@ -468,7 +474,7 @@ // memory while not impeding optimization. def int_prefetch : Intrinsic<[], [ llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty ], - [ IntrInaccessibleMemOrArgMemOnly, IntrWillReturn, ReadOnly<0>, NoCapture<0>, + [ IntrInaccessibleMemOrArgMemOnly, ReadOnly<0>, NoCapture<0>, ImmArg<1>, ImmArg<2>]>; def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>; @@ -476,7 +482,7 @@ // The assume intrinsic is marked as arbitrarily writing so that proper // control dependencies will be maintained. -def int_assume : Intrinsic<[], [llvm_i1_ty], [IntrWillReturn]>; +def int_assume : Intrinsic<[], [llvm_i1_ty], []>; // Stack Protector Intrinsic - The stackprotector intrinsic writes the stack // guard to the correct place on the stack frame. @@ -509,23 +515,23 @@ def int_memcpy : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i1_ty], - [IntrArgMemOnly, IntrWillReturn, NoCapture<0>, NoCapture<1>, + [IntrArgMemOnly, NoCapture<0>, NoCapture<1>, NoAlias<0>, NoAlias<1>, WriteOnly<0>, ReadOnly<1>, ImmArg<3>]>; def int_memmove : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i1_ty], - [IntrArgMemOnly, IntrWillReturn, NoCapture<0>, NoCapture<1>, + [IntrArgMemOnly, NoCapture<0>, NoCapture<1>, ReadOnly<1>, ImmArg<3>]>; def int_memset : Intrinsic<[], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i1_ty], - [IntrArgMemOnly, IntrWillReturn, NoCapture<0>, WriteOnly<0>, + [IntrArgMemOnly, NoCapture<0>, WriteOnly<0>, ImmArg<3>]>; // FIXME: Add version of these floating point intrinsics which allow non-default // rounding modes and FP exception handling. -let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in { +let IntrProperties = [IntrNoMem, IntrSpeculatable] in { def int_fma : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; @@ -567,19 +573,19 @@ def int_minnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative] + [IntrNoMem, IntrSpeculatable, Commutative] >; def int_maxnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative] + [IntrNoMem, IntrSpeculatable, Commutative] >; def int_minimum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative] + [IntrNoMem, IntrSpeculatable, Commutative] >; def int_maximum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative] + [IntrNoMem, IntrSpeculatable, Commutative] >; // NOTE: these are internal interfaces. @@ -592,13 +598,13 @@ def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, llvm_i1_ty, llvm_i1_ty, llvm_i1_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, ImmArg<1>, ImmArg<2>, ImmArg<3>]>, + [IntrNoMem, IntrSpeculatable, ImmArg<1>, ImmArg<2>, ImmArg<3>]>, GCCBuiltin<"__builtin_object_size">; //===--------------- Constrained Floating Point Intrinsics ----------------===// // -let IntrProperties = [IntrInaccessibleMemOnly, IntrWillReturn] in { +let IntrProperties = [IntrInaccessibleMemOnly] in { def int_experimental_constrained_fadd : Intrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, @@ -750,13 +756,13 @@ //===------------------------- Expect Intrinsics --------------------------===// // def int_expect : Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrWillReturn]>; + [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; //===-------------------- Bit Manipulation Intrinsics ---------------------===// // // None of these intrinsics accesses memory at all. -let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in { +let IntrProperties = [IntrNoMem, IntrSpeculatable] in { def int_bswap: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; def int_ctpop: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; def int_bitreverse : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; @@ -766,7 +772,7 @@ [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; } -let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn, ImmArg<1>] in { +let IntrProperties = [IntrNoMem, IntrSpeculatable, ImmArg<1>] in { def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; def int_cttz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; } @@ -778,7 +784,7 @@ // mean the optimizers can change them aggressively. Special handling // needed in a few places. These synthetic intrinsics have no // side-effects and just mark information about their operands. -let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in { +let IntrProperties = [IntrNoMem, IntrSpeculatable] in { def int_dbg_declare : Intrinsic<[], [llvm_metadata_ty, llvm_metadata_ty, @@ -835,21 +841,21 @@ def int_var_annotation : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrWillReturn], "llvm.var.annotation">; + [], "llvm.var.annotation">; def int_ptr_annotation : Intrinsic<[LLVMAnyPointerType], [LLVMMatchType<0>, llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrWillReturn], "llvm.ptr.annotation">; + [], "llvm.ptr.annotation">; def int_annotation : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrWillReturn], "llvm.annotation">; + [], "llvm.annotation">; // Annotates the current program point with metadata strings which are emitted // as CodeView debug info records. This is expensive, as it disables inlining // and is modelled as having side effects. def int_codeview_annotation : Intrinsic<[], [llvm_metadata_ty], - [IntrInaccessibleMemOnly, IntrNoDuplicate, IntrWillReturn], + [IntrInaccessibleMemOnly, IntrNoDuplicate], "llvm.codeview.annotation">; //===------------------------ Trampoline Intrinsics -----------------------===// @@ -867,7 +873,7 @@ // // Expose the carry flag from add operations on two integrals. -let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in { +let IntrProperties = [IntrNoMem, IntrSpeculatable] in { def int_sadd_with_overflow : Intrinsic<[llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>]>; @@ -893,51 +899,51 @@ // def int_sadd_sat : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]>; + [IntrNoMem, IntrSpeculatable, Commutative]>; def int_uadd_sat : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]>; + [IntrNoMem, IntrSpeculatable, Commutative]>; def int_ssub_sat : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; + [IntrNoMem, IntrSpeculatable]>; def int_usub_sat : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; + [IntrNoMem, IntrSpeculatable]>; //===------------------------- Fixed Point Arithmetic Intrinsics ---------------------===// // def int_smul_fix : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative, ImmArg<2>]>; + [IntrNoMem, IntrSpeculatable, Commutative, ImmArg<2>]>; def int_umul_fix : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative, ImmArg<2>]>; + [IntrNoMem, IntrSpeculatable, Commutative, ImmArg<2>]>; //===------------------- Fixed Point Saturation Arithmetic Intrinsics ----------------===// // def int_smul_fix_sat : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative, ImmArg<2>]>; + [IntrNoMem, IntrSpeculatable, Commutative, ImmArg<2>]>; def int_umul_fix_sat : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative, ImmArg<2>]>; + [IntrNoMem, IntrSpeculatable, Commutative, ImmArg<2>]>; //===------------------------- Memory Use Markers -------------------------===// // def int_lifetime_start : Intrinsic<[], [llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, IntrWillReturn, NoCapture<1>, ImmArg<0>]>; + [IntrArgMemOnly, NoCapture<1>, ImmArg<0>]>; def int_lifetime_end : Intrinsic<[], [llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, IntrWillReturn, NoCapture<1>, ImmArg<0>]>; + [IntrArgMemOnly, NoCapture<1>, ImmArg<0>]>; def int_invariant_start : Intrinsic<[llvm_descriptor_ty], [llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, IntrWillReturn, NoCapture<1>, ImmArg<0>]>; + [IntrArgMemOnly, NoCapture<1>, ImmArg<0>]>; def int_invariant_end : Intrinsic<[], [llvm_descriptor_ty, llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, IntrWillReturn, NoCapture<2>, ImmArg<1>]>; + [IntrArgMemOnly, NoCapture<2>, ImmArg<1>]>; // launder.invariant.group can't be marked with 'readnone' (IntrNoMem), // because it would cause CSE of two barriers with the same argument. @@ -953,12 +959,12 @@ // might change in the future. def int_launder_invariant_group : Intrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>], - [IntrInaccessibleMemOnly, IntrSpeculatable, IntrWillReturn]>; + [IntrInaccessibleMemOnly, IntrSpeculatable]>; def int_strip_invariant_group : Intrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>], - [IntrSpeculatable, IntrNoMem, IntrWillReturn]>; + [IntrSpeculatable, IntrNoMem]>; //===------------------------ Stackmap Intrinsics -------------------------===// // @@ -1070,19 +1076,19 @@ // Supports widenable conditions for guards represented as explicit branches. def int_experimental_widenable_condition : Intrinsic<[llvm_i1_ty], [], - [IntrInaccessibleMemOnly, IntrWillReturn, IntrSpeculatable]>; + [IntrInaccessibleMemOnly, IntrSpeculatable]>; // NOP: calls/invokes to this intrinsic are removed by codegen -def int_donothing : Intrinsic<[], [], [IntrNoMem, IntrWillReturn]>; +def int_donothing : Intrinsic<[], [], [IntrNoMem]>; // This instruction has no actual effect, though it is treated by the optimizer // has having opaque side effects. This may be inserted into loops to ensure // that they are not removed even if they turn out to be empty, for languages // which specify that infinite loops must be preserved. -def int_sideeffect : Intrinsic<[], [], [IntrInaccessibleMemOnly, IntrWillReturn]>; +def int_sideeffect : Intrinsic<[], [], [IntrInaccessibleMemOnly]>; // Intrinsics to support half precision floating point format -let IntrProperties = [IntrNoMem, IntrWillReturn] in { +let IntrProperties = [IntrNoMem] in { def int_convert_to_fp16 : Intrinsic<[llvm_i16_ty], [llvm_anyfloat_ty]>; def int_convert_from_fp16 : Intrinsic<[llvm_anyfloat_ty], [llvm_i16_ty]>; } @@ -1093,11 +1099,11 @@ [], "llvm.clear_cache">; // Intrinsic to detect whether its argument is a constant. -def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem, IntrWillReturn], "llvm.is.constant">; +def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem], "llvm.is.constant">; // Intrinsic to mask out bits of a pointer. def int_ptrmask: Intrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty, llvm_anyint_ty], - [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; + [IntrNoMem, IntrSpeculatable]>; //===-------------------------- Masked Intrinsics -------------------------===// // @@ -1105,45 +1111,45 @@ LLVMAnyPointerType>, llvm_i32_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [IntrArgMemOnly, IntrWillReturn, ImmArg<2>]>; + [IntrArgMemOnly, ImmArg<2>]>; def int_masked_load : Intrinsic<[llvm_anyvector_ty], [LLVMAnyPointerType>, llvm_i32_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], - [IntrReadMem, IntrArgMemOnly, IntrWillReturn, ImmArg<1>]>; + [IntrReadMem, IntrArgMemOnly, ImmArg<1>]>; def int_masked_gather: Intrinsic<[llvm_anyvector_ty], [LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], - [IntrReadMem, IntrWillReturn, ImmArg<1>]>; + [IntrReadMem, ImmArg<1>]>; def int_masked_scatter: Intrinsic<[], [llvm_anyvector_ty, LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [IntrWillReturn, ImmArg<2>]>; + [ImmArg<2>]>; def int_masked_expandload: Intrinsic<[llvm_anyvector_ty], [LLVMPointerToElt<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], - [IntrReadMem, IntrWillReturn]>; + [IntrReadMem]>; def int_masked_compressstore: Intrinsic<[], [llvm_anyvector_ty, LLVMPointerToElt<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [IntrArgMemOnly, IntrWillReturn]>; + [IntrArgMemOnly]>; // Test whether a pointer is associated with a type metadata identifier. def int_type_test : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty], - [IntrNoMem, IntrWillReturn]>; + [IntrNoMem]>; // Safely loads a function pointer from a virtual table pointer using type metadata. def int_type_checked_load : Intrinsic<[llvm_ptr_ty, llvm_i1_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_metadata_ty], - [IntrNoMem, IntrWillReturn]>; + [IntrNoMem]>; // Create a branch funnel that implements an indirect call to a limited set of // callees. This needs to be a musttail call. @@ -1179,7 +1185,7 @@ llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty ], [ - IntrArgMemOnly, IntrWillReturn, NoCapture<0>, NoCapture<1>, WriteOnly<0>, + IntrArgMemOnly, NoCapture<0>, NoCapture<1>, WriteOnly<0>, ReadOnly<1>, ImmArg<3> ]>; @@ -1190,18 +1196,18 @@ llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty ], [ - IntrArgMemOnly, IntrWillReturn, NoCapture<0>, NoCapture<1>, WriteOnly<0>, + IntrArgMemOnly, NoCapture<0>, NoCapture<1>, WriteOnly<0>, ReadOnly<1>, ImmArg<3> ]>; // @llvm.memset.element.unordered.atomic.*(dest, value, length, elementsize) def int_memset_element_unordered_atomic : Intrinsic<[], [ llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i32_ty ], - [ IntrArgMemOnly, IntrWillReturn, NoCapture<0>, WriteOnly<0>, ImmArg<3> ]>; + [ IntrArgMemOnly, NoCapture<0>, WriteOnly<0>, ImmArg<3> ]>; //===------------------------ Reduction Intrinsics ------------------------===// // -let IntrProperties = [IntrNoMem, IntrWillReturn] in { +let IntrProperties = [IntrNoMem] in { def int_experimental_vector_reduce_v2_fadd : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_anyvector_ty]>; diff --git a/llvm/test/Feature/intrinsics.ll b/llvm/test/Feature/intrinsics.ll --- a/llvm/test/Feature/intrinsics.ll +++ b/llvm/test/Feature/intrinsics.ll @@ -69,5 +69,5 @@ ret void } -; CHECK: attributes #0 = { nounwind readnone speculatable willreturn } -; CHECK: attributes #1 = { cold noreturn nounwind } +; CHECK: attributes #0 = { nofree nosync nounwind readnone speculatable willreturn } +; CHECK: attributes #1 = { cold nofree noreturn nosync nounwind willreturn } diff --git a/llvm/utils/TableGen/CodeGenIntrinsics.h b/llvm/utils/TableGen/CodeGenIntrinsics.h --- a/llvm/utils/TableGen/CodeGenIntrinsics.h +++ b/llvm/utils/TableGen/CodeGenIntrinsics.h @@ -123,6 +123,12 @@ /// True if the intrinsic is no-return. bool isNoReturn; + /// True if the intrinsic is nosync. + bool isNoSync; + + /// True if the intrinsic is nofree. + bool isNoFree; + /// True if the intrinsic is will-return. bool isWillReturn; diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -25,6 +25,7 @@ #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include + using namespace llvm; cl::OptionCategory AsmParserCat("Options for -gen-asm-parser"); @@ -609,13 +610,18 @@ isCommutative = false; canThrow = false; isNoReturn = false; - isWillReturn = false; isCold = false; isNoDuplicate = false; isConvergent = false; isSpeculatable = false; hasSideEffects = false; + // Default IntrProperties. Will be set to false if present in + // OptOutIntrProperties. + isNoSync = true; + isNoFree = true; + isWillReturn = true; + if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin() + 4) != "int_") PrintFatalError(DefLoc, @@ -744,6 +750,23 @@ IS.ParamTypeDefs.push_back(TyEl); } + // Parse the opt-out intrinsic properties. + ListInit *OptOutPropList = R->getValueAsListInit("OptOutIntrProperties"); + for (unsigned i = 0, e = OptOutPropList->size(); i != e; ++i) { + Record *Property = OptOutPropList->getElementAsRecord(i); + assert(Property->isSubClassOf("IntrinsicProperty") && + "Expected a property"); + + if (Property->getName() == "IntrWillReturn") + isWillReturn = false; + else if (Property->getName() == "IntrNoSync") + isNoSync = false; + else if (Property->getName() == "IntrNoFree") + isNoFree = false; + else + llvm_unreachable("Unknown property!"); + } + // Parse the intrinsic properties. ListInit *PropList = R->getValueAsListInit("IntrProperties"); for (unsigned i = 0, e = PropList->size(); i != e; ++i) { @@ -774,8 +797,6 @@ isConvergent = true; else if (Property->getName() == "IntrNoReturn") isNoReturn = true; - else if (Property->getName() == "IntrWillReturn") - isWillReturn = true; else if (Property->getName() == "IntrCold") isCold = true; else if (Property->getName() == "IntrSpeculatable") diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp --- a/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -557,6 +557,12 @@ if (L->isNoReturn != R->isNoReturn) return R->isNoReturn; + if (L->isNoFree != R->isNoFree) + return R->isNoFree; + + if (L->isNoSync != R->isNoSync) + return R->isNoSync; + if (L->isWillReturn != R->isWillReturn) return R->isWillReturn; @@ -706,10 +712,11 @@ } if (!intrinsic.canThrow || - (intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem && !intrinsic.hasSideEffects) || - intrinsic.isNoReturn || intrinsic.isWillReturn || intrinsic.isCold || - intrinsic.isNoDuplicate || intrinsic.isConvergent || - intrinsic.isSpeculatable) { + (intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem && + !intrinsic.hasSideEffects) || + intrinsic.isNoReturn || intrinsic.isNoSync || intrinsic.isNoFree || + intrinsic.isWillReturn || intrinsic.isCold || intrinsic.isNoDuplicate || + intrinsic.isConvergent || intrinsic.isSpeculatable) { OS << " const Attribute::AttrKind Atts[] = {"; bool addComma = false; if (!intrinsic.canThrow) { @@ -722,6 +729,18 @@ OS << "Attribute::NoReturn"; addComma = true; } + if (intrinsic.isNoSync) { + if (addComma) + OS << ","; + OS << "Attribute::NoSync"; + addComma = true; + } + if (intrinsic.isNoFree) { + if (addComma) + OS << ","; + OS << "Attribute::NoFree"; + addComma = true; + } if (intrinsic.isWillReturn) { if (addComma) OS << ",";