llvm.org GIT mirror llvm / 4ec0f60
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 Alex Lorenz 5 years ago
7 changed file(s) with 119 addition(s) and 23 deletion(s). Raw diff Collapse all Expand all
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "MILexer.h"
14 #include "llvm/ADT/StringSwitch.h"
1415 #include "llvm/ADT/Twine.h"
1516 #include
1617
6364 return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.';
6465 }
6566
67 static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
68 return StringSwitch(Identifier)
69 .Case("_", MIToken::underscore)
70 .Case("implicit", MIToken::kw_implicit)
71 .Case("implicit-def", MIToken::kw_implicit_define)
72 .Default(MIToken::Identifier);
73 }
74
6675 static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
6776 if (!isalpha(C.peek()) && C.peek() != '_')
6877 return None;
7079 while (isIdentifierChar(C.peek()))
7180 C.advance();
7281 auto Identifier = Range.upto(C);
73 Token = MIToken(Identifier == "_" ? MIToken::underscore : MIToken::Identifier,
74 Identifier);
82 Token = MIToken(getIdentifierKind(Identifier), Identifier);
7583 return C;
7684 }
7785
3535 equal,
3636 underscore,
3737
38 // Keywords
39 kw_implicit,
40 kw_implicit_define,
41
3842 // Identifier tokens
3943 Identifier,
4044 NamedRegister,
6872 return Kind == NamedRegister || Kind == underscore;
6973 }
7074
75 bool isRegisterFlag() const {
76 return Kind == kw_implicit || Kind == kw_implicit_define;
77 }
78
7179 bool is(TokenKind K) const { return Kind == K; }
7280
7381 bool isNot(TokenKind K) const { return Kind != K; }
1717 #include "llvm/CodeGen/MachineBasicBlock.h"
1818 #include "llvm/CodeGen/MachineFunction.h"
1919 #include "llvm/CodeGen/MachineInstr.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
2021 #include "llvm/IR/Module.h"
2122 #include "llvm/Support/raw_ostream.h"
2223 #include "llvm/Support/SourceMgr.h"
6667 bool parseMBB(MachineBasicBlock *&MBB);
6768
6869 bool parseRegister(unsigned &Reg);
70 bool parseRegisterFlag(unsigned &Flags);
6971 bool parseRegisterOperand(MachineOperand &Dest, bool IsDef = false);
7072 bool parseImmediateOperand(MachineOperand &Dest);
7173 bool parseMBBReference(MachineBasicBlock *&MBB);
137139 // TODO: Allow parsing of multiple operands before '='
138140 MachineOperand MO = MachineOperand::CreateImm(0);
139141 SmallVector Operands;
140 if (Token.isRegister()) {
142 if (Token.isRegister() || Token.isRegisterFlag()) {
141143 if (parseRegisterOperand(MO, /*IsDef=*/true))
142144 return true;
143145 Operands.push_back(MO);
166168
167169 const auto &MCID = MF.getSubtarget().getInstrInfo()->get(OpCode);
168170
169 // Verify machine operands.
170 if (!MCID.isVariadic()) {
171 for (size_t I = 0, E = Operands.size(); I < E; ++I) {
172 if (I < MCID.getNumOperands())
173 continue;
174 // Mark this register as implicit to prevent an assertion when it's added
175 // to an instruction. This is a temporary workaround until the implicit
176 // register flag can be parsed.
177 if (Operands[I].isReg())
178 Operands[I].setImplicit();
179 }
180 }
181
182 // TODO: Determine the implicit behaviour when implicit register flags are
183 // parsed.
171 // TODO: Check for extraneous machine operands.
172 // TODO: Check that this instruction has the implicit register operands.
184173 MI = MF.CreateMachineInstr(MCID, DebugLoc(), /*NoImplicit=*/true);
185174 for (const auto &Operand : Operands)
186175 MI->addOperand(MF, Operand);
228217 return false;
229218 }
230219
220 bool MIParser::parseRegisterFlag(unsigned &Flags) {
221 switch (Token.kind()) {
222 case MIToken::kw_implicit:
223 Flags |= RegState::Implicit;
224 break;
225 case MIToken::kw_implicit_define:
226 Flags |= RegState::ImplicitDefine;
227 break;
228 // TODO: report an error when we specify the same flag more than once.
229 // TODO: parse the other register flags.
230 default:
231 llvm_unreachable("The current token should be a register flag");
232 }
233 lex();
234 return false;
235 }
236
231237 bool MIParser::parseRegisterOperand(MachineOperand &Dest, bool IsDef) {
232238 unsigned Reg;
233 // TODO: Parse register flags.
239 unsigned Flags = IsDef ? RegState::Define : 0;
240 while (Token.isRegisterFlag()) {
241 if (parseRegisterFlag(Flags))
242 return true;
243 }
244 if (!Token.isRegister())
245 return error("expected a register after register flags");
234246 if (parseRegister(Reg))
235247 return true;
236248 lex();
237249 // TODO: Parse subregister.
238 Dest = MachineOperand::CreateReg(Reg, IsDef);
250 Dest = MachineOperand::CreateReg(Reg, Flags & RegState::Define,
251 Flags & RegState::Implicit);
239252 return false;
240253 }
241254
317330
318331 bool MIParser::parseMachineOperand(MachineOperand &Dest) {
319332 switch (Token.kind()) {
333 case MIToken::kw_implicit:
334 case MIToken::kw_implicit_define:
320335 case MIToken::underscore:
321336 case MIToken::NamedRegister:
322337 return parseRegisterOperand(Dest);
210210 void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
211211 switch (Op.getType()) {
212212 case MachineOperand::MO_Register:
213 // TODO: Print register flags.
213 // TODO: Print the other register flags.
214 if (Op.isImplicit())
215 OS << (Op.isDef() ? "implicit-def " : "implicit ");
214216 printReg(Op.getReg(), OS, TRI);
215217 // TODO: Print sub register.
216218 break;
0 # RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
1 # This test ensures that an error is reported when a register operand doesn't
2 # follow register flags.
3
4 --- |
5
6 define i32 @foo() {
7 entry:
8 ret i32 0
9 }
10
11 ...
12 ---
13 name: foo
14 body:
15 - id: 0
16 name: entry
17 instructions:
18 # CHECK: [[@LINE+1]]:37: expected a register after register flags
19 - '%eax = MOV32r0 implicit-def 2'
20 - 'RETQ %eax'
21 ...
0 # RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s
1 # This test ensures that the MIR parser parses the 'implicit' and 'implicit-def'
2 # register flags correctly.
3
4 --- |
5
6 define i32 @foo(i32 %a) {
7 entry:
8 %0 = icmp sle i32 %a, 10
9 br i1 %0, label %less, label %exit
10
11 less:
12 ret i32 0
13
14 exit:
15 ret i32 %a
16 }
17
18 ...
19 ---
20 name: foo
21 body:
22 - id: 0
23 name: entry
24 instructions:
25 # CHECK: - 'CMP32ri8 %edi, 10, implicit-def %eflags'
26 # CHECK-NEXT: - 'JG_1 %bb.2.exit, implicit %eflags'
27 - 'CMP32ri8 %edi, 10, implicit-def %eflags'
28 - 'JG_1 %bb.2.exit, implicit %eflags'
29 - id: 1
30 name: less
31 instructions:
32 # CHECK: - '%eax = MOV32r0 implicit-def %eflags'
33 - '%eax = MOV32r0 implicit-def %eflags'
34 - 'RETQ %eax'
35 - id: 2
36 name: exit
37 instructions:
38 - '%eax = COPY %edi'
39 - 'RETQ %eax'
40 ...
3434 name: entry
3535 instructions:
3636 # CHECK: - 'PUSH64r %rax
37 # CHECK-NEXT: - 'CALL64pcrel32 @compute, csr_64, %rsp, %edi, %rsp, %eax'
37 # CHECK-NEXT: - 'CALL64pcrel32 @compute, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp, implicit-def %eax'
3838 - 'PUSH64r %rax'
39 - 'CALL64pcrel32 @compute, csr_64, %rsp, %edi, %rsp, %eax'
39 - 'CALL64pcrel32 @compute, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp, implicit-def %eax'
4040 - '%rdx = POP64r'
4141 - 'RETQ %eax'
4242 ...