[Bug 1811798]
Krebbel
1811798 at bugs.launchpad.net
Fri Feb 1 17:46:52 UTC 2019
The r265193 patch was found via reghunt. However, it just reveals an
underlying issue.
The problem can also be seen with mainline.
The miscompile happens in the following loop:
do 110 j = 1, n
if (sdiag(j) .eq. zero .and. nsing .eq. n) nsing = j - 1
if (nsing .lt. n) wa(j) = zero
110 continue
The problem appears to be rather related to ifcvt. ifcvt generates a
load on condition for the sdiag(j) .eq. zero comparison by inserting
insns: 2480, 2481, 2482:
265.ce2
(insn 915 918 916 88 (set (reg:DF 590 [ MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ])
(mem:DF (reg/v/f:DI 239 [ sdiag ]) [2 MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B]+0 S8 A64])) "min.qrsolv.f":51 1289 {*movdf_64dfp}
(nil))
(insn 916 915 2480 88 (set (reg:CCZ 33 %cc)
(compare:CCZ (reg:DF 590 [ MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ])
(const_double:DF 0.0 [0x0.0p+0]))) "min.qrsolv.f":51 1255 {*cmpdf_ccs}
(expr_list:REG_DEAD (reg:DF 590 [ MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ])
(nil)))
(insn 2480 916 2481 88 (set (reg:SI 733)
(const_int 0 [0])) 1274 {*movsi_zarch}
(nil))
(insn 2481 2480 2482 88 (set (reg:CCZ 33 %cc)
(compare:CCZ (reg:DF 590 [ MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ])
(const_double:DF 0.0 [0x0.0p+0]))) 1255 {*cmpdf_ccs}
(nil))
(insn 2482 2481 927 88 (set (reg/v:SI 109 [ nsing ])
(if_then_else:SI (ne (reg:CCZ 33 %cc)
(const_int 0 [0]))
(reg/v:SI 109 [ nsing ])
(reg:SI 733))) 1676 {*movsicc}
(nil))
(note 927 2482 928 88 NOTE_INSN_DELETED)
(jump_insn 928 927 932 88 (parallel [
(set (pc)
(if_then_else (le (reg:SI 320 [ _444 ])
(reg/v:SI 109 [ nsing ]))
(label_ref:DI 943)
(pc)))
(clobber (reg:CC 33 %cc))
]) "min.qrsolv.f":52 1260 {*cmp_and_br_signed_si}
(expr_list:REG_UNUSED (reg:CC 33 %cc)
(int_list:REG_BR_PROB 536870916 (nil)))
-> 943)
In the backend we have that interesting splitter which triggers for the
old and now obsolete compare in insn 916
(define_split
[(set (match_operand 0 "cc_reg_operand")
(compare (match_operand:FP 1 "register_operand")
(match_operand:FP 2 "const0_operand")))]
"TARGET_HARD_FLOAT && REG_P (operands[1]) && dead_or_set_p (insn, operands[1])"
[(parallel
[(set (match_dup 0) (match_dup 3))
(clobber (match_dup 1))])]
{
/* s390_match_ccmode requires the compare to have the same CC mode
as the CC destination register. */
operands[3] = gen_rtx_COMPARE (GET_MODE (operands[0]),
operands[1], operands[2]);
})
268.split1 insn 916 -> insn 2677
The REG_DEAD note becomes a clobber due to that
(insn 915 918 2677 105 (set (reg:DF 590 [ MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ])
(mem:DF (reg/v/f:DI 239 [ sdiag ]) [2 MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B]+0 S8 A64])) "min.qrsolv.f":51 1289 {*movdf_64dfp}
(nil))
(insn 2677 915 2480 105 (parallel [
(set (reg:CCZ 33 %cc)
(compare:CCZ (reg:DF 590 [ MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ])
(const_double:DF 0.0 [0x0.0p+0])))
(clobber (reg:DF 590 [ MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ]))
]) "min.qrsolv.f":51 -1
(nil))
(insn 2480 2677 2481 105 (set (reg:SI 733)
(const_int 0 [0])) 1274 {*movsi_zarch}
(nil))
(insn 2481 2480 2482 105 (set (reg:CCZ 33 %cc)
(compare:CCZ (reg:DF 590 [ MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ])
(const_double:DF 0.0 [0x0.0p+0]))) 1255 {*cmpdf_ccs}
(nil))
294.cprop_hardreg appears to mess up things: REG_DEAD note in insn 2677
does not appear to fit the used reg but CC is unused now
(insn 3107 927 915 121 (set (reg:DI 3 %r3 [1060])
(mem/f/c:DI (plus:DI (reg/f:DI 15 %r15)
(const_int 520 [0x208])) [3 sdiag+0 S8 A64])) "min.qrsolv.f":51 1270 {*movdi_64}
(nil))
(insn 915 3107 2677 121 (set (reg:DF 19 %f6 [orig:590 MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ] [590])
(mem:DF (reg:DI 3 %r3 [1060]) [2 MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B]+0 S8 A64])) "min.qrsolv.f":51 1289 {*movdf_64dfp}
(expr_list:REG_DEAD (reg:DI 3 %r3 [1060])
(nil)))
(insn 2677 915 3108 121 (parallel [
(set (reg:CCZ 33 %cc)
(compare:CCZ (reg:DF 19 %f6 [orig:590 MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ] [590])
(const_double:DF 0.0 [0x0.0p+0])))
(clobber (reg:DF 19 %f6 [orig:590 MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ] [590]))
]) "min.qrsolv.f":51 1250 {*cmpdf_ccs_0}
(expr_list:REG_DEAD (reg:DF 16 %f0 [orig:590 MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ] [590])
(expr_list:REG_UNUSED (reg:CCZ 33 %cc)
(nil))))
(insn 3108 2677 2481 121 (set (reg:DF 20 %f1 [1061])
(const_double:DF 0.0 [0x0.0p+0])) 1289 {*movdf_64dfp}
(nil))
(insn 2481 3108 2480 121 (set (reg:CCZ 33 %cc)
(compare:CCZ (reg:DF 16 %f0 [orig:590 MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ] [590])
(reg:DF 20 %f1 [1061]))) 1255 {*cmpdf_ccs}
(expr_list:REG_DEAD (reg:DF 16 %f0 [orig:590 MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ] [590])
(nil)))
295.rtl_dce consequently removes insn 3107, 915, 2677
(insn 3108 927 2481 121 (set (reg:DF 20 %f1 [1061])
(const_double:DF 0.0 [0x0.0p+0])) 1289 {*movdf_64dfp}
(nil))
(insn 2481 3108 2480 121 (set (reg:CCZ 33 %cc)
(compare:CCZ (reg:DF 16 %f0 [orig:590 MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ] [590])
(reg:DF 20 %f1 [1061]))) 1255 {*cmpdf_ccs}
(expr_list:REG_DEAD (reg:DF 16 %f0 [orig:590 MEM[base: sdiag_143(D), index: ivtmp.67_240, offset: 0B] ] [590])
(nil)))
(insn 2480 2481 2482 121 (set (reg:SI 0 %r0 [733])
(const_int 0 [0])) 1274 {*movsi_zarch}
(expr_list:REG_EQUIV (const_int 0 [0])
(nil)))
(insn 2482 2480 928 121 (set (reg/v:SI 2 %r2 [orig:109 nsing ] [109])
(if_then_else:SI (ne (reg:CCZ 33 %cc)
(const_int 0 [0]))
(reg/v:SI 2 %r2 [orig:109 nsing ] [109])
(reg:SI 0 %r0 [733]))) 1676 {*movsicc}
(expr_list:REG_DEAD (reg:CCZ 33 %cc)
(expr_list:REG_DEAD (reg:SI 3 %r3 [733])
(nil))))
To my understanding the data flow is already broken after ifcvt inserted the new compare while leaving the REG_DEAD note in the old. The new compare already appears to read a dead register here and this appears to trigger the rest of the unfortunate events.
--
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to gcc-8 in Ubuntu.
https://bugs.launchpad.net/bugs/1811798
Title:
gcc 8 miscompiles scipy/optimize/minpack/qrsolv.f
Status in gcc:
In Progress
Status in gcc-8 package in Ubuntu:
New
Status in imexam package in Ubuntu:
New
Status in python-scipy package in Ubuntu:
New
Status in python-scipy package in Debian:
New
Bug description:
Originally reported in https://bugs.debian.org/906198
The following simple test fails on s390x:
---------------------------8<------------------------------
import numpy as np
from scipy.optimize import leastsq
y = np.array([0., 1., 1., 2., 1., 1., 0.])
x = np.arange(len(y))
def func(par):
return par[2] * np.exp(-(x - par[0])**2/par[1]) - y
print(leastsq(func, [0,1,0]))
---------------------------8<------------------------------
The expected result is
(array([3. , 4.42280548, 1.67210345]), 1)
while on S390x, one gets
(array([0. , 1. , 0.34027645]), 3)
Further information from https://bugs.debian.org/915738
The bug seems to be a miscompilation of scipy/optimize/minpack/qrsolv.f
with -funroll-loops. Removing -funroll-loops is enough to get the
leastsq testcase to pass.
To manage notifications about this bug go to:
https://bugs.launchpad.net/gcc/+bug/1811798/+subscriptions
More information about the foundations-bugs
mailing list