diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2310,6 +2310,7 @@ B.addAttribute(llvm::Attribute::Naked); // OptimizeNone wins over OptimizeForSize and MinSize. + F->removeFnAttr(llvm::Attribute::OptimizeForDebugging); F->removeFnAttr(llvm::Attribute::OptimizeForSize); F->removeFnAttr(llvm::Attribute::MinSize); } else if (D->hasAttr()) { diff --git a/llvm/docs/BitCodeFormat.rst b/llvm/docs/BitCodeFormat.rst --- a/llvm/docs/BitCodeFormat.rst +++ b/llvm/docs/BitCodeFormat.rst @@ -1080,6 +1080,7 @@ * code 77: ``elementtype`` * code 78: ``disable_sanitizer_instrumentation`` * code 79: ``nosanitize_bounds`` +* code 88: ``optdebug`` .. note:: The ``allocsize`` attribute has a special encoding for its arguments. Its two diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2024,6 +2024,10 @@ Note: Comparing address of a global variable to ``null`` may still evaluate to false because of a limitation in querying this attribute inside constant expressions. +``optdebug`` + This attribute suggests that optimization passes and code generator passes + should make choices that try to preserve debug info without significantly + degrading runtime performance. ``optforfuzzing`` This attribute indicates that this function should be optimized for maximum fuzzing signal. diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -713,6 +713,7 @@ ATTR_KIND_SKIP_PROFILE = 85, ATTR_KIND_MEMORY = 86, ATTR_KIND_NOFPCLASS = 87, + ATTR_KIND_OPTIMIZE_FOR_DEBUGGING = 88, }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -200,6 +200,9 @@ /// Null pointer in address space zero is valid. def NullPointerIsValid : EnumAttr<"null_pointer_is_valid", [FnAttr]>; +/// Select optimizations that give decent debug info. +def OptimizeForDebugging : EnumAttr<"optdebug", [FnAttr]>; + /// Select optimizations for best fuzzing signal. def OptForFuzzing : EnumAttr<"optforfuzzing", [FnAttr]>; diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1984,6 +1984,8 @@ return Attribute::NoSanitizeCoverage; case bitc::ATTR_KIND_NULL_POINTER_IS_VALID: return Attribute::NullPointerIsValid; + case bitc::ATTR_KIND_OPTIMIZE_FOR_DEBUGGING: + return Attribute::OptimizeForDebugging; case bitc::ATTR_KIND_OPT_FOR_FUZZING: return Attribute::OptForFuzzing; case bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE: diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -735,6 +735,8 @@ return bitc::ATTR_KIND_NO_SANITIZE_COVERAGE; case Attribute::NullPointerIsValid: return bitc::ATTR_KIND_NULL_POINTER_IS_VALID; + case Attribute::OptimizeForDebugging: + return bitc::ATTR_KIND_OPTIMIZE_FOR_DEBUGGING; case Attribute::OptForFuzzing: return bitc::ATTR_KIND_OPT_FOR_FUZZING; case Attribute::OptimizeForSize: diff --git a/llvm/lib/CodeGen/PostRASchedulerList.cpp b/llvm/lib/CodeGen/PostRASchedulerList.cpp --- a/llvm/lib/CodeGen/PostRASchedulerList.cpp +++ b/llvm/lib/CodeGen/PostRASchedulerList.cpp @@ -279,6 +279,9 @@ if (skipFunction(Fn.getFunction())) return false; + if (Fn.getFunction().hasFnAttribute(Attribute::OptimizeForDebugging)) + return false; + TII = Fn.getSubtarget().getInstrInfo(); MachineLoopInfo &MLI = getAnalysis(); AliasAnalysis *AA = &getAnalysis().getAAResults(); diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -940,6 +940,7 @@ case Attribute::NoSanitizeBounds: case Attribute::NoSanitizeCoverage: case Attribute::NullPointerIsValid: + case Attribute::OptimizeForDebugging: case Attribute::OptForFuzzing: case Attribute::OptimizeNone: case Attribute::OptimizeForSize: diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll --- a/llvm/test/Bitcode/attributes.ll +++ b/llvm/test/Bitcode/attributes.ll @@ -511,6 +511,12 @@ ; CHECK: define void @f88() [[SKIPPROFILE:#[0-9]+]] define void @f88() skipprofile { ret void } +define void @f89() optdebug +; CHECK: define void @f89() [[OPTDEBUG:#[0-9]+]] +{ + ret void; +} + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { memory(none) } @@ -566,4 +572,5 @@ ; CHECK: attributes #52 = { nosanitize_bounds } ; CHECK: attributes [[FNRETTHUNKEXTERN]] = { fn_ret_thunk_extern } ; CHECK: attributes [[SKIPPROFILE]] = { skipprofile } +; CHECK: attributes [[OPTDEBUG]] = { optdebug } ; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin } diff --git a/llvm/test/CodeGen/X86/suppress-post-ra.mir b/llvm/test/CodeGen/X86/suppress-post-ra.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/suppress-post-ra.mir @@ -0,0 +1,78 @@ +# Check if the function attribute "optdebug" suppresses the post-RA scheduler. + +# Note: This code is a reduced sample of code that will be affected by the +# post-RA scheduler, and the test will start to fail if the post-RA scheduler +# no longer makes any change to this test case; if this starts to happen due to +# a valid post-RA scheduler change, either change the test so that it is still +# affected, or XFAIL the test. + +# RUN: llc %s -run-pass verify -o %t1 +# RUN: llc %s -run-pass post-RA-sched -o %t2 +# RUN: diff %t1 %t2 + +# Detect if this test becomes rotten by verifying that post-RA-sched does +# *something* to this test case. +# RUN: sed 's/optdebug //' %s | llc - -x mir -run-pass verify -o %t3 +# RUN: sed 's/optdebug //' %s | llc - -x mir -run-pass post-RA-sched -o %t4 +# RUN: not diff %t3 %t4 + +--- | + ; ModuleID = '/tmp/llvm-reduce-efe8f0.ll' + source_filename = "/tmp/llvm-reduce-efe8f0.ll" + target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128" + target triple = "i686-unknown-unknown" + + define void @update() #0 { + entry: + %v = alloca <3 x i16>, i32 0, align 8 + ret void + } + + attributes #0 = { optdebug "target-cpu"="slm" } + +... +--- +name: update +alignment: 16 +tracksRegLiveness: true +tracksDebugUserValues: true +registers: [] +liveins: [] +frameInfo: + stackSize: 12 + offsetAdjustment: -8 + maxAlignment: 8 + stackProtector: '' + functionContext: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: + - { id: 0, type: spill-slot, offset: -8, size: 4, alignment: 4, stack-id: default, + callee-saved-register: '', callee-saved-restored: true, debug-info-variable: '', + debug-info-expression: '', debug-info-location: '' } +stack: + - { id: 0, name: v, type: default, offset: -16, size: 1, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + frame-setup PUSH32r killed $ebp, implicit-def $esp, implicit $esp + frame-setup CFI_INSTRUCTION def_cfa_offset 8 + frame-setup CFI_INSTRUCTION offset $ebp, -8 + $ebp = frame-setup MOV32rr $esp + frame-setup CFI_INSTRUCTION def_cfa_register $ebp + $esp = frame-setup AND32ri $esp, -8, implicit-def dead $eflags + $esp = MOV32rr $ebp + $ebp = frame-destroy POP32r implicit-def $esp, implicit $esp + frame-destroy CFI_INSTRUCTION def_cfa $esp, 4 + RET32 + +... diff --git a/llvm/utils/emacs/llvm-mode.el b/llvm/utils/emacs/llvm-mode.el --- a/llvm/utils/emacs/llvm-mode.el +++ b/llvm/utils/emacs/llvm-mode.el @@ -25,7 +25,7 @@ '("alwaysinline" "argmemonly" "allocsize" "builtin" "cold" "convergent" "dereferenceable" "dereferenceable_or_null" "hot" "immarg" "inaccessiblememonly" "inaccessiblemem_or_argmemonly" "inalloca" "inlinehint" "jumptable" "minsize" "mustprogress" "naked" "nobuiltin" "nonnull" "nocapture" "nocallback" "nocf_check" "noduplicate" "nofree" "noimplicitfloat" "noinline" "nomerge" "nonlazybind" "noprofile" "noredzone" "noreturn" - "norecurse" "nosync" "noundef" "nounwind" "nosanitize_bounds" "nosanitize_coverage" "null_pointer_is_valid" "optforfuzzing" "optnone" "optsize" "preallocated" "readnone" "readonly" "returned" "returns_twice" + "norecurse" "nosync" "noundef" "nounwind" "nosanitize_bounds" "nosanitize_coverage" "null_pointer_is_valid" "optdebug" "optforfuzzing" "optnone" "optsize" "preallocated" "readnone" "readonly" "returned" "returns_twice" "shadowcallstack" "signext" "speculatable" "speculative_load_hardening" "ssp" "sspreq" "sspstrong" "safestack" "sanitize_address" "sanitize_hwaddress" "sanitize_memtag" "sanitize_thread" "sanitize_memory" "strictfp" "swifterror" "uwtable" "vscale_range" "willreturn" "writeonly" "zeroext") 'symbols) . font-lock-constant-face) ;; Variables diff --git a/llvm/utils/kate/llvm.xml b/llvm/utils/kate/llvm.xml --- a/llvm/utils/kate/llvm.xml +++ b/llvm/utils/kate/llvm.xml @@ -111,6 +111,7 @@ nosync nounwind null_pointer_is_valid + optdebug optforfuzzing optnone optsize diff --git a/llvm/utils/vim/syntax/llvm.vim b/llvm/utils/vim/syntax/llvm.vim --- a/llvm/utils/vim/syntax/llvm.vim +++ b/llvm/utils/vim/syntax/llvm.vim @@ -142,6 +142,7 @@ \ nosanitize_bounds \ nosanitize_coverage \ null_pointer_is_valid + \ optdebug \ optforfuzzing \ optnone \ optsize