Hello! Function calls, generated directly through emit_library_call (for the testcase from PR the compiler builds a call to _Unwind_SjLj_Register via sjlj_emit_function_enter) miss a whole lot of stack realignmnet setup. There is an update to crtl->preferred_stack_boundary present, but several updates for SUPPORTS_STACK_ALIGNMENT targets are missing, including eventual DRAP setup.
Attached patch introduces additional updates to stack realignment crtl variables in emit_library_call_1, based on what expand_stack_alignment from cfgrtl.c does. In addition to update of preferred_stack_boundary, it updates stack_alignment_estimated and stack_alignment_needed. The patch also updates dependent variables stack_realign_meeded and stack_realign_tried. Additionally, if needed, DRAP register is prepared. 2018-10-30 Uros Bizjak <ubiz...@gmail.com> PR middle-end/58372 * calls.c (emit_library_call_value_1): For SUPPORTS_STACK_ALIGNMENT targets, also update crtl->stack_alignment_estimated, crtl->stack_alignment_needed, crtl->stack_realign_needed, crtl->stack_realign_tried and prepare DRAP register if needed. testsuite/ChangeLog: 2018-10-30 Uros Bizjak <ubiz...@gmail.com> PR middle-end/58372 * g++.target/i386/pr58372.C: New test. The patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Additionally, the testcase from PR (and a couple of similar ones) were compiled for i686-w64-mingw32 target with various combinations of -mpreferred-stack-boundary= -mincoming-stack-boundary= -mforce-drap and -m{no-}accumulate-outgoing-args. The patch is posted as RFT, to leave some time for eventual tests on other targets, comments and possible approval. Uros.
Index: calls.c =================================================================== --- calls.c (revision 265582) +++ calls.c (working copy) @@ -4736,9 +4736,41 @@ emit_library_call_value_1 (int retval, rtx orgfun, /* Ensure current function's preferred stack boundary is at least what we need. */ - if (crtl->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY) - crtl->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY; + unsigned int preferred_stack_boundary = PREFERRED_STACK_BOUNDARY; + if (preferred_stack_boundary > crtl->preferred_stack_boundary) + crtl->preferred_stack_boundary = preferred_stack_boundary; + + if (SUPPORTS_STACK_ALIGNMENT) + { + if (preferred_stack_boundary > crtl->stack_alignment_estimated) + crtl->stack_alignment_estimated = preferred_stack_boundary; + if (preferred_stack_boundary > crtl->stack_alignment_needed) + crtl->stack_alignment_needed = preferred_stack_boundary; + + crtl->stack_realign_needed + = INCOMING_STACK_BOUNDARY < crtl->stack_alignment_estimated; + crtl->stack_realign_tried = crtl->stack_realign_needed; + + if (crtl->drap_reg == NULL_RTX) + { + rtx drap_rtx = targetm.calls.get_drap_rtx (); + + /* stack_realign_drap and drap_rtx must match. */ + gcc_assert ((stack_realign_drap != 0) == (drap_rtx != NULL)); + + /* Do nothing if NULL is returned, which means DRAP is not needed. */ + if (drap_rtx != NULL) + { + crtl->args.internal_arg_pointer = drap_rtx; + + /* Call fixup_tail_calls to clean up REG_EQUIV note if DRAP is + needed. */ + fixup_tail_calls (); + } + } + } + /* If this kind of value comes back in memory, decide where in memory it should come back. */ if (outmode != VOIDmode) Index: testsuite/g++.target/i386/pr58372.C =================================================================== --- testsuite/g++.target/i386/pr58372.C (nonexistent) +++ testsuite/g++.target/i386/pr58372.C (working copy) @@ -0,0 +1,9 @@ +/* PR target/58372 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +__attribute__ ((__target__ ("rdrnd"))) +void f (unsigned int *b) noexcept +{ + __builtin_ia32_rdrand32_step (b); +}