summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2016-02-04 18:56:33 -0800
committerH.J. Lu <hjl.tools@gmail.com>2016-02-05 09:35:13 -0800
commited64cfe34c8fb65f6b651599d176fa5bc4b934c1 (patch)
tree686f69f68d0eafcde4b8efbf688817b7a84690d7
parent9c28a298bdc19a284c10c90d5f4bd433eaf63eed (diff)
downloadgcc-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.c51
-rw-r--r--gcc/config/i386/sse.md10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr69692.c22
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" } } */