@@ -272,7 +272,7 @@ private static void retainDiscardedValue(ImExpr value, ImStmts stmts, ImTranslat
272272 }
273273 return ;
274274 }
275- if (isTriviallyDiscardable (value )) {
275+ if (isSafelyDiscardable (value )) {
276276 return ;
277277 }
278278 if (SideEffectAnalyzer .quickcheckHasSideeffects (value )) {
@@ -284,14 +284,34 @@ private static void retainDiscardedValue(ImExpr value, ImStmts stmts, ImTranslat
284284 }
285285 }
286286
287- private static boolean isTriviallyDiscardable (ImExpr value ) {
288- return value instanceof ImBoolVal
287+ private static boolean isSafelyDiscardable (ImExpr value ) {
288+ if ( value instanceof ImBoolVal
289289 || value instanceof ImIntVal
290290 || value instanceof ImRealVal
291291 || value instanceof ImStringVal
292292 || value instanceof ImNull
293293 || value instanceof ImVarAccess
294- || value instanceof ImFuncRef ;
294+ || value instanceof ImFuncRef ) {
295+ return true ;
296+ }
297+ if (value instanceof ImOperatorCall operatorCall
298+ && isTotalOperator (operatorCall .getOp ())) {
299+ return operatorCall .getArguments ().stream ()
300+ .allMatch (EliminateTuples ::isSafelyDiscardable );
301+ }
302+ return false ;
303+ }
304+
305+ /**
306+ * Operators other than integer division and modulo are total for well-typed scalar IM values.
307+ * Keeping their unused results in a Lua discard sink only repeats pure scalar work and prevents
308+ * tuple-component DCE. Division and modulo stay conservative because a zero divisor can fail.
309+ */
310+ private static boolean isTotalOperator (WurstOperator operator ) {
311+ return switch (operator ) {
312+ case DIV_INT , MOD_INT , MOD_REAL , JASS_MOD_INT -> false ;
313+ default -> true ;
314+ };
295315 }
296316
297317 /**
@@ -1006,7 +1026,7 @@ private static void lowerBundleInto(ImExpr expression, ImFunction f, boolean cap
10061026
10071027 value .setParent (null );
10081028 boolean requiresEagerEvaluation = capturePotentiallyFailingValues
1009- && !isTriviallyDiscardable (value )
1029+ && !isSafelyDiscardable (value )
10101030 && !SideEffectAnalyzer .quickcheckHasSideeffects (value );
10111031 if ((capture || requiresEagerEvaluation ) && !isImmutableValue (value )) {
10121032 result .values .add (captureValue (value , temporaryName , result .prelude , f ));
0 commit comments