Skip to content

Enzyme generates undef-fed tape PHIs for packed-state nested guard reproducer #2834

Description

@minansys

https://tinyurl.com/2c2v5q9u

Summary

On current Enzyme main (d0749cbb, Attempt to fix rematerialization ficticious phi issues (#2827)), the attached LLVM IR reproducer still generates undef-fed tape state in augmented_eval.

This looks related to the old nested-guard family from #2629, but not like the exact same control-flow bug. In this reproducer, reverse still remains gated by the saved outer state, but Enzyme still packs undef into saved i1, ptr, and double values along inactive paths.

So this appears to be a remaining tape / PHI / rematerialization issue rather than a duplicate of the specific nested-predicate control-flow bug fixed for #2629.

Attached reproducer

The reproducer is the attached LLVM IR file:

  • packed_state_outer_guard_undef_tape.ll

It is self-contained and does not depend on any C++ source or Cromwell code.

The reduced shape is:

  • packed state with booleans and an optional pointer
  • outer guard around a helper call
  • nested helper branches inside that helper
  • a looped dot-product path that Enzyme tapes as { ptr, double }
  • a later unrelated optional-pointer join

Reproduction

The file already contains RUN: lines for the Enzyme test suite.

Equivalent local reproduction command:

opt < packed_state_outer_guard_undef_tape.ll \
	-load-pass-plugin=/path/to/LLVMEnzyme.so \
	-passes="enzyme,function(sroa,mem2reg,early-cse,simplifycfg,instsimplify,correlated-propagation,simplifycfg,adce)" \
	-S -enzyme-preopt=0 -enzyme-detect-readthrow=0 | \
	FileCheck packed_state_outer_guard_undef_tape.ll

Problematic transformed shape

In the transformed IR, Enzyme emits:

define internal { { ptr, ptr, { double, double, double }, ptr, i1, i1, i1, double, double, ptr, i1, double }, double } @augmented_eval(...)

and the scalarized output still contains undef-fed tape fields such as:

%.sroa.14.0 = phi i1 [ %has_rotation, %with.frame ], [ undef, %entry ]
%.sroa.16.0 = phi i1 [ %has_translation, %with.frame ], [ undef, %entry ]
%.sroa.10.0 = phi ptr [ %subcache, %with.dot ], [ undef, %after.frame ]
%.sroa.26.0 = phi double [ undef, %have.second ], [ %roughness_limit, %no.second ]

Those values are then packed back into the tape via insertvalue.

The attached .ll file checks exactly for this shape.

Why this does not look like a straight duplicate of #2629

Expected behavior

Enzyme should not emit undef into saved reverse/tape state for semantically "not executed" paths. Those values should have a safe inactive default, or the reverse should be structured so such tape fields are not materialized at all.

Actual behavior

Current main still emits undef-fed saved i1, ptr, and double values in the tape for this attached IR reproducer.

Question

Is this expected / benign IR, or is this still a real remaining bug in Enzyme's tape construction / PHI rematerialization for packed-state nested-guard code?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions