diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2022-05-18 13:00:47 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2022-06-01 14:23:26 -0700 |
commit | a743a72714fc4a9d7036d28d0cacdf2a3621f629 (patch) | |
tree | 4a2da93e3ac20ae6f5be420e5792cc84a6f2f3ad /gcc/df-core.cc | |
parent | e2e471d83d16449a325315c0f33dc52b90ce0fac (diff) | |
download | gcc-a743a72714fc4a9d7036d28d0cacdf2a3621f629.zip gcc-a743a72714fc4a9d7036d28d0cacdf2a3621f629.tar.gz gcc-a743a72714fc4a9d7036d28d0cacdf2a3621f629.tar.bz2 |
DSE: Use the constant store source if possible
RTL DSE tracks redundant constant stores within a basic block. When RTL
loop invariant motion hoists a constant initialization out of the loop
into a separate basic block, the constant store value becomes unknown
within the original basic block. When recording store for RTL DSE, check
if the source register is set only once to a constant by a non-partial
unconditional load. If yes, record the constant as the constant store
source. It eliminates unrolled zero stores after memset 0 in a loop
where a vector register is used as the zero store source.
gcc/
PR rtl-optimization/105638
* df-core.cc (df_find_single_def_src): Moved and renamed from
find_single_def_src in loop-iv.cc. Change the argument to rtx
and use rtx_equal_p. Return null for partial or conditional
defs.
* df.h (df_find_single_def_src): New prototype.
* dse.cc (record_store): Use the constant source if the source
register is set only once.
* loop-iv.cc (find_single_def_src): Moved to df-core.cc.
(replace_single_def_regs): Replace find_single_def_src with
df_find_single_def_src.
gcc/testsuite/
PR rtl-optimization/105638
* g++.target/i386/pr105638.C: New test.
Diffstat (limited to 'gcc/df-core.cc')
-rw-r--r-- | gcc/df-core.cc | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/gcc/df-core.cc b/gcc/df-core.cc index a901b84..e3a56bf 100644 --- a/gcc/df-core.cc +++ b/gcc/df-core.cc @@ -2009,6 +2009,47 @@ df_reg_used (rtx_insn *insn, rtx reg) return df_find_use (insn, reg) != NULL; } +/* If REG has a single definition, return its known value, otherwise return + null. */ + +rtx +df_find_single_def_src (rtx reg) +{ + rtx src = NULL_RTX; + + /* Don't look through unbounded number of single definition REG copies, + there might be loops for sources with uninitialized variables. */ + for (int cnt = 0; cnt < 128; cnt++) + { + df_ref adef = DF_REG_DEF_CHAIN (REGNO (reg)); + if (adef == NULL || DF_REF_NEXT_REG (adef) != NULL + || DF_REF_IS_ARTIFICIAL (adef) + || (DF_REF_FLAGS (adef) + & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))) + return NULL_RTX; + + rtx set = single_set (DF_REF_INSN (adef)); + if (set == NULL || !rtx_equal_p (SET_DEST (set), reg)) + return NULL_RTX; + + rtx note = find_reg_equal_equiv_note (DF_REF_INSN (adef)); + if (note && function_invariant_p (XEXP (note, 0))) + return XEXP (note, 0); + src = SET_SRC (set); + + if (REG_P (src)) + { + reg = src; + continue; + } + break; + } + if (!function_invariant_p (src)) + return NULL_RTX; + + return src; +} + /*---------------------------------------------------------------------------- Debugging and printing functions. |