Index: include/llvm/IR/Intrinsics.td =================================================================== --- include/llvm/IR/Intrinsics.td +++ include/llvm/IR/Intrinsics.td @@ -101,6 +101,9 @@ // This property indicates that the intrinsic is safe to speculate. def IntrSpeculatable : IntrinsicProperty; +// IntrNoRecurse - This property indicates that the intrinsic is non-recursive. +def IntrNoRecurse : IntrinsicProperty; + // This property can be used to override the 'has no other side effects' // language of the IntrNoMem, IntrReadMem, IntrWriteMem, and IntrArgMemOnly // intrinsic properties. By default, intrinsics are assumed to have side @@ -580,7 +583,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] in { +let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrNoRecurse] in { def int_dbg_declare : Intrinsic<[], [llvm_metadata_ty, llvm_metadata_ty, Index: test/CodeGen/Generic/dbg-influenced-attrs.ll =================================================================== --- test/CodeGen/Generic/dbg-influenced-attrs.ll +++ test/CodeGen/Generic/dbg-influenced-attrs.ll @@ -0,0 +1,34 @@ +; RUN: opt -S -functionattrs < %s | FileCheck %s + +define void @f0() #0 { + call void @llvm.dbg.value(metadata i16 0, metadata !19, metadata !DIExpression()), !dbg !21 + ret void +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind } +attributes #1 = { norecurse nounwind readnone speculatable } + +; CHECK: attributes #0 = { norecurse nounwind readnone } +; CHECK: attributes #1 = { norecurse nounwind readnone speculatable } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "foo.c", directory: "/") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 1} +!6 = !{!"clang version 6.0.0"} +!7 = distinct !DISubprogram(name: "f2", scope: !1, file: !1, line: 33, type: !8, isLocal: true, isDefinition: true, scopeLine: 33, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null} +!17 = distinct !DISubprogram(name: "f0", scope: !1, file: !1, line: 31, type: !8, isLocal: true, isDefinition: true, scopeLine: 31, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !18) +!18 = !{!19} +!19 = !DILocalVariable(name: "a", scope: !17, file: !1, line: 31, type: !20) +!20 = !DIBasicType(name: "int", size: 16, encoding: DW_ATE_signed) +!21 = !DILocation(line: 31, column: 36, scope: !17) Index: test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll =================================================================== --- test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll +++ test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll @@ -39,7 +39,7 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone ; CHECK: attributes #0 = { nounwind ssp } -; CHECK: attributes #1 = { nounwind readnone speculatable } +; CHECK: attributes #1 = { norecurse nounwind readnone speculatable } ; CHECK: attributes #2 = { noinline nounwind ssp } ; CHECK: attributes [[NUW]] = { nounwind } Index: test/Transforms/ObjCARC/basic.ll =================================================================== --- test/Transforms/ObjCARC/basic.ll +++ test/Transforms/ObjCARC/basic.ll @@ -3069,6 +3069,6 @@ !4 = !DIFile(filename: "path/to/file", directory: "/path/to/dir") !5 = !{i32 2, !"Debug Info Version", i32 3} -; CHECK: attributes #0 = { nounwind readnone speculatable } +; CHECK: attributes #0 = { norecurse nounwind readnone speculatable } ; CHECK: attributes [[NUW]] = { nounwind } ; CHECK: ![[RELEASE]] = !{} Index: test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll =================================================================== --- test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll +++ test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll @@ -105,7 +105,7 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone ; CHECK: attributes #0 = { ssp uwtable } -; CHECK: attributes #1 = { nounwind readnone speculatable } +; CHECK: attributes #1 = { norecurse nounwind readnone speculatable } ; CHECK: attributes #2 = { nonlazybind } ; CHECK: attributes #3 = { noinline ssp uwtable } ; CHECK: attributes [[NUW]] = { nounwind } Index: utils/TableGen/CodeGenIntrinsics.h =================================================================== --- utils/TableGen/CodeGenIntrinsics.h +++ utils/TableGen/CodeGenIntrinsics.h @@ -130,6 +130,9 @@ // True if the intrinsic is marked as speculatable. bool isSpeculatable; + // True if the intrinsic is marked as norecurse. + bool isNoRecurse; + enum ArgAttribute { NoCapture, Returned, ReadOnly, WriteOnly, ReadNone }; std::vector> ArgumentAttributes; Index: utils/TableGen/CodeGenTarget.cpp =================================================================== --- utils/TableGen/CodeGenTarget.cpp +++ utils/TableGen/CodeGenTarget.cpp @@ -518,6 +518,7 @@ isNoDuplicate = false; isConvergent = false; isSpeculatable = false; + isNoRecurse = false; hasSideEffects = false; if (DefName.size() <= 4 || @@ -659,6 +660,8 @@ isNoReturn = true; else if (Property->getName() == "IntrSpeculatable") isSpeculatable = true; + else if (Property->getName() == "IntrNoRecurse") + isNoRecurse = true; else if (Property->getName() == "IntrHasSideEffects") hasSideEffects = true; else if (Property->isSubClassOf("NoCapture")) { Index: utils/TableGen/IntrinsicEmitter.cpp =================================================================== --- utils/TableGen/IntrinsicEmitter.cpp +++ utils/TableGen/IntrinsicEmitter.cpp @@ -491,6 +491,9 @@ if (L->isSpeculatable != R->isSpeculatable) return R->isSpeculatable; + if (L->isNoRecurse != R->isNoRecurse) + return R->isNoRecurse; + if (L->hasSideEffects != R->hasSideEffects) return R->hasSideEffects; @@ -619,7 +622,8 @@ if (!intrinsic.canThrow || intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem || intrinsic.isNoReturn || intrinsic.isNoDuplicate || - intrinsic.isConvergent || intrinsic.isSpeculatable) { + intrinsic.isConvergent || intrinsic.isSpeculatable || + intrinsic.isNoRecurse) { OS << " const Attribute::AttrKind Atts[] = {"; bool addComma = false; if (!intrinsic.canThrow) { @@ -650,6 +654,12 @@ OS << "Attribute::Speculatable"; addComma = true; } + if (intrinsic.isNoRecurse) { + if (addComma) + OS << ","; + OS << "Attribute::NoRecurse"; + addComma = true; + } switch (intrinsic.ModRef) { case CodeGenIntrinsic::NoMem: