Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions mlir/lib/Target/Cpp/TranslateToCpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ struct CppEmitter {
/// Return the existing or a new name for a Value.
StringRef getOrCreateName(Value val);

// Return the existing or a new name for an iteration variable Value
StringRef getOrCreateName(emitc::ForOp forOp);

// Returns the textual representation of a subscript operation.
std::string getSubscriptName(emitc::SubscriptOp op);

Expand All @@ -204,17 +207,22 @@ struct CppEmitter {
struct Scope {
Scope(CppEmitter &emitter)
: valueMapperScope(emitter.valueMapper),
iterationVarMapperScope(emitter.iterationVarMapper),
blockMapperScope(emitter.blockMapper), emitter(emitter) {
emitter.valueInScopeCount.push(emitter.valueInScopeCount.top());
emitter.iterationVarInScopeCount.push(
emitter.iterationVarInScopeCount.top());
emitter.labelInScopeCount.push(emitter.labelInScopeCount.top());
}
~Scope() {
emitter.valueInScopeCount.pop();
emitter.iterationVarInScopeCount.pop();
emitter.labelInScopeCount.pop();
}

private:
llvm::ScopedHashTableScope<Value, std::string> valueMapperScope;
llvm::ScopedHashTableScope<Value, std::string> iterationVarMapperScope;
llvm::ScopedHashTableScope<Block *, std::string> blockMapperScope;
CppEmitter &emitter;
};
Expand Down Expand Up @@ -285,12 +293,16 @@ struct CppEmitter {
/// Map from value to name of C++ variable that contain the name.
ValueMapper valueMapper;

// Map from value to name of C++ iteration variable that contains the name.
ValueMapper iterationVarMapper;

/// Map from block to name of C++ label.
BlockMapper blockMapper;

/// The number of values in the current scope. This is used to declare the
/// names of values in a scope.
std::stack<int64_t> valueInScopeCount;
std::stack<int64_t> iterationVarInScopeCount;
std::stack<int64_t> labelInScopeCount;

/// State of the current expression being emitted.
Expand Down Expand Up @@ -930,12 +942,12 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
emitter.emitType(forOp.getLoc(), forOp.getInductionVar().getType())))
return failure();
os << " ";
os << emitter.getOrCreateName(forOp.getInductionVar());
os << emitter.getOrCreateName(forOp);
os << " = ";
if (failed(emitter.emitOperand(forOp.getLowerBound())))
return failure();
os << "; ";
os << emitter.getOrCreateName(forOp.getInductionVar());
os << emitter.getOrCreateName(forOp);
os << " < ";
Value upperBound = forOp.getUpperBound();
bool upperBoundRequiresParentheses = requiresParentheses(upperBound);
Expand All @@ -946,7 +958,7 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
if (upperBoundRequiresParentheses)
os << ")";
os << "; ";
os << emitter.getOrCreateName(forOp.getInductionVar());
os << emitter.getOrCreateName(forOp);
os << " += ";
if (failed(emitter.emitOperand(forOp.getStep())))
return failure();
Expand Down Expand Up @@ -1312,6 +1324,7 @@ CppEmitter::CppEmitter(raw_ostream &os, bool declareVariablesAtTop,
: os(os), declareVariablesAtTop(declareVariablesAtTop),
onlyTu(onlyTu.str()), constantsAsVariables(constantsAsVariables) {
valueInScopeCount.push(0);
iterationVarInScopeCount.push(0);
labelInScopeCount.push(0);
}

Expand Down Expand Up @@ -1348,15 +1361,39 @@ void CppEmitter::cacheDeferredOpResult(Value value, StringRef str) {

/// Return the existing or a new name for a Value.
StringRef CppEmitter::getOrCreateName(Value val) {
if (!valueMapper.count(val)) {
if (!valueMapper.count(val) && !iterationVarMapper.count(val)) {
assert(!hasDeferredEmission(val.getDefiningOp()) &&
"cacheDeferredOpResult should have been called on this value, "
"update the emitOperation function.");

valueMapper.insert(val, formatv("v{0}", ++valueInScopeCount.top()));
}
// Check whether value belongs to iteration variable
if (iterationVarMapper.count(val)) {
return *iterationVarMapper.begin(val);
}
return *valueMapper.begin(val);
}

/// Return the existing or a new name for an iteration variable Value.
// Iteration variables follow natural naming: i,j,k,...
StringRef CppEmitter::getOrCreateName(emitc::ForOp forOp) {
Value val = forOp.getInductionVar();

if (!iterationVarMapper.count(val)) {
int64_t incdCount = iterationVarInScopeCount.top()++;

if (incdCount >= 0 && incdCount <= 'z' - 'i') {
iterationVarMapper.insert(val, std::string(1, (char)(incdCount + 'i')));
} else {
// If running out of letters, continue with iX
iterationVarMapper.insert(val,
formatv("i{0}", incdCount - ('z' - 'i') - 1));
}
}
return *iterationVarMapper.begin(val);
}

/// Return the existing or a new label for a Block.
StringRef CppEmitter::getOrCreateName(Block &block) {
if (!blockMapper.count(&block))
Expand Down
145 changes: 145 additions & 0 deletions mlir/test/Target/Cpp/for_iteration_vars.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s -check-prefix=CPP-DEFAULT

func.func @test_for_siblings(%arg0 : !emitc.size_t, %arg1 : !emitc.size_t, %arg2 : !emitc.size_t) {
%lb = emitc.expression : !emitc.size_t {
%a = emitc.add %arg0, %arg1 : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
emitc.yield %a : !emitc.size_t
}
%ub = emitc.expression : !emitc.size_t {
%a = emitc.mul %arg1, %arg2 : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
emitc.yield %a : !emitc.size_t
}
%step = emitc.expression : !emitc.size_t {
%a = emitc.div %arg0, %arg2 : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
emitc.yield %a : !emitc.size_t
}
emitc.for %i0 = %lb to %ub step %step {
emitc.for %i1 = %lb to %ub step %step {
%0 = emitc.call_opaque "f"() : () -> i32
}
}
emitc.for %ki2 = %lb to %ub step %step {
emitc.for %i3 = %lb to %ub step %step {
%1 = emitc.call_opaque "f"() : () -> i32
}
}
return
}
// CPP-DEFAULT: void test_for_siblings(size_t [[V1:[^ ]*]], size_t [[V2:[^ ]*]], size_t [[V3:[^ ]*]]) {
// CPP-DEFAULT-NEXT: size_t [[V4:[^ ]*]] = [[V1]] + [[V2]];
// CPP-DEFAULT-NEXT: size_t [[V5:[^ ]*]] = [[V2]] * [[V3]];
// CPP-DEFAULT-NEXT: size_t [[V6:[^ ]*]] = [[V1]] / [[V3]];
// CPP-DEFAULT-NEXT: for (size_t [[ITER0:i]] = [[V4]]; [[ITER0]] < [[V5]]; [[ITER0]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITER1:j]] = [[V4]]; [[ITER1]] < [[V5]]; [[ITER1]] += [[V6]]) {
// CPP-DEFAULT-NEXT: int32_t [[V7:[^ ]*]] = f();
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: for (size_t [[ITER2:k]] = [[V4]]; [[ITER2]] < [[V5]]; [[ITER2]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITER3:l]] = [[V4]]; [[ITER3]] < [[V5]]; [[ITER3]] += [[V6]]) {
// CPP-DEFAULT-NEXT: int32_t [[V8:[^ ]*]] = f();
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: return;

func.func @test_for_nesting(%arg0 : !emitc.size_t, %arg1 : !emitc.size_t, %arg2 : !emitc.size_t) {
%lb = emitc.expression : !emitc.size_t {
%a = emitc.add %arg0, %arg1 : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
emitc.yield %a : !emitc.size_t
}
%ub = emitc.expression : !emitc.size_t {
%a = emitc.mul %arg1, %arg2 : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
emitc.yield %a : !emitc.size_t
}
%step = emitc.expression : !emitc.size_t {
%a = emitc.div %arg0, %arg2 : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
emitc.yield %a : !emitc.size_t
}
emitc.for %i0 = %lb to %ub step %step {
emitc.for %i1 = %lb to %ub step %step {
emitc.for %i2 = %lb to %ub step %step {
emitc.for %i3 = %lb to %ub step %step {
emitc.for %i4 = %lb to %ub step %step {
emitc.for %i5 = %lb to %ub step %step {
emitc.for %i6 = %lb to %ub step %step {
emitc.for %i7 = %lb to %ub step %step {
emitc.for %i8 = %lb to %ub step %step {
emitc.for %i9 = %lb to %ub step %step {
emitc.for %i10 = %lb to %ub step %step {
emitc.for %i11 = %lb to %ub step %step {
emitc.for %i12 = %lb to %ub step %step {
emitc.for %i13 = %lb to %ub step %step {
emitc.for %i14 = %lb to %ub step %step {
emitc.for %i15 = %lb to %ub step %step {
emitc.for %i16 = %lb to %ub step %step {
emitc.for %i17 = %lb to %ub step %step {
emitc.for %i18 = %lb to %ub step %step {
emitc.for %i19 = %lb to %ub step %step {
%0 = emitc.call_opaque "f"() : () -> i32
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
return
}
// CPP-DEFAULT: void test_for_nesting(size_t [[V1:[^ ]*]], size_t [[V2:[^ ]*]], size_t [[V3:[^ ]*]]) {
// CPP-DEFAULT-NEXT: size_t [[V4:[^ ]*]] = [[V1]] + [[V2]];
// CPP-DEFAULT-NEXT: size_t [[V5:[^ ]*]] = [[V2]] * [[V3]];
// CPP-DEFAULT-NEXT: size_t [[V6:[^ ]*]] = [[V1]] / [[V3]];
// CPP-DEFAULT-NEXT: for (size_t [[ITERi:i]] = [[V4]]; [[ITERi]] < [[V5]]; [[ITERi]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERj:j]] = [[V4]]; [[ITERj]] < [[V5]]; [[ITERj]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERk:[i-z]]] = [[V4]]; [[ITERk]] < [[V5]]; [[ITERk]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERl:[i-z]]] = [[V4]]; [[ITERl]] < [[V5]]; [[ITERl]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERm:[i-z]]] = [[V4]]; [[ITERm]] < [[V5]]; [[ITERm]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERn:[i-z]]] = [[V4]]; [[ITERn]] < [[V5]]; [[ITERn]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERo:[i-z]]] = [[V4]]; [[ITERo]] < [[V5]]; [[ITERo]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERp:[i-z]]] = [[V4]]; [[ITERp]] < [[V5]]; [[ITERp]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERq:[i-z]]] = [[V4]]; [[ITERq]] < [[V5]]; [[ITERq]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERr:[i-z]]] = [[V4]]; [[ITERr]] < [[V5]]; [[ITERr]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERs:[i-z]]] = [[V4]]; [[ITERs]] < [[V5]]; [[ITERs]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERt:[i-z]]] = [[V4]]; [[ITERt]] < [[V5]]; [[ITERt]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERu:[i-z]]] = [[V4]]; [[ITERu]] < [[V5]]; [[ITERu]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERv:[i-z]]] = [[V4]]; [[ITERv]] < [[V5]]; [[ITERv]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERw:[i-z]]] = [[V4]]; [[ITERw]] < [[V5]]; [[ITERw]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERx:[i-z]]] = [[V4]]; [[ITERx]] < [[V5]]; [[ITERx]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERy:[i-z]]] = [[V4]]; [[ITERy]] < [[V5]]; [[ITERy]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERz:z]] = [[V4]]; [[ITERz]] < [[V5]]; [[ITERz]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERi0:i0]] = [[V4]]; [[ITERi0]] < [[V5]]; [[ITERi0]] += [[V6]]) {
// CPP-DEFAULT-NEXT: for (size_t [[ITERi1:i1]] = [[V4]]; [[ITERi1]] < [[V5]]; [[ITERi1]] += [[V6]]) {
// CPP-DEFAULT-NEXT: int32_t [[V7:[^ ]*]] = f();
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: return;
Loading