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: unassig...@gcc.gnu.org ReportedBy: wschm...@gcc.gnu.org CC: rgue...@gcc.gnu.org, berg...@gcc.gnu.org, pthau...@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