diff --git a/src/script_opt/ZAM/AM-Opt.cc b/src/script_opt/ZAM/AM-Opt.cc index dbb5804a58..cd4a3e6b6f 100644 --- a/src/script_opt/ZAM/AM-Opt.cc +++ b/src/script_opt/ZAM/AM-Opt.cc @@ -158,15 +158,15 @@ bool ZAMCompiler::RemoveDeadCode() { } if ( t && t->inst_num > i0->inst_num && (! i1 || t->inst_num <= i1->inst_num) ) { - // This is effectively a branch to the next - // instruction. Even if i0 is conditional, there's - // no point executing it because regardless of the - // outcome of the conditional, we go to the next - // successive live instruction (and we don't have - // conditionals with side effects). - KillInst(i0); - did_removal = true; - continue; + // This is effectively a branch to the next instruction. + // We can remove it *unless* the instruction has side effects. + // Conditionals don't, but loop-iteration-advancement + // instructions do. + if ( ! i0->IsLoopIterationAdvancement() ) { + KillInst(i0); + did_removal = true; + continue; + } } if ( i0->DoesNotContinue() && i1 && i1->num_labels == 0 ) { diff --git a/src/script_opt/ZAM/ZInst.cc b/src/script_opt/ZAM/ZInst.cc index ae9cf7999b..4224576fe1 100644 --- a/src/script_opt/ZAM/ZInst.cc +++ b/src/script_opt/ZAM/ZInst.cc @@ -214,6 +214,23 @@ ValPtr ZInst::ConstVal() const { return nullptr; } +bool ZInst::IsLoopIterationAdvancement() const { + switch ( op ) { + case OP_NEXT_TABLE_ITER_VV: + case OP_NEXT_TABLE_ITER_NO_VARS_VV: + case OP_NEXT_TABLE_ITER_VAL_VAR_VVV: + case OP_NEXT_TABLE_ITER_VAL_VAR_NO_VARS_VVV: + case OP_NEXT_VECTOR_ITER_VVV: + case OP_NEXT_VECTOR_BLANK_ITER_VV: + case OP_NEXT_VECTOR_ITER_VAL_VAR_VVVV: + case OP_NEXT_VECTOR_BLANK_ITER_VAL_VAR_VVV: + case OP_NEXT_STRING_ITER_VVV: + case OP_NEXT_STRING_BLANK_ITER_VV: return true; + + default: return false; + } +} + string ZInst::ConstDump() const { auto v = ConstVal(); diff --git a/src/script_opt/ZAM/ZInst.h b/src/script_opt/ZAM/ZInst.h index 2d58b7ac2e..8e53d39b69 100644 --- a/src/script_opt/ZAM/ZInst.h +++ b/src/script_opt/ZAM/ZInst.h @@ -88,6 +88,10 @@ public: // Returns nil if this instruction doesn't have an associated constant. ValPtr ConstVal() const; + // Returns true if this instruction represents a form of advancing + // a loop iteration, false otherwise. + bool IsLoopIterationAdvancement() const; + // Returns a string describing the constant. std::string ConstDump() const;