From 24d0d4d2ecd5f2d612e3e6e9acaae1778b2f4b84 Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Tue, 2 Aug 2016 15:10:32 +0000 Subject: [PATCH] [GlobalISel] Set, require, and verify Legalized MF property. RegBankSelect and InstructionSelect run after the legalizer and require a Legalized function: check that all instructions are legal. Note that this should be in the MachineVerifier, but it can't use the MachineLegalizer as it's currently in the separate GlobalISel library. Note that the RegBankSelect verifier checks have the same layering problem, but we only use inline methods so end up not needing to link against the GlobalISel library. llvm-svn: 277472 --- .../llvm/CodeGen/GlobalISel/InstructionSelect.h | 3 ++- .../llvm/CodeGen/GlobalISel/MachineLegalizePass.h | 5 +++++ .../include/llvm/CodeGen/GlobalISel/RegBankSelect.h | 3 ++- llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp | 14 ++++++++++++++ llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp | 21 +++++++++++++++++++++ .../AArch64/GlobalISel/arm64-instructionselect.mir | 15 +++++++++++++++ .../AArch64/GlobalISel/arm64-regbankselect.mir | 11 +++++++++++ .../AArch64/GlobalISel/legalize-property.mir | 20 ++++++++++++++++++++ 8 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/legalize-property.mir diff --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelect.h b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelect.h index fcc85b5..8828cc8 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelect.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelect.h @@ -32,7 +32,8 @@ public: MachineFunctionProperties getRequiredProperties() const override { return MachineFunctionProperties() - .set(MachineFunctionProperties::Property::IsSSA); + .set(MachineFunctionProperties::Property::IsSSA) + .set(MachineFunctionProperties::Property::Legalized); } InstructionSelect(); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineLegalizePass.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineLegalizePass.h index 4bb503a..5863913 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineLegalizePass.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineLegalizePass.h @@ -48,6 +48,11 @@ public: MachineFunctionProperties::Property::IsSSA); } + MachineFunctionProperties getSetProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::Legalized); + } + bool runOnMachineFunction(MachineFunction &MF) override; }; } // End namespace llvm. diff --git a/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h index db8d483..abaf9cd 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h @@ -586,7 +586,8 @@ public: MachineFunctionProperties getRequiredProperties() const override { return MachineFunctionProperties() - .set(MachineFunctionProperties::Property::IsSSA); + .set(MachineFunctionProperties::Property::IsSSA) + .set(MachineFunctionProperties::Property::Legalized); } /// Walk through \p MF and assign a register bank to every virtual register diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp index 3279d13..92a755c 100644 --- a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp @@ -14,6 +14,7 @@ #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" +#include "llvm/CodeGen/GlobalISel/MachineLegalizer.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/IR/Function.h" #include "llvm/Support/CommandLine.h" @@ -51,6 +52,19 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) { // other MF/MFI fields we need to initialize. #ifndef NDEBUG + // Check that our input is fully legal: we require the function to have the + // Legalized property, so it should be. + // FIXME: This should be in the MachineVerifier, but it can't use the + // MachineLegalizer as it's currently in the separate GlobalISel library. + // The RegBankSelected property is already checked in the verifier. Note + // that it has the same layering problem, but we only use inline methods so + // end up not needing to link against the GlobalISel library. + if (const MachineLegalizer *MLI = MF.getSubtarget().getMachineLegalizer()) + for (const MachineBasicBlock &MBB : MF) + for (const MachineInstr &MI : MBB) + if (isPreISelGenericOpcode(MI.getOpcode()) && !MLI->isLegal(MI)) + reportSelectionError(MI, "Instruction is not legal"); + // FIXME: We could introduce new blocks and will need to fix the outer loop. // Until then, keep track of the number of blocks to assert that we don't. const size_t NumBlocks = MF.size(); diff --git a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp index 6248ab4..bf88d74 100644 --- a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp +++ b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp @@ -12,6 +12,7 @@ #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" #include "llvm/ADT/PostOrderIterator.h" +#include "llvm/CodeGen/GlobalISel/MachineLegalizer.h" #include "llvm/CodeGen/GlobalISel/RegisterBank.h" #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" @@ -542,6 +543,26 @@ bool RegBankSelect::runOnMachineFunction(MachineFunction &MF) { if (F->hasFnAttribute(Attribute::OptimizeNone)) OptMode = Mode::Fast; init(MF); + +#ifndef NDEBUG + // Check that our input is fully legal: we require the function to have the + // Legalized property, so it should be. + // FIXME: This should be in the MachineVerifier, but it can't use the + // MachineLegalizer as it's currently in the separate GlobalISel library. + if (const MachineLegalizer *MLI = MF.getSubtarget().getMachineLegalizer()) { + for (const MachineBasicBlock &MBB : MF) { + for (const MachineInstr &MI : MBB) { + if (isPreISelGenericOpcode(MI.getOpcode()) && !MLI->isLegal(MI)) { + std::string ErrStorage; + raw_string_ostream Err(ErrStorage); + Err << "Instruction is not legal: " << MI << '\n'; + report_fatal_error(Err.str()); + } + } + } + } +#endif + // Walk the function and assign register banks to all operands. // Use a RPOT to make sure all registers are assigned before we choose // the best mapping of the current instruction. diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir index 8efbaea..fdb6f6b 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir @@ -39,6 +39,7 @@ # CHECK-LABEL: name: add_s32_gpr name: add_s32_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr32 } @@ -63,6 +64,7 @@ body: | # CHECK-LABEL: name: add_s64_gpr name: add_s64_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr64 } @@ -87,6 +89,7 @@ body: | # CHECK-LABEL: name: sub_s32_gpr name: sub_s32_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr32 } @@ -111,6 +114,7 @@ body: | # CHECK-LABEL: name: sub_s64_gpr name: sub_s64_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr64 } @@ -135,6 +139,7 @@ body: | # CHECK-LABEL: name: or_s32_gpr name: or_s32_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr32 } @@ -159,6 +164,7 @@ body: | # CHECK-LABEL: name: or_s64_gpr name: or_s64_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr64 } @@ -183,6 +189,7 @@ body: | # CHECK-LABEL: name: xor_s32_gpr name: xor_s32_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr32 } @@ -207,6 +214,7 @@ body: | # CHECK-LABEL: name: xor_s64_gpr name: xor_s64_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr64 } @@ -231,6 +239,7 @@ body: | # CHECK-LABEL: name: and_s32_gpr name: and_s32_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr32 } @@ -255,6 +264,7 @@ body: | # CHECK-LABEL: name: and_s64_gpr name: and_s64_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr64 } @@ -278,6 +288,7 @@ body: | # CHECK-LABEL: name: unconditional_br name: unconditional_br isSSA: true +legalized: true # CHECK: body: # CHECK: bb.0: @@ -294,6 +305,7 @@ body: | # CHECK-LABEL: name: load_s64_gpr name: load_s64_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr64sp } @@ -318,6 +330,7 @@ body: | # CHECK-LABEL: name: load_s32_gpr name: load_s32_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr64sp } @@ -342,6 +355,7 @@ body: | # CHECK-LABEL: name: store_s64_gpr name: store_s64_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr64sp } @@ -368,6 +382,7 @@ body: | # CHECK-LABEL: name: store_s32_gpr name: store_s32_gpr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr64sp } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir index 76fe671..1e04de4 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir @@ -63,6 +63,7 @@ # Based on the type i32, this should be gpr. name: defaultMapping isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr } registers: @@ -80,6 +81,7 @@ body: | # FPR is used for both floating point and vector registers. name: defaultMappingVector isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: fpr } registers: @@ -97,6 +99,7 @@ body: | # in FPR, but at the use, it should be GPR. name: defaultMapping1Repair isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: fpr } # CHECK-NEXT: - { id: 1, class: gpr } @@ -117,6 +120,7 @@ body: | # Check that we repair the assignment for %0 differently for both uses. name: defaultMapping2Repairs isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: fpr } # CHECK-NEXT: - { id: 1, class: gpr } @@ -143,6 +147,7 @@ body: | # fixes that. name: defaultMappingDefRepair isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr } # CHECK-NEXT: - { id: 1, class: fpr } @@ -164,6 +169,7 @@ body: | # Check that we are able to propagate register banks from phis. name: phiPropagation isSSA: true +legalized: true tracksRegLiveness: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr32 } @@ -201,6 +207,7 @@ body: | # Make sure we can repair physical register uses as well. name: defaultMappingUseRepairPhysReg isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr } # CHECK-NEXT: - { id: 1, class: gpr } @@ -222,6 +229,7 @@ body: | # Make sure we can repair physical register defs. name: defaultMappingDefRepairPhysReg isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr } # CHECK-NEXT: - { id: 1, class: gpr } @@ -242,6 +250,7 @@ body: | # G_OR instruction from fpr to gpr. name: greedyMappingOr isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr } # CHECK-NEXT: - { id: 1, class: gpr } @@ -288,6 +297,7 @@ body: | # %2 constraint. name: greedyMappingOrWithConstraints isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr } # CHECK-NEXT: - { id: 1, class: gpr } @@ -334,6 +344,7 @@ body: | # CHECK-LABEL: name: ignoreTargetSpecificInst name: ignoreTargetSpecificInst isSSA: true +legalized: true # CHECK: registers: # CHECK-NEXT: - { id: 0, class: gpr64 } # CHECK-NEXT: - { id: 1, class: gpr64 } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-property.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-property.mir new file mode 100644 index 0000000..fbac08c --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-property.mir @@ -0,0 +1,20 @@ +# RUN: llc -O0 -run-pass=legalize-mir -global-isel %s -o - | FileCheck %s +# REQUIRES: global-isel + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @legalized_property() { ret void } +... + +--- +# Check that we set the "legalized" property. +# CHECK-LABEL: name: legalized_property +# CHECK: legalized: true +# CHECK: isSSA: true +name: legalized_property +isSSA: true +legalized: false +body: | + bb.0: +... -- 2.7.4