diff options
author | Jakub Jelinek <jakub@redhat.com> | 2020-07-15 11:26:22 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2020-07-15 11:26:22 +0200 |
commit | 410675cb63466d8de9ad590521f0766b012d2475 (patch) | |
tree | 7abbcf66e3de58b3bf89a06714571c0f37a4570f /gcc/builtins.c | |
parent | 7a9fd18598e638b55c591624e753fb7a88abe1ab (diff) |
builtins: Avoid useless char/short -> int promotions before atomics [PR96176]
As mentioned in the PR, we generate a useless movzbl insn before lock cmpxchg.
The problem is that the builtin for the char/short cases has the arguments
promoted to int and combine gives up, because the instructions have
MEM_VOLATILE_P arguments and recog in that case doesn't recognize anything
when volatile_ok is false, and nothing afterwards optimizes the
(reg:SI a) = (zero_extend:SI (reg:QI a))
... (subreg:QI (reg:SI a) 0) ...
The following patch fixes it at expansion time, we already have a function
that is meant to undo the promotion, so this just adds the very common case
to that.
2020-07-15 Jakub Jelinek <jakub@redhat.com>
PR target/96176
* builtins.c: Include gimple-ssa.h, tree-ssa-live.h and
tree-outof-ssa.h.
(expand_expr_force_mode): If exp is a SSA_NAME with different mode
from MODE and get_gimple_for_ssa_name is a cast from MODE, use the
cast's rhs.
* gcc.target/i386/pr96176.c: New test.
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 4754602e0ec..eb662112b32 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -73,6 +73,9 @@ along with GCC; see the file COPYING3. If not see #include "gomp-constants.h" #include "omp-general.h" #include "tree-dfa.h" +#include "gimple-ssa.h" +#include "tree-ssa-live.h" +#include "tree-outof-ssa.h" struct target_builtins default_target_builtins; #if SWITCHABLE_TARGET @@ -6671,6 +6674,27 @@ expand_expr_force_mode (tree exp, machine_mode mode) rtx val; machine_mode old_mode; + if (TREE_CODE (exp) == SSA_NAME + && TYPE_MODE (TREE_TYPE (exp)) != mode) + { + /* Undo argument promotion if possible, as combine might not + be able to do it later due to MEM_VOLATILE_P uses in the + patterns. */ + gimple *g = get_gimple_for_ssa_name (exp); + if (g && gimple_assign_cast_p (g)) + { + tree rhs = gimple_assign_rhs1 (g); + tree_code code = gimple_assign_rhs_code (g); + if (CONVERT_EXPR_CODE_P (code) + && TYPE_MODE (TREE_TYPE (rhs)) == mode + && INTEGRAL_TYPE_P (TREE_TYPE (exp)) + && INTEGRAL_TYPE_P (TREE_TYPE (rhs)) + && (TYPE_PRECISION (TREE_TYPE (exp)) + > TYPE_PRECISION (TREE_TYPE (rhs)))) + exp = rhs; + } + } + val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL); /* If VAL is promoted to a wider mode, convert it back to MODE. Take care of CONST_INTs, where we know the old_mode only from the call argument. */ |