diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 07b57713062..0b45507893a 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -1272,6 +1272,23 @@ public: return None; } + /// Decompose the machine operand's target flags into two values - the direct + /// target flag value and any of bit flags that are applied. + virtual std::pair + decomposeMachineOperandsTargetFlags(unsigned /*TF*/) const { + return std::make_pair(0u, 0u); + } + + /// Return an array that contains the direct target flag values and their + /// names. + /// + /// MIR Serialization is able to serialize only the target flags that are + /// defined by this method. + virtual ArrayRef> + getSerializableDirectMachineOperandTargetFlags() const { + return None; + } + private: unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode; }; diff --git a/lib/CodeGen/MIRParser/MILexer.cpp b/lib/CodeGen/MIRParser/MILexer.cpp index fece542d60e..892a15f9273 100644 --- a/lib/CodeGen/MIRParser/MILexer.cpp +++ b/lib/CodeGen/MIRParser/MILexer.cpp @@ -173,6 +173,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { .Case("x86_fp80", MIToken::kw_x86_fp80) .Case("fp128", MIToken::kw_fp128) .Case("ppc_fp128", MIToken::kw_ppc_fp128) + .Case("target-flags", MIToken::kw_target_flags) .Case("volatile", MIToken::kw_volatile) .Default(MIToken::Identifier); } diff --git a/lib/CodeGen/MIRParser/MILexer.h b/lib/CodeGen/MIRParser/MILexer.h index 064f68e2d5d..407a85a32a1 100644 --- a/lib/CodeGen/MIRParser/MILexer.h +++ b/lib/CodeGen/MIRParser/MILexer.h @@ -65,6 +65,7 @@ struct MIToken { kw_x86_fp80, kw_fp128, kw_ppc_fp128, + kw_target_flags, kw_volatile, // Identifier tokens diff --git a/lib/CodeGen/MIRParser/MIParser.cpp b/lib/CodeGen/MIRParser/MIParser.cpp index 1a47c5865bb..1596889b065 100644 --- a/lib/CodeGen/MIRParser/MIParser.cpp +++ b/lib/CodeGen/MIRParser/MIParser.cpp @@ -70,6 +70,8 @@ class MIParser { DenseMap Slots2BasicBlocks; /// Maps from target index names to target indices. StringMap Names2TargetIndices; + /// Maps from direct target flag names to the direct target flag values. + StringMap Names2DirectTargetFlags; public: MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error, @@ -120,6 +122,7 @@ public: bool parseBlockAddressOperand(MachineOperand &Dest); bool parseTargetIndexOperand(MachineOperand &Dest); bool parseMachineOperand(MachineOperand &Dest); + bool parseMachineOperandAndTargetFlags(MachineOperand &Dest); bool parseOperandsOffset(MachineOperand &Op); bool parseIRValue(Value *&V); bool parseMemoryOperandFlag(unsigned &Flags); @@ -181,6 +184,14 @@ private: /// /// Return true if the name isn't a name of a target index. bool getTargetIndex(StringRef Name, int &Index); + + void initNames2DirectTargetFlags(); + + /// Try to convert a name of a direct target flag to the corresponding + /// target flag. + /// + /// Return true if the name isn't a name of a direct flag. + bool getDirectTargetFlag(StringRef Name, unsigned &Flag); }; } // end anonymous namespace @@ -258,7 +269,7 @@ bool MIParser::parse(MachineInstr *&MI) { while (Token.isNot(MIToken::Eof) && Token.isNot(MIToken::kw_debug_location) && Token.isNot(MIToken::coloncolon)) { auto Loc = Token.location(); - if (parseMachineOperand(MO)) + if (parseMachineOperandAndTargetFlags(MO)) return true; Operands.push_back(MachineOperandWithLocation(MO, Loc, Token.location())); if (Token.is(MIToken::Eof) || Token.is(MIToken::coloncolon)) @@ -696,7 +707,6 @@ bool MIParser::parseGlobalAddressOperand(MachineOperand &Dest) { return true; lex(); Dest = MachineOperand::CreateGA(GV, /*Offset=*/0); - // TODO: Parse the target flags. if (parseOperandsOffset(Dest)) return true; return false; @@ -711,7 +721,6 @@ bool MIParser::parseConstantPoolIndexOperand(MachineOperand &Dest) { if (ConstantInfo == PFS.ConstantPoolSlots.end()) return error("use of undefined constant '%const." + Twine(ID) + "'"); lex(); - // TODO: Parse the target flags. Dest = MachineOperand::CreateCPI(ID, /*Offset=*/0); if (parseOperandsOffset(Dest)) return true; @@ -727,7 +736,6 @@ bool MIParser::parseJumpTableIndexOperand(MachineOperand &Dest) { if (JumpTableEntryInfo == PFS.JumpTableSlots.end()) return error("use of undefined jump table '%jump-table." + Twine(ID) + "'"); lex(); - // TODO: Parse target flags. Dest = MachineOperand::CreateJTI(JumpTableEntryInfo->second); return false; } @@ -736,7 +744,6 @@ bool MIParser::parseExternalSymbolOperand(MachineOperand &Dest) { assert(Token.is(MIToken::ExternalSymbol)); const char *Symbol = MF.createExternalSymbolName(Token.stringValue()); lex(); - // TODO: Parse the target flags. Dest = MachineOperand::CreateES(Symbol); if (parseOperandsOffset(Dest)) return true; @@ -889,7 +896,6 @@ bool MIParser::parseBlockAddressOperand(MachineOperand &Dest) { lex(); if (expectAndConsume(MIToken::rparen)) return true; - // TODO: parse the target flags. Dest = MachineOperand::CreateBA(BlockAddress::get(F, BB), /*Offset=*/0); if (parseOperandsOffset(Dest)) return true; @@ -909,7 +915,6 @@ bool MIParser::parseTargetIndexOperand(MachineOperand &Dest) { lex(); if (expectAndConsume(MIToken::rparen)) return true; - // TODO: Parse the target flags. Dest = MachineOperand::CreateTargetIndex(unsigned(Index), /*Offset=*/0); if (parseOperandsOffset(Dest)) return true; @@ -982,6 +987,35 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest) { return false; } +bool MIParser::parseMachineOperandAndTargetFlags(MachineOperand &Dest) { + unsigned TF = 0; + bool HasTargetFlags = false; + if (Token.is(MIToken::kw_target_flags)) { + HasTargetFlags = true; + lex(); + if (expectAndConsume(MIToken::lparen)) + return true; + if (Token.isNot(MIToken::Identifier)) + return error("expected the name of the target flag"); + if (getDirectTargetFlag(Token.stringValue(), TF)) + return error("use of undefined target flag '" + Token.stringValue() + + "'"); + lex(); + // TODO: Parse target's bit target flags. + if (expectAndConsume(MIToken::rparen)) + return true; + } + auto Loc = Token.location(); + if (parseMachineOperand(Dest)) + return true; + if (!HasTargetFlags) + return false; + if (Dest.isReg()) + return error(Loc, "register operands can't have target flags"); + Dest.setTargetFlags(TF); + return false; +} + bool MIParser::parseOperandsOffset(MachineOperand &Op) { if (Token.isNot(MIToken::plus) && Token.isNot(MIToken::minus)) return false; @@ -1209,6 +1243,26 @@ bool MIParser::getTargetIndex(StringRef Name, int &Index) { return false; } +void MIParser::initNames2DirectTargetFlags() { + if (!Names2DirectTargetFlags.empty()) + return; + const auto *TII = MF.getSubtarget().getInstrInfo(); + assert(TII && "Expected target instruction info"); + auto Flags = TII->getSerializableDirectMachineOperandTargetFlags(); + for (const auto &I : Flags) + Names2DirectTargetFlags.insert( + std::make_pair(StringRef(I.second), I.first)); +} + +bool MIParser::getDirectTargetFlag(StringRef Name, unsigned &Flag) { + initNames2DirectTargetFlags(); + auto FlagInfo = Names2DirectTargetFlags.find(Name); + if (FlagInfo == Names2DirectTargetFlags.end()) + return true; + Flag = FlagInfo->second; + return false; +} + bool llvm::parseMachineInstr(MachineInstr *&MI, SourceMgr &SM, MachineFunction &MF, StringRef Src, const PerFunctionMIParsingState &PFS, diff --git a/lib/CodeGen/MIRPrinter.cpp b/lib/CodeGen/MIRPrinter.cpp index 9af64823d04..a166dd58fe4 100644 --- a/lib/CodeGen/MIRPrinter.cpp +++ b/lib/CodeGen/MIRPrinter.cpp @@ -118,6 +118,7 @@ public: void printIRValueReference(const Value &V); void printStackObjectReference(int FrameIndex); void printOffset(int64_t Offset); + void printTargetFlags(const MachineOperand &Op); void print(const MachineOperand &Op, const TargetRegisterInfo *TRI); void print(const MachineMemOperand &Op); @@ -516,6 +517,32 @@ void MIPrinter::printOffset(int64_t Offset) { OS << " + " << Offset; } +static const char *getTargetFlagName(const TargetInstrInfo *TII, unsigned TF) { + auto Flags = TII->getSerializableDirectMachineOperandTargetFlags(); + for (const auto &I : Flags) { + if (I.first == TF) { + return I.second; + } + } + return nullptr; +} + +void MIPrinter::printTargetFlags(const MachineOperand &Op) { + if (!Op.getTargetFlags()) + return; + const auto *TII = + Op.getParent()->getParent()->getParent()->getSubtarget().getInstrInfo(); + assert(TII && "expected instruction info"); + auto Flags = TII->decomposeMachineOperandsTargetFlags(Op.getTargetFlags()); + OS << "target-flags("; + if (const auto *Name = getTargetFlagName(TII, Flags.first)) + OS << Name; + else + OS << ""; + // TODO: Print the target's bit flags. + OS << ") "; +} + static const char *getTargetIndexName(const MachineFunction &MF, int Index) { const auto *TII = MF.getSubtarget().getInstrInfo(); assert(TII && "expected instruction info"); @@ -529,6 +556,7 @@ static const char *getTargetIndexName(const MachineFunction &MF, int Index) { } void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { + printTargetFlags(Op); switch (Op.getType()) { case MachineOperand::MO_Register: // TODO: Print the other register flags. @@ -567,7 +595,6 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { case MachineOperand::MO_ConstantPoolIndex: OS << "%const." << Op.getIndex(); printOffset(Op.getOffset()); - // TODO: Print the target flags. break; case MachineOperand::MO_TargetIndex: { OS << "target-index("; @@ -578,23 +605,19 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { OS << ""; OS << ')'; printOffset(Op.getOffset()); - // TODO: Print the target flags. break; } case MachineOperand::MO_JumpTableIndex: OS << "%jump-table." << Op.getIndex(); - // TODO: Print target flags. break; case MachineOperand::MO_ExternalSymbol: OS << '$'; printLLVMNameWithoutPrefix(OS, Op.getSymbolName()); printOffset(Op.getOffset()); - // TODO: Print the target flags. break; case MachineOperand::MO_GlobalAddress: Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST); printOffset(Op.getOffset()); - // TODO: Print the target flags. break; case MachineOperand::MO_BlockAddress: OS << "blockaddress("; @@ -604,7 +627,6 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { printIRBlockReference(*Op.getBlockAddress()->getBasicBlock()); OS << ')'; printOffset(Op.getOffset()); - // TODO: Print the target flags. break; case MachineOperand::MO_RegisterMask: { auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask()); diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 810fdb77a0d..01d59f9a8b4 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -6581,6 +6581,41 @@ void X86InstrInfo::genAlternativeCodeSequence( return; } +std::pair +X86InstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { + return std::make_pair(TF, 0u); +} + +ArrayRef> +X86InstrInfo::getSerializableDirectMachineOperandTargetFlags() const { + using namespace X86II; + static std::pair TargetFlags[] = { + {MO_GOT_ABSOLUTE_ADDRESS, "x86-got-absolute-address"}, + {MO_PIC_BASE_OFFSET, "x86-pic-base-offset"}, + {MO_GOT, "x86-got"}, + {MO_GOTOFF, "x86-gotoff"}, + {MO_GOTPCREL, "x86-gotpcrel"}, + {MO_PLT, "x86-plt"}, + {MO_TLSGD, "x86-tlsgd"}, + {MO_TLSLD, "x86-tlsld"}, + {MO_TLSLDM, "x86-tlsldm"}, + {MO_GOTTPOFF, "x86-gottpoff"}, + {MO_INDNTPOFF, "x86-indntpoff"}, + {MO_TPOFF, "x86-tpoff"}, + {MO_DTPOFF, "x86-dtpoff"}, + {MO_NTPOFF, "x86-ntpoff"}, + {MO_GOTNTPOFF, "x86-gotntpoff"}, + {MO_DLLIMPORT, "x86-dllimport"}, + {MO_DARWIN_STUB, "x86-darwin-stub"}, + {MO_DARWIN_NONLAZY, "x86-darwin-nonlazy"}, + {MO_DARWIN_NONLAZY_PIC_BASE, "x86-darwin-nonlazy-pic-base"}, + {MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE, "x86-darwin-hidden-nonlazy-pic-base"}, + {MO_TLVP, "x86-tlvp"}, + {MO_TLVP_PIC_BASE, "x86-tlvp-pic-base"}, + {MO_SECREL, "x86-secrel"}}; + return makeArrayRef(TargetFlags); +} + namespace { /// Create Global Base Reg pass. This initializes the PIC /// global base register for x86-32. diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index 0ef4b088eac..71a48866df4 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -495,6 +495,12 @@ public: unsigned &FoldAsLoadDefReg, MachineInstr *&DefMI) const override; + std::pair + decomposeMachineOperandsTargetFlags(unsigned TF) const override; + + ArrayRef> + getSerializableDirectMachineOperandTargetFlags() const override; + private: MachineInstr * convertToThreeAddressWithLEA(unsigned MIOpc, MachineFunction::iterator &MFI, diff --git a/test/CodeGen/MIR/X86/expected-target-flag-name.mir b/test/CodeGen/MIR/X86/expected-target-flag-name.mir new file mode 100644 index 00000000000..a885a566b67 --- /dev/null +++ b/test/CodeGen/MIR/X86/expected-target-flag-name.mir @@ -0,0 +1,26 @@ +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + @G = external global i32 + + define i32 @inc() { + entry: + %a = load i32, i32* @G + %b = add i32 %a, 1 + ret i32 %b + } + +... +--- +name: inc +body: + - id: 0 + name: entry + instructions: +# CHECK: [[@LINE+1]]:51: expected the name of the target flag + - '%rax = MOV64rm %rip, 1, _, target-flags( ) @G, _' + - '%eax = MOV32rm killed %rax, 1, _, 0, _' + - '%eax = INC32r killed %eax, implicit-def dead %eflags' + - 'RETQ %eax' +... diff --git a/test/CodeGen/MIR/X86/global-value-operands.mir b/test/CodeGen/MIR/X86/global-value-operands.mir index 251d1ff3617..f29ed358a71 100644 --- a/test/CodeGen/MIR/X86/global-value-operands.mir +++ b/test/CodeGen/MIR/X86/global-value-operands.mir @@ -51,6 +51,13 @@ ret i32 %b } + define i32 @tf() { + entry: + %a = load i32, i32* @G + %b = add i32 %a, 1 + ret i32 %b + } + ... --- # CHECK: name: inc @@ -130,3 +137,16 @@ body: - 'MOV32mr killed %rcx, 1, _, 0, _, %eax' - 'RETQ %eax' ... +--- +# CHECK: name: tf +name: tf +body: + - id: 0 + name: entry + instructions: +# CHECK: %rax = MOV64rm %rip, 1, _, target-flags(x86-gotpcrel) @G, _ + - '%rax = MOV64rm %rip, 1, _, target-flags(x86-gotpcrel) @G, _' + - '%eax = MOV32rm %rax, 1, _, 0, _' + - '%eax = INC32r %eax, implicit-def %eflags' + - 'RETQ %eax' +... diff --git a/test/CodeGen/MIR/X86/invalid-target-flag-name.mir b/test/CodeGen/MIR/X86/invalid-target-flag-name.mir new file mode 100644 index 00000000000..1e1fc7b302d --- /dev/null +++ b/test/CodeGen/MIR/X86/invalid-target-flag-name.mir @@ -0,0 +1,26 @@ +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + @G = external global i32 + + define i32 @inc() { + entry: + %a = load i32, i32* @G + %b = add i32 %a, 1 + ret i32 %b + } + +... +--- +name: inc +body: + - id: 0 + name: entry + instructions: +# CHECK: [[@LINE+1]]:50: use of undefined target flag 'x86-test' + - '%rax = MOV64rm %rip, 1, _, target-flags(x86-test) @G, _' + - '%eax = MOV32rm killed %rax, 1, _, 0, _' + - '%eax = INC32r killed %eax, implicit-def dead %eflags' + - 'RETQ %eax' +... diff --git a/test/CodeGen/MIR/X86/register-operands-target-flag-error.mir b/test/CodeGen/MIR/X86/register-operands-target-flag-error.mir new file mode 100644 index 00000000000..219a0d32ae9 --- /dev/null +++ b/test/CodeGen/MIR/X86/register-operands-target-flag-error.mir @@ -0,0 +1,26 @@ +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + @G = external global i32 + + define i32 @inc() { + entry: + %a = load i32, i32* @G + %b = add i32 %a, 1 + ret i32 %b + } + +... +--- +name: inc +body: + - id: 0 + name: entry + instructions: +# CHECK: [[@LINE+1]]:47: register operands can't have target flags + - '%rax = MOV64rm target-flags(x86-got) %rip, 1, _, @G, _' + - '%eax = MOV32rm killed %rax, 1, _, 0, _' + - '%eax = INC32r killed %eax, implicit-def dead %eflags' + - 'RETQ %eax' +...