Skip to content

Commit 5f55822

Browse files
authored
Merge pull request #529 from Xilinx/niklas.variable_naming
Changed naming of loop induction variables to follow natural naming (i, j, k, ...). This helps readability and locating positions referred to. Created new scopes to represent different behavior at function and loop level, to still enable re-using value names between different functions. Removed unused scoping at other levels.
2 parents 692c2e4 + 0635689 commit 5f55822

File tree

3 files changed

+172
-27
lines changed

3 files changed

+172
-27
lines changed

mlir/lib/Target/Cpp/TranslateToCpp.cpp

Lines changed: 88 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ struct CppEmitter {
185185
/// Return the existing or a new name for a Value.
186186
StringRef getOrCreateName(Value val);
187187

188+
/// Return the existing or a new name for a loop induction variable of an
189+
/// emitc::ForOp.
190+
StringRef getOrCreateName(emitc::ForOp forOp);
191+
188192
// Returns the textual representation of a subscript operation.
189193
std::string getSubscriptName(emitc::SubscriptOp op);
190194

@@ -200,23 +204,39 @@ struct CppEmitter {
200204
/// Whether to map an mlir integer to a unsigned integer in C++.
201205
bool shouldMapToUnsigned(IntegerType::SignednessSemantics val);
202206

203-
/// RAII helper function to manage entering/exiting C++ scopes.
207+
/// Abstract RAII helper function to manage entering/exiting C++ scopes.
204208
struct Scope {
209+
~Scope() { emitter.labelInScopeCount.pop(); }
210+
211+
private:
212+
llvm::ScopedHashTableScope<Value, std::string> valueMapperScope;
213+
llvm::ScopedHashTableScope<Block *, std::string> blockMapperScope;
214+
215+
protected:
205216
Scope(CppEmitter &emitter)
206217
: valueMapperScope(emitter.valueMapper),
207218
blockMapperScope(emitter.blockMapper), emitter(emitter) {
208-
emitter.valueInScopeCount.push(emitter.valueInScopeCount.top());
209219
emitter.labelInScopeCount.push(emitter.labelInScopeCount.top());
210220
}
211-
~Scope() {
212-
emitter.valueInScopeCount.pop();
213-
emitter.labelInScopeCount.pop();
221+
CppEmitter &emitter;
222+
};
223+
224+
/// RAII helper function to manage entering/exiting functions, while re-using
225+
/// value names.
226+
struct FunctionScope : Scope {
227+
FunctionScope(CppEmitter &emitter) : Scope(emitter) {
228+
// Re-use value names
229+
emitter.resetValueCounter();
214230
}
231+
};
215232

216-
private:
217-
llvm::ScopedHashTableScope<Value, std::string> valueMapperScope;
218-
llvm::ScopedHashTableScope<Block *, std::string> blockMapperScope;
219-
CppEmitter &emitter;
233+
/// RAII helper function to manage entering/exiting emitc::forOp loops and
234+
/// handle induction variable naming.
235+
struct LoopScope : Scope {
236+
LoopScope(CppEmitter &emitter) : Scope(emitter) {
237+
emitter.increaseLoopNestingLevel();
238+
}
239+
~LoopScope() { emitter.decreaseLoopNestingLevel(); }
220240
};
221241

222242
/// Returns wether the Value is assigned to a C++ variable in the scope.
@@ -264,6 +284,15 @@ struct CppEmitter {
264284
/// This emitter will only emit translation units whos id matches this value.
265285
StringRef willOnlyEmitTu() { return onlyTu; }
266286

287+
// Resets the value counter to 0
288+
void resetValueCounter();
289+
290+
// Increases the loop nesting level by 1
291+
void increaseLoopNestingLevel();
292+
293+
// Decreases the loop nesting level by 1
294+
void decreaseLoopNestingLevel();
295+
267296
private:
268297
using ValueMapper = llvm::ScopedHashTable<Value, std::string>;
269298
using BlockMapper = llvm::ScopedHashTable<Block *, std::string>;
@@ -288,11 +317,19 @@ struct CppEmitter {
288317
/// Map from block to name of C++ label.
289318
BlockMapper blockMapper;
290319

291-
/// The number of values in the current scope. This is used to declare the
292-
/// names of values in a scope.
293-
std::stack<int64_t> valueInScopeCount;
320+
/// Default values representing outermost scope
321+
llvm::ScopedHashTableScope<Value, std::string> defaultValueMapperScope;
322+
llvm::ScopedHashTableScope<Block *, std::string> defaultBlockMapperScope;
323+
294324
std::stack<int64_t> labelInScopeCount;
295325

326+
/// Keeps track of the amount of nested loops the emitter currently operates
327+
/// in.
328+
uint64_t loopNestingLevel{0};
329+
330+
/// Emitter-level count of created values to enable unique identifiers.
331+
unsigned int valueCount{0};
332+
296333
/// State of the current expression being emitted.
297334
ExpressionOp emittedExpression;
298335
SmallVector<int> emittedExpressionPrecedence;
@@ -911,7 +948,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
911948
}
912949

913950
static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
914-
915951
raw_indented_ostream &os = emitter.ostream();
916952

917953
// Utility function to determine whether a value is an expression that will be
@@ -930,12 +966,12 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
930966
emitter.emitType(forOp.getLoc(), forOp.getInductionVar().getType())))
931967
return failure();
932968
os << " ";
933-
os << emitter.getOrCreateName(forOp.getInductionVar());
969+
os << emitter.getOrCreateName(forOp);
934970
os << " = ";
935971
if (failed(emitter.emitOperand(forOp.getLowerBound())))
936972
return failure();
937973
os << "; ";
938-
os << emitter.getOrCreateName(forOp.getInductionVar());
974+
os << emitter.getOrCreateName(forOp);
939975
os << " < ";
940976
Value upperBound = forOp.getUpperBound();
941977
bool upperBoundRequiresParentheses = requiresParentheses(upperBound);
@@ -946,13 +982,15 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
946982
if (upperBoundRequiresParentheses)
947983
os << ")";
948984
os << "; ";
949-
os << emitter.getOrCreateName(forOp.getInductionVar());
985+
os << emitter.getOrCreateName(forOp);
950986
os << " += ";
951987
if (failed(emitter.emitOperand(forOp.getStep())))
952988
return failure();
953989
os << ") {\n";
954990
os.indent();
955991

992+
CppEmitter::LoopScope lScope(emitter);
993+
956994
Region &forRegion = forOp.getRegion();
957995
auto regionOps = forRegion.getOps();
958996

@@ -1039,8 +1077,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
10391077
}
10401078

10411079
static LogicalResult printOperation(CppEmitter &emitter, ModuleOp moduleOp) {
1042-
CppEmitter::Scope scope(emitter);
1043-
10441080
for (Operation &op : moduleOp) {
10451081
if (failed(emitter.emitOperation(op, /*trailingSemicolon=*/false)))
10461082
return failure();
@@ -1052,8 +1088,6 @@ static LogicalResult printOperation(CppEmitter &emitter, TranslationUnitOp tu) {
10521088
if (!emitter.shouldEmitTu(tu))
10531089
return success();
10541090

1055-
CppEmitter::Scope scope(emitter);
1056-
10571091
for (Operation &op : tu) {
10581092
if (failed(emitter.emitOperation(op, /*trailingSemicolon=*/false)))
10591093
return failure();
@@ -1216,7 +1250,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
12161250
return functionOp.emitOpError() << "cannot emit array type as result type";
12171251
}
12181252

1219-
CppEmitter::Scope scope(emitter);
1253+
CppEmitter::FunctionScope scope(emitter);
12201254
raw_indented_ostream &os = emitter.ostream();
12211255
if (failed(emitter.emitTypes(functionOp.getLoc(),
12221256
functionOp.getFunctionType().getResults())))
@@ -1244,7 +1278,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
12441278
"with multiple blocks needs variables declared at top");
12451279
}
12461280

1247-
CppEmitter::Scope scope(emitter);
1281+
CppEmitter::FunctionScope scope(emitter);
12481282
raw_indented_ostream &os = emitter.ostream();
12491283
if (functionOp.getSpecifiers()) {
12501284
for (Attribute specifier : functionOp.getSpecifiersAttr()) {
@@ -1278,7 +1312,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
12781312

12791313
static LogicalResult printOperation(CppEmitter &emitter,
12801314
DeclareFuncOp declareFuncOp) {
1281-
CppEmitter::Scope scope(emitter);
12821315
raw_indented_ostream &os = emitter.ostream();
12831316

12841317
auto functionOp = SymbolTable::lookupNearestSymbolFrom<emitc::FuncOp>(
@@ -1310,8 +1343,9 @@ static LogicalResult printOperation(CppEmitter &emitter,
13101343
CppEmitter::CppEmitter(raw_ostream &os, bool declareVariablesAtTop,
13111344
StringRef onlyTu, bool constantsAsVariables)
13121345
: os(os), declareVariablesAtTop(declareVariablesAtTop),
1313-
onlyTu(onlyTu.str()), constantsAsVariables(constantsAsVariables) {
1314-
valueInScopeCount.push(0);
1346+
onlyTu(onlyTu.str()), constantsAsVariables(constantsAsVariables),
1347+
defaultValueMapperScope(valueMapper),
1348+
defaultBlockMapperScope(blockMapper) {
13151349
labelInScopeCount.push(0);
13161350
}
13171351

@@ -1352,7 +1386,29 @@ StringRef CppEmitter::getOrCreateName(Value val) {
13521386
assert(!hasDeferredEmission(val.getDefiningOp()) &&
13531387
"cacheDeferredOpResult should have been called on this value, "
13541388
"update the emitOperation function.");
1355-
valueMapper.insert(val, formatv("v{0}", ++valueInScopeCount.top()));
1389+
1390+
valueMapper.insert(val, formatv("v{0}", ++valueCount));
1391+
}
1392+
return *valueMapper.begin(val);
1393+
}
1394+
1395+
/// Return the existing or a new name for a loop induction variable Value.
1396+
/// Loop induction variables follow natural naming: i, j, k,...
1397+
StringRef CppEmitter::getOrCreateName(emitc::ForOp forOp) {
1398+
Value val = forOp.getInductionVar();
1399+
1400+
if (!valueMapper.count(val)) {
1401+
1402+
int64_t identifier = 'i' + loopNestingLevel;
1403+
1404+
if (identifier >= 'i' && identifier <= 'z') {
1405+
valueMapper.insert(val,
1406+
formatv("{0}_{1}", (char)identifier, ++valueCount));
1407+
} else {
1408+
// If running out of letters, continue with zX
1409+
valueMapper.insert(
1410+
val, formatv("z{0}_{1}", identifier - 'z' - 1, ++valueCount));
1411+
}
13561412
}
13571413
return *valueMapper.begin(val);
13581414
}
@@ -1946,6 +2002,12 @@ LogicalResult CppEmitter::emitTupleType(Location loc, ArrayRef<Type> types) {
19462002
return success();
19472003
}
19482004

2005+
void CppEmitter::resetValueCounter() { valueCount = 0; }
2006+
2007+
void CppEmitter::increaseLoopNestingLevel() { loopNestingLevel++; }
2008+
2009+
void CppEmitter::decreaseLoopNestingLevel() { loopNestingLevel--; }
2010+
19492011
LogicalResult emitc::translateToCpp(Operation *op, raw_ostream &os,
19502012
bool declareVariablesAtTop,
19512013
StringRef onlyTu,

mlir/test/Target/Cpp/emitc-constants-as-variables.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ func.func @test() {
1212
return
1313
}
1414
// CPP-DEFAULT-LABEL: void test() {
15-
// CPP-DEFAULT-NEXT: for (size_t v1 = (size_t) 0; v1 < (size_t) 10; v1 += (size_t) 1) {
15+
// CPP-DEFAULT-NEXT: for (size_t [[V1:[^ ]*]] = (size_t) 0; [[V1]] < (size_t) 10; [[V1]] += (size_t) 1) {
1616
// CPP-DEFAULT-NEXT: }
1717
// CPP-DEFAULT-NEXT: return;
1818
// CPP-DEFAULT-NEXT: }
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
2+
3+
// CHECK-LABEL: test_for_siblings
4+
func.func @test_for_siblings() {
5+
%start = "emitc.constant"() <{value = 0 : index}> : () -> !emitc.size_t
6+
%stop = "emitc.constant"() <{value = 10 : index}> : () -> !emitc.size_t
7+
%step = "emitc.constant"() <{value = 1 : index}> : () -> !emitc.size_t
8+
9+
%var1 = "emitc.variable"() <{value = 0 : index}> : () -> !emitc.lvalue<!emitc.size_t>
10+
%var2 = "emitc.variable"() <{value = 0 : index}> : () -> !emitc.lvalue<!emitc.size_t>
11+
12+
// CHECK: for (size_t [[ITER0:i_[0-9]*]] = {{.*}}; [[ITER0]] < {{.*}}; [[ITER0]] += {{.*}}) {
13+
emitc.for %i0 = %start to %stop step %step {
14+
// CHECK: for (size_t [[ITER1:j_[0-9]*]] = {{.*}}; [[ITER1]] < {{.*}}; [[ITER1]] += {{.*}}) {
15+
emitc.for %i1 = %start to %stop step %step {
16+
// CHECK: {{.*}} = [[ITER0]];
17+
"emitc.assign"(%var1,%i0) : (!emitc.lvalue<!emitc.size_t>, !emitc.size_t) -> ()
18+
// CHECK: {{.*}} = [[ITER1]];
19+
"emitc.assign"(%var2,%i1) : (!emitc.lvalue<!emitc.size_t>, !emitc.size_t) -> ()
20+
}
21+
}
22+
// CHECK: for (size_t [[ITER2:i_[0-9]*]] = {{.*}}; [[ITER2]] < {{.*}}; [[ITER2]] += {{.*}})
23+
emitc.for %ki2 = %start to %stop step %step {
24+
// CHECK: for (size_t [[ITER3:j_[0-9]*]] = {{.*}}; [[ITER3]] < {{.*}}; [[ITER3]] += {{.*}})
25+
emitc.for %i3 = %start to %stop step %step {
26+
%1 = emitc.call_opaque "f"() : () -> i32
27+
}
28+
}
29+
return
30+
}
31+
32+
// CHECK-LABEL: test_for_nesting
33+
func.func @test_for_nesting() {
34+
%start = "emitc.constant"() <{value = 0 : index}> : () -> !emitc.size_t
35+
%stop = "emitc.constant"() <{value = 10 : index}> : () -> !emitc.size_t
36+
%step = "emitc.constant"() <{value = 1 : index}> : () -> !emitc.size_t
37+
38+
// CHECK-COUNT-18: for (size_t [[ITER:[i-z]_[0-9]*]] = {{.*}}; [[ITER]] < {{.*}}; [[ITER]] += {{.*}}) {
39+
emitc.for %i0 = %start to %stop step %step {
40+
emitc.for %i1 = %start to %stop step %step {
41+
emitc.for %i2 = %start to %stop step %step {
42+
emitc.for %i3 = %start to %stop step %step {
43+
emitc.for %i4 = %start to %stop step %step {
44+
emitc.for %i5 = %start to %stop step %step {
45+
emitc.for %i6 = %start to %stop step %step {
46+
emitc.for %i7 = %start to %stop step %step {
47+
emitc.for %i8 = %start to %stop step %step {
48+
emitc.for %i9 = %start to %stop step %step {
49+
emitc.for %i10 = %start to %stop step %step {
50+
emitc.for %i11 = %start to %stop step %step {
51+
emitc.for %i12 = %start to %stop step %step {
52+
emitc.for %i13 = %start to %stop step %step {
53+
emitc.for %i14 = %start to %stop step %step {
54+
emitc.for %i15 = %start to %stop step %step {
55+
emitc.for %i16 = %start to %stop step %step {
56+
emitc.for %i17 = %start to %stop step %step {
57+
// CHECK: for (size_t [[ITERz0:z0_[0-9]*]] = {{.*}}; [[ITERz0]] < {{.*}}; [[ITERz0]] += {{.*}}) {
58+
emitc.for %i18 = %start to %stop step %step {
59+
// CHECK: for (size_t [[ITERz1:z1_[0-9]*]] = {{.*}}; [[ITERz1]] < {{.*}}; [[ITERz1]] += {{.*}}) {
60+
emitc.for %i19 = %start to %stop step %step {
61+
%0 = emitc.call_opaque "f"() : () -> i32
62+
}
63+
}
64+
}
65+
}
66+
}
67+
}
68+
}
69+
}
70+
}
71+
}
72+
}
73+
}
74+
}
75+
}
76+
}
77+
}
78+
}
79+
}
80+
}
81+
}
82+
return
83+
}

0 commit comments

Comments
 (0)