Thank you Ryan and Ivan for reporting and debugging this. Godbolt.org shows that icc 19.0.1 with -O2 -ipo (inter-procedural optimizations) is too smart and optimizes this stack growth detection code so that it returns incorrect result on x86_64. Detecting stack growth from C is tricky - in principle, it cannot be done correctly in a portable way. As the compilers are getting more sophisticated, it is increasingly more difficult. We'll have to improve the test, perhaps re-using some or completely remove it and assume stack grows down. I doubt anyone today would run a real, non-emulated, system running R where stack would grow up.

(and yes, the elif conditional should use 255)

Tomas


On 4/17/21 11:40 AM, Ivan Krylov wrote:
On Fri, 16 Apr 2021 18:39:04 +0000
Ryan Novosielski <novos...@rutgers.edu> wrote:

I guess there’s probably some mode of m4 I could run against that and
see if there’s any indication?
Here's a shell script that should be doing the same thing that
R's .../configure does, but a bit more verbose:

-----------------------------------8<-----------------------------------
#!/bin/sh
cat > conftest1.c <<EOF
#include <stdint.h>
uintptr_t dummy_ii(void)
{
     int ii;

     /* This is intended to return a local address. We could just return
        (uintptr_t) &ii, but doing it indirectly through ii_addr avoids
        a compiler warning (-Wno-return-local-addr would do as well).
     */
     volatile uintptr_t ii_addr = (uintptr_t) &ii;
     return ii_addr;
}
EOF
cat > conftest.c <<EOF
#include <stdio.h>
#include <stdint.h>
extern uintptr_t dummy_ii(void);

typedef uintptr_t (*dptr_type)(void);
volatile dptr_type dummy_ii_ptr;

int main(int ac, char **av)
{
     int i;
     dummy_ii_ptr = dummy_ii;
/* call dummy_ii via a volatile function pointer to prevent
        inlinining in case the tests are accidentally built with
        LTO */
     uintptr_t ii = dummy_ii_ptr();
#ifndef EXACTLY_AS_R_CONFIGURE
     printf(
         "main = %p, sub = %p, main %c sub, ret = %d\n",
         &i, (void*)ii,
         ((uintptr_t)&i > ii) ? '>' : ((uintptr_t)&i < ii) ? '<' : '=',
         ((uintptr_t)&i > ii) ? 1 : -1
     );
#endif
     /* 1 is downwards */
     return ((uintptr_t)&i > ii) ? 1 : -1;
}
EOF
echo "${CC:=cc} ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} ${MAIN_LDFLAGS}" \
     "-o conftest conftest.c conftest1.c"
${CC} ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} ${MAIN_LDFLAGS} -o conftest \
     conftest.c conftest1.c || exit $?
echo ./conftest
./conftest
ret=$?
echo "./conftest exited with $ret"
if test ${ret} = 1; then
   echo r_cv_cstack_direction=down
elif test ${ret} = 1; then
   echo r_cv_cstack_direction=up
fi
exit 0
-----------------------------------8<-----------------------------------

Please run it similarly to the way you run .../configure:

export CC=icc
export CFLAGS="-O3 -ipo -qopenmp -axAVX,CORE-AVX2,CORE-AVX512"
sh .../runme.sh

Does it give the right answer, that is, r_cv_cstack_direction=down?
Does the answer change if you add -DEXACTLY_AS_R_CONFIGURE to CFLAGS?
If the answer is always "down" and you have reused the build directory
(keeping the config.site file between .../configure runs), this is going
to be hard to track down. If you manage to get the "up" answer, it
should be possible to tweak the test until ICC doesn't optimise it to
the point of confusing the stack growth direction.

Either way, I think that the elif branch in the R_STACK_DIRECTION test
should be testing for $? = 255, not 1. I'm almost convinced that the
behaviour would be incorrect on platforms where the test exits with -1.


______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to