[Bug tree-optimization/48067] New: FMA with no add operand produced by convert_mul_to_fma

wschmidt at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Fri Mar 11 00:42:00 GMT 2011


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48067

           Summary: FMA with no add operand produced by convert_mul_to_fma
           Product: gcc
           Version: tree-ssa
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: wschmidt@gcc.gnu.org
                CC: rguenth@gcc.gnu.org, bergner@gcc.gnu.org,
                    pthaugen@gcc.gnu.org


There is a latent bug in tree-ssa-math-ops.c: convert_mul_to_fma.  This is
exposed when building SPEC cpu2000 benchmark 191.fma3d for
branches/ibm/gcc-4_5-branch, but does not currently reproduce on mainline or
fsf 4.5.

Prior to the widening_mul pass, the gimple contains the following (stripped of
unrelated statements):

  c12_7 = D.743_5 * cim_6(D);
  d12_8 = -c12_7;
  D.745_11 = c12_7 - d12_8;

The FMA transform produces this:

  D.768_8 = -D.743_5;
  D.767_20 = D.768_8 * cim_6(D) + ;
  D.745_11 = D.743_5 * cim_6(D) + D.767_20;

The second instruction is a ternary op with a null rhs3 operand.  This causes a
segv in the verify_ssa code following this pass.

convert_mul_to_fma has two loops over the immediate uses of mul_result (c12_7
in this case).  In the first loop, if a use is found to be a NEGATE_EXPR, it is
only processed if it has a single immediate use, which must be a PLUS_EXPR or a
MINUS_EXPR.  The second loop assumes this still holds.  Unfortunately, this
case demonstrates that it is possible for the assumption to be violated.

The first pass through the second loop processes the assignment to D.745_11
first, and converts it to an FMA:

  D.767_20 = -d12_8;
  D.745_11 = D.743_5 * cim_6(D) + D.767_20;

Note that this has removed the original use of d12_8 in a MINUS_EXPR, and
replaced it with a new use in a NEGATE_EXPR.  Now the statement

  d12_8 = -c12_7;

no longer satisfies the rule that its single use is in a PLUS_EXPR or a
MINUS_EXPR.  It's now part of a NEGATE_EXPR that can't be converted into an
FMA.

I believe the right thing to do here is probably to check for neguse_stmt still
being either a PLUS_EXPR or a MINUS_EXPR after the call to single_imm_use in
the second loop.  If not, avoid replacing the original use_stmt with
neguse_stmt and just continue to the next use.  But I'll defer to those with
more knowledge of the code.

(As a side note, the first loop over immediate uses manipulates a "negate_p"
local var that doesn't appear to have any effect.  The second loop has its own
copy of negate_p.  Looks like something left over from an earlier design?)

The procedure where the above occurs in 191.fma3d is:

      SUBROUTINE MATERIAL_22_INTEGRATION                                      
&
     &          (                                                             
&
     &          STRESS,A,B,Strain_A,Strain_B,Strain_C,Akk,                    
&
     &          DTnext,Drr,Dss,Drs,MatID                                      
&
     &          )
      REAL(KIND(0D0))                                                         
&
     &          STRESS(3),A(2),B(2)
      IF (PAB .GT. 0.0) THEN
        C12 = C1*C2 * Cim
        D12 = -C12
        IF (SMD .EQ. 0.0) THEN
        ENDIF
        STRESS(3) = STRESS(3) + (Shear * (C12 - D12))
      ENDIF
      IF (Akk .LE. Afc) THEN
      ENDIF
      END



More information about the Gcc-bugs mailing list