Skip to content

Commit 6937bb0

Browse files
author
git apple-llvm automerger
committed
Merge commit 'dcc692a42f6a' from llvm.org/main into next
2 parents 5808950 + dcc692a commit 6937bb0

File tree

2 files changed

+157
-27
lines changed

2 files changed

+157
-27
lines changed

mlir/lib/Target/Cpp/TranslateToCpp.cpp

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

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

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

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

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

223243
/// Returns wether the Value is assigned to a C++ variable in the scope.
@@ -253,6 +273,15 @@ struct CppEmitter {
253273
return operandExpression == emittedExpression;
254274
};
255275

276+
// Resets the value counter to 0.
277+
void resetValueCounter();
278+
279+
// Increases the loop nesting level by 1.
280+
void increaseLoopNestingLevel();
281+
282+
// Decreases the loop nesting level by 1.
283+
void decreaseLoopNestingLevel();
284+
256285
private:
257286
using ValueMapper = llvm::ScopedHashTable<Value, std::string>;
258287
using BlockMapper = llvm::ScopedHashTable<Block *, std::string>;
@@ -274,11 +303,19 @@ struct CppEmitter {
274303
/// Map from block to name of C++ label.
275304
BlockMapper blockMapper;
276305

277-
/// The number of values in the current scope. This is used to declare the
278-
/// names of values in a scope.
279-
std::stack<int64_t> valueInScopeCount;
306+
/// Default values representing outermost scope.
307+
llvm::ScopedHashTableScope<Value, std::string> defaultValueMapperScope;
308+
llvm::ScopedHashTableScope<Block *, std::string> defaultBlockMapperScope;
309+
280310
std::stack<int64_t> labelInScopeCount;
281311

312+
/// Keeps track of the amount of nested loops the emitter currently operates
313+
/// in.
314+
uint64_t loopNestingLevel{0};
315+
316+
/// Emitter-level count of created values to enable unique identifiers.
317+
unsigned int valueCount{0};
318+
282319
/// State of the current expression being emitted.
283320
ExpressionOp emittedExpression;
284321
SmallVector<int> emittedExpressionPrecedence;
@@ -860,7 +897,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
860897
}
861898

862899
static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
863-
864900
raw_indented_ostream &os = emitter.ostream();
865901

866902
// Utility function to determine whether a value is an expression that will be
@@ -879,12 +915,12 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
879915
emitter.emitType(forOp.getLoc(), forOp.getInductionVar().getType())))
880916
return failure();
881917
os << " ";
882-
os << emitter.getOrCreateName(forOp.getInductionVar());
918+
os << emitter.getOrCreateInductionVarName(forOp.getInductionVar());
883919
os << " = ";
884920
if (failed(emitter.emitOperand(forOp.getLowerBound())))
885921
return failure();
886922
os << "; ";
887-
os << emitter.getOrCreateName(forOp.getInductionVar());
923+
os << emitter.getOrCreateInductionVarName(forOp.getInductionVar());
888924
os << " < ";
889925
Value upperBound = forOp.getUpperBound();
890926
bool upperBoundRequiresParentheses = requiresParentheses(upperBound);
@@ -895,13 +931,15 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
895931
if (upperBoundRequiresParentheses)
896932
os << ")";
897933
os << "; ";
898-
os << emitter.getOrCreateName(forOp.getInductionVar());
934+
os << emitter.getOrCreateInductionVarName(forOp.getInductionVar());
899935
os << " += ";
900936
if (failed(emitter.emitOperand(forOp.getStep())))
901937
return failure();
902938
os << ") {\n";
903939
os.indent();
904940

941+
CppEmitter::LoopScope lScope(emitter);
942+
905943
Region &forRegion = forOp.getRegion();
906944
auto regionOps = forRegion.getOps();
907945

@@ -988,8 +1026,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
9881026
}
9891027

