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.
This commit is contained in:
Jakub Jelinek 2020-07-15 11:26:22 +02:00
parent 7a9fd18598
commit 410675cb63
2 changed files with 37 additions and 0 deletions

View File

@ -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. */

View File

@ -0,0 +1,13 @@
/* PR target/96176 */
/* { dg-do compile { target lp64 } } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-not "\tmovzbl\t" } } */
unsigned char v;
void
foo (unsigned char *x, unsigned char y, unsigned char z)
{
__atomic_compare_exchange_n (x, &y, z, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
v = y;
}