@@ -978,11 +978,12 @@ struct SPIRVEmitContext
978
978
template <typename ... Operands>
979
979
SpvInst* emitInst (SpvInstParent* parent, IRInst* irInst, SpvOp opcode, const Operands& ...ops)
980
980
{
981
- InstConstructScope scopeInst (this , opcode, irInst);
982
- SpvInst* spvInst = scopeInst;
983
- (emitOperand (ops), ...);
984
- parent->addInst (spvInst);
985
- return spvInst;
981
+ return emitInstCustomOperandFunc (
982
+ parent,
983
+ irInst,
984
+ opcode,
985
+ [&](){(emitOperand (ops), ...);}
986
+ );
986
987
}
987
988
988
989
template <typename OperandEmitFunc>
@@ -1008,11 +1009,31 @@ struct SPIRVEmitContext
1008
1009
ResultIDToken resultId,
1009
1010
const Operands& ...ops
1010
1011
)
1012
+ {
1013
+ return emitInstMemoizedCustomOperandFunc (
1014
+ parent,
1015
+ irInst,
1016
+ opcode,
1017
+ resultId,
1018
+ [&](){(emitOperand (ops), ...);}
1019
+ );
1020
+ }
1021
+
1022
+ template <typename OperandEmitFunc>
1023
+ SpvInst* emitInstMemoizedCustomOperandFunc (
1024
+ SpvInstParent* parent,
1025
+ IRInst* irInst,
1026
+ SpvOp opcode,
1027
+ // We take the resultId here explicitly here to make sure we don't try
1028
+ // and memoize its value.
1029
+ ResultIDToken resultId,
1030
+ const OperandEmitFunc& f
1031
+ )
1011
1032
{
1012
1033
List<SpvWord> ourOperands;
1013
1034
{
1014
1035
auto scopePeek = OperandMemoizeScope (this );
1015
- ( emitOperand (ops), ... );
1036
+ f ( );
1016
1037
// Steal our operands back, so we don't have to calculate them
1017
1038
// again
1018
1039
ourOperands = std::move (m_operandStack);
@@ -4187,21 +4208,63 @@ struct SPIRVEmitContext
4187
4208
default :
4188
4209
break ;
4189
4210
}
4211
+ const auto opParent = parentForOpCode (opcode, parent);
4212
+ const auto opInfo = m_grammarInfo->opInfos .lookup (opcode);
4213
+
4214
+ // TODO: handle resultIdIndex == 1, for constants
4215
+ const bool memoize = opParent == getSection (SpvLogicalSectionID::ConstantsAndTypes)
4216
+ && opInfo && opInfo->resultIdIndex == 0 ;
4217
+
4218
+ // We want the "result instruction" to refer to the top level
4219
+ // block which assumes its value, the others are free to refer
4220
+ // to whatever, so just use the internal spv inst rep
4221
+ // TODO: This is not correct, because the instruction which is
4222
+ // assigned to result is not necessarily the last instruction
4223
+ const auto assignedInst = isLast ? as<IRInst>(inst) : spvInst;
4190
4224
4191
- last = emitInstCustomOperandFunc (
4192
- parentForOpCode (opcode, parent),
4193
- // We want the "result instruction" to refer to the top level
4194
- // block which assumes its value, the others are free to refer
4195
- // to whatever, so just use the internal spv inst rep
4196
- // TODO: This is not correct, because the instruction which is
4197
- // assigned to result is not necessarily the last instruction
4198
- isLast ? as<IRInst>(inst) : spvInst,
4199
- opcode,
4200
- [&](){
4201
- for (const auto operand : spvInst->getSPIRVOperands ())
4202
- emitSpvAsmOperand (operand);
4225
+ if (memoize)
4226
+ {
4227
+ last = emitInstMemoizedCustomOperandFunc (
4228
+ opParent,
4229
+ assignedInst,
4230
+ opcode,
4231
+ kResultID ,
4232
+ [&](){
4233
+ Index i = 0 ;
4234
+ for (const auto operand : spvInst->getSPIRVOperands ()) {
4235
+ if (i++ != 0 )
4236
+ emitSpvAsmOperand (operand);
4237
+ };
4238
+ }
4239
+ );
4240
+
4241
+ // The result operand is the one at index 1, after the
4242
+ // opcode itself.
4243
+ // If this happens to be an "id" operand, then we need to
4244
+ // correct the Id we have stored in our map with the actual
4245
+ // memoized result. This is safe because a condition on
4246
+ // memoized instructions is that they come before their
4247
+ // uses.
4248
+ const auto resOperand = cast<IRSPIRVAsmOperand>(spvInst->getOperand (1 ));
4249
+ if (resOperand->getOp () == kIROp_SPIRVAsmOperandId )
4250
+ {
4251
+ const auto idName =
4252
+ cast<IRStringLit>(resOperand->getValue ())->getStringSlice ();
4253
+ idMap[idName] = last->id ;
4203
4254
}
4204
- );
4255
+ }
4256
+ else
4257
+ {
4258
+ emitInstCustomOperandFunc (
4259
+ opParent,
4260
+ assignedInst,
4261
+ opcode,
4262
+ [&](){
4263
+ for (const auto operand : spvInst->getSPIRVOperands ())
4264
+ emitSpvAsmOperand (operand);
4265
+ }
4266
+ );
4267
+ }
4205
4268
}
4206
4269
}
4207
4270
0 commit comments