Closed
Description
Specdiff is reporting the following miscompare:
0397: EXTRAP=T DAMP=T SHIFT=T RSTRCT=F DIIS=F SOSCF=T
EXTRAP=T DAMP=F SHIFT=F RSTRCT=F DIIS=F SOSCF=T
^
Values computed for DAMP
is not passed correctly to Fortran runtime:
4019 SUBROUTINE UHFOP(SZ,S2)
...
4187 DAMPH = MOD(MCONV,4) .GE. 2
4188 VSHIFT = MOD(MCONV,8) .GE. 4
...
4591 IF(SOME) WRITE(IW,9020) EN,MAXIT,MPUNCH,MUL,EXTRAH,DAMPH,
4592 * VSHIFT,RSTRCT,DODIIS,SOSCF
The problem appears after SLPVectorizerPass
with -march=native
(Icelake), but it is just a trigger.
I believe the following C++ test demonstrates the problem:
repro.cpp
mimics the Fortran code:
extern void printer(bool x);
__attribute__((noinline)) void test(int x) {
bool t1 = (x % 4) >= 2;
bool t2 = (x % 8) >= 4;
printer(t1);
printer(t2);
}
int main() {
test(65);
}
report_rt.cpp
mimics Fortran runtime code that prints logical values:
#include <cstdint>
#include <cstdio>
__attribute__((noinline)) void printer2(void *x) {
printf("%s\n", *(std::int8_t *)x ? "T" : "F");
}
__attribute__((noinline)) void printer(bool x) {
printer2(reinterpret_cast<void *>(&x));
}
Compilation commands to reproduce the issue:
$ clang++ repro.cpp -march=native -O3 -emit-llvm -Xclang -disable-llvm-passes -S -o repro_orig.ll
$ clang++ -march=native -O3 repro_rt.cpp repro_orig.ll
$ ./a.out
F
F
This is the correct result above, but it becomes incorrect (as with Flang generated code) when I remove zeroext
attribute from _Z7printerb
in repro_orig.ll
- see attached repro_error.ll
:
$ clang++ -march=native -O3 repro_rt.cpp repro_error.ll
$ ./a.out
T
T
So the problem is that the caller of printer
does not zero extends the i1
argument before the calls as required by ABI because of the missing zeroext
attribute.