MIR Serialization: Serialize the bundled machine instructions.

llvm-svn: 245082
This commit is contained in:
Alex Lorenz 2015-08-14 18:57:24 +00:00
parent 2f079be789
commit f9a2b12361
9 changed files with 240 additions and 10 deletions

View File

@ -454,6 +454,10 @@ static MIToken::TokenKind symbolToken(char C) {
return MIToken::lparen;
case ')':
return MIToken::rparen;
case '{':
return MIToken::lbrace;
case '}':
return MIToken::rbrace;
case '+':
return MIToken::plus;
case '-':

View File

@ -41,6 +41,8 @@ struct MIToken {
exclaim,
lparen,
rparen,
lbrace,
rbrace,
plus,
minus,

View File

@ -351,6 +351,7 @@ bool MIParser::parseBasicBlockDefinitions(
return Token.isError();
if (Token.isNot(MIToken::MachineBasicBlockLabel))
return error("expected a basic block definition before instructions");
unsigned BraceDepth = 0;
do {
if (parseBasicBlockDefinition(MBBSlots))
return true;
@ -363,12 +364,23 @@ bool MIParser::parseBasicBlockDefinitions(
else if (Token.is(MIToken::MachineBasicBlockLabel))
return error("basic block definition should be located at the start of "
"the line");
if (Token.is(MIToken::Newline))
else if (consumeIfPresent(MIToken::Newline)) {
IsAfterNewline = true;
else
IsAfterNewline = false;
continue;
}
IsAfterNewline = false;
if (Token.is(MIToken::lbrace))
++BraceDepth;
if (Token.is(MIToken::rbrace)) {
if (!BraceDepth)
return error("extraneous closing brace ('}')");
--BraceDepth;
}
lex();
}
// Verify that we closed all of the '{' at the end of a file or a block.
if (!Token.isError() && BraceDepth)
return error("expected '}'"); // FIXME: Report a note that shows '{'.
} while (!Token.isErrorOrEOF());
return Token.isError();
}
@ -458,15 +470,40 @@ bool MIParser::parseBasicBlock(MachineBasicBlock &MBB) {
}
// Parse the instructions.
bool IsInBundle = false;
MachineInstr *PrevMI = nullptr;
while (true) {
if (Token.is(MIToken::MachineBasicBlockLabel) || Token.is(MIToken::Eof))
return false;
else if (consumeIfPresent(MIToken::Newline))
continue;
if (consumeIfPresent(MIToken::rbrace)) {
// The first parsing pass should verify that all closing '}' have an
// opening '{'.
assert(IsInBundle);
IsInBundle = false;
continue;
}
MachineInstr *MI = nullptr;
if (parse(MI))
return true;
MBB.insert(MBB.end(), MI);
if (IsInBundle) {
PrevMI->setFlag(MachineInstr::BundledSucc);
MI->setFlag(MachineInstr::BundledPred);
}
PrevMI = MI;
if (Token.is(MIToken::lbrace)) {
if (IsInBundle)
return error("nested instruction bundles are not allowed");
lex();
// This instruction is the start of the bundle.
MI->setFlag(MachineInstr::BundledSucc);
IsInBundle = true;
if (!Token.is(MIToken::Newline))
// The next instruction can be on the same line.
continue;
}
assert(Token.isNewlineOrEOF() && "MI is not fully parsed");
lex();
}
@ -516,16 +553,15 @@ bool MIParser::parse(MachineInstr *&MI) {
if (Token.isError() || parseInstruction(OpCode, Flags))
return true;
// TODO: Parse the bundle instruction flags.
// Parse the remaining machine operands.
while (!Token.isNewlineOrEOF() && Token.isNot(MIToken::kw_debug_location) &&
Token.isNot(MIToken::coloncolon)) {
Token.isNot(MIToken::coloncolon) && Token.isNot(MIToken::lbrace)) {
auto Loc = Token.location();
if (parseMachineOperandAndTargetFlags(MO))
return true;
Operands.push_back(MachineOperandWithLocation(MO, Loc, Token.location()));
if (Token.isNewlineOrEOF() || Token.is(MIToken::coloncolon))
if (Token.isNewlineOrEOF() || Token.is(MIToken::coloncolon) ||
Token.is(MIToken::lbrace))
break;
if (Token.isNot(MIToken::comma))
return error("expected ',' before the next machine operand");

View File

@ -439,11 +439,23 @@ void MIPrinter::print(const MachineBasicBlock &MBB) {
if (HasLineAttributes)
OS << "\n";
for (const auto &MI : MBB) {
OS.indent(2);
bool IsInBundle = false;
for (auto I = MBB.instr_begin(), E = MBB.instr_end(); I != E; ++I) {
const MachineInstr &MI = *I;
if (IsInBundle && !MI.isInsideBundle()) {
OS.indent(2) << "}\n";
IsInBundle = false;
}
OS.indent(IsInBundle ? 4 : 2);
print(MI);
if (!IsInBundle && MI.getFlag(MachineInstr::BundledSucc)) {
OS << " {";
IsInBundle = true;
}
OS << "\n";
}
if (IsInBundle)
OS.indent(2) << "}\n";
}
void MIPrinter::print(const MachineInstr &MI) {
@ -469,7 +481,6 @@ void MIPrinter::print(const MachineInstr &MI) {
if (MI.getFlag(MachineInstr::FrameSetup))
OS << "frame-setup ";
OS << TII->getName(MI.getOpcode());
// TODO: Print the bundling instruction flags.
if (I < E)
OS << ' ';

View File

@ -0,0 +1,75 @@
# RUN: llc -mtriple thumbv7-apple-ios -start-after block-placement -stop-after block-placement -o /dev/null %s | FileCheck %s
# This test ensures that the MIR parser parses the bundled machine instructions
# correctly.
--- |
define i32 @test1(i32 %a) {
entry:
%cmp = icmp sgt i32 %a, -78
%. = zext i1 %cmp to i32
ret i32 %.
}
define i32 @test2(i32 %a) {
entry:
%cmp = icmp sgt i32 %a, -78
%. = zext i1 %cmp to i32
ret i32 %.
}
...
---
name: test1
tracksRegLiveness: true
liveins:
- { reg: '%r0' }
body: |
bb.0.entry:
liveins: %r0
; CHECK-LABEL: name: test1
; CHECK: %r1 = t2MOVi 0, 14, _, _
; CHECK-NEXT: t2CMNri killed %r0, 78, 14, _, implicit-def %cpsr
; CHECK-NEXT: BUNDLE implicit-def dead %itstate, implicit-def %r1, implicit killed %cpsr {
; CHECK-NEXT: t2IT 12, 8, implicit-def %itstate
; CHECK-NEXT: %r1 = t2MOVi 1, 12, killed %cpsr, _
; CHECK-NEXT: }
; CHECK-NEXT: %r0 = tMOVr killed %r1, 14, _
; CHECK-NEXT: tBX_RET 14, _, implicit killed %r0
%r1 = t2MOVi 0, 14, _, _
t2CMNri killed %r0, 78, 14, _, implicit-def %cpsr
BUNDLE implicit-def dead %itstate, implicit-def %r1, implicit killed %cpsr {
t2IT 12, 8, implicit-def %itstate
%r1 = t2MOVi 1, 12, killed %cpsr, _
}
%r0 = tMOVr killed %r1, 14, _
tBX_RET 14, _, implicit killed %r0
...
---
name: test2
tracksRegLiveness: true
liveins:
- { reg: '%r0' }
body: |
bb.0.entry:
liveins: %r0
; Verify that the next machine instruction can be on the same line as
; '{' or '}'.
; CHECK-LABEL: name: test2
; CHECK: %r1 = t2MOVi 0, 14, _, _
; CHECK-NEXT: t2CMNri killed %r0, 78, 14, _, implicit-def %cpsr
; CHECK-NEXT: BUNDLE implicit-def dead %itstate, implicit-def %r1, implicit killed %cpsr {
; CHECK-NEXT: t2IT 12, 8, implicit-def %itstate
; CHECK-NEXT: %r1 = t2MOVi 1, 12, killed %cpsr, _
; CHECK-NEXT: }
; CHECK-NEXT: %r0 = tMOVr killed %r1, 14, _
; CHECK-NEXT: tBX_RET 14, _, implicit killed %r0
%r1 = t2MOVi 0, 14, _, _
t2CMNri killed %r0, 78, 14, _, implicit-def %cpsr
BUNDLE implicit-def dead %itstate, implicit-def %r1, implicit killed %cpsr { t2IT 12, 8, implicit-def %itstate
%r1 = t2MOVi 1, 12, killed %cpsr, _
} %r0 = tMOVr killed %r1, 14, _
tBX_RET 14, _, implicit killed %r0
...

View File

@ -0,0 +1,50 @@
# RUN: not llc -mtriple thumbv7-apple-ios -start-after block-placement -stop-after block-placement -o /dev/null %s 2>&1 | FileCheck %s
--- |
@G = external global i32
define i32 @test1(i32 %a) {
entry:
br label %foo
foo:
%cmp = icmp sgt i32 %a, -78
%. = zext i1 %cmp to i32
br i1 %cmp, label %if.then, label %if.else
if.then:
ret i32 %.
if.else:
%b = load i32, i32* @G
%c = add i32 %b, 1
br label %foo
}
...
---
name: test1
tracksRegLiveness: true
liveins:
- { reg: '%r0' }
body: |
bb.0.entry:
successors: %bb.1.foo
liveins: %r0
bb.1.foo:
successors: %bb.2.if.then, %bb.1.foo
liveins: %r0
t2CMNri %r0, 78, 14, _, implicit-def %cpsr
%r1 = t2MOVi 0, 14, _, _
BUNDLE implicit-def dead %itstate, implicit-def %r1, implicit killed %cpsr {
t2IT 12, 8, implicit-def %itstate
%r1 = t2MOVi 1, 12, killed %cpsr, _, implicit killed %itstate
t2CMNri %r0, 77, 14, _, implicit-def %cpsr
t2Bcc %bb.1.foo, 11, killed %cpsr
; CHECK: [[@LINE+1]]:3: expected '}'
bb.2.if.then:
liveins: %r1
%r0 = tMOVr killed %r1, 14, _
tBX_RET 14, _, implicit killed %r0
...

View File

@ -0,0 +1,20 @@
# RUN: not llc -mtriple thumbv7-apple-ios -start-after block-placement -stop-after block-placement -o /dev/null %s 2>&1 | FileCheck %s
--- |
define i32 @test1(i32 %a) {
entry:
ret i32 %a
}
...
---
name: test1
tracksRegLiveness: true
liveins:
- { reg: '%r0' }
body: |
bb.0.entry:
liveins: %r0
tBX_RET 14, _, implicit killed %r0
; CHECK: [[@LINE+1]]:5: extraneous closing brace ('}')
}
...

View File

@ -0,0 +1,2 @@
if not 'ARM' in config.root.targets:
config.unsupported = True

View File

@ -0,0 +1,30 @@
# RUN: not llc -mtriple thumbv7-apple-ios -start-after block-placement -stop-after block-placement -o /dev/null %s 2>&1 | FileCheck %s
--- |
define i32 @test1(i32 %a) {
entry:
%cmp = icmp sgt i32 %a, -78
%. = zext i1 %cmp to i32
ret i32 %.
}
...
---
name: test1
tracksRegLiveness: true
liveins:
- { reg: '%r0' }
body: |
bb.0.entry:
liveins: %r0
%r1 = t2MOVi 0, 14, _, _
t2CMNri killed %r0, 78, 14, _, implicit-def %cpsr
BUNDLE implicit-def dead %itstate, implicit-def %r1, implicit killed %cpsr {
t2IT 12, 8, implicit-def %itstate
%r1 = t2MOVi 1, 12, killed %cpsr, _
; CHECK: [[@LINE+1]]:14: nested instruction bundles are not allowed
BUNDLE {
}
}
%r0 = tMOVr killed %r1, 14, _
tBX_RET 14, _, implicit killed %r0
...