Skip to content

Commit 9c2b99e

Browse files
committed
add todo
Created using spr 1.3.5
2 parents e58602d + 8f54bcd commit 9c2b99e

File tree

19 files changed

+1128
-908
lines changed

19 files changed

+1128
-908
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 165 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,8 @@ def LoadOp : CIR_Op<"load", [
600600
}];
601601

602602
let extraClassDeclaration = [{
603+
// TODO(CIR): The final interface here should include an argument for the
604+
// SyncScope::ID.
603605
void setAtomic(mlir::cir::MemOrder order);
604606
}];
605607

@@ -669,7 +671,7 @@ def StoreOp : CIR_Op<"store", [
669671

670672
def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp", "IfOp",
671673
"SwitchOp", "DoWhileOp",
672-
"WhileOp", "ForOp"]>,
674+
"WhileOp", "ForOp", "CaseOp"]>,
673675
Terminator]> {
674676
let summary = "Return from function";
675677
let description = [{
@@ -904,7 +906,7 @@ def ConditionOp : CIR_Op<"condition", [
904906
def YieldOp : CIR_Op<"yield", [ReturnLike, Terminator,
905907
ParentOneOf<["IfOp", "ScopeOp", "SwitchOp", "WhileOp", "ForOp", "AwaitOp",
906908
"TernaryOp", "GlobalOp", "DoWhileOp", "TryOp", "ArrayCtor",
907-
"ArrayDtor", "CallOp"]>]> {
909+
"ArrayDtor", "CallOp", "CaseOp"]>]> {
908910
let summary = "Represents the default branching behaviour of a region";
909911
let description = [{
910912
The `cir.yield` operation terminates regions on different CIR operations,
@@ -1823,22 +1825,38 @@ def CaseOpKind : I32EnumAttr<
18231825
let cppNamespace = "::mlir::cir";
18241826
}
18251827

1826-
def CaseEltValueListAttr :
1827-
TypedArrayAttrBase<AnyAttr, "cir.switch case value condition"> {
1828-
let constBuilderCall = ?;
1829-
}
1828+
def CaseOp : CIR_Op<"case", [
1829+
DeclareOpInterfaceMethods<RegionBranchOpInterface>,
1830+
RecursivelySpeculatable, AutomaticAllocationScope]> {
1831+
let summary = "Case operation";
1832+
let description = [{
1833+
The `cir.case` operation represents a case within a C/C++ switch.
1834+
The `cir.case` operation must be in a `cir.switch` operation directly or indirectly.
18301835

1831-
def CaseAttr : AttrDef<CIR_Dialect, "Case"> {
1832-
// FIXME: value should probably be optional for more clear "default"
1833-
// representation.
1834-
let parameters = (ins "ArrayAttr":$value, "CaseOpKindAttr":$kind);
1835-
let mnemonic = "case";
1836-
let assemblyFormat = "`<` struct(params) `>`";
1837-
}
1836+
The `cir.case` have 4 kinds:
1837+
- `equal, <constant>`: equality of the second case operand against the
1838+
condition.
1839+
- `anyof, [constant-list]`: equals to any of the values in a subsequent
1840+
following list.
1841+
- `range, [lower-bound, upper-bound]`: the condition is within the closed interval.
1842+
- `default`: any other value.
1843+
1844+
Each case region must be explicitly terminated.
1845+
}];
1846+
1847+
let arguments = (ins ArrayAttr:$value, CaseOpKind:$kind);
1848+
let regions = (region AnyRegion:$caseRegion);
1849+
1850+
let assemblyFormat = "`(` $kind `,` $value `)` $caseRegion attr-dict";
1851+
1852+
let hasVerifier = 1;
18381853

1839-
def CaseArrayAttr :
1840-
TypedArrayAttrBase<CaseAttr, "cir.switch case array attribute"> {
1841-
let constBuilderCall = ?;
1854+
let skipDefaultBuilders = 1;
1855+
let builders = [
1856+
OpBuilder<(ins "ArrayAttr":$value,
1857+
"CaseOpKind":$kind,
1858+
"OpBuilder::InsertPoint &":$insertPoint)>
1859+
];
18421860
}
18431861

18441862
def SwitchOp : CIR_Op<"switch",
@@ -1851,45 +1869,136 @@ def SwitchOp : CIR_Op<"switch",
18511869
conditionally executing multiple regions of code. The operand to an switch
18521870
is an integral condition value.
18531871

1854-
A variadic list of "case" attribute operands and regions track the possible
1855-
control flow within `cir.switch`. A `case` must be in one of the following forms:
1856-
- `equal, <constant>`: equality of the second case operand against the
1857-
condition.
1858-
- `anyof, [constant-list]`: equals to any of the values in a subsequent
1859-
following list.
1860-
- `range, [lower-bound, upper-bound]`: the condition is within the closed interval.
1861-
- `default`: any other value.
1872+
The set of `cir.case` operations and their enclosing `cir.switch`
1873+
represents the semantics of a C/C++ switch statement. Users can use
1874+
`collectCases(llvm::SmallVector<CaseOp> &cases)` to collect the `cir.case`
1875+
operation in the `cir.switch` operation easily.
18621876

1863-
Each case region must be explicitly terminated.
1877+
The `cir.case` operations doesn't have to be in the region of `cir.switch`
1878+
directly. However, when all the `cir.case` operations lives in the region
1879+
of `cir.switch` directly and there is no other operations except the ending
1880+
`cir.yield` operation in the region of `cir.switch` directly, we call the
1881+
`cir.switch` operation is in a simple form. Users can use
1882+
`bool isSimpleForm(llvm::SmallVector<CaseOp> &cases)` member function to
1883+
detect if the `cir.switch` operation is in a simple form. The simple form
1884+
makes analysis easier to handle the `cir.switch` operation
1885+
and makes the boundary to give up pretty clear.
18641886

1865-
Examples:
1887+
To make the simple form as common as possible, CIR code generation attaches
1888+
operations corresponding to the statements that lives between top level
1889+
cases into the closest `cir.case` operation.
18661890

1867-
```mlir
1868-
cir.switch (%b : i32) [
1869-
case (equal, 20) {
1870-
...
1871-
cir.yield break
1872-
},
1873-
case (anyof, [1, 2, 3] : i32) {
1874-
...
1875-
cir.return ...
1891+
For example,
1892+
1893+
```
1894+
switch(int cond) {
1895+
case 4:
1896+
a++;
1897+
1898+
b++;
1899+
case 5;
1900+
c++;
1901+
1902+
...
1903+
}
1904+
```
1905+
1906+
The statement `b++` is not a sub-statement of the case statement `case 4`.
1907+
But to make the generated `cir.switch` a simple form, we will attach the
1908+
statement `b++` into the closest `cir.case` operation. So that the generated
1909+
code will be like:
1910+
1911+
```
1912+
cir.switch(int cond) {
1913+
cir.case(equal, 4) {
1914+
a++;
1915+
b++;
1916+
cir.yield
18761917
}
1877-
case (range, [10, 15]) {
1878-
...
1879-
cir.yield break
1880-
},
1881-
case (default) {
1882-
...
1883-
cir.yield fallthrough
1918+
cir.case(equal, 5) {
1919+
c++;
1920+
cir.yield
18841921
}
1885-
]
1922+
...
1923+
}
1924+
```
1925+
1926+
For the same reason, we will hoist the case statement as the substatement
1927+
of another case statement so that they will be in the same level. For
1928+
example,
1929+
1930+
```
1931+
switch(int cond) {
1932+
case 4:
1933+
default;
1934+
case 5;
1935+
a++;
1936+
...
1937+
}
1938+
```
1939+
1940+
will be generated as
1941+
1942+
```
1943+
cir.switch(int cond) {
1944+
cir.case(equal, 4) {
1945+
cir.yield
1946+
}
1947+
cir.case(default) {
1948+
cir.yield
1949+
}
1950+
cir.case(equal, 5) {
1951+
a++;
1952+
cir.yield
1953+
}
1954+
...
1955+
}
1956+
```
1957+
1958+
The cir.switch might not be considered "simple" if any of the following is
1959+
true:
1960+
- There are case statements of the switch statement lives in other scopes
1961+
other than the top level compound statement scope. Note that a case
1962+
statement itself doesn't form a scope.
1963+
- The sub-statement of the switch statement is not a compound statement.
1964+
- There are codes before the first case statement. For example,
1965+
1966+
```
1967+
switch(int cond) {
1968+
l:
1969+
b++;
1970+
1971+
case 4:
1972+
a++;
1973+
break;
1974+
1975+
case 5:
1976+
goto l;
1977+
...
1978+
}
1979+
```
1980+
1981+
the generated CIR for this non-simple switch would be:
1982+
1983+
```
1984+
cir.switch(int cond) {
1985+
cir.label "l"
1986+
b++;
1987+
cir.case(4) {
1988+
a++;
1989+
cir.break
1990+
}
1991+
cir.case(5) {
1992+
goto "l"
1993+
}
1994+
cir.yield
1995+
}
18861996
```
18871997
}];
18881998

1889-
let arguments = (ins CIR_IntType:$condition,
1890-
OptionalAttr<CaseArrayAttr>:$cases);
1999+
let arguments = (ins CIR_IntType:$condition);
18912000

1892-
let regions = (region VariadicRegion<AnyRegion>:$regions);
2001+
let regions = (region AnyRegion:$body);
18932002

18942003
let hasVerifier = 1;
18952004

@@ -1901,10 +2010,19 @@ def SwitchOp : CIR_Op<"switch",
19012010

19022011
let assemblyFormat = [{
19032012
custom<SwitchOp>(
1904-
$regions, $cases, $condition, type($condition)
2013+
$body, $condition, type($condition)
19052014
)
19062015
attr-dict
19072016
}];
2017+
2018+
let extraClassDeclaration = [{
2019+
// Collect cases in the switch.
2020+
void collectCases(llvm::SmallVector<CaseOp> &cases);
2021+
2022+
// Check if the switch is in a simple form. If yes, collect the cases to \param cases.
2023+
// This is an expensive and need to be used with caution.
2024+
bool isSimpleForm(llvm::SmallVector<CaseOp> &cases);
2025+
}];
19082026
}
19092027

19102028
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)