Skip to content

Commit 8505f84

Browse files
authored
Conversion to relational algebra (#18)
1 parent 6fedb56 commit 8505f84

42 files changed

Lines changed: 3805 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ endif ()
6666

6767
# Directories with MLIR dialects
6868
add_subdirectory(include/graphalg)
69+
add_subdirectory(include/garel)
6970

7071
add_subdirectory(src)
7172
add_subdirectory(test)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
include_directories(SYSTEM ${MLIR_INCLUDE_DIRS})
2+
include_directories(SYSTEM ${PROJECT_BINARY_DIR}/include)
3+
4+
set(LLVM_TARGET_DEFINITIONS GARelAttr.td)
5+
mlir_tablegen(GARelEnumAttr.h.inc -gen-enum-decls)
6+
mlir_tablegen(GARelEnumAttr.cpp.inc -gen-enum-defs)
7+
mlir_tablegen(GARelAttr.h.inc --gen-attrdef-decls)
8+
mlir_tablegen(GARelAttr.cpp.inc -gen-attrdef-defs)
9+
10+
set(LLVM_TARGET_DEFINITIONS GARelOps.td)
11+
add_mlir_dialect(GARelOps garel)
12+
13+
set(LLVM_TARGET_DEFINITIONS GARelPasses.td)
14+
mlir_tablegen(GARelPasses.h.inc --gen-pass-decls)
15+
add_public_tablegen_target(MLIRGARelPassesIncGen)

compiler/include/garel/GARelAttr.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
#include <mlir/IR/Attributes.h>
4+
#include <mlir/IR/BuiltinAttributes.h>
5+
6+
#include "garel/GARelEnumAttr.h.inc"
7+
8+
namespace garel {
9+
10+
/** Reference to a column inside of \c RelationType or \c TupleType. */
11+
using ColumnIdx = std::int32_t;
12+
13+
} // namespace garel
14+
15+
#define GET_ATTRDEF_CLASSES
16+
#include "garel/GARelAttr.h.inc"
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#ifndef GAREL_ATTR
2+
#define GAREL_ATTR
3+
4+
include "mlir/IR/BuiltinAttributeInterfaces.td"
5+
6+
include "GARelDialect.td"
7+
8+
class GARel_Attr<string name, string attrMnemonic, list<Trait> traits = []>
9+
: AttrDef<GARel_Dialect, name, traits> {
10+
let mnemonic = attrMnemonic;
11+
}
12+
13+
def JoinPredicate : GARel_Attr<"JoinPredicate", "join_pred"> {
14+
let summary = "A binary equality join predicate";
15+
16+
let parameters = (ins
17+
"std::int32_t":$lhsRelIdx,
18+
"ColumnIdx":$lhsColIdx,
19+
"std::int32_t":$rhsRelIdx,
20+
"ColumnIdx":$rhsColIdx);
21+
22+
let assemblyFormat = [{
23+
`<` $lhsRelIdx `[` $lhsColIdx `]` `=` $rhsRelIdx `[` $rhsColIdx `]` `>`
24+
}];
25+
}
26+
27+
def JoinPredicates : ArrayOfAttr<
28+
GARel_Dialect,
29+
"JoinPredicates",
30+
"join_preds",
31+
"JoinPredicateAttr">;
32+
33+
def AggregateFunc : I64EnumAttr<
34+
"AggregateFunc", "",
35+
[
36+
I64EnumAttrCase<"SUM", 0>,
37+
I64EnumAttrCase<"MIN", 1>,
38+
I64EnumAttrCase<"MAX", 2>,
39+
I64EnumAttrCase<"LOR", 3>, /* Logical OR (over i1) */
40+
I64EnumAttrCase<"ARGMIN", 4>,
41+
]
42+
> {
43+
let cppNamespace = "::garel";
44+
}
45+
46+
// NOTE: assumes an aggregator produces exactly one output column.
47+
def Aggregator : GARel_Attr<"Aggregator", "aggregator"> {
48+
let summary = "Aggregate function with bound input columns";
49+
50+
let parameters = (ins
51+
"AggregateFunc":$func,
52+
ArrayRefParameter<"ColumnIdx">:$inputs);
53+
54+
let assemblyFormat = [{
55+
`<` $func $inputs `>`
56+
}];
57+
58+
let genVerifyDecl = 1;
59+
60+
let extraClassDeclaration = [{
61+
/** Type for values in the output column. */
62+
mlir::Type getResultType(::mlir::Type relType);
63+
}];
64+
}
65+
66+
def Aggregators : ArrayOfAttr<
67+
GARel_Dialect,
68+
"Aggregators",
69+
"aggregators",
70+
"AggregatorAttr">;
71+
72+
#endif // GAREL_ATTR
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#pragma once
2+
3+
#include <mlir/IR/Dialect.h>
4+
#include <mlir/Interfaces/SideEffectInterfaces.h>
5+
6+
#include "garel/GARelOpsDialect.h.inc"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#ifndef GAREL_DIALECT
2+
#define GAREL_DIALECT
3+
4+
include "mlir/Interfaces/SideEffectInterfaces.td"
5+
include "mlir/IR/EnumAttr.td"
6+
include "mlir/IR/OpBase.td"
7+
8+
def GARel_Dialect : Dialect {
9+
let name = "garel";
10+
let cppNamespace = "::garel";
11+
12+
let extraClassDeclaration = [{
13+
private:
14+
void registerAttributes();
15+
void registerTypes();
16+
}];
17+
18+
let usePropertiesForAttributes = 1;
19+
let useDefaultAttributePrinterParser = 1;
20+
let useDefaultTypePrinterParser = 1;
21+
}
22+
23+
// NOTE: GARel ops are always 'Pure'
24+
class GARel_Op<string mnemonic, list<Trait> traits = []> :
25+
Op<GARel_Dialect, mnemonic, !listconcat(traits, [Pure])>;
26+
27+
#endif // GAREL_DIALECT

compiler/include/garel/GARelOps.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
3+
#include <mlir/Bytecode/BytecodeOpInterface.h>
4+
#include <mlir/IR/BuiltinAttributes.h>
5+
#include <mlir/IR/OpDefinition.h>
6+
#include <mlir/IR/OpImplementation.h>
7+
#include <mlir/IR/OperationSupport.h>
8+
#include <mlir/IR/Region.h>
9+
#include <mlir/Interfaces/InferTypeOpInterface.h>
10+
#include <mlir/Interfaces/SideEffectInterfaces.h>
11+
12+
#include "garel/GARelTypes.h"
13+
14+
#define GET_OP_CLASSES
15+
#include "garel/GARelOps.h.inc"

compiler/include/garel/GARelOps.td

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
#ifndef GAREL_OPS
2+
#define GAREL_OPS
3+
4+
/**
5+
* Relation-level ops in the GARel dialect.
6+
*
7+
* See ./GARelTupleOps.td for the tuple-level ops.
8+
*/
9+
10+
include "mlir/Interfaces/InferTypeOpInterface.td"
11+
12+
include "GARelDialect.td"
13+
include "GARelTypes.td"
14+
15+
// Per-tuple ops kept in a separate file.
16+
include "GARelTupleOps.td"
17+
18+
def ProjectOp : GARel_Op<"project", [IsolatedFromAbove]> {
19+
let summary = "Remaps, reorders, drops and computes columns";
20+
21+
let arguments = (ins Relation:$input);
22+
23+
let regions = (region SizedRegion<1>:$projections);
24+
25+
let results = (outs Relation:$result);
26+
27+
let assemblyFormat = [{
28+
$input `:` type($input) `->` type($result) $projections attr-dict
29+
}];
30+
31+
let hasRegionVerifier = 1;
32+
33+
let extraClassDeclaration = [{
34+
mlir::Block& createProjectionsBlock();
35+
ProjectReturnOp getTerminator();
36+
}];
37+
}
38+
39+
def ProjectReturnOp : GARel_Op<"project.return", [
40+
Terminator,
41+
HasParent<"ProjectOp">]> {
42+
let summary = "The output projections";
43+
44+
let arguments = (ins Variadic<ColumnType>:$projections);
45+
46+
let assemblyFormat = [{
47+
$projections `:` type($projections) attr-dict
48+
}];
49+
50+
// NOTE: verification performed by ProjectOp
51+
}
52+
53+
def SelectOp : GARel_Op<"select", [
54+
SameOperandsAndResultType,
55+
IsolatedFromAbove]> {
56+
let summary = "Removes tuples that fail (one of) the predicates";
57+
58+
let arguments = (ins Relation:$input);
59+
let regions = (region SizedRegion<1>:$predicates);
60+
61+
let results = (outs Relation:$result);
62+
63+
let assemblyFormat = [{
64+
$input `:` type($input) $predicates attr-dict
65+
}];
66+
67+
let hasRegionVerifier = 1;
68+
69+
let extraClassDeclaration = [{
70+
mlir::Block& createPredicatesBlock();
71+
SelectReturnOp getTerminator();
72+
}];
73+
}
74+
75+
def SelectReturnOp : GARel_Op<"select.return", [
76+
Terminator,
77+
HasParent<"SelectOp">]> {
78+
let summary = "Return the select predicates";
79+
80+
let arguments = (ins Variadic<I1>:$predicates);
81+
82+
let assemblyFormat = [{
83+
$predicates attr-dict
84+
}];
85+
}
86+
87+
def JoinOp : GARel_Op<"join", [InferTypeOpAdaptor]> {
88+
let summary = "Natural (equi)join of relations";
89+
90+
let arguments = (ins
91+
// NOTE: All inputs must have distinct columns
92+
Variadic<Relation>:$inputs,
93+
// NOTE: Equality predicates only
94+
JoinPredicates:$predicates);
95+
96+
let results = (outs Relation:$result);
97+
98+
let assemblyFormat = [{
99+
$inputs `:` type($inputs)
100+
$predicates
101+
attr-dict
102+
}];
103+
104+
let hasVerifier = 1;
105+
let hasFolder = 1;
106+
}
107+
108+
def UnionOp : GARel_Op<"union", [SameOperandsAndResultType]> {
109+
let summary = "Union of relations";
110+
111+
let arguments = (ins Variadic<Relation>:$inputs);
112+
113+
let results = (outs Relation:$result);
114+
115+
let assemblyFormat = [{
116+
$inputs `:` type($inputs)
117+
attr-dict
118+
}];
119+
120+
let hasFolder = 1;
121+
}
122+
123+
def AggregateOp : GARel_Op<"aggregate", [InferTypeOpAdaptor]> {
124+
let summary = "Groups tuples by key columns, aggregating values of other columns";
125+
126+
let arguments = (ins
127+
Relation:$input,
128+
DenseI32ArrayAttr:$groupBy,
129+
Aggregators:$aggregators);
130+
131+
let results = (outs Relation:$result);
132+
133+
let assemblyFormat = [{
134+
$input `:` type($input)
135+
`group_by` `` `=` `` $groupBy
136+
`aggregators` `` `=` `` $aggregators
137+
attr-dict
138+
}];
139+
}
140+
141+
def ForOp : GARel_Op<"for", [InferTypeOpAdaptor]> {
142+
let summary = "Bounded iteration";
143+
144+
let arguments = (ins
145+
Variadic<Relation>:$init,
146+
I64Attr:$iters,
147+
I64Attr:$resultIdx);
148+
149+
let regions = (region
150+
SizedRegion<1>:$body,
151+
MaxSizedRegion<1>:$until);
152+
153+
let results = (outs Relation:$result);
154+
155+
let assemblyFormat = [{
156+
$init `:` type($init)
157+
`iters` `` `=` `` $iters
158+
`result_idx` `` `=` `` $resultIdx
159+
$body
160+
(`until` $until^)?
161+
attr-dict
162+
}];
163+
164+
let hasVerifier = 1;
165+
let hasRegionVerifier = 1;
166+
}
167+
168+
def ForYieldOp : GARel_Op<"for.yield", [
169+
Terminator,
170+
HasParent<"ForOp">]> {
171+
let summary = "Produces the iter args for the next iteration";
172+
173+
let arguments = (ins Variadic<Relation>:$inputs);
174+
175+
let assemblyFormat = [{
176+
$inputs `:` type($inputs)
177+
attr-dict
178+
}];
179+
180+
// Note: verification performed by parent ForOp.
181+
}
182+
183+
def RangeOp : GARel_Op<"range", [InferTypeOpAdaptor]> {
184+
let summary = "generates a range of `index` values from `[0, size)`";
185+
186+
let arguments = (ins I64Attr:$size);
187+
188+
let results = (outs Relation:$result);
189+
190+
let assemblyFormat = [{
191+
$size attr-dict
192+
}];
193+
}
194+
195+
def RemapOp : GARel_Op<"remap", [InferTypeOpAdaptor]> {
196+
let summary = "reorders or drop columns";
197+
198+
let arguments = (ins Relation:$input, DenseI32ArrayAttr:$remap);
199+
200+
let results = (outs Relation:$result);
201+
202+
let assemblyFormat = [{
203+
$input `:` type($input)
204+
$remap
205+
attr-dict
206+
}];
207+
208+
let hasVerifier = 1;
209+
let hasFolder = 1;
210+
}
211+
212+
def ConstantOp : GARel_Op<"const", [InferTypeOpAdaptor]> {
213+
let summary = "A relation with one constant-value tuple";
214+
215+
let arguments = (ins TypedAttrInterface:$value);
216+
217+
let results = (outs Relation:$result);
218+
219+
let assemblyFormat = [{
220+
$value attr-dict
221+
}];
222+
}
223+
224+
#endif // GAREL_OPS

0 commit comments

Comments
 (0)