9901028
static LogicalResult printOperation(CppEmitter &emitter, ModuleOp moduleOp) {
991-
CppEmitter::Scope scope(emitter);
992-
9931029
for (Operation &op : moduleOp) {
9941030
if (failed(emitter.emitOperation(op, /*trailingSemicolon=*/false)))
9951031
return failure();
@@ -998,7 +1034,6 @@ static LogicalResult printOperation(CppEmitter &emitter, ModuleOp moduleOp) {
9981034
}
9991035

10001036
static LogicalResult printOperation(CppEmitter &emitter, ClassOp classOp) {
1001-
CppEmitter::Scope classScope(emitter);
10021037
raw_indented_ostream &os = emitter.ostream();
10031038
os << "class " << classOp.getSymName();
10041039
if (classOp.getFinalSpecifier())
@@ -1044,8 +1079,6 @@ static LogicalResult printOperation(CppEmitter &emitter, FileOp file) {
10441079
if (!emitter.shouldEmitFile(file))
10451080
return success();
10461081

1047-
CppEmitter::Scope scope(emitter);
1048-
10491082
for (Operation &op : file) {
10501083
if (failed(emitter.emitOperation(op, /*trailingSemicolon=*/false)))
10511084
return failure();
@@ -1161,7 +1194,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
11611194
return functionOp.emitOpError() << "cannot emit array type as result type";
11621195
}
11631196

1164-
CppEmitter::Scope scope(emitter);
1197+
CppEmitter::FunctionScope scope(emitter);
11651198
raw_indented_ostream &os = emitter.ostream();
11661199
if (failed(emitter.emitTypes(functionOp.getLoc(),
11671200
functionOp.getFunctionType().getResults())))
@@ -1189,7 +1222,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
11891222
"with multiple blocks needs variables declared at top");
11901223
}
11911224

1192-
CppEmitter::Scope scope(emitter);
1225+
CppEmitter::FunctionScope scope(emitter);
11931226
raw_indented_ostream &os = emitter.ostream();
11941227
if (functionOp.getSpecifiers()) {
11951228
for (Attribute specifier : functionOp.getSpecifiersAttr()) {
@@ -1223,7 +1256,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
12231256

12241257
static LogicalResult printOperation(CppEmitter &emitter,
12251258
DeclareFuncOp declareFuncOp) {
1226-
CppEmitter::Scope scope(emitter);
12271259
raw_indented_ostream &os = emitter.ostream();
12281260

12291261
auto functionOp = SymbolTable::lookupNearestSymbolFrom<emitc::FuncOp>(
@@ -1255,8 +1287,8 @@ static LogicalResult printOperation(CppEmitter &emitter,
12551287
CppEmitter::CppEmitter(raw_ostream &os, bool declareVariablesAtTop,
12561288
StringRef fileId)
12571289
: os(os), declareVariablesAtTop(declareVariablesAtTop),
1258-
fileId(fileId.str()) {
1259-
valueInScopeCount.push(0);
1290+
fileId(fileId.str()), defaultValueMapperScope(valueMapper),
1291+
defaultBlockMapperScope(blockMapper) {
12601292
labelInScopeCount.push(0);
12611293
}
12621294

@@ -1297,7 +1329,26 @@ StringRef CppEmitter::getOrCreateName(Value val) {
12971329
assert(!hasDeferredEmission(val.getDefiningOp()) &&
12981330
"cacheDeferredOpResult should have been called on this value, "
12991331
"update the emitOperation function.");
1300-
valueMapper.insert(val, formatv("v{0}", ++valueInScopeCount.top()));
1332+
1333+
valueMapper.insert(val, formatv("v{0}", ++valueCount));
1334+
}
1335+
return *valueMapper.begin(val);
1336+
}
1337+
1338+
/// Return the existing or a new name for a loop induction variable Value.
1339+
/// Loop induction variables follow natural naming: i, j, k, ..., t, uX.
1340+
StringRef CppEmitter::getOrCreateInductionVarName(Value val) {
1341+
if (!valueMapper.count(val)) {
1342+
1343+
int64_t identifier = 'i' + loopNestingLevel;
1344+
1345+
if (identifier >= 'i' && identifier <= 't') {
1346+
valueMapper.insert(val,
1347+
formatv("{0}{1}", (char)identifier, ++valueCount));
1348+
} else {
1349+
// If running out of letters, continue with uX.
1350+
valueMapper.insert(val, formatv("u{0}", ++valueCount));
1351+
}
13011352
}
13021353
return *valueMapper.begin(val);
13031354
}
@@ -1838,6 +1889,12 @@ LogicalResult CppEmitter::emitTupleType(Location loc, ArrayRef<Type> types) {
18381889
return success();
18391890
}
18401891

1892+
void CppEmitter::resetValueCounter() { valueCount = 0; }
1893+
1894+
void CppEmitter::increaseLoopNestingLevel() { loopNestingLevel++; }
1895+
1896+
void CppEmitter::decreaseLoopNestingLevel() { loopNestingLevel--; }
1897+
18411898
LogicalResult emitc::translateToCpp(Operation *op, raw_ostream &os,
18421899
bool declareVariablesAtTop,
18431900
StringRef fileId) {
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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.literal "0" : index
6+
%stop = emitc.literal "10" : index
7+
%step = emitc.literal "1" : index
8+
9+
%var1 = "emitc.variable"() <{value = 0 : index}> : () -> !emitc.lvalue<index>
10+
%var2 = "emitc.variable"() <{value = 0 : index}> : () -> !emitc.lvalue<index>
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+
emitc.assign %i0 : index to %var1 : !emitc.lvalue<index>
19+
// CHECK: {{.*}} = [[ITER1]];
20+
//"emitc.assign"(%var2,%i1) : (!emitc.lvalue<!emitc.size_t>, !emitc.size_t) -> ()
21+
emitc.assign %i1 : index to %var2 : !emitc.lvalue<index>
22+
}
23+
}
24+
// CHECK: for (size_t [[ITER2:i[0-9]*]] = {{.*}}; [[ITER2]] < {{.*}}; [[ITER2]] += {{.*}})
25+
emitc.for %ki2 = %start to %stop step %step {
26+
// CHECK: for (size_t [[ITER3:j[0-9]*]] = {{.*}}; [[ITER3]] < {{.*}}; [[ITER3]] += {{.*}})
27+
emitc.for %i3 = %start to %stop step %step {
28+
%1 = emitc.call_opaque "f"() : () -> i32
29+
}
30+
}
31+
return
32+
}
33+
34+
// CHECK-LABEL: test_for_nesting
35+
func.func @test_for_nesting() {
36+
%start = emitc.literal "0" : index
37+
%stop = emitc.literal "10" : index
38+
%step = emitc.literal "1" : index
39+
40+
// CHECK-COUNT-12: for (size_t [[ITER:[i-t][0-9]*]] = {{.*}}; [[ITER]] < {{.*}}; [[ITER]] += {{.*}}) {
41+
emitc.for %i0 = %start to %stop step %step {
42+
emitc.for %i1 = %start to %stop step %step {
43+
emitc.for %i2 = %start to %stop step %step {
44+
emitc.for %i3 = %start to %stop step %step {
45+
emitc.for %i4 = %start to %stop step %step {
46+
emitc.for %i5 = %start to %stop step %step {
47+
emitc.for %i6 = %start to %stop step %step {
48+
emitc.for %i7 = %start to %stop step %step {
49+
emitc.for %i8 = %start to %stop step %step {
50+
emitc.for %i9 = %start to %stop step %step {
51+
emitc.for %i10 = %start to %stop step %step {
52+
emitc.for %i11 = %start to %stop step %step {
53+
// CHECK: for (size_t [[ITERu0:u13]] = {{.*}}; [[ITERu0]] < {{.*}}; [[ITERu0]] += {{.*}}) {
54+
emitc.for %i14 = %start to %stop step %step {
55+
// CHECK: for (size_t [[ITERu1:u14]] = {{.*}}; [[ITERu1]] < {{.*}}; [[ITERu1]] += {{.*}}) {
56+
emitc.for %i15 = %start to %stop step %step {
57+
%0 = emitc.call_opaque "f"() : () -> i32
58+
}
59+
}
60+
}
61+
}
62+
}
63+
}
64+
}
65+
}
66+
}
67+
}
68+
}
69+
}
70+
}
71+
}
72+
return
73+
}

0 commit comments

Comments
 (0)