From 4ec0f60807eed1e1269c8ae54658dcc12eff9100 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 6 Jul 2015 23:07:26 +0000 Subject: [PATCH] MIR Serialization: Serialize the implicit register flag. This commit serializes the implicit flag for the register machine operands. It introduces two new keywords into the machine instruction syntax: 'implicit' and 'implicit-def'. The 'implicit' keyword is used for the implicit register operands, and the 'implicit-def' keyword is used for the register operands that have both the implicit and the define flags set. Reviewers: Duncan P. N. Exon Smith Differential Revision: http://reviews.llvm.org/D10709 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241519 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MIRParser/MILexer.cpp | 12 ++++- lib/CodeGen/MIRParser/MILexer.h | 8 +++ lib/CodeGen/MIRParser/MIParser.cpp | 51 ++++++++++++------- lib/CodeGen/MIRPrinter.cpp | 4 +- .../MIR/X86/expected-register-after-flags.mir | 22 ++++++++ .../MIR/X86/implicit-register-flag.mir | 41 +++++++++++++++ .../MIR/X86/register-mask-operands.mir | 4 +- 7 files changed, 119 insertions(+), 23 deletions(-) create mode 100644 test/CodeGen/MIR/X86/expected-register-after-flags.mir create mode 100644 test/CodeGen/MIR/X86/implicit-register-flag.mir diff --git a/lib/CodeGen/MIRParser/MILexer.cpp b/lib/CodeGen/MIRParser/MILexer.cpp index e9b3916a11f..856d908b778 100644 --- a/lib/CodeGen/MIRParser/MILexer.cpp +++ b/lib/CodeGen/MIRParser/MILexer.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "MILexer.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include @@ -64,6 +65,14 @@ static bool isIdentifierChar(char C) { return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.'; } +static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { + return StringSwitch(Identifier) + .Case("_", MIToken::underscore) + .Case("implicit", MIToken::kw_implicit) + .Case("implicit-def", MIToken::kw_implicit_define) + .Default(MIToken::Identifier); +} + static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) { if (!isalpha(C.peek()) && C.peek() != '_') return None; @@ -71,8 +80,7 @@ static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) { while (isIdentifierChar(C.peek())) C.advance(); auto Identifier = Range.upto(C); - Token = MIToken(Identifier == "_" ? MIToken::underscore : MIToken::Identifier, - Identifier); + Token = MIToken(getIdentifierKind(Identifier), Identifier); return C; } diff --git a/lib/CodeGen/MIRParser/MILexer.h b/lib/CodeGen/MIRParser/MILexer.h index c28935f3890..c66b2006e35 100644 --- a/lib/CodeGen/MIRParser/MILexer.h +++ b/lib/CodeGen/MIRParser/MILexer.h @@ -36,6 +36,10 @@ struct MIToken { equal, underscore, + // Keywords + kw_implicit, + kw_implicit_define, + // Identifier tokens Identifier, NamedRegister, @@ -69,6 +73,10 @@ public: return Kind == NamedRegister || Kind == underscore; } + bool isRegisterFlag() const { + return Kind == kw_implicit || Kind == kw_implicit_define; + } + bool is(TokenKind K) const { return Kind == K; } bool isNot(TokenKind K) const { return Kind != K; } diff --git a/lib/CodeGen/MIRParser/MIParser.cpp b/lib/CodeGen/MIRParser/MIParser.cpp index b618e53b8e4..a2ddd48ab16 100644 --- a/lib/CodeGen/MIRParser/MIParser.cpp +++ b/lib/CodeGen/MIRParser/MIParser.cpp @@ -18,6 +18,7 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/IR/Module.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/SourceMgr.h" @@ -67,6 +68,7 @@ public: bool parseMBB(MachineBasicBlock *&MBB); bool parseRegister(unsigned &Reg); + bool parseRegisterFlag(unsigned &Flags); bool parseRegisterOperand(MachineOperand &Dest, bool IsDef = false); bool parseImmediateOperand(MachineOperand &Dest); bool parseMBBReference(MachineBasicBlock *&MBB); @@ -138,7 +140,7 @@ bool MIParser::parse(MachineInstr *&MI) { // TODO: Allow parsing of multiple operands before '=' MachineOperand MO = MachineOperand::CreateImm(0); SmallVector Operands; - if (Token.isRegister()) { + if (Token.isRegister() || Token.isRegisterFlag()) { if (parseRegisterOperand(MO, /*IsDef=*/true)) return true; Operands.push_back(MO); @@ -167,21 +169,8 @@ bool MIParser::parse(MachineInstr *&MI) { const auto &MCID = MF.getSubtarget().getInstrInfo()->get(OpCode); - // Verify machine operands. - if (!MCID.isVariadic()) { - for (size_t I = 0, E = Operands.size(); I < E; ++I) { - if (I < MCID.getNumOperands()) - continue; - // Mark this register as implicit to prevent an assertion when it's added - // to an instruction. This is a temporary workaround until the implicit - // register flag can be parsed. - if (Operands[I].isReg()) - Operands[I].setImplicit(); - } - } - - // TODO: Determine the implicit behaviour when implicit register flags are - // parsed. + // TODO: Check for extraneous machine operands. + // TODO: Check that this instruction has the implicit register operands. MI = MF.CreateMachineInstr(MCID, DebugLoc(), /*NoImplicit=*/true); for (const auto &Operand : Operands) MI->addOperand(MF, Operand); @@ -229,14 +218,38 @@ bool MIParser::parseRegister(unsigned &Reg) { return false; } +bool MIParser::parseRegisterFlag(unsigned &Flags) { + switch (Token.kind()) { + case MIToken::kw_implicit: + Flags |= RegState::Implicit; + break; + case MIToken::kw_implicit_define: + Flags |= RegState::ImplicitDefine; + break; + // TODO: report an error when we specify the same flag more than once. + // TODO: parse the other register flags. + default: + llvm_unreachable("The current token should be a register flag"); + } + lex(); + return false; +} + bool MIParser::parseRegisterOperand(MachineOperand &Dest, bool IsDef) { unsigned Reg; - // TODO: Parse register flags. + unsigned Flags = IsDef ? RegState::Define : 0; + while (Token.isRegisterFlag()) { + if (parseRegisterFlag(Flags)) + return true; + } + if (!Token.isRegister()) + return error("expected a register after register flags"); if (parseRegister(Reg)) return true; lex(); // TODO: Parse subregister. - Dest = MachineOperand::CreateReg(Reg, IsDef); + Dest = MachineOperand::CreateReg(Reg, Flags & RegState::Define, + Flags & RegState::Implicit); return false; } @@ -318,6 +331,8 @@ bool MIParser::parseGlobalAddressOperand(MachineOperand &Dest) { bool MIParser::parseMachineOperand(MachineOperand &Dest) { switch (Token.kind()) { + case MIToken::kw_implicit: + case MIToken::kw_implicit_define: case MIToken::underscore: case MIToken::NamedRegister: return parseRegisterOperand(Dest); diff --git a/lib/CodeGen/MIRPrinter.cpp b/lib/CodeGen/MIRPrinter.cpp index 76cbe2994c9..5301df0fc4a 100644 --- a/lib/CodeGen/MIRPrinter.cpp +++ b/lib/CodeGen/MIRPrinter.cpp @@ -211,7 +211,9 @@ void MIPrinter::printMBBReference(const MachineBasicBlock &MBB) { void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { switch (Op.getType()) { case MachineOperand::MO_Register: - // TODO: Print register flags. + // TODO: Print the other register flags. + if (Op.isImplicit()) + OS << (Op.isDef() ? "implicit-def " : "implicit "); printReg(Op.getReg(), OS, TRI); // TODO: Print sub register. break; diff --git a/test/CodeGen/MIR/X86/expected-register-after-flags.mir b/test/CodeGen/MIR/X86/expected-register-after-flags.mir new file mode 100644 index 00000000000..111f5496a37 --- /dev/null +++ b/test/CodeGen/MIR/X86/expected-register-after-flags.mir @@ -0,0 +1,22 @@ +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# This test ensures that an error is reported when a register operand doesn't +# follow register flags. + +--- | + + define i32 @foo() { + entry: + ret i32 0 + } + +... +--- +name: foo +body: + - id: 0 + name: entry + instructions: + # CHECK: [[@LINE+1]]:37: expected a register after register flags + - '%eax = MOV32r0 implicit-def 2' + - 'RETQ %eax' +... diff --git a/test/CodeGen/MIR/X86/implicit-register-flag.mir b/test/CodeGen/MIR/X86/implicit-register-flag.mir new file mode 100644 index 00000000000..9c6882d27bd --- /dev/null +++ b/test/CodeGen/MIR/X86/implicit-register-flag.mir @@ -0,0 +1,41 @@ +# RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s +# This test ensures that the MIR parser parses the 'implicit' and 'implicit-def' +# register flags correctly. + +--- | + + define i32 @foo(i32 %a) { + entry: + %0 = icmp sle i32 %a, 10 + br i1 %0, label %less, label %exit + + less: + ret i32 0 + + exit: + ret i32 %a + } + +... +--- +name: foo +body: + - id: 0 + name: entry + instructions: + # CHECK: - 'CMP32ri8 %edi, 10, implicit-def %eflags' + # CHECK-NEXT: - 'JG_1 %bb.2.exit, implicit %eflags' + - 'CMP32ri8 %edi, 10, implicit-def %eflags' + - 'JG_1 %bb.2.exit, implicit %eflags' + - id: 1 + name: less + instructions: + # CHECK: - '%eax = MOV32r0 implicit-def %eflags' + - '%eax = MOV32r0 implicit-def %eflags' + - 'RETQ %eax' + - id: 2 + name: exit + instructions: + - '%eax = COPY %edi' + - 'RETQ %eax' +... diff --git a/test/CodeGen/MIR/X86/register-mask-operands.mir b/test/CodeGen/MIR/X86/register-mask-operands.mir index ecaedeae4db..719bd9c905d 100644 --- a/test/CodeGen/MIR/X86/register-mask-operands.mir +++ b/test/CodeGen/MIR/X86/register-mask-operands.mir @@ -35,9 +35,9 @@ body: name: entry instructions: # CHECK: - 'PUSH64r %rax - # CHECK-NEXT: - 'CALL64pcrel32 @compute, csr_64, %rsp, %edi, %rsp, %eax' + # CHECK-NEXT: - 'CALL64pcrel32 @compute, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp, implicit-def %eax' - 'PUSH64r %rax' - - 'CALL64pcrel32 @compute, csr_64, %rsp, %edi, %rsp, %eax' + - 'CALL64pcrel32 @compute, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp, implicit-def %eax' - '%rdx = POP64r' - 'RETQ %eax' ... -- 2.34.1