From 7f64318938cecbe53ee3ba59c79dd3b32cb7373b Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Sat, 1 Apr 2017 01:26:14 +0000 Subject: [PATCH] [RegBankSelect] Support REG_SEQUENCE for generic mapping REG_SEQUENCE falls into the same category as COPY for operands mapping: - They don't have MCInstrDesc with register constraints - The input variable could use whatever register classes - It is possible to have register class already assigned to the operands In particular, given REG_SEQUENCE are always target specific because of the subreg indices. Those indices must apply to the register class of the definition of the REG_SEQUENCE and therefore, the target must set a register class to that definition. As a result, the generic code can always use that register class to derive a valid mapping for a REG_SEQUENCE. llvm-svn: 299285 --- llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp | 26 +++++++++++++++------- .../GlobalISel/regbankselect-reg_sequence.mir | 25 +++++++++++++++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/regbankselect-reg_sequence.mir diff --git a/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp b/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp index 2901761..b2df2f1 100644 --- a/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp +++ b/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp @@ -126,15 +126,26 @@ const TargetRegisterClass *RegisterBankInfo::constrainGenericRegister( return &RC; } +/// Check whether or not \p MI should be treated like a copy +/// for the mappings. +/// Copy like instruction are special for mapping because +/// they don't have actual register constraints. Moreover, +/// they sometimes have register classes assigned and we can +/// just use that instead of failing to provide a generic mapping. +static bool isCopyLike(const MachineInstr &MI) { + return MI.isCopy() || MI.isPHI() || + MI.getOpcode() == TargetOpcode::REG_SEQUENCE; +} + RegisterBankInfo::InstructionMapping RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const { // For copies we want to walk over the operands and try to find one // that has a register bank since the instruction itself will not get // us any constraint. - bool isCopyLike = MI.isCopy() || MI.isPHI(); + bool IsCopyLike = isCopyLike(MI); // For copy like instruction, only the mapping of the definition // is important. The rest is not constrained. - unsigned NumOperandsForMapping = isCopyLike ? 1 : MI.getNumOperands(); + unsigned NumOperandsForMapping = IsCopyLike ? 1 : MI.getNumOperands(); RegisterBankInfo::InstructionMapping Mapping(DefaultMappingID, /*Cost*/ 1, /*OperandsMapping*/ nullptr, @@ -168,7 +179,7 @@ RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const { // For copy-like instruction, we want to reuse the register bank // that is already set on Reg, if any, since those instructions do // not have any constraints. - const RegisterBank *CurRegBank = isCopyLike ? AltRegBank : nullptr; + const RegisterBank *CurRegBank = IsCopyLike ? AltRegBank : nullptr; if (!CurRegBank) { // If this is a target specific instruction, we can deduce // the register bank from the encoding constraints. @@ -177,7 +188,7 @@ RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const { // All our attempts failed, give up. CompleteMapping = false; - if (!isCopyLike) + if (!IsCopyLike) // MI does not carry enough information to guess the mapping. return InstructionMapping(); continue; @@ -185,7 +196,7 @@ RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const { } const ValueMapping *ValMapping = &getValueMapping(0, getSizeInBits(Reg, MRI, TRI), *CurRegBank); - if (isCopyLike) { + if (IsCopyLike) { OperandsMapping[0] = ValMapping; CompleteMapping = true; break; @@ -193,7 +204,7 @@ RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const { OperandsMapping[OpIdx] = ValMapping; } - if (isCopyLike && !CompleteMapping) + if (IsCopyLike && !CompleteMapping) // No way to deduce the type from what we have. return InstructionMapping(); @@ -492,8 +503,7 @@ bool RegisterBankInfo::InstructionMapping::verify( // Check that all the register operands are properly mapped. // Check the constructor invariant. // For PHI, we only care about mapping the definition. - assert(NumOperands == - ((MI.isCopy() || MI.isPHI()) ? 1 : MI.getNumOperands()) && + assert(NumOperands == (isCopyLike(MI) ? 1 : MI.getNumOperands()) && "NumOperands must match, see constructor"); assert(MI.getParent() && MI.getParent()->getParent() && "MI must be connected to a MachineFunction"); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/regbankselect-reg_sequence.mir b/llvm/test/CodeGen/AArch64/GlobalISel/regbankselect-reg_sequence.mir new file mode 100644 index 0000000..15ccf1f --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/regbankselect-reg_sequence.mir @@ -0,0 +1,25 @@ +# RUN: llc %s -mtriple aarch64-- -o - -run-pass regbankselect | FileCheck %s +--- | + define void @foo() { ret void } +... +--- +# CHECK-LABEL: foo +# Check that we produce a valid mapping for REG_SEQUENCE. +# This used to fail the RegisterBankInfo verify because +# we were using the exclusively the type of the definition +# whereas since REG_SEQUENCE are kind of target opcode +# their definition may not have a type. +# +# CHECK: id: 0, class: dd +name: foo +legalized: true +tracksRegLiveness: true +registers: + - { id: 0, class: dd } +body: | + bb.0: + liveins: %d0, %d1 + + %0 = REG_SEQUENCE %d0, %subreg.dsub0, %d1, %subreg.dsub1 + +... -- 2.7.4