@@ -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+
256285private:
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
862899static 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
9901028static 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
10001036static 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
12241257static 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,
12551287CppEmitter::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+
18411898LogicalResult emitc::translateToCpp (Operation *op, raw_ostream &os,
18421899 bool declareVariablesAtTop,
18431900 StringRef fileId) {
0 commit comments