Hello! Attached patch adds new insn_and_split pattern to handle pre_modify XFmode push variant. -m96bit-long-double option sets XFmode size to 12 bytes that is not divisible with push size (8 bytes), resulting in pre_modify push variant.
2017-03-02 Uros Bizjak <ubiz...@gmail.com> PR target/79514 * config/i386/i386.md (*pushxf_rounded): New insn_and_split pattern. testsuite/ChangeLog: 2017-03-02 Uros Bizjak <ubiz...@gmail.com> PR target/79514 * gcc.target/i386/pr79514.c: New test. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline, will be backported to release branches. Uros.
Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 245842) +++ config/i386/i386.md (working copy) @@ -3015,6 +3015,36 @@ operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx); }) +(define_insn_and_split "*pushxf_rounded" + [(set (mem:XF + (pre_modify:DI + (reg:DI SP_REG) + (plus:DI (reg:DI SP_REG) (const_int -16)))) + (match_operand:XF 0 "nonmemory_no_elim_operand" "f,r,*r,C"))] + "TARGET_64BIT" + "#" + "&& 1" + [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16))) + (set (match_dup 1) (match_dup 0))] +{ + rtx pat = PATTERN (curr_insn); + operands[1] = SET_DEST (pat); + + /* Preserve memory attributes. */ + operands[1] = replace_equiv_address (operands[1], stack_pointer_rtx); +} + [(set_attr "type" "multi") + (set_attr "unit" "i387,*,*,*") + (set (attr "mode") + (cond [(eq_attr "alternative" "1,2,3") + (const_string "DI") + ] + (const_string "XF"))) + (set (attr "preferred_for_size") + (cond [(eq_attr "alternative" "1") + (symbol_ref "false")] + (symbol_ref "true")))]) + (define_insn "*pushxf" [(set (match_operand:XF 0 "push_operand" "=<,<,<,<") (match_operand:XF 1 "general_no_elim_operand" "f,r,*r,oF"))] Index: testsuite/gcc.target/i386/pr79514.c =================================================================== --- testsuite/gcc.target/i386/pr79514.c (nonexistent) +++ testsuite/gcc.target/i386/pr79514.c (working copy) @@ -0,0 +1,12 @@ +/* PR target/79514 */ +/* { dg-do compile } */ +/* { dg-options "-m96bit-long-double" } */ + +extern void bar (long double); + +extern long double x; + +void foo (void) +{ + bar (x); +}