bool Started = true;
bool Stopped = false;
bool AddingMachinePasses = false;
+ bool DebugifyIsSafe = true;
/// Set the StartAfter, StartBefore and StopAfter passes to allow running only
/// a portion of the normal code-gen pass sequence.
/// verification is enabled.
void addVerifyPass(const std::string &Banner);
+ /// Add a pass to add synthesized debug info to the MIR.
+ void addDebugifyPass();
+
+ /// Add a pass to remove debug info from the MIR.
+ void addStripDebugPass();
+
/// Add standard passes before a pass that's about to be added. For example,
/// the DebugifyMachineModulePass if it is enabled.
- void addMachinePrePasses();
+ void addMachinePrePasses(bool AllowDebugify = true);
/// Add standard passes after a pass that has just been added. For example,
/// the MachineVerifier if it is enabled.
void addMachinePostPasses(const std::string &Banner, bool AllowPrint = true,
- bool AllowVerify = true);
+ bool AllowVerify = true, bool AllowStrip = true);
/// Check whether or not GlobalISel should abort on error.
/// When this is disabled, GlobalISel will fall back on SDISel instead of
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineModuleInfoWrapperPass>();
AU.addPreserved<MachineModuleInfoWrapperPass>();
+ AU.setPreservesCFG();
}
static char ID; // Pass identification.
INITIALIZE_PASS_END(DebugifyMachineModule, DEBUG_TYPE,
"Machine Debugify Module", false, false)
-ModulePass *createDebugifyMachineModulePass() {
+ModulePass *llvm::createDebugifyMachineModulePass() {
return new DebugifyMachineModule();
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineModuleInfoWrapperPass>();
AU.addPreserved<MachineModuleInfoWrapperPass>();
+ AU.setPreservesCFG();
}
static char ID; // Pass identification.
INITIALIZE_PASS_END(StripDebugMachineModule, DEBUG_TYPE,
"Machine Strip Debug Module", false, false)
-ModulePass *createStripDebugMachineModulePass(bool OnlyDebugified) {
+ModulePass *llvm::createStripDebugMachineModulePass(bool OnlyDebugified) {
return new StripDebugMachineModule(OnlyDebugified);
}
VerifyMachineCode("verify-machineinstrs", cl::Hidden,
cl::desc("Verify generated machine code"),
cl::ZeroOrMore);
+static cl::opt<cl::boolOrDefault> DebugifyAndStripAll(
+ "debugify-and-strip-all-safe", cl::Hidden,
+ cl::desc(
+ "Debugify MIR before and Strip debug after "
+ "each pass except those known to be unsafe when debug info is present"),
+ cl::ZeroOrMore);
enum RunOutliner { AlwaysOutline, NeverOutline, TargetDefault };
// Enable or disable the MachineOutliner.
static cl::opt<RunOutliner> EnableMachineOutliner(
PM->add(createMachineVerifierPass(Banner));
}
-void TargetPassConfig::addMachinePrePasses() {}
+void TargetPassConfig::addDebugifyPass() {
+ PM->add(createDebugifyMachineModulePass());
+}
+
+void TargetPassConfig::addStripDebugPass() {
+ PM->add(createStripDebugMachineModulePass(/*OnlyDebugified=*/true));
+}
+
+void TargetPassConfig::addMachinePrePasses(bool AllowDebugify) {
+ if (AllowDebugify && DebugifyAndStripAll == cl::BOU_TRUE && DebugifyIsSafe)
+ addDebugifyPass();
+}
void TargetPassConfig::addMachinePostPasses(const std::string &Banner,
- bool AllowPrint, bool AllowVerify) {
+ bool AllowPrint, bool AllowVerify,
+ bool AllowStrip) {
+ if (DebugifyAndStripAll == cl::BOU_TRUE && DebugifyIsSafe)
+ addStripDebugPass();
if (AllowPrint)
addPrintPass(Banner);
if (AllowVerify)
TM->setGlobalISel(true);
}
+ // FIXME: Injecting into the DAGISel pipeline seems to cause issues with
+ // analyses needing to be re-run. This can result in being unable to
+ // schedule passes (particularly with 'Function Alias Analysis
+ // Results'). It's not entirely clear why but AFAICT this seems to be
+ // due to one FunctionPassManager not being able to use analyses from a
+ // previous one. As we're injecting a ModulePass we break the usual
+ // pass manager into two. GlobalISel with the fallback path disabled
+ // and -run-pass seem to be unaffected. The majority of GlobalISel
+ // testing uses -run-pass so this probably isn't too bad.
+ SaveAndRestore<bool> SavedDebugifyIsSafe(DebugifyIsSafe);
+ if (Selector != SelectorType::GlobalISel || !isGlobalISelAbortEnabled())
+ DebugifyIsSafe = false;
+
// Add instruction selector passes.
if (Selector == SelectorType::GlobalISel) {
SaveAndRestore<bool> SavedAddingMachinePasses(AddingMachinePasses, true);
// Run pre-ra passes.
addPreRegAlloc();
+ // Debugifying the register allocator passes seems to provoke some
+ // non-determinism that affects CodeGen and there doesn't seem to be a point
+ // where it becomes safe again so stop debugifying here.
+ DebugifyIsSafe = false;
+
// Run register allocation and passes that are tightly coupled with it,
// including phi elimination and scheduling.
if (getOptimizeRegAlloc())
// Finally rewrite virtual registers.
addPass(&VirtRegRewriterID);
+
// Perform stack slot coloring and post-ra machine LICM.
//
// FIXME: Re-enable coloring with register when it's capable of adding
; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs=0 -O0 \
; RUN: | FileCheck %s --check-prefixes=ENABLED,ENABLED-O0,FALLBACK
; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs -O0 \
; RUN: | FileCheck %s --check-prefixes=ENABLED,ENABLED-O0,FALLBACK,VERIFY,VERIFY-O0
; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs=0 -O0 -aarch64-enable-global-isel-at-O=0 -global-isel-abort=1 \
; RUN: | FileCheck %s --check-prefix ENABLED --check-prefix ENABLED-O0 --check-prefix NOFALLBACK
; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs=0 -O0 -aarch64-enable-global-isel-at-O=0 -global-isel-abort=2 \
; RUN: | FileCheck %s --check-prefix ENABLED --check-prefix ENABLED-O0 --check-prefix FALLBACK
; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs=0 -global-isel \
; RUN: | FileCheck %s --check-prefix ENABLED --check-prefix NOFALLBACK --check-prefix ENABLED-O1
; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs=0 -global-isel -global-isel-abort=2 \
; RUN: | FileCheck %s --check-prefix ENABLED --check-prefix FALLBACK --check-prefix ENABLED-O1
; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs=0 -O1 -aarch64-enable-global-isel-at-O=3 \
; RUN: | FileCheck %s --check-prefix ENABLED --check-prefix ENABLED-O1
; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs=0 -O1 -aarch64-enable-global-isel-at-O=0 \
; RUN: | FileCheck %s --check-prefix DISABLED
; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs=0 -aarch64-enable-global-isel-at-O=-1 \
; RUN: | FileCheck %s --check-prefix DISABLED
; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs=0 | FileCheck %s --check-prefix DISABLED
; RUN: llc -mtriple=aarch64-- -fast-isel=0 -global-isel=false \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -debug-pass=Structure %s -o /dev/null 2>&1 -verify-machineinstrs=0 \
; RUN: | FileCheck %s --check-prefix DISABLED
# a test of the debug output and a test.
#
# CHECK-WORKLIST-LABEL: Generic MI Combiner for: multiple_copies
-# CHECK-WORKLIST: Try combining [[IN0:%[0-9]+]]:_(s8) = G_LOAD [[IN1:%[0-9]+]]:_(p0) :: (load 1 from %ir.addr)
+# CHECK-WORKLIST: Try combining [[IN0:%[0-9]+]]:_(s8) = G_LOAD [[IN1:%[0-9]+]]:_(p0){{.*}} :: (load 1 from %ir.addr)
# CHECK-WORKLIST: Preferred use is: [[IN2:%[0-9]+]]:_(s32) = G_SEXT [[IN0]]:_(s8)
-# CHECK-WORKLIST-DAG: Changing: [[IN0]]:_(s8) = G_LOAD [[IN1]]:_(p0) :: (load 1 from %ir.addr)
+# CHECK-WORKLIST-DAG: Changing: [[IN0]]:_(s8) = G_LOAD [[IN1]]:_(p0){{.*}} :: (load 1 from %ir.addr)
# CHECK-WORKLIST-DAG: Changing: [[IN3:%[0-9]+]]:_(s8) = G_ADD [[IN0]]:_, [[IN4:%[0-9]+]]:_
# CHECK-WORKLIST-DAG: Changed: [[IN3]]:_(s8) = G_ADD [[NEW1:%[0-9]+]]:_, [[IN4]]:_
# CHECK-WORKLIST-DAG: Changing: [[IN5:%[0-9]+]]:_(s8) = G_SUB [[IN0]]:_, [[IN6:%[0-9]+]]:_
# CHECK-WORKLIST-DAG: Changed: [[IN5]]:_(s8) = G_SUB [[NEW2:%[0-9]+]]:_, [[IN6]]:_
# CHECK-WORKLIST-DAG: Erasing: [[IN2]]:_(s32) = G_SEXT [[IN0]]:_(s8)
-# CHECK-WORKLIST-DAG: Changed: [[IN2]]:_(s32) = G_SEXTLOAD [[IN1]]:_(p0) :: (load 1 from %ir.addr)
+# CHECK-WORKLIST-DAG: Changed: [[IN2]]:_(s32) = G_SEXTLOAD [[IN1]]:_(p0){{.*}} :: (load 1 from %ir.addr)
# CHECK-WORKLIST-DAG: Created: [[NEW1]]:_(s8) = G_TRUNC [[IN2]]:_(s32)
# CHECK-WORKLIST-DAG: Created: [[NEW2]]:_(s8) = G_TRUNC [[IN2]]:_(s32)
# CHECK-WORKLIST: Try combining
$w0 = COPY %10
$w1 = COPY %11
# CHECK-WORKLIST-LABEL: Generic MI Combiner for: sink_to_phi_nondominating
-# CHECK-WORKLIST: Try combining [[IN0:%[0-9]+]]:_(s8) = G_LOAD [[IN1:%[0-9]+]]:_(p0) :: (load 1 from %ir.addr)
+# CHECK-WORKLIST: Try combining [[IN0:%[0-9]+]]:_(s8) = G_LOAD [[IN1:%[0-9]+]]:_(p0){{.*}} :: (load 1 from %ir.addr)
# CHECK-WORKLIST: Preferred use is: [[IN2:%[0-9]+]]:_(s32) = G_SEXT [[IN0]]:_(s8)
-# CHECK-WORKLIST-DAG: Changing: [[IN0]]:_(s8) = G_LOAD [[IN1]]:_(p0) :: (load 1 from %ir.addr)
+# CHECK-WORKLIST-DAG: Changing: [[IN0]]:_(s8) = G_LOAD [[IN1]]:_(p0){{.*}} :: (load 1 from %ir.addr)
# CHECK-WORKLIST-DAG: Creating: G_TRUNC
# CHECK-WORKLIST-DAG: Changing: [[IN3:%[0-9]+]]:_(s8) = G_ADD [[IN0]]:_, [[IN4:%[0-9]+]]:_
# CHECK-WORKLIST-DAG: Changed: [[IN3]]:_(s8) = G_ADD [[OUT1:%[0-9]+]]:_, [[IN4]]:_
# CHECK-WORKLIST-DAG: Changing: [[IN5:%[0-9]+]]:_(s8) = G_SUB [[IN0]]:_, [[IN6:%[0-9]+]]:_
# CHECK-WORKLIST-DAG: Changed: [[IN5]]:_(s8) = G_SUB [[OUT2:%[0-9]+]]:_, [[IN6]]:_
# CHECK-WORKLIST-DAG: Erasing: [[IN2]]:_(s32) = G_SEXT [[IN0]]:_(s8)
-# CHECK-WORKLIST-DAG: Changed: [[IN2]]:_(s32) = G_SEXTLOAD [[IN1]]:_(p0) :: (load 1 from %ir.addr)
+# CHECK-WORKLIST-DAG: Changed: [[IN2]]:_(s32) = G_SEXTLOAD [[IN1]]:_(p0){{.*}} :: (load 1 from %ir.addr)
# CHECK-WORKLIST-DAG: Created: [[OUT1]]:_(s8) = G_TRUNC [[IN2]]:_(s32)
# CHECK-WORKLIST-DAG: Created: [[OUT2]]:_(s8) = G_TRUNC [[IN2]]:_(s32)
# CHECK-WORKLIST: Try combining
-; RUN: llc -mtriple=arm64-- -O0 -debug-pass=Structure < %s -o /dev/null 2>&1 | grep -v "Verify generated machine code" | FileCheck %s
+; RUN: llc --debugify-and-strip-all-safe=0 -mtriple=arm64-- -O0 -debug-pass=Structure < %s -o /dev/null 2>&1 | \
+; RUN: grep -v "Verify generated machine code" | FileCheck %s
; REQUIRES: asserts
-; RUN: llc -mtriple=arm64-- -O3 -debug-pass=Structure < %s -o /dev/null 2>&1 | grep -v "Verify generated machine code" | FileCheck %s
+; RUN: llc --debugify-and-strip-all-safe=0 -mtriple=arm64-- -O3 -debug-pass=Structure < %s -o /dev/null 2>&1 | \
+; RUN: grep -v "Verify generated machine code" | FileCheck %s
; REQUIRES: asserts
; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -pass-remarks-analysis=asm-printer \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs \
; RUN: -pass-remarks-with-hotness=1 -asm-verbose=0 \
; RUN: -debug-only=lazy-machine-block-freq,block-freq \
; RUN: -debug-pass=Executions 2>&1 | FileCheck %s -check-prefix=HOTNESS
; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -pass-remarks-analysis=asm-printer \
+; RUN: --debugify-and-strip-all-safe=0 \
; RUN: -verify-machineinstrs \
; RUN: -pass-remarks-with-hotness=0 -asm-verbose=0 \
; RUN: -debug-only=lazy-machine-block-freq,block-freq \
declare void @llvm.dbg.value(metadata, metadata, metadata)
!llvm.dbg.cu = !{!0}
-!llvm.debugify = !{!3, !4}
!llvm.module.flags = !{!5}
!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "t.ll", directory: "/")
!2 = !{}
-!3 = !{i32 2}
-!4 = !{i32 1}
!5 = !{i32 2, !"Debug Info Version", i32 3}
!6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
!7 = !DISubroutineType(types: !2)
# CHECK: name: empty
# CHECK: bb.0.entry
# CHECK: PATCHABLE_FUNCTION_ENTER{{$}}
-# CHECK-NEXT: RET undef $lr, debug-location !DILocation(line: 1,
+# CHECK-NEXT: RET undef $lr, debug-location !9
--- |
- define void @empty() #0 !dbg !7 {
+ define void @empty() #0 !dbg !6 {
entry:
- ret void, !dbg !10
+ ret void, !dbg !9
}
attributes #0 = { "patchable-function-entry"="1" }
!3 = !{i32 7, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 4}
- !6 = !{!"clang version 11.0.0 "}
- !7 = distinct !DISubprogram(name: "empty", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
- !8 = !DISubroutineType(types: !9)
- !9 = !{null}
- !10 = !DILocation(line: 1, column: 61, scope: !7)
+ !6 = distinct !DISubprogram(name: "empty", scope: !1, file: !1, line: 1, type: !7, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
+ !7 = !DISubroutineType(types: !8)
+ !8 = !{null}
+ !9 = !DILocation(line: 1, column: 61, scope: !6)
+ !llvm.dbg.cu = !{!0}
+ !llvm.module.flags = !{!3, !4, !5}
...
---
body: |
bb.0.entry:
liveins: $lr
- RET undef $lr, debug-location !10
+ RET undef $lr, debug-location !9
...
name: fun0
stack:
- { id: 0, type: default, offset: 0, size: 8, alignment: 4 }
-# CHECK: --- !Analysis
+# CHECK-LABEL: --- !Analysis
# CHECK-NEXT: Pass: prologepilog
# CHECK-NEXT: Name: StackSize
-# CHECK-NEXT: Function: fun0
+# CHECK: Function: fun0
# CHECK-NEXT: Args:
# CHECK-NEXT: - NumStackBytes: '16'
# CHECK-NEXT: - String: ' stack bytes in function'
name: fun1
stack:
- { id: 0, type: default, offset: 0, size: 19, alignment: 4 }
-# CHECK: --- !Analysis
+# CHECK-LABEL: --- !Analysis
# CHECK-NEXT: Pass: prologepilog
# CHECK-NEXT: Name: StackSize
-# CHECK-NEXT: Function: fun1
+# CHECK: Function: fun1
# CHECK-NEXT: Args:
# CHECK-NEXT: - NumStackBytes: '32'
# CHECK-NEXT: - String: ' stack bytes in function'
name: fun2
stack:
- { id: 0, type: default, offset: 0, size: 1024, alignment: 4 }
-# --- !Analysis
+# CHECK-LABEL: --- !Analysis
# CHECK: Pass: prologepilog
# CHECK-NEXT: Name: StackSize
-# CHECK-NEXT: Function: fun2
+# CHECK: Function: fun2
# CHECK-NEXT: Args:
# CHECK-NEXT: - NumStackBytes: '1040'
# CHECK-NEXT: - String: ' stack bytes in function'
-# RUN: llc -o - %s -mtriple=aarch64-- -mattr=+v8.1a -run-pass=greedy,virtregrewriter | FileCheck %s
+# RUN: llc --debugify-and-strip-all-safe=0 -o - %s -mtriple=aarch64-- -mattr=+v8.1a -run-pass=greedy,virtregrewriter | FileCheck %s
# Make sure spills/reloads from xseqpairs and wseqpairs work correctly.
---
# CHECK-LABEL: name: spill_reload_xseqpairs
!7 = !DILocalVariable(name: "x", arg: 1, scope: !5, file: !1, line: 1, type: !8)
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!9 = !DILocation(line: 1, column: 1, scope: !5)
+ !10 = !{i32 2, !"Debug Info Version", i32 3}
+ !llvm.dbg.cu = !{!0}
+ !llvm.module.flags = !{!10}
---
# Check we do not crash when checking $noreg debug operands.
#