forked from OSchip/llvm-project
MIR Serialization: Serialize the bundled machine instructions.
llvm-svn: 245082
This commit is contained in:
parent
2f079be789
commit
f9a2b12361
|
@ -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 '-':
|
||||
|
|
|
@ -41,6 +41,8 @@ struct MIToken {
|
|||
exclaim,
|
||||
lparen,
|
||||
rparen,
|
||||
lbrace,
|
||||
rbrace,
|
||||
plus,
|
||||
minus,
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 << ' ';
|
||||
|
||||
|
|
|
@ -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
|
||||
...
|
|
@ -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
|
||||
...
|
|
@ -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 ('}')
|
||||
}
|
||||
...
|
|
@ -0,0 +1,2 @@
|
|||
if not 'ARM' in config.root.targets:
|
||||
config.unsupported = True
|
|
@ -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
|
||||
...
|
Loading…
Reference in New Issue