BooleanOptimizer and StaticArgumentTransformation both run when options.optimizeUplc is set. MutualRecursionElimination is unconditional (backends reject multi-binding recursive lets); running StaticArgumentTransformation after it lifts the peers-as-params static arguments MRE introduces. The backends keep their own MRE calls as safety nets for direct construction - MRE is idempotent, so the second call is a no-op walk.
The optimizer run should use when the caller has no version-specific one: V1/V2 -> V1V2Optimizer (V3Optimizer's CaseConstrApply emits Case/Constr terms that are illegal before Plutus V3); otherwise V3Optimizer configured from the options.
The optimizer run should use when the caller has no version-specific one: V1/V2 -> V1V2Optimizer (V3Optimizer's CaseConstrApply emits Case/Constr terms that are illegal before Plutus V3); otherwise V3Optimizer configured from the options.