diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2016-02-04 18:56:33 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2016-02-05 09:35:13 -0800 |
commit | ed64cfe34c8fb65f6b651599d176fa5bc4b934c1 (patch) | |
tree | 686f69f68d0eafcde4b8efbf688817b7a84690d7 | |
parent | 9c28a298bdc19a284c10c90d5f4bd433eaf63eed (diff) | |
download | gcc-hjl/pr69692/master.tar.gz |
Enable STV if no stack realignment is neededhjl/pr69692/master
Add *movdi_to_v2di for STV to load a DI into an xmm register.
-rw-r--r-- | gcc/config/i386/i386.c | 51 | ||||
-rw-r--r-- | gcc/config/i386/sse.md | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr69692.c | 22 |
3 files changed, 63 insertions, 20 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 1215ae45a4b..5d29feb1b03 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -3588,14 +3588,21 @@ convert_scalars_to_vector () bitmap_obstack_release (NULL); df_process_deferred_rescans (); - /* Conversion means we may have 128bit register spills/fills - which require aligned stack. */ - if (converted_insns) - { - if (crtl->stack_alignment_needed < 128) - crtl->stack_alignment_needed = 128; - if (crtl->stack_alignment_estimated < 128) - crtl->stack_alignment_estimated = 128; + /* Conversion means we may have 64-bit register spills/fills which + require aligned stack. No stack realignment is needed to get + 64-bit stack alignment since the incoming stack boundary >= 64 + bits. */ + if (converted_insns && crtl->stack_alignment_estimated < 64) + { + unsigned int incoming_stack_boundary + = (crtl->parm_stack_boundary > ix86_incoming_stack_boundary + ? crtl->parm_stack_boundary : ix86_incoming_stack_boundary); + if (incoming_stack_boundary < 64) + gcc_unreachable (); + + /* Increase stack_alignment_estimated up to incoming_stack_boundary + won't affect stack realignment. */ + crtl->stack_alignment_estimated = 64; } return 0; @@ -3661,7 +3668,21 @@ public: /* opt_pass methods: */ virtual bool gate (function *) { - return !TARGET_64BIT && TARGET_STV && TARGET_SSE2 && optimize > 1; + if (!TARGET_64BIT && TARGET_STV && TARGET_SSE2 && optimize > 1) + { + /* STV may need 64-bit register spills/fills which require + aligned stack. */ + if (crtl->stack_alignment_estimated >= 64) + return true; + + /* No stack realignment is needed to get 64-bit stack + alignment if incoming stack boundary >= 64 bits. */ + unsigned int incoming_stack_boundary + = (crtl->parm_stack_boundary > ix86_incoming_stack_boundary + ? crtl->parm_stack_boundary : ix86_incoming_stack_boundary); + return incoming_stack_boundary >= 64; + } + return false; } virtual unsigned int execute (function *) @@ -5453,13 +5474,6 @@ ix86_option_override_internal (bool main_args_p, opts->x_target_flags |= MASK_VZEROUPPER; if (!(opts_set->x_target_flags & MASK_STV)) opts->x_target_flags |= MASK_STV; - /* Disable STV if -mpreferred-stack-boundary={2,3} or - -mincoming-stack-boundary={2,3} - the needed - stack realignment will be extra cost the pass doesn't take into - account and the pass can't realign the stack. */ - if (ix86_preferred_stack_boundary < 128 - || ix86_incoming_stack_boundary < 128) - opts->x_target_flags &= ~MASK_STV; if (!ix86_tune_features[X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL] && !(opts_set->x_target_flags & MASK_AVX256_SPLIT_UNALIGNED_LOAD)) opts->x_target_flags |= MASK_AVX256_SPLIT_UNALIGNED_LOAD; @@ -29330,10 +29344,7 @@ ix86_minimum_alignment (tree exp, machine_mode mode, if ((mode == DImode || (type && TYPE_MODE (type) == DImode)) && (!type || !TYPE_USER_ALIGN (type)) && (!decl || !DECL_USER_ALIGN (decl))) - { - gcc_checking_assert (!TARGET_STV); - return 32; - } + return 32; return align; } diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 045a85f0ac3..201670a7c4b 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -1075,6 +1075,16 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) +;; Used by STV to load a DI into an xmm register. +(define_insn "*movdi_to_v2di" + [(set (match_operand:V2DI 0 "register_operand" "=x") + (subreg:V2DI (match_operand:DI 1 "nonimmediate_operand" "xm") 0))] + "!TARGET_64BIT && TARGET_SSE2" + "%vmovq\t{%1, %0|%0, %1}" + [(set_attr "type" "ssemov") + (set_attr "prefix" "maybe_vex") + (set_attr "mode" "DI")]) + ;; Move a DI from a 32-bit register pair (e.g. %edx:%eax) to an xmm. ;; We'd rather avoid this entirely; if the 32-bit reg pair was loaded ;; from memory, we'd prefer to load the memory directly into the %xmm diff --git a/gcc/testsuite/gcc.target/i386/pr69692.c b/gcc/testsuite/gcc.target/i386/pr69692.c new file mode 100644 index 00000000000..63b6f352e56 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr69692.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target { ia32 } } } */ +/* { dg-options "-O2 -msse2 -mno-accumulate-outgoing-args -mpreferred-stack-boundary=2" } */ + +struct bar +{ + int i[16] __attribute__ ((aligned(16))); +}; + +extern void fn2 (void); +long long a, b; + +struct bar +fn1 (struct bar x) +{ + long long c = a; + a = b ^ a; + fn2 (); + a = c; + return x; +} + +/* { dg-final { scan-assembler "pxor\[^\n\]*xmm" } } */ |