From 6748abe24d39eb31254dafbba4f0630a908514ad Mon Sep 17 00:00:00 2001 From: Geoff Berry Date: Thu, 13 Jul 2017 02:28:54 +0000 Subject: [PATCH] [MIR] Add support for printing and parsing target MMO flags Summary: Add target hooks for printing and parsing target MMO flags. Targets may override getSerializableMachineMemOperandTargetFlags() to return a mapping from string to flag value for target MMO values that should be serialized/parsed in MIR output. Add implementation of this hook for AArch64 SuppressPair MMO flag. Reviewers: bogner, hfinkel, qcolombet, MatzeB Subscribers: mcrosier, javed.absar, llvm-commits Differential Revision: https://reviews.llvm.org/D34962 llvm-svn: 307877 --- llvm/include/llvm/CodeGen/MachineMemOperand.h | 3 ++ llvm/include/llvm/Target/TargetInstrInfo.h | 10 +++++ llvm/lib/CodeGen/MIRParser/MILexer.h | 3 +- llvm/lib/CodeGen/MIRParser/MIParser.cpp | 40 ++++++++++++++++++- llvm/lib/CodeGen/MIRPrinter.cpp | 29 ++++++++++++-- llvm/lib/CodeGen/MachineInstr.cpp | 6 +++ llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 7 ++++ llvm/lib/Target/AArch64/AArch64InstrInfo.h | 2 + .../AArch64/invalid-target-memoperands.mir | 19 +++++++++ .../MIR/AArch64/target-memoperands.mir | 22 ++++++++++ 10 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 llvm/test/CodeGen/MIR/AArch64/invalid-target-memoperands.mir create mode 100644 llvm/test/CodeGen/MIR/AArch64/target-memoperands.mir diff --git a/llvm/include/llvm/CodeGen/MachineMemOperand.h b/llvm/include/llvm/CodeGen/MachineMemOperand.h index a2b13d9369c4c..a9de0db05d72c 100644 --- a/llvm/include/llvm/CodeGen/MachineMemOperand.h +++ b/llvm/include/llvm/CodeGen/MachineMemOperand.h @@ -114,6 +114,9 @@ class MachineMemOperand { MOInvariant = 1u << 5, // Reserved for use by target-specific passes. + // Targets may override getSerializableMachineMemOperandTargetFlags() to + // enable MIR serialization/parsing of these flags. If more of these flags + // are added, the MIR printing/parsing code will need to be updated as well. MOTargetFlag1 = 1u << 6, MOTargetFlag2 = 1u << 7, MOTargetFlag3 = 1u << 8, diff --git a/llvm/include/llvm/Target/TargetInstrInfo.h b/llvm/include/llvm/Target/TargetInstrInfo.h index 2fc3ec996e7f6..1843a2eed9bff 100644 --- a/llvm/include/llvm/Target/TargetInstrInfo.h +++ b/llvm/include/llvm/Target/TargetInstrInfo.h @@ -1545,6 +1545,16 @@ class TargetInstrInfo : public MCInstrInfo { return None; } + /// Return an array that contains the MMO target flag values and their + /// names. + /// + /// MIR Serialization is able to serialize only the MMO target flags that are + /// defined by this method. + virtual ArrayRef> + getSerializableMachineMemOperandTargetFlags() const { + return None; + } + /// Determines whether \p Inst is a tail call instruction. Override this /// method on targets that do not properly set MCID::Return and MCID::Call on /// tail call instructions." diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h index ed41e07e3c1c8..08b82e59c4fc1 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -169,7 +169,8 @@ struct MIToken { bool isMemoryOperandFlag() const { return Kind == kw_volatile || Kind == kw_non_temporal || - Kind == kw_dereferenceable || Kind == kw_invariant; + Kind == kw_dereferenceable || Kind == kw_invariant || + Kind == StringConstant; } bool is(TokenKind K) const { return Kind == K; } diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 70dca2777336c..c68d87b15a317 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -141,6 +141,8 @@ class MIParser { StringMap Names2DirectTargetFlags; /// Maps from direct target flag names to the bitmask target flag values. StringMap Names2BitmaskTargetFlags; + /// Maps from MMO target flag names to MMO target flag values. + StringMap Names2MMOTargetFlags; public: MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error, @@ -320,6 +322,14 @@ class MIParser { /// Return true if the name isn't a name of a bitmask target flag. bool getBitmaskTargetFlag(StringRef Name, unsigned &Flag); + void initNames2MMOTargetFlags(); + + /// Try to convert a name of a MachineMemOperand target flag to the + /// corresponding target flag. + /// + /// Return true if the name isn't a name of a target MMO flag. + bool getMMOTargetFlag(StringRef Name, MachineMemOperand::Flags &Flag); + /// parseStringConstant /// ::= StringConstant bool parseStringConstant(std::string &Result); @@ -2039,7 +2049,14 @@ bool MIParser::parseMemoryOperandFlag(MachineMemOperand::Flags &Flags) { case MIToken::kw_invariant: Flags |= MachineMemOperand::MOInvariant; break; - // TODO: parse the target specific memory operand flags. + case MIToken::StringConstant: { + MachineMemOperand::Flags TF; + if (getMMOTargetFlag(Token.stringValue(), TF)) + return error("use of undefined target MMO flag '" + Token.stringValue() + + "'"); + Flags |= TF; + break; + } default: llvm_unreachable("The current token should be a memory operand flag"); } @@ -2480,6 +2497,27 @@ bool MIParser::getBitmaskTargetFlag(StringRef Name, unsigned &Flag) { return false; } +void MIParser::initNames2MMOTargetFlags() { + if (!Names2MMOTargetFlags.empty()) + return; + const auto *TII = MF.getSubtarget().getInstrInfo(); + assert(TII && "Expected target instruction info"); + auto Flags = TII->getSerializableMachineMemOperandTargetFlags(); + for (const auto &I : Flags) + Names2MMOTargetFlags.insert( + std::make_pair(StringRef(I.second), I.first)); +} + +bool MIParser::getMMOTargetFlag(StringRef Name, + MachineMemOperand::Flags &Flag) { + initNames2MMOTargetFlags(); + auto FlagInfo = Names2MMOTargetFlags.find(Name); + if (FlagInfo == Names2MMOTargetFlags.end()) + return true; + Flag = FlagInfo->second; + return false; +} + bool MIParser::parseStringConstant(std::string &Result) { if (Token.isNot(MIToken::StringConstant)) return error("expected string constant"); diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index 4cc61420ab47a..ddeacf1d1bfb1 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -165,7 +165,8 @@ class MIPrinter { void print(const MachineOperand &Op, const TargetRegisterInfo *TRI, unsigned I, bool ShouldPrintRegisterTies, LLT TypeToPrint, bool IsDef = false); - void print(const LLVMContext &Context, const MachineMemOperand &Op); + void print(const LLVMContext &Context, const TargetInstrInfo &TII, + const MachineMemOperand &Op); void printSyncScope(const LLVMContext &Context, SyncScope::ID SSID); void print(const MCCFIInstruction &CFI, const TargetRegisterInfo *TRI); @@ -740,7 +741,7 @@ void MIPrinter::print(const MachineInstr &MI) { for (const auto *Op : MI.memoperands()) { if (NeedComma) OS << ", "; - print(Context, *Op); + print(Context, *TII, *Op); NeedComma = true; } } @@ -1036,9 +1037,20 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI, } } -void MIPrinter::print(const LLVMContext &Context, const MachineMemOperand &Op) { +static const char *getTargetMMOFlagName(const TargetInstrInfo &TII, + unsigned TMMOFlag) { + auto Flags = TII.getSerializableMachineMemOperandTargetFlags(); + for (const auto &I : Flags) { + if (I.first == TMMOFlag) { + return I.second; + } + } + return nullptr; +} + +void MIPrinter::print(const LLVMContext &Context, const TargetInstrInfo &TII, + const MachineMemOperand &Op) { OS << '('; - // TODO: Print operand's target specific flags. if (Op.isVolatile()) OS << "volatile "; if (Op.isNonTemporal()) @@ -1047,6 +1059,15 @@ void MIPrinter::print(const LLVMContext &Context, const MachineMemOperand &Op) { OS << "dereferenceable "; if (Op.isInvariant()) OS << "invariant "; + if (Op.getFlags() & MachineMemOperand::MOTargetFlag1) + OS << '"' << getTargetMMOFlagName(TII, MachineMemOperand::MOTargetFlag1) + << "\" "; + if (Op.getFlags() & MachineMemOperand::MOTargetFlag2) + OS << '"' << getTargetMMOFlagName(TII, MachineMemOperand::MOTargetFlag2) + << "\" "; + if (Op.getFlags() & MachineMemOperand::MOTargetFlag3) + OS << '"' << getTargetMMOFlagName(TII, MachineMemOperand::MOTargetFlag3) + << "\" "; if (Op.isLoad()) OS << "load "; else { diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index ca39db49bdb40..afea5575a3ae5 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -752,6 +752,12 @@ void MachineMemOperand::print(raw_ostream &OS, ModuleSlotTracker &MST) const { OS << "(dereferenceable)"; if (isInvariant()) OS << "(invariant)"; + if (getFlags() & MOTargetFlag1) + OS << "(flag1)"; + if (getFlags() & MOTargetFlag2) + OS << "(flag2)"; + if (getFlags() & MOTargetFlag3) + OS << "(flag3)"; } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index e4626b446b91f..dba3e4bdf82f1 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -4430,6 +4430,13 @@ AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const { return makeArrayRef(TargetFlags); } +ArrayRef> +AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags() const { + static const std::pair TargetFlags[] = + {{MOSuppressPair, "aarch64-suppress-pair"}}; + return makeArrayRef(TargetFlags); +} + unsigned AArch64InstrInfo::getOutliningBenefit(size_t SequenceSize, size_t Occurrences, bool CanBeTailCall) const { diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h index 29798196e46d1..0809ede4df2a5 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h @@ -289,6 +289,8 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo { getSerializableDirectMachineOperandTargetFlags() const override; ArrayRef> getSerializableBitmaskMachineOperandTargetFlags() const override; + ArrayRef> + getSerializableMachineMemOperandTargetFlags() const override; bool isFunctionSafeToOutlineFrom(MachineFunction &MF) const override; unsigned getOutliningBenefit(size_t SequenceSize, size_t Occurrences, diff --git a/llvm/test/CodeGen/MIR/AArch64/invalid-target-memoperands.mir b/llvm/test/CodeGen/MIR/AArch64/invalid-target-memoperands.mir new file mode 100644 index 0000000000000..731d7165b9df9 --- /dev/null +++ b/llvm/test/CodeGen/MIR/AArch64/invalid-target-memoperands.mir @@ -0,0 +1,19 @@ +# RUN: not llc -mtriple=aarch64-none-linux-gnu -run-pass none -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + define void @target_memoperands_error() { + ret void + } + +... +--- +name: target_memoperands_error +body: | + bb.0: + + %0:_(p0) = COPY %x0 + ; CHECK: [[@LINE+1]]:35: use of undefined target MMO flag 'aarch64-invalid' + %1:_(s64) = G_LOAD %0(p0) :: ("aarch64-invalid" load 8) + RET_ReallyLR +... diff --git a/llvm/test/CodeGen/MIR/AArch64/target-memoperands.mir b/llvm/test/CodeGen/MIR/AArch64/target-memoperands.mir new file mode 100644 index 0000000000000..f853b551e0986 --- /dev/null +++ b/llvm/test/CodeGen/MIR/AArch64/target-memoperands.mir @@ -0,0 +1,22 @@ +# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass none -o - %s | FileCheck %s + +--- | + + define void @target_memoperands() { + ret void + } + +... +--- +# CHECK-LABEL: name: target_memoperands +# CHECK: %1(s64) = G_LOAD %0(p0) :: ("aarch64-suppress-pair" load 8) +# CHECK: G_STORE %1(s64), %0(p0) :: ("aarch64-suppress-pair" store 8) +name: target_memoperands +body: | + bb.0: + + %0:_(p0) = COPY %x0 + %1:_(s64) = G_LOAD %0(p0) :: ("aarch64-suppress-pair" load 8) + G_STORE %1(s64), %0(p0) :: ("aarch64-suppress-pair" store 8) + RET_ReallyLR +...