aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorUros Bizjak <uros@gcc.gnu.org>2012-11-11 20:17:17 +0100
committerUros Bizjak <uros@gcc.gnu.org>2012-11-11 20:17:17 +0100
commitebbcbc2ed315384e2689ffcaf6141febb9e01765 (patch)
treeac8da306839f28c4b0dcf24f0d0f4c1111751736 /gcc/config
parent2059f70d74ecc06262ea6e8351299846f2e3e530 (diff)
downloadgcc-ebbcbc2ed315384e2689ffcaf6141febb9e01765.zip
gcc-ebbcbc2ed315384e2689ffcaf6141febb9e01765.tar.gz
gcc-ebbcbc2ed315384e2689ffcaf6141febb9e01765.tar.bz2
re PR target/47440 (Use LCM for vzeroupper insertion)
PR target/47440 * config/i386/i386.c (check_avx256_stores): Remove. (ix86_check_avx256_register): New. (ix86_avx_u128_mode_needed): Use ix86_check_avx256_register. Check the whole RTX for 256bit registers using for_each_rtx. (ix86_check_avx_stores): New. (ix86_avx_u128_mode_after): Change mode of CALL RTX to AVX_U128_CLEAN if there are no 256bit registers used in the function return register. (ix86_avx_u128_mode_entry): Use ix86_check_avx256_register. (ix86_avx_u128_mode_exit): Ditto. From-SVN: r193409
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386.c71
1 files changed, 39 insertions, 32 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 60a39b8..0872295 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -14942,20 +14942,16 @@ output_387_binary_op (rtx insn, rtx *operands)
return buf;
}
-/* Check if a 256bit AVX register is referenced in stores. */
+/* Check if a 256bit AVX register is referenced inside of EXP. */
-static void
-check_avx256_stores (rtx dest, const_rtx set, void *data)
+static int
+ix86_check_avx256_register (rtx *exp, void *data ATTRIBUTE_UNUSED)
{
- if (((REG_P (dest) || MEM_P (dest))
- && VALID_AVX256_REG_OR_OI_MODE (GET_MODE (dest)))
- || (GET_CODE (set) == SET
- && (REG_P (SET_SRC (set)) || MEM_P (SET_SRC (set)))
- && VALID_AVX256_REG_OR_OI_MODE (GET_MODE (SET_SRC (set)))))
- {
- bool *used = (bool *) data;
- *used = true;
- }
+ if (REG_P (*exp)
+ && VALID_AVX256_REG_OR_OI_MODE (GET_MODE (*exp)))
+ return 1;
+
+ return 0;
}
/* Return needed mode for entity in optimize_mode_switching pass. */
@@ -14963,8 +14959,6 @@ check_avx256_stores (rtx dest, const_rtx set, void *data)
static int
ix86_avx_u128_mode_needed (rtx insn)
{
- bool avx_u128_used;
-
if (CALL_P (insn))
{
rtx link;
@@ -14979,8 +14973,7 @@ ix86_avx_u128_mode_needed (rtx insn)
{
rtx arg = XEXP (XEXP (link, 0), 0);
- if (REG_P (arg)
- && VALID_AVX256_REG_OR_OI_MODE (GET_MODE (arg)))
+ if (ix86_check_avx256_register (&arg, NULL))
return AVX_U128_ANY;
}
}
@@ -14988,10 +14981,11 @@ ix86_avx_u128_mode_needed (rtx insn)
return AVX_U128_CLEAN;
}
- /* Check if a 256bit AVX register is referenced in stores. */
- avx_u128_used = false;
- note_stores (PATTERN (insn), check_avx256_stores, &avx_u128_used);
- if (avx_u128_used)
+ /* Require DIRTY mode if a 256bit AVX register is referenced. Hardware
+ changes state only when a 256bit register is written to, but we need
+ to prevent the compiler from moving optimal insertion point above
+ eventual read from 256bit register. */
+ if (for_each_rtx (&PATTERN (insn), ix86_check_avx256_register, NULL))
return AVX_U128_DIRTY;
return AVX_U128_ANY;
@@ -15071,28 +15065,42 @@ ix86_mode_needed (int entity, rtx insn)
return 0;
}
+/* Check if a 256bit AVX register is referenced in stores. */
+
+static void
+ix86_check_avx256_stores (rtx dest, const_rtx set ATTRIBUTE_UNUSED, void *data)
+ {
+ if (ix86_check_avx256_register (&dest, NULL))
+ {
+ bool *used = (bool *) data;
+ *used = true;
+ }
+ }
+
/* Calculate mode of upper 128bit AVX registers after the insn. */
static int
ix86_avx_u128_mode_after (int mode, rtx insn)
{
rtx pat = PATTERN (insn);
- bool avx_u128_used;
if (vzeroupper_operation (pat, VOIDmode)
|| vzeroall_operation (pat, VOIDmode))
return AVX_U128_CLEAN;
- /* Check if a 256bit AVX register is referenced in stores. */
- avx_u128_used = false;
- note_stores (pat, check_avx256_stores, &avx_u128_used);
- if (avx_u128_used)
- return AVX_U128_DIRTY;
/* We know that state is clean after CALL insn if there are no
- 256bit modes used in the function return register. */
- else if (CALL_P (insn))
- return AVX_U128_CLEAN;
+ 256bit registers used in the function return register. */
+ if (CALL_P (insn))
+ {
+ bool avx_reg256_found = false;
+ note_stores (pat, ix86_check_avx256_stores, &avx_reg256_found);
+ if (!avx_reg256_found)
+ return AVX_U128_CLEAN;
+ }
+ /* Otherwise, return current mode. Remember that if insn
+ references AVX 256bit registers, the mode was already changed
+ to DIRTY from MODE_NEEDED. */
return mode;
}
@@ -15127,8 +15135,7 @@ ix86_avx_u128_mode_entry (void)
{
rtx incoming = DECL_INCOMING_RTL (arg);
- if (incoming && REG_P (incoming)
- && VALID_AVX256_REG_OR_OI_MODE (GET_MODE (incoming)))
+ if (incoming && ix86_check_avx256_register (&incoming, NULL))
return AVX_U128_DIRTY;
}
@@ -15162,7 +15169,7 @@ ix86_avx_u128_mode_exit (void)
/* Exit mode is set to AVX_U128_DIRTY if there are
256bit modes used in the function return register. */
- if (reg && REG_P (reg) && VALID_AVX256_REG_OR_OI_MODE (GET_MODE (reg)))
+ if (reg && ix86_check_avx256_register (&reg, NULL))
return AVX_U128_DIRTY;
return AVX_U128_CLEAN;