diff --git a/llvm/include/llvm/CodeGen/TargetPassConfig.h b/llvm/include/llvm/CodeGen/TargetPassConfig.h --- a/llvm/include/llvm/CodeGen/TargetPassConfig.h +++ b/llvm/include/llvm/CodeGen/TargetPassConfig.h @@ -161,8 +161,9 @@ static bool hasLimitedCodeGenPipeline(); /// Returns true if none of the `-stop-before` and `-stop-after` options is - /// set. - static bool willCompleteCodeGenPipeline(); + /// set. If one of them is set and `StopOpt` is not null, return the specified + /// pass in `StopOpt`. + static bool willCompleteCodeGenPipeline(std::string *StopOpt = nullptr); /// If hasLimitedCodeGenPipeline is true, this method /// returns a string with the name of the options, separated diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -601,8 +601,15 @@ "triple set?"); } -bool TargetPassConfig::willCompleteCodeGenPipeline() { - return StopBeforeOpt.empty() && StopAfterOpt.empty(); +bool TargetPassConfig::willCompleteCodeGenPipeline(std::string *StopOpt) { + bool Ret = StopBeforeOpt.empty() && StopAfterOpt.empty(); + if (!Ret && StopOpt) { + if (!StopBeforeOpt.empty()) + *StopOpt = StopBeforeOpt; + if (!StopAfterOpt.empty()) + *StopOpt = StopAfterOpt; + } + return Ret; } bool TargetPassConfig::hasLimitedCodeGenPipeline() { diff --git a/llvm/test/CodeGen/Generic/llc-start-stop-instance-errors.ll b/llvm/test/CodeGen/Generic/llc-start-stop-instance-errors.ll --- a/llvm/test/CodeGen/Generic/llc-start-stop-instance-errors.ll +++ b/llvm/test/CodeGen/Generic/llc-start-stop-instance-errors.ll @@ -1,4 +1,6 @@ ; RUN: not --crash llc -debug-pass=Structure -stop-after=dead-mi-elimination,arst %s -o /dev/null 2>&1 \ ; RUN: | FileCheck -check-prefix=NOT-NUM %s +; RUN: not --crash llc -enable-new-pm -debug-pass-manager -stop-after=dead-mi-elimination,arst %s -o /dev/null 2>&1 \ +; RUN: | FileCheck -check-prefix=NOT-NUM %s ; NOT-NUM: LLVM ERROR: invalid pass instance specifier dead-mi-elimination,arst diff --git a/llvm/test/CodeGen/Generic/new-pm/llc-start-stop.ll b/llvm/test/CodeGen/Generic/new-pm/llc-start-stop.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Generic/new-pm/llc-start-stop.ll @@ -0,0 +1,48 @@ +; RUN: llc < %s -enable-new-pm -debug-pass-manager -stop-after=verify \ +; RUN: -o /dev/null 2>&1 | FileCheck %s -check-prefix=STOP-AFTER +; STOP-AFTER: Running pass: AtomicExpandPass +; STOP-AFTER-NEXT: Running pass: VerifierPass +; STOP-AFTER-NOT: Running pass: + +; RUN: llc < %s -enable-new-pm -debug-pass-manager -stop-before=verify \ +; RUN: -o /dev/null 2>&1 | FileCheck %s -check-prefix=STOP-BEFORE +; STOP-BEFORE: Running pass: AtomicExpandPass +; STOP-BEFORE-NOT: Running pass: + +; RUN: llc < %s -enable-new-pm -debug-pass-manager -start-after=verify \ +; RUN: -o /dev/null 2>&1 | FileCheck %s -check-prefix=START-AFTER +; START-AFTER: Starting llvm::Function pass manager run +; START-AFTER-NOT: Running pass: VerifierPass +; START-AFTER: Running pass: LoopStrengthReducePass + +; RUN: llc < %s -enable-new-pm -debug-pass-manager -start-before=verify \ +; RUN: -o /dev/null 2>&1 | FileCheck %s -check-prefix=START-BEFORE +; START-BEFORE-NOT: Running pass: +; START-BEFORE: Running pass: VerifierPass + +; RUN: not --crash llc < %s -enable-new-pm -start-before=nonexistent -o /dev/null 2>&1 \ +; RUN: | FileCheck %s -check-prefix=NONEXISTENT-START-BEFORE +; RUN: not --crash llc < %s -enable-new-pm -stop-before=nonexistent -o /dev/null 2>&1 \ +; RUN: | FileCheck %s -check-prefix=NONEXISTENT-STOP-BEFORE +; RUN: not --crash llc < %s -enable-new-pm -start-after=nonexistent -o /dev/null 2>&1 \ +; RUN: | FileCheck %s -check-prefix=NONEXISTENT-START-AFTER +; RUN: not --crash llc < %s -enable-new-pm -stop-after=nonexistent -o /dev/null 2>&1 \ +; RUN: | FileCheck %s -check-prefix=NONEXISTENT-STOP-AFTER +; NONEXISTENT-START-BEFORE: "nonexistent" pass could not be found. +; NONEXISTENT-STOP-BEFORE: "nonexistent" pass could not be found. +; NONEXISTENT-START-AFTER: "nonexistent" pass could not be found. +; NONEXISTENT-STOP-AFTER: "nonexistent" pass could not be found. + +; RUN: not --crash llc < %s -enable-new-pm -start-before=verify -start-after=verify \ +; RUN: -o /dev/null 2>&1 | FileCheck %s -check-prefix=DOUBLE-START +; RUN: not --crash llc < %s -enable-new-pm -stop-before=verify -stop-after=verify \ +; RUN: -o /dev/null 2>&1 | FileCheck %s -check-prefix=DOUBLE-STOP +; DOUBLE-START: start-before and start-after specified! +; DOUBLE-STOP: stop-before and stop-after specified! + +define void @f() { + br label %b +b: + br label %b + ret void +} diff --git a/llvm/test/CodeGen/X86/new-pm/O0-pipeline.ll b/llvm/test/CodeGen/X86/new-pm/O0-pipeline.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/new-pm/O0-pipeline.ll @@ -0,0 +1,70 @@ +; When EXPENSIVE_CHECKS are enabled, the machine verifier appears between each +; pass. Ignore it with 'grep -v'. +; RUN: llc -mtriple=x86_64-- -O0 -debug-pass-manager -enable-new-pm < %s \ +; RUN: -o /dev/null 2>&1 | grep -v 'Verify generated machine code' | FileCheck %s + +; REQUIRES: asserts + +; CHECK-LABEL: Starting llvm::Module pass manager run. +; CHECK-NEXT: Running pass: PreISelIntrinsicLoweringPass +; CHECK-NEXT: Running analysis: InnerAnalysisManagerProxy +; CHECK-NEXT: Starting llvm::Function pass manager run. +; CHECK-NEXT: Running pass: AtomicExpandPass +; CHECK-NEXT: Running pass: VerifierPass +; CHECK-NEXT: Running analysis: VerifierAnalysis +; CHECK-NEXT: Running pass: GCLoweringPass +; CHECK-NEXT: Running pass: ShadowStackGCLoweringPass +; CHECK-NEXT: Running pass: LowerConstantIntrinsicsPass +; CHECK-NEXT: Running pass: UnreachableBlockElimPass +; CHECK-NEXT: Running pass: EntryExitInstrumenterPass +; CHECK-NEXT: Invalidating all non-preserved analyses for: +; CHECK-NEXT: Invalidating analysis: VerifierAnalysis +; CHECK-NEXT: Running pass: ScalarizeMaskedMemIntrinPass +; CHECK-NEXT: Running pass: ExpandReductionsPass +; CHECK-NEXT: Running analysis: TargetIRAnalysis +; CHECK-NEXT: Running pass: IndirectBrExpandPass +; CHECK-NEXT: Running pass: DwarfEHPass +; CHECK-NEXT: Running pass: SafeStackPass +; CHECK-NEXT: Running pass: StackProtectorPass +; CHECK-NEXT: Running pass: VerifierPass +; CHECK-NEXT: Running analysis: VerifierAnalysis +; CHECK-NEXT: Finished llvm::Function pass manager run. +; CHECK-NEXT: Invalidating all non-preserved analyses for: +; CHECK-NEXT: Finished llvm::Module pass manager run. +; CHECK-NEXT: Running analysis: MachineModuleAnalysis +; CHECK-NEXT: Starting llvm::MachineFunction pass manager run. +; CHECK-NEXT: Running pass: {{.*}}X86ISelDagPass +; CHECK-NEXT: Running pass: {{.*}}X86GlobalBaseRegPass +; CHECK-NEXT: Running pass: FinalizeISelPass +; CHECK-NEXT: Running pass: LocalStackSlotPass +; CHECK-NEXT: Running pass: {{.*}}X86SpeculativeLoadHardeningPass +; CHECK-NEXT: Running pass: {{.*}}X86FlagsCopyLoweringDummyPass +; CHECK-NEXT: Running pass: {{.*}}X86WinAllocaExpanderPass +; CHECK-NEXT: Running pass: PHIEliminationPass +; CHECK-NEXT: Running pass: TwoAddressInstructionPass +; CHECK-NEXT: Running pass: RAFastPass +; CHECK-NEXT: Running pass: {{.*}}X86FloatingPointStackifierPass +; CHECK-NEXT: Running pass: PrologEpilogInserterPass +; CHECK-NEXT: Running pass: ExpandPostRAPseudosPass +; CHECK-NEXT: Running pass: {{.*}}X86ExpandPseudoPass +; CHECK-NEXT: Running pass: FEntryInserterPass +; CHECK-NEXT: Running pass: XRayInstrumentationPass +; CHECK-NEXT: Running pass: PatchableFunctionPass +; CHECK-NEXT: Running pass: {{.*}}X86IndirectBranchTrackingPass +; CHECK-NEXT: Running pass: {{.*}}X86IssueVZeroUpperPass +; CHECK-NEXT: Running pass: {{.*}}X86EvexToVexInstsPass +; CHECK-NEXT: Running pass: {{.*}}X86DiscriminateMemOpsPass +; CHECK-NEXT: Running pass: {{.*}}X86InsertPrefetchPass +; CHECK-NEXT: Running pass: {{.*}}X86InsertX87waitPass +; CHECK-NEXT: Running pass: FuncletLayoutPass +; CHECK-NEXT: Running pass: StackMapLivenessPass +; CHECK-NEXT: Running pass: LiveDebugValuesPass +; CHECK-NEXT: Running pass: {{.*}}X86RetpolineThunksPass +; CHECK-NEXT: Running pass: CFIInstrInserterPass +; CHECK-NEXT: Running pass: {{.*}}X86AsmPrinterPass +; CHECK-NEXT: Running pass: FreeMachineFunctionPass +; CHECK-NEXT: Finished llvm::MachineFunction pass manager run. + +define void @f() { + ret void +} diff --git a/llvm/test/CodeGen/X86/new-pm/llc-start-stop-instance.ll b/llvm/test/CodeGen/X86/new-pm/llc-start-stop-instance.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/new-pm/llc-start-stop-instance.ll @@ -0,0 +1,35 @@ +; RUN: llc -mtriple=x86_64-- -enable-new-pm -debug-pass-manager -stop-after=verify,1 \ +; RUN: %s -o /dev/null 2>&1 | FileCheck -check-prefix=STOP-AFTER-1 %s + +; RUN: llc -mtriple=x86_64-- -enable-new-pm -debug-pass-manager -stop-after=verify,0 \ +; RUN: %s -o /dev/null 2>&1 | FileCheck -check-prefix=STOP-AFTER-0 %s + +; RUN: llc -mtriple=x86_64-- -enable-new-pm -debug-pass-manager -stop-before=verify,1 \ +; RUN: %s -o /dev/null 2>&1 | FileCheck -check-prefix=STOP-BEFORE-1 %s + +; RUN: llc -mtriple=x86_64-- -enable-new-pm -debug-pass-manager -start-before=verify,1 \ +; RUN: %s -o /dev/null 2>&1 | FileCheck -check-prefix=START-BEFORE-1 %s + +; RUN: llc -mtriple=x86_64-- -enable-new-pm -debug-pass-manager -start-after=verify,1 \ +; RUN: %s -o /dev/null 2>&1 | FileCheck -check-prefix=START-AFTER-1 %s + + +; STOP-AFTER-1: Running pass: VerifierPass +; STOP-AFTER-1: Running pass: VerifierPass + +; STOP-AFTER-0-NOT: Running pass: VerifierPass +; STOP-AFTER-0: Running pass: VerifierPass +; STOP-AFTER-0-NOT: Running pass: VerifierPass + +; STOP-BEFORE-1: Running pass: VerifierPass +; STOP-BEFORE-1-NOT: Running pass: VerifierPass + +; START-BEFORE-1-NOT: Running pass: VerifierPass +; START-BEFORE-1: Running pass: VerifierPass +; START-BEFORE-1-NOT: Running pass: VerifierPass + +; START-AFTER-1-NOT: Running pass: VerifierPass + +define void @f() { + ret void +} diff --git a/llvm/test/CodeGen/X86/new-pm/opt-pipeline.ll b/llvm/test/CodeGen/X86/new-pm/opt-pipeline.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/new-pm/opt-pipeline.ll @@ -0,0 +1,146 @@ +; When EXPENSIVE_CHECKS are enabled, the machine verifier appears between each +; pass. Ignore it with 'grep -v'. +; RUN: llc -mtriple=x86_64-- -O1 -debug-pass-manager -enable-new-pm < %s \ +; RUN: -o /dev/null 2>&1 | FileCheck %s +; RUN: llc -mtriple=x86_64-- -O2 -debug-pass-manager -enable-new-pm < %s \ +; RUN: -o /dev/null 2>&1 | FileCheck %s +; RUN: llc -mtriple=x86_64-- -O3 -debug-pass-manager -enable-new-pm < %s \ +; RUN: -o /dev/null 2>&1 | FileCheck %s + +; REQUIRES: asserts + +; CHECK-LABEL: Starting llvm::Module pass manager run. +; CHECK-NEXT: Running pass: PreISelIntrinsicLoweringPass +; CHECK-NEXT: Running analysis: InnerAnalysisManagerProxy +; CHECK-NEXT: Starting llvm::Function pass manager run. +; CHECK-NEXT: Running pass: AtomicExpandPass +; CHECK-NEXT: Running pass: VerifierPass +; CHECK-NEXT: Running analysis: VerifierAnalysis +; CHECK-NEXT: Starting llvm::Function pass manager run. +; CHECK-NEXT: Running pass: LoopSimplifyPass +; CHECK-NEXT: Running analysis: LoopAnalysis +; CHECK-NEXT: Running analysis: DominatorTreeAnalysis +; CHECK-NEXT: Running analysis: AssumptionAnalysis +; CHECK-NEXT: Running pass: LCSSAPass +; CHECK-NEXT: Finished llvm::Function pass manager run. +; CHECK-NEXT: Running analysis: MemorySSAAnalysis +; CHECK-NEXT: Running analysis: AAManager +; CHECK-NEXT: Running analysis: TargetLibraryAnalysis +; CHECK-NEXT: Running analysis: ScalarEvolutionAnalysis +; CHECK-NEXT: Running analysis: TargetIRAnalysis +; CHECK-NEXT: Running analysis: InnerAnalysisManagerProxy +; CHECK-NEXT: Running pass: LoopStrengthReducePass +; CHECK-NEXT: Running analysis: IVUsersAnalysis +; CHECK-NEXT: Running pass: MergeICmpsPass +; CHECK-NEXT: Running pass: ExpandMemCmpPass +; CHECK-NEXT: Running pass: GCLoweringPass +; CHECK-NEXT: Running pass: ShadowStackGCLoweringPass +; CHECK-NEXT: Running pass: LowerConstantIntrinsicsPass +; CHECK-NEXT: Running pass: UnreachableBlockElimPass +; CHECK-NEXT: Invalidating all non-preserved analyses for +; CHECK-NEXT: Clearing all analysis results for +; CHECK-NEXT: Invalidating analysis: VerifierAnalysis +; CHECK-NEXT: Invalidating analysis: LoopAnalysis +; CHECK-NEXT: Invalidating analysis: MemorySSAAnalysis +; CHECK-NEXT: Invalidating analysis: ScalarEvolutionAnalysis +; CHECK-NEXT: Invalidating analysis: InnerAnalysisManagerProxy +; CHECK-NEXT: Running pass: ConstantHoistingPass +; CHECK-NEXT: Running analysis: BlockFrequencyAnalysis +; CHECK-NEXT: Running analysis: BranchProbabilityAnalysis +; CHECK-NEXT: Running analysis: LoopAnalysis +; CHECK-NEXT: Running analysis: PostDominatorTreeAnalysis +; CHECK-NEXT: Running analysis: OuterAnalysisManagerProxy +; CHECK-NEXT: Running pass: PartiallyInlineLibCallsPass +; CHECK-NEXT: Running pass: EntryExitInstrumenterPass +; CHECK-NEXT: Invalidating all non-preserved analyses for +; CHECK-NEXT: Running pass: ScalarizeMaskedMemIntrinPass +; CHECK-NEXT: Running pass: ExpandReductionsPass +; CHECK-NEXT: Running pass: InterleavedAccessPass +; CHECK-NEXT: Running pass: IndirectBrExpandPass +; CHECK-NEXT: Running pass: CodeGenPreparePass +; CHECK-NEXT: Running pass: DwarfEHPass +; CHECK-NEXT: Running pass: SafeStackPass +; CHECK-NEXT: Running pass: StackProtectorPass +; CHECK-NEXT: Running pass: VerifierPass +; CHECK-NEXT: Running analysis: VerifierAnalysis +; CHECK-NEXT: Finished llvm::Function pass manager run. +; CHECK-NEXT: Invalidating all non-preserved analyses for: +; CHECK-NEXT: Finished llvm::Module pass manager run. +; CHECK-NEXT: Running analysis: MachineModuleAnalysis +; CHECK-NEXT: Starting llvm::MachineFunction pass manager run. +; CHECK-NEXT: Running pass: {{.*}}X86ISelDagPass +; CHECK-NEXT: Running pass: {{.*}}CleanupLocalDynamicTLSPass +; CHECK-NEXT: Running pass: {{.*}}X86GlobalBaseRegPass +; CHECK-NEXT: Running pass: FinalizeISelPass +; CHECK-NEXT: Running pass: {{.*}}X86DomainReassignmentPass +; CHECK-NEXT: Running pass: EarlyTailDuplicatePass +; CHECK-NEXT: Running pass: OptimizePHIsPass +; CHECK-NEXT: Running pass: StackColoringPass +; CHECK-NEXT: Running pass: LocalStackSlotPass +; CHECK-NEXT: Running pass: DeadMachineInstructionElimPass +; CHECK-NEXT: Running pass: EarlyIfConverterPass +; CHECK-NEXT: Running pass: MachineCombinerPass +; CHECK-NEXT: Running pass: {{.*}}X86CmovConverterDummyPass +; CHECK-NEXT: Running pass: EarlyMachineLICMPass +; CHECK-NEXT: Running pass: MachineCSEPass +; CHECK-NEXT: Running pass: MachineSinkingPass +; CHECK-NEXT: Running pass: PeepholeOptimizerPass +; CHECK-NEXT: Running pass: DeadMachineInstructionElimPass +; CHECK-NEXT: Running pass: LiveRangeShrinkPass +; CHECK-NEXT: Running pass: {{.*}}X86FixupSetCCPass +; CHECK-NEXT: Running pass: {{.*}}X86OptimizeLEAsPass +; CHECK-NEXT: Running pass: {{.*}}X86CallFrameOptimizationPass +; CHECK-NEXT: Running pass: {{.*}}X86AvoidStoreForwardingBlocksPass +; CHECK-NEXT: Running pass: {{.*}}X86SpeculativeLoadHardeningPass +; CHECK-NEXT: Running pass: {{.*}}X86FlagsCopyLoweringDummyPass +; CHECK-NEXT: Running pass: {{.*}}X86WinAllocaExpanderPass +; CHECK-NEXT: Running pass: DetectDeadLanesPass +; CHECK-NEXT: Running pass: ProcessImplicitDefsPass +; CHECK-NEXT: Running pass: PHIEliminationPass +; CHECK-NEXT: Running pass: TwoAddressInstructionPass +; CHECK-NEXT: Running pass: RegisterCoalescerPass +; CHECK-NEXT: Running pass: RenameIndependentSubregsPass +; CHECK-NEXT: Running pass: MachineSchedulerPass +; CHECK-NEXT: Running pass: RAGreedyPass +; CHECK-NEXT: Running pass: VirtRegRewriterPass +; CHECK-NEXT: Running pass: StackSlotColoringPass +; CHECK-NEXT: Running pass: {{.*}}X86FloatingPointStackifierPass +; CHECK-NEXT: Running pass: PostRAMachineSinkingPass +; CHECK-NEXT: Running pass: ShrinkWrapPass +; CHECK-NEXT: Running pass: PrologEpilogInserterPass +; CHECK-NEXT: Running pass: BranchFolderPass +; CHECK-NEXT: Running pass: TailDuplicatePass +; CHECK-NEXT: Running pass: MachineCopyPropagationPass +; CHECK-NEXT: Running pass: ExpandPostRAPseudosPass +; CHECK-NEXT: Running pass: {{.*}}X86ExpandPseudoPass +; CHECK-NEXT: Running pass: PostRASchedulerPass +; CHECK-NEXT: Running pass: MachineBlockPlacementPass +; CHECK-NEXT: Running pass: FEntryInserterPass +; CHECK-NEXT: Running pass: XRayInstrumentationPass +; CHECK-NEXT: Running pass: PatchableFunctionPass +; CHECK-NEXT: Running pass: {{.*}}X86ExecutionDomainFixPass +; CHECK-NEXT: Running pass: BreakFalseDepsPass +; CHECK-NEXT: Running pass: {{.*}}X86IndirectBranchTrackingPass +; CHECK-NEXT: Running pass: {{.*}}X86IssueVZeroUpperPass +; CHECK-NEXT: Running pass: {{.*}}X86FixupBWInstsPass +; CHECK-NEXT: Running pass: {{.*}}X86PadShortFunctionsPass +; CHECK-NEXT: Running pass: {{.*}}X86FixupLEAsPass +; CHECK-NEXT: Running pass: {{.*}}X86EvexToVexInstsPass +; CHECK-NEXT: Running pass: {{.*}}X86DiscriminateMemOpsPass +; CHECK-NEXT: Running pass: {{.*}}X86InsertPrefetchPass +; CHECK-NEXT: Running pass: {{.*}}X86InsertX87waitPass +; CHECK-NEXT: Running pass: FuncletLayoutPass +; CHECK-NEXT: Running pass: StackMapLivenessPass +; CHECK-NEXT: Running pass: LiveDebugValuesPass +; CHECK-NEXT: Running pass: {{.*}}X86RetpolineThunksPass +; CHECK-NEXT: Running pass: CFIInstrInserterPass +; CHECK-NEXT: Running pass: {{.*}}X86AsmPrinterPass +; CHECK-NEXT: Running pass: FreeMachineFunctionPass +; CHECK-NEXT: Finished llvm::MachineFunction pass manager run. + +define void @f() { + br label %b +b: + br label %b + ret void +} diff --git a/llvm/tools/llc/CMakeLists.txt b/llvm/tools/llc/CMakeLists.txt --- a/llvm/tools/llc/CMakeLists.txt +++ b/llvm/tools/llc/CMakeLists.txt @@ -22,6 +22,7 @@ add_llvm_tool(llc llc.cpp + NewPMDriver.cpp DEPENDS intrinsics_gen diff --git a/llvm/tools/llc/NewPMDriver.h b/llvm/tools/llc/NewPMDriver.h new file mode 100644 --- /dev/null +++ b/llvm/tools/llc/NewPMDriver.h @@ -0,0 +1,49 @@ +//===- NewPMDriver.h - Function to drive llc with the new PM --------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// A single function which is called to drive the llc behavior for the new +/// PassManager. +/// +/// This is only in a separate TU with a header to avoid including all of the +/// old pass manager headers and the new pass manager headers into the same +/// file. Eventually all of the routines here will get folded back into +/// llc.cpp. +/// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TOOLS_OPT_NEWPMDRIVER_H +#define LLVM_TOOLS_OPT_NEWPMDRIVER_H + +#include "llvm/IR/DiagnosticHandler.h" +#include "llvm/Support/CodeGen.h" +#include +#include + +namespace llvm { +class Module; +class TargetLibraryInfoImpl; +class TargetMachine; +class ToolOutputFile; +class LLVMContext; +class MIRParser; + +struct LLCDiagnosticHandler : public DiagnosticHandler { + bool *HasError; + LLCDiagnosticHandler(bool *HasErrorPtr) : HasError(HasErrorPtr) {} + bool handleDiagnostics(const DiagnosticInfo &DI) override; +}; + +int compileModuleWithNewPM( + StringRef Arg0, std::unique_ptr M, std::unique_ptr MIR, + std::unique_ptr Target, std::unique_ptr Out, + std::unique_ptr DwoOut, LLVMContext &Context, + const TargetLibraryInfoImpl &TLII, bool NoVerify, bool CompileTwice, + const std::vector &RunPassNames, CodeGenFileType FileType); +} // namespace llvm + +#endif \ No newline at end of file diff --git a/llvm/tools/llc/NewPMDriver.cpp b/llvm/tools/llc/NewPMDriver.cpp new file mode 100644 --- /dev/null +++ b/llvm/tools/llc/NewPMDriver.cpp @@ -0,0 +1,250 @@ +//===- NewPMDriver.cpp - Driver for llc using new PM ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file is just a split of the code that logically belongs in llc.cpp but +/// that includes the new pass manager headers. +/// +//===----------------------------------------------------------------------===// + +#include "NewPMDriver.h" +#include "llvm/Analysis/CGSCCPassManager.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/CodeGen/CGPassBuilderOption.h" +#include "llvm/CodeGen/CommandFlags.h" +#include "llvm/CodeGen/MIRParser/MIRParser.h" +#include "llvm/CodeGen/MIRPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachinePassManager.h" +#include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Verifier.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/StandardInstrumentations.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/WithColor.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" +#include "llvm/Transforms/Utils/Cloning.h" + +using namespace llvm; + +static cl::opt RegAlloc( + "regalloc2", cl::desc("Register allocator to use for new pass manager"), + cl::Hidden, cl::ValueOptional, cl::init(RegAllocType::Default), + cl::values( + clEnumValN(RegAllocType::Default, "default", + "pick register allocator based on -O option"), + clEnumValN(RegAllocType::Basic, "basic", "basic register allocator"), + clEnumValN(RegAllocType::Fast, "fast", "fast register allocator"), + clEnumValN(RegAllocType::Greedy, "greedy", "greedy register allocator"), + clEnumValN(RegAllocType::PBQP, "pbqp", "PBQP register allocator"))); + +static cl::opt + DebugPM("debug-pass-manager", cl::Hidden, + cl::desc("Print pass management debugging information")); + +bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { + if (DI.getSeverity() == DS_Error) + *HasError = true; + + if (auto *Remark = dyn_cast(&DI)) + if (!Remark->isEnabled()) + return true; + + DiagnosticPrinterRawOStream DP(errs()); + errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; + DI.print(DP); + errs() << "\n"; + return true; +} + +llvm::ExitOnError ExitOnErr; + +static void RunPasses(bool CompileTwice, bool BOS, ToolOutputFile *Out, + Module *M, LLVMContext &Context, + SmallVector &Buffer, ModulePassManager *MPM, + ModuleAnalysisManager *MAM, + MachineFunctionPassManager *MFPM, + MachineFunctionAnalysisManager *MFAM) { + auto RunPM = [=]() { + if (MPM) { + assert(MAM); + MPM->run(*M, *MAM); + } + + if (MFPM) { + assert(MFAM); + ExitOnErr(MFPM->run(*M, *MFAM)); + } + }; + + assert(M); + + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + + // If requested, run the pass manager over the same module again, + // to catch any bugs due to persistent state in the passes. Note that + // opt has the same functionality, so it may be worth abstracting this out + // in the future. + SmallVector CompileTwiceBuffer; + if (CompileTwice) { + std::unique_ptr M2(llvm::CloneModule(*M)); + RunPM(); + CompileTwiceBuffer = Buffer; + Buffer.clear(); + } + + RunPM(); + + auto HasError = + ((const LLCDiagnosticHandler *)(Context.getDiagHandlerPtr()))->HasError; + if (*HasError) + exit(1); + + // Compare the two outputs and make sure they're the same + if (CompileTwice) { + if (Buffer.size() != CompileTwiceBuffer.size() || + (memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) != + 0)) { + errs() << "Running the pass manager twice changed the output.\n" + "Writing the result of the second run to the specified output\n" + "To generate the one-run comparison binary, just run without\n" + "the compile-twice option\n"; + Out->os() << Buffer; + Out->keep(); + exit(1); + } + } + + if (BOS) { + Out->os() << Buffer; + } +} + +int llvm::compileModuleWithNewPM( + StringRef Arg0, std::unique_ptr M, std::unique_ptr MIR, + std::unique_ptr Target, std::unique_ptr Out, + std::unique_ptr DwoOut, LLVMContext &Context, + const TargetLibraryInfoImpl &TLII, bool NoVerify, bool CompileTwice, + const std::vector &RunPassNames, CodeGenFileType FileType) { + + if (!RunPassNames.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) { + WithColor::warning(errs(), Arg0) + << "run-pass cannot be used with " + << TargetPassConfig::getLimitedCodeGenPipelineReason(" and ") << ".\n"; + return 1; + } + + LLVMTargetMachine &LLVMTM = static_cast(*Target); + + { + raw_pwrite_stream *OS = &Out->os(); + + // Manually do the buffering rather than using buffer_ostream, + // so we can memcmp the contents in CompileTwice mode + SmallVector Buffer; + std::unique_ptr BOS; + if ((codegen::getFileType() != CGFT_AssemblyFile && + !Out->os().supportsSeeking()) || + CompileTwice) { + BOS = std::make_unique(Buffer); + OS = BOS.get(); + } + + // Fetch options from TargetPassConfig + CGPassBuilderOption Opt = getCGPassBuilderOption(); + Opt.DisableVerify = NoVerify; + Opt.DebugPM = DebugPM; + Opt.RegAlloc = RegAlloc; + + PassInstrumentationCallbacks PIC; + StandardInstrumentations SI(Opt.DebugPM); + SI.registerCallbacks(PIC); + registerCodeGenCallback(PIC, LLVMTM); + + LoopAnalysisManager LAM(Opt.DebugPM); + FunctionAnalysisManager FAM(Opt.DebugPM); + CGSCCAnalysisManager CGAM(Opt.DebugPM); + ModuleAnalysisManager MAM(Opt.DebugPM); + PassBuilder PB(Target.get(), PipelineTuningOptions(), None, &PIC); + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); + + FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); + MAM.registerPass([&] { return MachineModuleAnalysis(&LLVMTM); }); + + MachineFunctionAnalysisManager MFAM(FAM, MAM, Opt.DebugPM); + + if (!RunPassNames.empty()) { + // Construct a custom pass pipeline that starts after instruction + // selection. + + if (!MIR) { + WithColor::warning(errs(), Arg0) << "run-pass is for .mir file only.\n"; + return 1; + } + + MachineFunctionPassManager MFPM = ExitOnErr(LLVMTM.parseMIRPipeline( + llvm::join(RunPassNames, ","), Opt, MFAM, &PIC)); + MFPM.addPass(PrintMIRPass(*OS)); + MFPM.addPass(FreeMachineFunctionPass()); + + auto &MMI = MFAM.getResult(*M); + if (MIR->parseMachineFunctions(*M, MMI)) + return 1; + + RunPasses(CompileTwice, BOS.get(), Out.get(), M.get(), Context, Buffer, + nullptr, nullptr, &MFPM, &MFAM); + } else { + std::pair PMPair = + ExitOnErr( + LLVMTM.buildCodeGenPipeline(*OS, DwoOut ? &DwoOut->os() : nullptr, + FileType, Opt, MFAM, &PIC)); + + // Add IR or MIR printing pass according the pass type. + std::string StopPass; + if (!TargetPassConfig::willCompleteCodeGenPipeline(&StopPass)) { + bool IsMachinePass = false; + StopPass = StringRef(StopPass).split(',').first.str(); + std::tie(std::ignore, IsMachinePass) = + LLVMTM.getPassNameFromLegacyName(StopPass); + if (IsMachinePass) + PMPair.second.addPass(PrintMIRPass(*OS)); + else + PMPair.first.addPass(PrintModulePass(*OS)); + } + + RunPasses(CompileTwice, BOS.get(), Out.get(), M.get(), Context, Buffer, + &PMPair.first, &MAM, &PMPair.second, &MFAM); + } + } + + // Declare success. + Out->keep(); + if (DwoOut) + DwoOut->keep(); + + return 0; +} diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "NewPMDriver.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/TargetLibraryInfo.h" @@ -164,6 +165,9 @@ cl::desc("The format used for serializing remarks (default: YAML)"), cl::value_desc("format"), cl::init("yaml")); +static cl::opt EnableNewPassManager( + "enable-new-pm", cl::desc("Enable the new pass manager"), cl::init(false)); + namespace { static ManagedStatic> RunPassNames; @@ -255,25 +259,6 @@ return FDOut; } -struct LLCDiagnosticHandler : public DiagnosticHandler { - bool *HasError; - LLCDiagnosticHandler(bool *HasErrorPtr) : HasError(HasErrorPtr) {} - bool handleDiagnostics(const DiagnosticInfo &DI) override { - if (DI.getSeverity() == DS_Error) - *HasError = true; - - if (auto *Remark = dyn_cast(&DI)) - if (!Remark->isEnabled()) - return true; - - DiagnosticPrinterRawOStream DP(errs()); - errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; - DI.print(DP); - errs() << "\n"; - return true; - } -}; - static void InlineAsmDiagHandler(const SMDiagnostic &SMD, void *Context, unsigned LocCookie) { bool *HasError = static_cast(Context); @@ -541,16 +526,12 @@ } } - // Build up all of the passes that we want to do to the module. - legacy::PassManager PM; - // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) TLII.disableAllFunctions(); - PM.add(new TargetLibraryInfoWrapperPass(TLII)); // Verify module immediately to catch problems before doInitialization() is // called on any passes. @@ -569,6 +550,17 @@ WithColor::warning(errs(), argv[0]) << ": warning: ignoring -mc-relax-all because filetype != obj"; + bool RunPassNone = !RunPassNames->empty() && RunPassNames->at(0) == "none"; + if (EnableNewPassManager && !RunPassNone) + return compileModuleWithNewPM( + argv[0], std::move(M), std::move(MIR), std::move(Target), + std::move(Out), std::move(DwoOut), Context, TLII, NoVerify, + CompileTwice, *RunPassNames, codegen::getFileType()); + + // Build up all of the passes that we want to do to the module. + legacy::PassManager PM; + PM.add(new TargetLibraryInfoWrapperPass(TLII)); + { raw_pwrite_stream *OS = &Out->os();