https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92305
--- Comment #17 from Jakub Jelinek <jakub at gcc dot gnu.org> --- So, to sum up, in #c9 we are (or want to do) in Fortran roughly what in C we would do with: void foo (double aa, double bb, void *c_aptr, void *c_bptr, double **aptr, double **bptr, _Bool _aa, _Bool _bb, _Bool _c_aptr, _Bool _c_bptr) { if (!_c_aptr | !_c_bptr) __builtin_abort (); } void bar (double aa, double bb, void *c_aptr, void *c_bptr, double **aptr, double **bptr, unsigned char _aa, unsigned char _bb, unsigned char _c_aptr, unsigned char _c_bptr) { if (!_c_aptr | !_c_bptr) __builtin_abort (); } int main () { double *aptr, *bptr; foo (0.0, 0.0, 0, 0, &aptr, &bptr, 1, 1, 1, 1); bar (0.0, 0.0, 0, 0, &aptr, &bptr, 1, 1, 1, 1); return 0; } and that works just fine in C, even at -O0. Looking at expand dump of foo vs. test_dummy_opt_val_callee_2 I don't see any relevant differences in the arg passing: -;; _1 = ~_c_aptr_4(D); +;; _1 = ~_c_aptr_6(D); -(insn 17 16 18 (set (reg:QI 124) +(insn 17 16 18 (set (reg:QI 126) (mem/c:QI (plus:DI (reg/f:DI 111 virtual-incoming-args) - (const_int 64 [0x40])) [4 _c_aptr+0 S1 A64])) "pr92305.c":3:7 -1 + (const_int 64 [0x40])) [4 _c_aptr+0 S1 A64])) "pr92305.f90":14:0 -1 (nil)) ... -;; _2 = ~_c_bptr_5(D); +;; _3 = ~_c_bptr_7(D); -(insn 20 19 21 (set (reg:QI 126) +(insn 22 21 23 (set (reg:QI 129) (mem/c:QI (plus:DI (reg/f:DI 111 virtual-incoming-args) - (const_int 72 [0x48])) [4 _c_bptr+0 S1 A64])) "pr92305.c":3:18 -1 + (const_int 72 [0x48])) [4 _c_bptr+0 S1 A64])) "pr92305.f90":14:0 -1 (nil)) In the caller, in Fortran I see: (expr_list (use (reg:DI 2 2)) (expr_list:DF (use (reg:DF 33 1)) (expr_list:DF (use (reg:DF 34 2)) (expr_list:DI (use (reg:DI 5 5)) (expr_list:DI (use (reg:DI 6 6)) (expr_list:DI (use (reg:DI 7 7)) (expr_list:DI (use (reg:DI 8 8)) (expr_list:QI (use (reg:DI 9 9)) (expr_list:QI (use (reg:DI 10 10)) (expr_list:QI (use (mem:DI (reg/f:DI 114 virtual-outgoing-args) [0 S1 A64])) (expr_list:QI (use (mem:DI (plus:DI (reg/f:DI 114 virtual-outgoing-args) (const_int 8 [0x8])) [0 S1 A64])) (nil))))))))))))) and both DImode slot at virtual-outgoing-args and at +8 are initialized with full DImode store of 1 in there, while in C: (expr_list (use (reg:DI 2 2)) (expr_list:DF (use (reg:DF 33 1)) (expr_list:DF (use (reg:DF 34 2)) (expr_list:DI (use (reg:DI 5 5)) (expr_list:DI (use (reg:DI 6 6)) (expr_list:DI (use (reg:DI 7 7)) (expr_list:DI (use (reg:DI 8 8)) (expr_list:QI (use (reg:DI 9 9)) (expr_list:QI (use (reg:DI 10 10)) (expr_list:QI (use (mem:DI (plus:DI (reg/f:DI 114 virtual-outgoing-args) (const_int 64 [0x40])) [0 S1 A64])) (expr_list:QI (use (mem:DI (plus:DI (reg/f:DI 114 virtual-outgoing-args) (const_int 72 [0x48])) [0 S1 A64])) (nil))))))))))))) and again, the +64 and +72 slots are initialized to full DImode values of 1.