diff --git a/src/script_opt/ZAM/Compile.h b/src/script_opt/ZAM/Compile.h index e1cd35bf2b..1287dcdc6a 100644 --- a/src/script_opt/ZAM/Compile.h +++ b/src/script_opt/ZAM/Compile.h @@ -333,7 +333,10 @@ private: // Returns how many values were added. int InternalAddVal(ZInstAux* zi, int i, Expr* e); - const ZAMStmt AddInst(const ZInstI& inst); + // Adds the given instruction to the ZAM program. The second + // argument, if true, suppresses generation of any pending + // global/capture store for this instruction. + const ZAMStmt AddInst(const ZInstI& inst, bool suppress_non_local = false); // Returns the statement just before the given one. ZAMStmt PrevStmt(const ZAMStmt s); diff --git a/src/script_opt/ZAM/Low-Level.cc b/src/script_opt/ZAM/Low-Level.cc index 6aefbea1f0..40fd4c30df 100644 --- a/src/script_opt/ZAM/Low-Level.cc +++ b/src/script_opt/ZAM/Low-Level.cc @@ -128,7 +128,7 @@ int ZAMCompiler::InternalAddVal(ZInstAux* zi, int i, Expr* e) return 1; } -const ZAMStmt ZAMCompiler::AddInst(const ZInstI& inst) +const ZAMStmt ZAMCompiler::AddInst(const ZInstI& inst, bool suppress_non_local) { ZInstI* i; @@ -146,17 +146,22 @@ const ZAMStmt ZAMCompiler::AddInst(const ZInstI& inst) top_main_inst = insts1.size() - 1; - if ( pending_global_store < 0 ) + if ( suppress_non_local ) return ZAMStmt(top_main_inst); - auto global_slot = pending_global_store; - pending_global_store = -1; + if ( pending_global_store >= 0 ) + { + auto gs = pending_global_store; + pending_global_store = -1; - auto store_inst = ZInstI(OP_STORE_GLOBAL_V, global_slot); - store_inst.op_type = OP_V_I1; - store_inst.t = globalsI[global_slot].id->GetType(); + auto store_inst = ZInstI(OP_STORE_GLOBAL_V, gs); + store_inst.op_type = OP_V_I1; + store_inst.t = globalsI[gs].id->GetType(); - return AddInst(store_inst); + return AddInst(store_inst); + } + + return ZAMStmt(top_main_inst); } const Stmt* ZAMCompiler::LastStmt(const Stmt* s) const diff --git a/src/script_opt/ZAM/Vars.cc b/src/script_opt/ZAM/Vars.cc index 543b32e32d..4bd1653c80 100644 --- a/src/script_opt/ZAM/Vars.cc +++ b/src/script_opt/ZAM/Vars.cc @@ -66,7 +66,7 @@ const ZAMStmt ZAMCompiler::LoadGlobal(const ID* id) z.aux = new ZInstAux(0); z.aux->id_val = id; - return AddInst(z); + return AddInst(z, true); } int ZAMCompiler::AddToFrame(const ID* id) @@ -81,38 +81,27 @@ int ZAMCompiler::FrameSlot(const ID* id) auto slot = RawSlot(id); if ( id->IsGlobal() ) - (void)LoadGlobal(frame_denizens[slot]); + (void)LoadGlobal(id); return slot; } int ZAMCompiler::Frame1Slot(const ID* id, ZAMOp1Flavor fl) { - auto slot = RawSlot(id); + if ( fl == OP1_READ ) + return FrameSlot(id); - switch ( fl ) - { - case OP1_READ: - if ( id->IsGlobal() ) - (void)LoadGlobal(frame_denizens[slot]); - break; + if ( fl == OP1_INTERNAL ) + return RawSlot(id); - case OP1_WRITE: - if ( id->IsGlobal() ) - pending_global_store = global_id_to_info[id]; - break; + ASSERT(fl == OP1_WRITE || fl == OP1_READ_WRITE); - case OP1_READ_WRITE: - if ( id->IsGlobal() ) - { - (void)LoadGlobal(frame_denizens[slot]); - pending_global_store = global_id_to_info[id]; - } - break; + // Important: get the slot *before* tracking non-locals, so we don't + // prematurely generate a Store for the read/write case. + auto slot = fl == OP1_READ_WRITE ? FrameSlot(id) : RawSlot(id); - case OP1_INTERNAL: - break; - } + if ( id->IsGlobal() ) + pending_global_store = global_id_to_info[id]; return slot; }