Skip to content

Commit

Permalink
MIR Serialization: Serialize the implicit register flag.
Browse files Browse the repository at this point in the history
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

llvm-svn: 241519
  • Loading branch information
hyp committed Jul 6, 2015
1 parent e869b75 commit cb268d4
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 23 deletions.
12 changes: 10 additions & 2 deletions llvm/lib/CodeGen/MIRParser/MILexer.cpp
Expand Up @@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//

#include "MILexer.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include <cctype>

Expand Down Expand Up @@ -64,15 +65,22 @@ static bool isIdentifierChar(char C) {
return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.';
}

static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
return StringSwitch<MIToken::TokenKind>(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;
auto Range = C;
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;
}

Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/CodeGen/MIRParser/MILexer.h
Expand Up @@ -36,6 +36,10 @@ struct MIToken {
equal,
underscore,

// Keywords
kw_implicit,
kw_implicit_define,

// Identifier tokens
Identifier,
NamedRegister,
Expand Down Expand Up @@ -69,6 +73,10 @@ struct MIToken {
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; }
Expand Down
51 changes: 33 additions & 18 deletions llvm/lib/CodeGen/MIRParser/MIParser.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -67,6 +68,7 @@ class MIParser {
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);
Expand Down Expand Up @@ -138,7 +140,7 @@ bool MIParser::parse(MachineInstr *&MI) {
// TODO: Allow parsing of multiple operands before '='
MachineOperand MO = MachineOperand::CreateImm(0);
SmallVector<MachineOperand, 8> Operands;
if (Token.isRegister()) {
if (Token.isRegister() || Token.isRegisterFlag()) {
if (parseRegisterOperand(MO, /*IsDef=*/true))
return true;
Operands.push_back(MO);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/CodeGen/MIRPrinter.cpp
Expand Up @@ -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;
Expand Down
22 changes: 22 additions & 0 deletions llvm/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'
...
41 changes: 41 additions & 0 deletions llvm/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'
...
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/MIR/X86/register-mask-operands.mir
Expand Up @@ -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'
...

0 comments on commit cb268d4

Please sign in to comment.