@@ -174,6 +174,9 @@ struct CppEmitter {
174
174
// / Emit an expression as a C expression.
175
175
LogicalResult emitExpression (ExpressionOp expressionOp);
176
176
177
+ // / Insert the expression representing the operation into the value cache.
178
+ LogicalResult cacheDeferredOpResult (Operation *op);
179
+
177
180
// / Return the existing or a new name for a Value.
178
181
StringRef getOrCreateName (Value val);
179
182
@@ -273,6 +276,18 @@ struct CppEmitter {
273
276
};
274
277
} // namespace
275
278
279
+ // / Determine whether expression \p op should be emitted in a deferred way.
280
+ static bool hasDeferredEmission (Operation *op) {
281
+ if (isa_and_nonnull<emitc::GetGlobalOp, emitc::LiteralOp, emitc::SubscriptOp>(
282
+ op))
283
+ return true ;
284
+
285
+ if (auto applyOp = dyn_cast_or_null<emitc::ApplyOp>(op))
286
+ return applyOp.getApplicableOperator () == " *" ;
287
+
288
+ return false ;
289
+ }
290
+
276
291
// / Determine whether expression \p expressionOp should be emitted inline, i.e.
277
292
// / as part of its user. This function recommends inlining of any expressions
278
293
// / that can be inlined unless it is used by another expression, under the
@@ -295,10 +310,10 @@ static bool shouldBeInlined(ExpressionOp expressionOp) {
295
310
296
311
Operation *user = *result.getUsers ().begin ();
297
312
298
- // Do not inline expressions used by subscript operations, since the
299
- // way the subscript operation translation is implemented requires that
300
- // variables be materialized.
301
- if (isa<emitc::SubscriptOp, emitc::GetGlobalOp> (user))
313
+ // Do not inline expressions used by operations with deferred emission , since
314
+ // the way their translation is implemented requires that variables be
315
+ // materialized.
316
+ if (hasDeferredEmission (user))
302
317
return false ;
303
318
304
319
// Do not inline expressions used by ops with the CExpression trait. If this
@@ -370,13 +385,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
370
385
return emitter.emitOperand (assignOp.getValue ());
371
386
}
372
387
373
- static LogicalResult printOperation (CppEmitter &emitter,
374
- emitc::GetGlobalOp op) {
375
- // Add name to cache so that `hasValueInScope` works.
376
- emitter.getOrCreateName (op.getResult ());
377
- return success ();
378
- }
379
-
380
388
static LogicalResult printOperation (CppEmitter &emitter,
381
389
emitc::LValueLoadOp lValueLoadOp) {
382
390
if (failed (emitter.emitAssignPrefix (*lValueLoadOp)))
@@ -385,13 +393,6 @@ static LogicalResult printOperation(CppEmitter &emitter,
385
393
return emitter.emitOperand (lValueLoadOp.getOperand ());
386
394
}
387
395
388
- static LogicalResult printOperation (CppEmitter &emitter,
389
- emitc::SubscriptOp subscriptOp) {
390
- // Add name to cache so that `hasValueInScope` works.
391
- emitter.getOrCreateName (subscriptOp.getResult ());
392
- return success ();
393
- }
394
-
395
396
static LogicalResult printBinaryOperation (CppEmitter &emitter,
396
397
Operation *operation,
397
398
StringRef binaryOperator) {
@@ -629,9 +630,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
629
630
if (t.getType ().isIndex ()) {
630
631
int64_t idx = t.getInt ();
631
632
Value operand = op.getOperand (idx);
632
- auto literalDef =
633
- dyn_cast_if_present<LiteralOp>(operand.getDefiningOp ());
634
- if (!literalDef && !emitter.hasValueInScope (operand))
633
+ if (!emitter.hasValueInScope (operand))
635
634
return op.emitOpError (" operand " )
636
635
<< idx << " 's value not defined in scope" ;
637
636
os << emitter.getOrCreateName (operand);
@@ -668,6 +667,10 @@ static LogicalResult printOperation(CppEmitter &emitter,
668
667
emitc::ApplyOp applyOp) {
669
668
raw_ostream &os = emitter.ostream ();
670
669
Operation &op = *applyOp.getOperation ();
670
+ StringRef applicableOp = applyOp.getApplicableOperator ();
671
+
672
+ if (applicableOp == " *" )
673
+ return emitter.cacheDeferredOpResult (applyOp);
671
674
672
675
if (failed (emitter.emitAssignPrefix (op)))
673
676
return failure ();
@@ -956,8 +959,7 @@ static LogicalResult printFunctionBody(CppEmitter &emitter,
956
959
// regions.
957
960
WalkResult result =
958
961
functionOp->walk <WalkOrder::PreOrder>([&](Operation *op) -> WalkResult {
959
- if (isa<emitc::LiteralOp>(op) ||
960
- isa<emitc::ExpressionOp>(op->getParentOp ()) ||
962
+ if (isa<emitc::ExpressionOp>(op->getParentOp ()) ||
961
963
(isa<emitc::ExpressionOp>(op) &&
962
964
shouldBeInlined (cast<emitc::ExpressionOp>(op))))
963
965
return WalkResult::skip ();
@@ -1009,7 +1011,8 @@ static LogicalResult printFunctionBody(CppEmitter &emitter,
1009
1011
// trailing semicolon is handled within the printOperation function.
1010
1012
bool trailingSemicolon =
1011
1013
!isa<cf::CondBranchOp, emitc::DeclareFuncOp, emitc::ForOp,
1012
- emitc::IfOp, emitc::LiteralOp, emitc::VerbatimOp>(op);
1014
+ emitc::IfOp, emitc::VerbatimOp>(op) ||
1015
+ hasDeferredEmission (&op);
1013
1016
1014
1017
if (failed (emitter.emitOperation (
1015
1018
op, /* trailingSemicolon=*/ trailingSemicolon)))
@@ -1142,20 +1145,48 @@ std::string CppEmitter::getSubscriptName(emitc::SubscriptOp op) {
1142
1145
return out;
1143
1146
}
1144
1147
1148
+ LogicalResult CppEmitter::cacheDeferredOpResult (Operation *op) {
1149
+ if (op->getNumResults () != 1 )
1150
+ return op->emitError (" Adding deferred ops into value cahce only works for "
1151
+ " single results operations, got " )
1152
+ << op->getNumResults () << " results" ;
1153
+
1154
+ Value result = op->getResult (0 );
1155
+ if (valueMapper.count (result))
1156
+ return success ();
1157
+
1158
+ if (auto applyOp = dyn_cast<emitc::ApplyOp>(op)) {
1159
+ assert (applyOp.getApplicableOperator () == " *" && " expected derefernce" );
1160
+ valueMapper.insert (result, std::string (" *" ) +
1161
+ getOrCreateName (applyOp.getOperand ()).str ());
1162
+ return success ();
1163
+ }
1164
+
1165
+ if (auto getGlobal = dyn_cast<emitc::GetGlobalOp>(op)) {
1166
+ valueMapper.insert (result, getGlobal.getName ().str ());
1167
+ return success ();
1168
+ }
1169
+
1170
+ if (auto literal = dyn_cast<emitc::LiteralOp>(op)) {
1171
+ valueMapper.insert (result, literal.getValue ().str ());
1172
+ return success ();
1173
+ }
1174
+
1175
+ if (auto subscript = dyn_cast<emitc::SubscriptOp>(op)) {
1176
+ valueMapper.insert (result, getSubscriptName (subscript));
1177
+ return success ();
1178
+ }
1179
+
1180
+ return op->emitError (" cacheDeferredOpResult not implemented" );
1181
+ }
1182
+
1145
1183
// / Return the existing or a new name for a Value.
1146
1184
StringRef CppEmitter::getOrCreateName (Value val) {
1147
- if (auto literal = dyn_cast_if_present<emitc::LiteralOp>(val.getDefiningOp ()))
1148
- return literal.getValue ();
1149
1185
if (!valueMapper.count (val)) {
1150
- if (auto subscript =
1151
- dyn_cast_if_present<emitc::SubscriptOp>(val.getDefiningOp ())) {
1152
- valueMapper.insert (val, getSubscriptName (subscript));
1153
- } else if (auto getGlobal = dyn_cast_if_present<emitc::GetGlobalOp>(
1154
- val.getDefiningOp ())) {
1155
- valueMapper.insert (val, getGlobal.getName ().str ());
1156
- } else {
1157
- valueMapper.insert (val, formatv (" v{0}" , ++valueInScopeCount.top ()));
1158
- }
1186
+ assert (!hasDeferredEmission (val.getDefiningOp ()) &&
1187
+ " cacheDeferredOpResult should have been called on this value, "
1188
+ " update the emitOperation function." );
1189
+ valueMapper.insert (val, formatv (" v{0}" , ++valueInScopeCount.top ()));
1159
1190
}
1160
1191
return *valueMapper.begin (val);
1161
1192
}
@@ -1349,9 +1380,6 @@ LogicalResult CppEmitter::emitOperand(Value value) {
1349
1380
if (expressionOp && shouldBeInlined (expressionOp))
1350
1381
return emitExpression (expressionOp);
1351
1382
1352
- auto literalOp = dyn_cast_if_present<LiteralOp>(value.getDefiningOp ());
1353
- if (!literalOp && !hasValueInScope (value))
1354
- return failure ();
1355
1383
os << getOrCreateName (value);
1356
1384
return success ();
1357
1385
}
@@ -1407,7 +1435,7 @@ LogicalResult CppEmitter::emitVariableAssignment(OpResult result) {
1407
1435
1408
1436
LogicalResult CppEmitter::emitVariableDeclaration (OpResult result,
1409
1437
bool trailingSemicolon) {
1410
- if (isa<emitc::SubscriptOp, emitc::GetGlobalOp> (result.getDefiningOp ()))
1438
+ if (hasDeferredEmission (result.getDefiningOp ()))
1411
1439
return success ();
1412
1440
if (hasValueInScope (result)) {
1413
1441
return result.getDefiningOp ()->emitError (
@@ -1506,25 +1534,25 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
1506
1534
emitc::CallOpaqueOp, emitc::CastOp, emitc::CmpOp,
1507
1535
emitc::ConditionalOp, emitc::ConstantOp, emitc::DeclareFuncOp,
1508
1536
emitc::DivOp, emitc::ExpressionOp, emitc::ForOp, emitc::FuncOp,
1509
- emitc::GlobalOp, emitc::GetGlobalOp, emitc::IfOp,
1510
- emitc::IncludeOp, emitc::LogicalAndOp, emitc::LogicalNotOp,
1511
- emitc::LogicalOrOp, emitc::LValueLoadOp, emitc::MulOp,
1512
- emitc::RemOp, emitc::ReturnOp, emitc::SubOp, emitc::SubscriptOp,
1513
- emitc::UnaryMinusOp, emitc::UnaryPlusOp, emitc::VariableOp,
1514
- emitc::VerbatimOp>(
1537
+ emitc::GlobalOp, emitc::IfOp, emitc::IncludeOp,
1538
+ emitc::LogicalAndOp, emitc::LogicalNotOp, emitc::LogicalOrOp,
1539
+ emitc::LValueLoadOp, emitc::MulOp, emitc::RemOp,
1540
+ emitc::ReturnOp, emitc::SubOp, emitc::UnaryMinusOp,
1541
+ emitc::UnaryPlusOp, emitc::VariableOp, emitc::VerbatimOp>(
1515
1542
[&](auto op) { return printOperation (*this , op); })
1516
1543
// Func ops.
1517
1544
.Case <func::CallOp, func::FuncOp, func::ReturnOp>(
1518
1545
[&](auto op) { return printOperation (*this , op); })
1519
- .Case <emitc::LiteralOp>([&](auto op) { return success (); })
1546
+ .Case <emitc::GetGlobalOp, emitc::LiteralOp, emitc::SubscriptOp>(
1547
+ [&](Operation *op) { return cacheDeferredOpResult (op); })
1520
1548
.Default ([&](Operation *) {
1521
1549
return op.emitOpError (" unable to find printer for op" );
1522
1550
});
1523
1551
1524
1552
if (failed (status))
1525
1553
return failure ();
1526
1554
1527
- if (isa<emitc::LiteralOp, emitc::SubscriptOp, emitc::GetGlobalOp>( op))
1555
+ if (hasDeferredEmission (& op))
1528
1556
return success ();
1529
1557
1530
1558
if (getEmittedExpression () ||
0 commit comments