forked from OSchip/llvm-project
Homogenize branch instruction arguments.
Branch instruction arguments were defined and used inconsistently across different instructions, in both the spec and the implementation. In particular, conditional and unconditional branch instructions were using different syntax in the implementation. This led to the IR we produce not being accepted by the parser. Update the printer to use common syntax: `(` list-of-SSA-uses `:` list-of-types `)`. The motivation for choosing this syntax as opposed to the one in the spec, `(` list-of-SSA-uses `)` `:` list-of-types is double-fold. First, it is tricky to differentiate the label of the false branch from the type while parsing conditional branches (which is what apparently motivated the implementation to diverge from the spec in the first place). Second, the ongoing convergence between terminator instructions and other operations prompts for consistency between their operand list syntax. After this change, the only remaining difference between the two is the use of parentheses. Update the comment of the parser that did not correspond to the code. Remove the unused isParenthesized argument from parseSSAUseAndTypeList. Update the spec accordingly. Note that the examples in the spec were _not_ using the EBNF defined a couple of lines above them, but were using the current syntax. Add a supplementary example of a branch to a basic block with multiple arguments. PiperOrigin-RevId: 221162655
This commit is contained in:
parent
5a0d3d0204
commit
cab24dc211
|
@ -975,8 +975,13 @@ bb2:
|
|||
br bb3(%b: i64) // Branch passes %b as the argument
|
||||
|
||||
// bb3 receives an argument, named %c, from predecessors
|
||||
// and passes it on to bb4 twice.
|
||||
bb3(%c: i64):
|
||||
return %c : i64
|
||||
br bb4(%c, %c : i64, i64)
|
||||
|
||||
bb4(%d : i64, %e : i64):
|
||||
%0 = addi %d, %e : i64
|
||||
return %0 : i64
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1004,7 +1009,7 @@ Syntax:
|
|||
|
||||
``` {.ebnf}
|
||||
terminator-stmt ::= `br` bb-id branch-use-list?
|
||||
branch-use-list ::= `(` ssa-use-list `)` `:` type-list-no-parens
|
||||
branch-use-list ::= `(` ssa-use-list `:` type-list-no-parens `)`
|
||||
```
|
||||
|
||||
The `br` terminator statement represents an unconditional jump to a target basic
|
||||
|
@ -1039,7 +1044,7 @@ instruction that targets the same basic block:
|
|||
cfgfunc @select(%a : i32, %b :i32, %flag : i1) -> i32 {
|
||||
bb0:
|
||||
// Both targets are the same, operands differ
|
||||
cond_br %flag : i1, bb1 (%a : i32), bb1 (%b : i32)
|
||||
cond_br %flag, bb1 (%a : i32), bb1 (%b : i32)
|
||||
|
||||
bb1 (%x : i32) :
|
||||
return %x : i32
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "mlir/Support/STLExtras.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
|
@ -1180,6 +1181,8 @@ private:
|
|||
DenseMap<const BasicBlock *, unsigned> basicBlockIDs;
|
||||
|
||||
void numberValuesInBlock(const BasicBlock *block);
|
||||
|
||||
template <typename Range> void printBranchOperands(const Range &range);
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
@ -1290,19 +1293,28 @@ void CFGFunctionPrinter::print(const OperationInst *inst) {
|
|||
printOperation(inst);
|
||||
}
|
||||
|
||||
// Print the operands from "container" to "os", followed by a colon and their
|
||||
// respective types, everything in parentheses. Do nothing if the container is
|
||||
// empty.
|
||||
template <typename Range>
|
||||
void CFGFunctionPrinter::printBranchOperands(const Range &range) {
|
||||
if (llvm::empty(range))
|
||||
return;
|
||||
|
||||
os << '(';
|
||||
interleaveComma(range,
|
||||
[this](const CFGValue *operand) { printValueID(operand); });
|
||||
os << " : ";
|
||||
interleaveComma(range, [this](const CFGValue *operand) {
|
||||
printType(operand->getType());
|
||||
});
|
||||
os << ')';
|
||||
}
|
||||
|
||||
void CFGFunctionPrinter::print(const BranchInst *inst) {
|
||||
os << "br ";
|
||||
printBBName(inst->getDest());
|
||||
|
||||
if (inst->getNumOperands() != 0) {
|
||||
os << '(';
|
||||
interleaveComma(inst->getOperands(),
|
||||
[&](const CFGValue *operand) { printValueID(operand); });
|
||||
os << ") : ";
|
||||
interleaveComma(inst->getOperands(), [&](const CFGValue *operand) {
|
||||
printType(operand->getType());
|
||||
});
|
||||
}
|
||||
printBranchOperands(inst->getOperands());
|
||||
}
|
||||
|
||||
void CFGFunctionPrinter::print(const CondBranchInst *inst) {
|
||||
|
@ -1311,29 +1323,11 @@ void CFGFunctionPrinter::print(const CondBranchInst *inst) {
|
|||
|
||||
os << ", ";
|
||||
printBBName(inst->getTrueDest());
|
||||
if (inst->getNumTrueOperands() != 0) {
|
||||
os << '(';
|
||||
interleaveComma(inst->getTrueOperands(),
|
||||
[&](const CFGValue *operand) { printValueID(operand); });
|
||||
os << " : ";
|
||||
interleaveComma(inst->getTrueOperands(), [&](const CFGValue *operand) {
|
||||
printType(operand->getType());
|
||||
});
|
||||
os << ")";
|
||||
}
|
||||
printBranchOperands(inst->getTrueOperands());
|
||||
|
||||
os << ", ";
|
||||
printBBName(inst->getFalseDest());
|
||||
if (inst->getNumFalseOperands() != 0) {
|
||||
os << '(';
|
||||
interleaveComma(inst->getFalseOperands(),
|
||||
[&](const CFGValue *operand) { printValueID(operand); });
|
||||
os << " : ";
|
||||
interleaveComma(inst->getFalseOperands(), [&](const CFGValue *operand) {
|
||||
printType(operand->getType());
|
||||
});
|
||||
os << ")";
|
||||
}
|
||||
printBranchOperands(inst->getFalseOperands());
|
||||
}
|
||||
|
||||
void CFGFunctionPrinter::print(const ReturnInst *inst) {
|
||||
|
|
|
@ -1844,8 +1844,7 @@ public:
|
|||
|
||||
template <typename ValueTy>
|
||||
ParseResult
|
||||
parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
|
||||
bool isParenthesized);
|
||||
parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results);
|
||||
|
||||
// Operations
|
||||
ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
|
||||
|
@ -2060,31 +2059,18 @@ ResultType FunctionParser::parseSSADefOrUseAndType(
|
|||
}
|
||||
|
||||
/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
|
||||
/// followed by a type list. If hasParens is true, then the operands are
|
||||
/// surrounded by parens.
|
||||
/// followed by a type list.
|
||||
///
|
||||
/// ssa-use-and-type-list[parens]
|
||||
/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
|
||||
///
|
||||
/// ssa-use-and-type-list[!parens]
|
||||
/// ssa-use-and-type-list
|
||||
/// ::= ssa-use-list ':' type-list-no-parens
|
||||
///
|
||||
template <typename ValueTy>
|
||||
ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
|
||||
SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
|
||||
|
||||
// If we are in the parenthesized form and no paren exists, then we succeed
|
||||
// with an empty list.
|
||||
if (isParenthesized && !consumeIf(Token::l_paren))
|
||||
return ParseSuccess;
|
||||
|
||||
SmallVectorImpl<ValueTy *> &results) {
|
||||
SmallVector<SSAUseInfo, 4> valueIDs;
|
||||
if (parseOptionalSSAUseList(valueIDs))
|
||||
return ParseFailure;
|
||||
|
||||
if (isParenthesized && !consumeIf(Token::r_paren))
|
||||
return emitError("expected ')' in operand list");
|
||||
|
||||
// If there were no operands, then there is no colon or type lists.
|
||||
if (valueIDs.empty())
|
||||
return ParseSuccess;
|
||||
|
@ -2650,7 +2636,7 @@ ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
|
|||
|
||||
// Handle optional arguments.
|
||||
if (consumeIf(Token::l_paren) &&
|
||||
(parseOptionalSSAUseAndTypeList(values, /*isParenthesized=*/false) ||
|
||||
(parseOptionalSSAUseAndTypeList(values) ||
|
||||
parseToken(Token::r_paren, "expected ')' to close argument list"))) {
|
||||
return ParseFailure;
|
||||
}
|
||||
|
@ -2661,7 +2647,7 @@ ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
|
|||
/// Parse the terminator instruction for a basic block.
|
||||
///
|
||||
/// terminator-stmt ::= `br` bb-id branch-use-list?
|
||||
/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
|
||||
/// branch-use-list ::= `(` ssa-use-list ':' type-list-no-parens `)`
|
||||
/// terminator-stmt ::=
|
||||
/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id
|
||||
/// branch-use-list?
|
||||
|
@ -2679,7 +2665,7 @@ TerminatorInst *CFGFunctionParser::parseTerminator() {
|
|||
|
||||
// Parse any operands.
|
||||
SmallVector<CFGValue *, 8> operands;
|
||||
if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized=*/false))
|
||||
if (parseOptionalSSAUseAndTypeList(operands))
|
||||
return nullptr;
|
||||
return builder.createReturn(getEncodedSourceLocation(loc), operands);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ extfunc @body(index) -> ()
|
|||
// CHECK-NEXT: bb1: // pred: bb0
|
||||
// CHECK-NEXT: %c1 = constant 1 : index
|
||||
// CHECK-NEXT: %c42 = constant 42 : index
|
||||
// CHECK-NEXT: br bb2(%c1) : index
|
||||
// CHECK-NEXT: br bb2(%c1 : index)
|
||||
// CHECK-NEXT: bb2(%0: index): // 2 preds: bb1, bb3
|
||||
// CHECK-NEXT: %1 = cmpi "slt", %0, %c42 : index
|
||||
// CHECK-NEXT: cond_br %1, bb3, bb4
|
||||
|
@ -23,7 +23,7 @@ extfunc @body(index) -> ()
|
|||
// CHECK-NEXT: call @body(%0) : (index) -> ()
|
||||
// CHECK-NEXT: %c1_0 = constant 1 : index
|
||||
// CHECK-NEXT: %2 = addi %0, %c1_0 : index
|
||||
// CHECK-NEXT: br bb2(%2) : index
|
||||
// CHECK-NEXT: br bb2(%2 : index)
|
||||
// CHECK-NEXT: bb4: // pred: bb2
|
||||
// CHECK-NEXT: return
|
||||
// CHECK-NEXT: }
|
||||
|
@ -78,7 +78,7 @@ extfunc @other(index, i32) -> (i32)
|
|||
// CHECK-NEXT: bb1: // pred: bb0
|
||||
// CHECK-NEXT: %c0 = constant 0 : index
|
||||
// CHECK-NEXT: %c42 = constant 42 : index
|
||||
// CHECK-NEXT: br bb2(%c0) : index
|
||||
// CHECK-NEXT: br bb2(%c0 : index)
|
||||
// CHECK-NEXT: bb2(%0: index): // 2 preds: bb1, bb3
|
||||
// CHECK-NEXT: %1 = cmpi "slt", %0, %c42 : index
|
||||
// CHECK-NEXT: cond_br %1, bb3, bb4
|
||||
|
@ -89,7 +89,7 @@ extfunc @other(index, i32) -> (i32)
|
|||
// CHECK-NEXT: %5 = call @other(%2, %arg1) : (index, i32) -> i32
|
||||
// CHECK-NEXT: %c1 = constant 1 : index
|
||||
// CHECK-NEXT: %6 = addi %0, %c1 : index
|
||||
// CHECK-NEXT: br bb2(%6) : index
|
||||
// CHECK-NEXT: br bb2(%6 : index)
|
||||
// CHECK-NEXT: bb4: // pred: bb2
|
||||
// CHECK-NEXT: %c0_0 = constant 0 : index
|
||||
// CHECK-NEXT: %7 = call @other(%c0_0, %c0_i32) : (index, i32) -> i32
|
||||
|
@ -120,7 +120,7 @@ extfunc @post(index) -> ()
|
|||
// CHECK-NEXT: bb1: // pred: bb0
|
||||
// CHECK-NEXT: %c0 = constant 0 : index
|
||||
// CHECK-NEXT: %c42 = constant 42 : index
|
||||
// CHECK-NEXT: br bb2(%c0) : index
|
||||
// CHECK-NEXT: br bb2(%c0 : index)
|
||||
// CHECK-NEXT: bb2(%0: index): // 2 preds: bb1, bb7
|
||||
// CHECK-NEXT: %1 = cmpi "slt", %0, %c42 : index
|
||||
// CHECK-NEXT: cond_br %1, bb3, bb8
|
||||
|
@ -130,7 +130,7 @@ extfunc @post(index) -> ()
|
|||
// CHECK-NEXT: bb4: // pred: bb3
|
||||
// CHECK-NEXT: %c7 = constant 7 : index
|
||||
// CHECK-NEXT: %c56 = constant 56 : index
|
||||
// CHECK-NEXT: br bb5(%c7) : index
|
||||
// CHECK-NEXT: br bb5(%c7 : index)
|
||||
// CHECK-NEXT: bb5(%2: index): // 2 preds: bb4, bb6
|
||||
// CHECK-NEXT: %3 = cmpi "slt", %2, %c56 : index
|
||||
// CHECK-NEXT: cond_br %3, bb6, bb7
|
||||
|
@ -138,12 +138,12 @@ extfunc @post(index) -> ()
|
|||
// CHECK-NEXT: call @body2(%0, %2) : (index, index) -> ()
|
||||
// CHECK-NEXT: %c2 = constant 2 : index
|
||||
// CHECK-NEXT: %4 = addi %2, %c2 : index
|
||||
// CHECK-NEXT: br bb5(%4) : index
|
||||
// CHECK-NEXT: br bb5(%4 : index)
|
||||
// CHECK-NEXT: bb7: // pred: bb5
|
||||
// CHECK-NEXT: call @post(%0) : (index) -> ()
|
||||
// CHECK-NEXT: %c1 = constant 1 : index
|
||||
// CHECK-NEXT: %5 = addi %0, %c1 : index
|
||||
// CHECK-NEXT: br bb2(%5) : index
|
||||
// CHECK-NEXT: br bb2(%5 : index)
|
||||
// CHECK-NEXT: bb8: // pred: bb2
|
||||
// CHECK-NEXT: return
|
||||
// CHECK-NEXT: }
|
||||
|
@ -169,7 +169,7 @@ extfunc @body3(index, index) -> ()
|
|||
// CHECK-NEXT: bb1: // pred: bb0
|
||||
// CHECK-NEXT: %c0 = constant 0 : index
|
||||
// CHECK-NEXT: %c42 = constant 42 : index
|
||||
// CHECK-NEXT: br bb2(%c0) : index
|
||||
// CHECK-NEXT: br bb2(%c0 : index)
|
||||
// CHECK-NEXT: bb2(%0: index): // 2 preds: bb1, bb11
|
||||
// CHECK-NEXT: %1 = cmpi "slt", %0, %c42 : index
|
||||
// CHECK-NEXT: cond_br %1, bb3, bb12
|
||||
|
@ -179,7 +179,7 @@ extfunc @body3(index, index) -> ()
|
|||
// CHECK-NEXT: bb4: // pred: bb3
|
||||
// CHECK-NEXT: %c7 = constant 7 : index
|
||||
// CHECK-NEXT: %c56 = constant 56 : index
|
||||
// CHECK-NEXT: br bb5(%c7) : index
|
||||
// CHECK-NEXT: br bb5(%c7 : index)
|
||||
// CHECK-NEXT: bb5(%2: index): // 2 preds: bb4, bb6
|
||||
// CHECK-NEXT: %3 = cmpi "slt", %2, %c56 : index
|
||||
// CHECK-NEXT: cond_br %3, bb6, bb7
|
||||
|
@ -187,14 +187,14 @@ extfunc @body3(index, index) -> ()
|
|||
// CHECK-NEXT: call @body2(%0, %2) : (index, index) -> ()
|
||||
// CHECK-NEXT: %c2 = constant 2 : index
|
||||
// CHECK-NEXT: %4 = addi %2, %c2 : index
|
||||
// CHECK-NEXT: br bb5(%4) : index
|
||||
// CHECK-NEXT: br bb5(%4 : index)
|
||||
// CHECK-NEXT: bb7: // pred: bb5
|
||||
// CHECK-NEXT: call @mid(%0) : (index) -> ()
|
||||
// CHECK-NEXT: br bb8
|
||||
// CHECK-NEXT: bb8: // pred: bb7
|
||||
// CHECK-NEXT: %c18 = constant 18 : index
|
||||
// CHECK-NEXT: %c37 = constant 37 : index
|
||||
// CHECK-NEXT: br bb9(%c18) : index
|
||||
// CHECK-NEXT: br bb9(%c18 : index)
|
||||
// CHECK-NEXT: bb9(%5: index): // 2 preds: bb8, bb10
|
||||
// CHECK-NEXT: %6 = cmpi "slt", %5, %c37 : index
|
||||
// CHECK-NEXT: cond_br %6, bb10, bb11
|
||||
|
@ -202,12 +202,12 @@ extfunc @body3(index, index) -> ()
|
|||
// CHECK-NEXT: call @body3(%0, %5) : (index, index) -> ()
|
||||
// CHECK-NEXT: %c3 = constant 3 : index
|
||||
// CHECK-NEXT: %7 = addi %5, %c3 : index
|
||||
// CHECK-NEXT: br bb9(%7) : index
|
||||
// CHECK-NEXT: br bb9(%7 : index)
|
||||
// CHECK-NEXT: bb11: // pred: bb9
|
||||
// CHECK-NEXT: call @post(%0) : (index) -> ()
|
||||
// CHECK-NEXT: %c1 = constant 1 : index
|
||||
// CHECK-NEXT: %8 = addi %0, %c1 : index
|
||||
// CHECK-NEXT: br bb2(%8) : index
|
||||
// CHECK-NEXT: br bb2(%8 : index)
|
||||
// CHECK-NEXT: bb12: // pred: bb2
|
||||
// CHECK-NEXT: return
|
||||
// CHECK-NEXT: }
|
||||
|
|
Loading…
Reference in New Issue