Index: include/llvm/CodeGen/MIRYamlMapping.h =================================================================== --- include/llvm/CodeGen/MIRYamlMapping.h +++ include/llvm/CodeGen/MIRYamlMapping.h @@ -472,6 +472,7 @@ bool Legalized = false; bool RegBankSelected = false; bool Selected = false; + bool FailedISel = false; // Register information bool TracksRegLiveness = false; std::vector VirtualRegisters; @@ -495,6 +496,7 @@ YamlIO.mapOptional("legalized", MF.Legalized, false); YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false); YamlIO.mapOptional("selected", MF.Selected, false); + YamlIO.mapOptional("failedISel", MF.FailedISel, false); YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false); YamlIO.mapOptional("registers", MF.VirtualRegisters, std::vector()); Index: lib/CodeGen/GlobalISel/InstructionSelect.cpp =================================================================== --- lib/CodeGen/GlobalISel/InstructionSelect.cpp +++ lib/CodeGen/GlobalISel/InstructionSelect.cpp @@ -12,7 +12,6 @@ #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" #include "llvm/ADT/PostOrderIterator.h" -#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" @@ -61,13 +60,6 @@ } bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) { - const MachineRegisterInfo &MRI = MF.getRegInfo(); - - // No matter what happens, whether we successfully select the function or not, - // nothing is going to use the vreg types after us. Make sure they disappear. - auto ClearVRegTypesOnReturn = - make_scope_exit([&]() { MRI.getVRegToType().clear(); }); - // If the ISel pipeline failed, do not bother running that pass. if (MF.getProperties().hasProperty( MachineFunctionProperties::Property::FailedISel)) @@ -85,6 +77,7 @@ // FIXME: There are many other MF/MFI fields we need to initialize. + const MachineRegisterInfo &MRI = MF.getRegInfo(); #ifndef NDEBUG // Check that our input is fully legal: we require the function to have the // Legalized property, so it should be. @@ -238,6 +231,11 @@ .getTarget() .getBackendName()); + // If we successfully selected the function nothing is going to use the vreg + // types after us (otherwise MIRPrinter would need them). Make sure the types + // disappear. + MRI.getVRegToType().clear(); + // FIXME: Should we accurately track changes? return true; } Index: lib/CodeGen/MIRParser/MIRParser.cpp =================================================================== --- lib/CodeGen/MIRParser/MIRParser.cpp +++ lib/CodeGen/MIRParser/MIRParser.cpp @@ -362,6 +362,8 @@ MachineFunctionProperties::Property::RegBankSelected); if (YamlMF.Selected) MF.getProperties().set(MachineFunctionProperties::Property::Selected); + if (YamlMF.FailedISel) + MF.getProperties().set(MachineFunctionProperties::Property::FailedISel); PerFunctionMIParsingState PFS(MF, SM, IRSlots, Names2RegClasses, Names2RegBanks); Index: lib/CodeGen/MIRPrinter.cpp =================================================================== --- lib/CodeGen/MIRPrinter.cpp +++ lib/CodeGen/MIRPrinter.cpp @@ -207,6 +207,8 @@ MachineFunctionProperties::Property::RegBankSelected); YamlMF.Selected = MF.getProperties().hasProperty( MachineFunctionProperties::Property::Selected); + YamlMF.FailedISel = MF.getProperties().hasProperty( + MachineFunctionProperties::Property::FailedISel); convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo()); ModuleSlotTracker MST(MF.getFunction().getParent()); Index: lib/CodeGen/MachineVerifier.cpp =================================================================== --- lib/CodeGen/MachineVerifier.cpp +++ lib/CodeGen/MachineVerifier.cpp @@ -359,11 +359,15 @@ TRI = MF.getSubtarget().getRegisterInfo(); MRI = &MF.getRegInfo(); - isFunctionRegBankSelected = MF.getProperties().hasProperty( - MachineFunctionProperties::Property::RegBankSelected); - isFunctionSelected = MF.getProperties().hasProperty( - MachineFunctionProperties::Property::Selected); - + const bool isFunctionFailedISel = MF.getProperties().hasProperty( + MachineFunctionProperties::Property::FailedISel); + isFunctionRegBankSelected = + !isFunctionFailedISel && + MF.getProperties().hasProperty( + MachineFunctionProperties::Property::RegBankSelected); + isFunctionSelected = !isFunctionFailedISel && + MF.getProperties().hasProperty( + MachineFunctionProperties::Property::Selected); LiveVars = nullptr; LiveInts = nullptr; LiveStks = nullptr; Index: lib/CodeGen/ResetMachineFunctionPass.cpp =================================================================== --- lib/CodeGen/ResetMachineFunctionPass.cpp +++ lib/CodeGen/ResetMachineFunctionPass.cpp @@ -13,9 +13,11 @@ /// happen is that the MachineFunction has the FailedISel property. //===----------------------------------------------------------------------===// +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/Support/Debug.h" @@ -43,6 +45,12 @@ StringRef getPassName() const override { return "ResetMachineFunction"; } bool runOnMachineFunction(MachineFunction &MF) override { + // No matter what happened, whether we successfully selected the function + // or not, nothing is going to use the vreg types after us. Make sure they + // disappear. + auto ClearVRegTypesOnReturn = + make_scope_exit([&MF]() { MF.getRegInfo().getVRegToType().clear(); }); + if (MF.getProperties().hasProperty( MachineFunctionProperties::Property::FailedISel)) { if (AbortOnFailedISel) Index: test/CodeGen/MIR/AArch64/print-parse-verify-failedISel-property.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/AArch64/print-parse-verify-failedISel-property.mir @@ -0,0 +1,65 @@ +# RUN: llc -mtriple aarch64-- -run-pass instruction-select -simplify-mir \ +# RUN: -verify-machineinstrs %s -o - | FileCheck %s +# +# RUN: llc -mtriple aarch64-- -global-isel=true -global-isel-abort=2 \ +# RUN: -start-after=regbankselect -stop-before=expand-isel-pseudos \ +# RUN: -simplify-mir -verify-machineinstrs %s -o - 2>&1 \ +# RUN: | FileCheck %s --check-prefix=FALLBACK + +# Test that: +# 1) MIRParser can deserialize FailedISel property. +# 2) Machine Verifier respects FailedISel and doesn't complain needlessly. +# 3) MIRPrinter is able to print FailedISel MIR after InstructionSelect pass. +# 4) MIRPrinter can serialize FailedISel property. +# 5) It's possible to start llc mid-GlobalISel pipeline from a MIR file with +# the FailedISel property set to true and watch it properly fallback to +# FastISel / SelectionDAG ISel. +--- | + target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + + define i32 @test(i32 %a, i32 %b) #0 { + entry: + %add = add i32 %b, %a + ret i32 %add + } + + attributes #0 = { nounwind readnone ssp } +... +--- +# CHECK-LABEL: name: test +# CHECK: failedISel: true +# +# FALLBACK: warning: Instruction selection used fallback path for test +# FALLBACK-LABEL: name: test +# FALLBACK-NOT: failedISel +name: test +alignment: 2 +legalized: true +regBankSelected: true +failedISel: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $w0, $w1 + + ; CHECK: liveins: $w0, $w1 + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK: [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[COPY1]], [[COPY]] + ; CHECK: $w0 = COPY [[ADD]](s32) + ; CHECK: RET_ReallyLR implicit $w0 + ; + ; FALLBACK: liveins: $w0, $w1 + ; FALLBACK: [[COPY:%[0-9]+]]:gpr32 = COPY $w1 + ; FALLBACK: [[COPY1:%[0-9]+]]:gpr32 = COPY $w0 + ; FALLBACK: [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[COPY]], [[COPY1]] + ; FALLBACK: $w0 = COPY [[ADDWrr]] + ; FALLBACK: RET_ReallyLR implicit $w0 + + %0:_(s32) = COPY $w0 + %1:_(s32) = COPY $w1 + %2:gpr(s32) = G_ADD %1, %0 + $w0 = COPY %2(s32) + RET_ReallyLR implicit $w0 +...