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 @@ -25,6 +25,7 @@ class PassConfigImpl; class ScheduleDAGInstrs; class CSEConfigBase; +class MachineFunction; // The old pass manager infrastructure is hidden in a legacy namespace now. namespace legacy { @@ -212,6 +213,8 @@ /// has not be overriden on the command line with '-regalloc=...' bool usingDefaultRegAlloc() const; + enum class SelectorType { SelectionDAG, FastISel, GlobalISel }; + /// High level function that adds all passes necessary to go from llvm IR /// representation to the MI representation. /// Adds IR based lowering and target specific optimization passes and finally @@ -275,6 +278,12 @@ /// Fully developed targets will not generally override this. virtual void addMachinePasses(); + /// Add a unified pipeline of GlobalISel and SelectionDAG isel passes. + /// The GISel passes are scheduled first, and then SDISel. Targets must + /// take care to ensure their custom passes are aware that two selectors + /// may be running. + virtual bool addUnifiedISelPipeline(SelectorType Selector); + /// Create an instance of ScheduleDAGInstrs to be run within the standard /// MachineScheduler pass for this function and target at the current /// optimization level. @@ -339,6 +348,11 @@ /// Returns the CSEConfig object to use for the current optimization level. virtual std::unique_ptr getCSEConfig() const; + /// Returns true if we should skip running GlobalISel passes on the given + /// MachineFunction \p MF based on the current codegen options in + /// TargetMachine and the attributes on \p MF. + static bool skipGISelPassesForFn(MachineFunction &MF); + protected: // Helper to verify the analysis is really immutable. void setOpt(bool &Opt, bool Val); diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -142,6 +142,12 @@ return false; } + /// Return true if the target wants to use a unified GlobalISel + SelectionDAG + /// pipeline. This is necessary for GlobalISel LTO support, as we need to be + /// able to choose an instruction selector based on attributes or metadata in + /// the bitcode. + virtual bool useUnifiedISelPipeline() const { return false; } + /// This method returns a pointer to the specified type of /// TargetSubtargetInfo. In debug builds, it verifies that the object being /// returned is of the correct type. @@ -228,6 +234,8 @@ bool getO0WantsFastISel() { return O0WantsFastISel; } void setO0WantsFastISel(bool Enable) { O0WantsFastISel = Enable; } void setGlobalISel(bool Enable) { Options.EnableGlobalISel = Enable; } + bool getGlobalISel() const { return Options.EnableGlobalISel; } + void setGlobalISelAbort(GlobalISelAbortMode Mode) { Options.GlobalISelAbort = Mode; } diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2262,6 +2262,17 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) { MF = &CurMF; const Function &F = MF->getFunction(); + if (TargetPassConfig::skipGISelPassesForFn(CurMF)) { + // If we're using a unified isel pipeline with SDISel, then some analyses + // like MachineDominator may try to run right after the translator. This + // doesn't end well when the translator leaves just an empty function + // without any basic blocks. So here we just create an entry block so that + // the MF is at least well-formed, even though the MF will be discarded + // later by the ResetMachineFunction pass. + MachineBasicBlock *EntryBB = MF->CreateMachineBasicBlock(); + MF->push_back(EntryBB); + return true; + } if (F.empty()) return false; GISelCSEAnalysisWrapper &Wrapper = diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp --- a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp @@ -68,8 +68,10 @@ if (MF.getProperties().hasProperty( MachineFunctionProperties::Property::FailedISel)) return false; + if (TargetPassConfig::skipGISelPassesForFn(MF)) + return false; - LLVM_DEBUG(dbgs() << "Selecting function: " << MF.getName() << '\n'); + LLVM_DEBUG(dbgs() << "GlobalISel selecting function: " << MF.getName() << '\n'); GISelKnownBits &KB = getAnalysis().get(MF); const TargetPassConfig &TPC = getAnalysis(); diff --git a/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp b/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp --- a/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp @@ -312,6 +312,8 @@ if (MF.getProperties().hasProperty( MachineFunctionProperties::Property::FailedISel)) return false; + if (TargetPassConfig::skipGISelPassesForFn(MF)) + return false; LLVM_DEBUG(dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n'); init(MF); const TargetPassConfig &TPC = getAnalysis(); diff --git a/llvm/lib/CodeGen/GlobalISel/Localizer.cpp b/llvm/lib/CodeGen/GlobalISel/Localizer.cpp --- a/llvm/lib/CodeGen/GlobalISel/Localizer.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Localizer.cpp @@ -14,6 +14,7 @@ #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetLowering.h" +#include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/InitializePasses.h" #include "llvm/Support/Debug.h" @@ -169,6 +170,9 @@ MachineFunctionProperties::Property::FailedISel)) return false; + if (TargetPassConfig::skipGISelPassesForFn(MF)) + return false; + // Don't run the pass if the target asked so. if (DoNotRunPass(MF)) return false; diff --git a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp --- a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp +++ b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp @@ -654,6 +654,8 @@ if (MF.getProperties().hasProperty( MachineFunctionProperties::Property::FailedISel)) return false; + if (TargetPassConfig::skipGISelPassesForFn(MF)) + return false; LLVM_DEBUG(dbgs() << "Assign register banks for: " << MF.getName() << '\n'); const Function &F = MF.getFunction(); diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp --- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -23,6 +23,7 @@ #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/IR/Constants.h" +#include "llvm/Target/TargetMachine.h" #define DEBUG_TYPE "globalisel-utils" diff --git a/llvm/lib/CodeGen/ResetMachineFunctionPass.cpp b/llvm/lib/CodeGen/ResetMachineFunctionPass.cpp --- a/llvm/lib/CodeGen/ResetMachineFunctionPass.cpp +++ b/llvm/lib/CodeGen/ResetMachineFunctionPass.cpp @@ -19,6 +19,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/StackProtector.h" +#include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/InitializePasses.h" #include "llvm/Support/Debug.h" @@ -73,6 +74,14 @@ } return true; } + if (TargetPassConfig::skipGISelPassesForFn(MF)) { + /* using MFP = MachineFunctionProperties::Property; + MF.getProperties().reset(MFP::Legalized); + MF.getProperties().reset(MFP::RegBankSelected); + MF.getProperties().reset(MFP::Selected);*/ + MF.reset(); + return true; + } return false; } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -55,6 +55,7 @@ #include "llvm/CodeGen/SwiftErrorValueTracking.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetLowering.h" +#include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/CodeGen/ValueTypes.h" @@ -408,6 +409,8 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { // If we already selected that function, we do not need to run SDISel. + // FIXME: GlobalISel passes are scheduled before SelectionDAGISel, and + // they will set the Selected property even if they are being skipped. if (mf.getProperties().hasProperty( MachineFunctionProperties::Property::Selected)) return false; @@ -415,6 +418,8 @@ assert((!EnableFastISelAbort || TM.Options.EnableFastISel) && "-fast-isel-abort > 0 requires -fast-isel"); + LLVM_DEBUG(dbgs() << "SDISel selecting function: " << mf.getName() << '\n'); + const Function &Fn = mf.getFunction(); MF = &mf; 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 @@ -791,7 +791,6 @@ TM->setO0WantsFastISel(EnableFastISelOption != cl::BOU_FALSE); // Determine an instruction selector. - enum class SelectorType { SelectionDAG, FastISel, GlobalISel }; SelectorType Selector; if (EnableFastISelOption == cl::BOU_TRUE) @@ -812,6 +811,8 @@ } else if (Selector == SelectorType::GlobalISel) { TM->setFastISel(false); TM->setGlobalISel(true); + } else { + TM->setGlobalISel(false); } // FIXME: Injecting into the DAGISel pipeline seems to cause issues with @@ -824,43 +825,49 @@ // and -run-pass seem to be unaffected. The majority of GlobalISel // testing uses -run-pass so this probably isn't too bad. SaveAndRestore SavedDebugifyIsSafe(DebugifyIsSafe); - if (Selector != SelectorType::GlobalISel || !isGlobalISelAbortEnabled()) + if (Selector != SelectorType::GlobalISel || isGlobalISelAbortEnabled()) DebugifyIsSafe = false; - // Add instruction selector passes. - if (Selector == SelectorType::GlobalISel) { - SaveAndRestore SavedAddingMachinePasses(AddingMachinePasses, true); - if (addIRTranslator()) + if (TM->useUnifiedISelPipeline()) { + if (addUnifiedISelPipeline(Selector)) return true; + } else { + // Add instruction selector passes. + if (Selector == SelectorType::GlobalISel) { + SaveAndRestore SavedAddingMachinePasses(AddingMachinePasses, true); + if (addIRTranslator()) + return true; - addPreLegalizeMachineIR(); + addPreLegalizeMachineIR(); - if (addLegalizeMachineIR()) - return true; + if (addLegalizeMachineIR()) + return true; - // Before running the register bank selector, ask the target if it - // wants to run some passes. - addPreRegBankSelect(); + // Before running the register bank selector, ask the target if it + // wants to run some passes. + addPreRegBankSelect(); - if (addRegBankSelect()) - return true; + if (addRegBankSelect()) + return true; - addPreGlobalInstructionSelect(); + addPreGlobalInstructionSelect(); - if (addGlobalInstructionSelect()) - return true; + if (addGlobalInstructionSelect()) + return true; - // Pass to reset the MachineFunction if the ISel failed. - addPass(createResetMachineFunctionPass( - reportDiagnosticWhenGlobalISelFallback(), isGlobalISelAbortEnabled())); + // Pass to reset the MachineFunction if the ISel failed. + addPass(createResetMachineFunctionPass( + reportDiagnosticWhenGlobalISelFallback(), + isGlobalISelAbortEnabled())); - // Provide a fallback path when we do not want to abort on - // not-yet-supported input. - if (!isGlobalISelAbortEnabled() && addInstSelector()) - return true; + // Provide a fallback path when we do not want to abort on + // not-yet-supported input. + if (!isGlobalISelAbortEnabled() && addInstSelector()) + return true; - } else if (addInstSelector()) - return true; + } else if (addInstSelector()) + return true; + } // Expand pseudo-instructions emitted by ISel. Don't run the verifier before // FinalizeISel. @@ -1240,6 +1247,42 @@ } } +bool TargetPassConfig::addUnifiedISelPipeline(SelectorType Selector) { + SaveAndRestore SavedAddingMachinePasses(AddingMachinePasses, true); + // Add instruction selector passes. We add the GlobalISel passes first + // and then schedule the FastISel/SelectionDAG selector afterwards. We don't + // have two separate pass pipelines because with LTO we need to run one + // selection framework or another using function attributes to decide, rather + // a global option switch. + AddingMachinePasses = true; + if (addIRTranslator()) + return true; + + addPreLegalizeMachineIR(); + + if (addLegalizeMachineIR()) + return true; + + // Before running the register bank selector, ask the target if it + // wants to run some passes. + addPreRegBankSelect(); + + if (addRegBankSelect()) + return true; + + addPreGlobalInstructionSelect(); + + if (addGlobalInstructionSelect()) + return true; + + // Pass to reset the MachineFunction if the ISel failed. + addPass(createResetMachineFunctionPass( + reportDiagnosticWhenGlobalISelFallback(), isGlobalISelAbortEnabled())); + + // Now add the SDAG selector. + return addInstSelector(); +} + //===---------------------------------------------------------------------===// /// Post RegAlloc Pass Configuration //===---------------------------------------------------------------------===// @@ -1293,3 +1336,19 @@ std::unique_ptr TargetPassConfig::getCSEConfig() const { return std::make_unique(); } + +bool TargetPassConfig::skipGISelPassesForFn(MachineFunction &MF) { + // If we have been specifically requested to run by llc's run-pass option, + // then don't do any skipping. + Function &F = MF.getFunction(); + if (F.getParent()->getNamedMetadata("llvm.llc.run.pass")) + return false; + + // Even if TargetMachine doesn't say we need to use GlobalISel, check the + // attributes before we skip the GISel pipeline. + if (!MF.getTarget().getGlobalISel()) { + if (!F.hasFnAttribute("use-globalisel")) + return true; + } + return false; +} diff --git a/llvm/lib/Target/AArch64/AArch64PreLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/AArch64PreLegalizerCombiner.cpp --- a/llvm/lib/Target/AArch64/AArch64PreLegalizerCombiner.cpp +++ b/llvm/lib/Target/AArch64/AArch64PreLegalizerCombiner.cpp @@ -163,6 +163,8 @@ if (MF.getProperties().hasProperty( MachineFunctionProperties::Property::FailedISel)) return false; + if (TargetPassConfig::skipGISelPassesForFn(MF)) + return false; auto *TPC = &getAnalysis(); const Function &F = MF.getFunction(); bool EnableOpt = diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.h b/llvm/lib/Target/AArch64/AArch64TargetMachine.h --- a/llvm/lib/Target/AArch64/AArch64TargetMachine.h +++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.h @@ -57,6 +57,10 @@ SMDiagnostic &Error, SMRange &SourceRange) const override; + bool useUnifiedISelPipeline() const override { + return true; + } + private: bool isLittle; }; diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option-fastisel.ll b/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option-fastisel.ll --- a/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option-fastisel.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option-fastisel.ll @@ -18,12 +18,6 @@ ; RUN: -debug-only=isel \ ; RUN: | FileCheck %s --check-prefixes=DISABLED,NOFASTISEL -; Check that the right instruction selector is chosen when using -; -global-isel=false. FastISel should be used at -O0 (unless -fast-isel=false is -; also present) and SelectionDAG otherwise. - -; DISABLED-NOT: IRTranslator - ; DISABLED: AArch64 Instruction Selection ; DISABLED: Finalize ISel and expand pseudo-instructions diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll b/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll --- a/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll @@ -70,11 +70,6 @@ ; VERIFY-NEXT: Verify generated machine code ; ENABLED-NEXT: ResetMachineFunction -; FALLBACK: AArch64 Instruction Selection -; NOFALLBACK-NOT: AArch64 Instruction Selection - -; DISABLED-NOT: IRTranslator - ; DISABLED: AArch64 Instruction Selection ; DISABLED: Finalize ISel and expand pseudo-instructions diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/use-globalisel-fn-attr.ll b/llvm/test/CodeGen/AArch64/GlobalISel/use-globalisel-fn-attr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/use-globalisel-fn-attr.ll @@ -0,0 +1,20 @@ +; RUN: llc -mtriple=aarch64-- %s -o - -debug 2>&1 | FileCheck %s +; REQUIRES: asserts +; +; CHECK: GlobalISel selecting function: has_gisel_attr +; CHECK-NOT: SDISel selecting function: has_gisel_attr +define i32 @has_gisel_attr(i32 %a, i32 %b) #0 { + %res = add i32 %a, %b + ret i32 %res +} + +; On AArch64 with opt enabled, we don't enable GISel by default. +; Shouldn't run GISel with no attribute. +; CHECK-NOT: GlobalISel selecting function: no_gisel_attr +; CHECK: SDISel selecting function: no_gisel_attr +define i32 @no_gisel_attr(i32 %a, i32 %b) { + %res = add i32 %a, %b + ret i32 %res +} + +attributes #0 = { "use-globalisel" } diff --git a/llvm/test/CodeGen/AArch64/O3-pipeline.ll b/llvm/test/CodeGen/AArch64/O3-pipeline.ll --- a/llvm/test/CodeGen/AArch64/O3-pipeline.ll +++ b/llvm/test/CodeGen/AArch64/O3-pipeline.ll @@ -82,6 +82,18 @@ ; CHECK-NEXT: Safe Stack instrumentation pass ; CHECK-NEXT: Insert stack protectors ; CHECK-NEXT: Module Verifier +; CHECK-NEXT: Analysis containing CSE Info +; CHECK-NEXT: IRTranslator +; CHECK-NEXT: Analysis for ComputingKnownBits +; CHECK-NEXT: MachineDominator Tree Construction +; CHECK-NEXT: AArch64PreLegalizerCombiner +; CHECK-NEXT: Analysis containing CSE Info +; CHECK-NEXT: Legalizer +; CHECK-NEXT: RegBankSelect +; CHECK-NEXT: Localizer +; CHECK-NEXT: Analysis for ComputingKnownBits +; CHECK-NEXT: InstructionSelect +; CHECK-NEXT: ResetMachineFunction ; CHECK-NEXT: Dominator Tree Construction ; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) ; CHECK-NEXT: Function Alias Analysis Results diff --git a/llvm/test/CodeGen/AArch64/max-jump-table.ll b/llvm/test/CodeGen/AArch64/max-jump-table.ll --- a/llvm/test/CodeGen/AArch64/max-jump-table.ll +++ b/llvm/test/CodeGen/AArch64/max-jump-table.ll @@ -28,7 +28,7 @@ i32 17, label %bb17 ] ; CHECK-LABEL: function jt1: -; CHECK-NEXT: Jump Tables: +; CHECK: Jump Tables: ; CHECK0-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.5 %bb.6 %bb.7 %bb.8 %bb.9 %bb.10 %bb.11 %bb.12 %bb.13 %bb.14 %bb.15 %bb.16 %bb.17 ; CHECK0-NOT: %jump-table.1: ; CHECK4-NEXT: %jump-table.0: %bb.2 %bb.3 %bb.4 %bb.5 @@ -77,7 +77,7 @@ i32 15, label %bb6 ] ; CHECK-LABEL: function jt2: -; CHECK-NEXT: Jump Tables: +; CHECK: Jump Tables: ; CHECK0-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.7 %bb.5 %bb.6{{$}} ; CHECK0-NOT: %jump-table.1: ; CHECK4-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4{{$}} @@ -119,7 +119,7 @@ i32 23, label %bb12 ] ; CHECK-LABEL: function jt3: -; CHECK-NEXT: Jump Tables: +; CHECK: Jump Tables: ; CHECK0-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10 %bb.13 %bb.11 %bb.12 ; CHECK0-NOT: %jump-table.1: ; CHECK4-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 @@ -171,7 +171,7 @@ i32 23, label %bb12 ] ; CHECK-LABEL: function jt4: -; CHECK-NEXT: Jump Tables: +; CHECK: Jump Tables: ; CHECK0-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.13 %bb.5 %bb.6 %bb.7 %bb.8 %bb.13 %bb.9 %bb.10 %bb.13 %bb.11 %bb.12 ; CHECK0-NOT: %jump-table.1: ; CHECK4-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 @@ -226,7 +226,7 @@ i32 17, label %bb17 ] ; CHECK-LABEL: function jt1_optsize: -; CHECK-NEXT: Jump Tables: +; CHECK: Jump Tables: ; CHECK0-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.5 %bb.6 %bb.7 %bb.8 %bb.9 %bb.10 %bb.11 %bb.12 %bb.13 %bb.14 %bb.15 %bb.16 %bb.17 ; CHECK0-NOT: %jump-table.1: ; CHECK4-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.5 %bb.6 %bb.7 %bb.8 %bb.9 %bb.10 %bb.11 %bb.12 %bb.13 %bb.14 %bb.15 %bb.16 %bb.17 @@ -284,7 +284,7 @@ i32 17, label %bb17 ] ; CHECK-LABEL: function jt1_pgso: -; CHECK-NEXT: Jump Tables: +; CHECK: Jump Tables: ; CHECK0-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.5 %bb.6 %bb.7 %bb.8 %bb.9 %bb.10 %bb.11 %bb.12 %bb.13 %bb.14 %bb.15 %bb.16 %bb.17 ; CHECK0-NOT: %jump-table.1: ; CHECK4-NEXT: %jump-table.0: %bb.1 %bb.2 %bb.3 %bb.4 %bb.5 %bb.6 %bb.7 %bb.8 %bb.9 %bb.10 %bb.11 %bb.12 %bb.13 %bb.14 %bb.15 %bb.16 %bb.17 diff --git a/llvm/test/CodeGen/AArch64/min-jump-table.ll b/llvm/test/CodeGen/AArch64/min-jump-table.ll --- a/llvm/test/CodeGen/AArch64/min-jump-table.ll +++ b/llvm/test/CodeGen/AArch64/min-jump-table.ll @@ -12,8 +12,8 @@ i32 3, label %bb2 ] ; CHECK-LABEL: function jt2: -; CHECK0-NEXT: Jump Tables: -; CHECK2-NEXT: Jump Tables: +; CHECK0: Jump Tables: +; CHECK2: Jump Tables: ; CHECK4-NOT: {{^}}Jump Tables: ; CHECK8-NOT: {{^}}Jump Tables: @@ -32,9 +32,9 @@ i32 5, label %bb4 ] ; CHECK-LABEL: function jt4: -; CHECK0-NEXT: Jump Tables: -; CHECK2-NEXT: Jump Tables: -; CHECK4-NEXT: Jump Tables: +; CHECK0: Jump Tables: +; CHECK2: Jump Tables: +; CHECK4: Jump Tables: ; CHECK8-NOT: {{^}}Jump Tables: bb1: tail call void @ext(i32 1, i32 0) br label %return @@ -58,7 +58,7 @@ i32 9, label %bb8 ] ; CHECK-LABEL: function jt8: -; CHECK-NEXT: Jump Tables: +; CHECK: Jump Tables: bb1: tail call void @ext(i32 1, i32 0) br label %return bb2: tail call void @ext(i32 2, i32 2) br label %return diff --git a/llvm/test/CodeGen/AArch64/multi-vector-store-size.ll b/llvm/test/CodeGen/AArch64/multi-vector-store-size.ll --- a/llvm/test/CodeGen/AArch64/multi-vector-store-size.ll +++ b/llvm/test/CodeGen/AArch64/multi-vector-store-size.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=aarch64-linux-gnu -stop-after=instruction-select < %s | FileCheck %s +; RUN: llc -mtriple=aarch64-linux-gnu -stop-after=finalize-isel < %s | FileCheck %s declare void @llvm.aarch64.neon.st2.v4f32.p0f32(<4 x float>, <4 x float>, float*) declare void @llvm.aarch64.neon.st3.v4f32.p0f32(<4 x float>, <4 x float>, <4 x float>, float*) 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 @@ -610,6 +610,13 @@ // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); + // Some passes like GlobalISel ones need to know when -run-pass is being + // used, otherwise they may skip unless some function attributes are set. + // Communicate via some module metadata here that we have specifically + // requested a pass to run. + if (!RunPassNames->empty()) + M->getOrInsertNamedMetadata(StringRef("llvm.llc.run.pass")); + // 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