aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.cc
diff options
context:
space:
mode:
authorAndrew Stubbs <ams@codesourcery.com>2023-10-20 16:26:51 +0100
committerAndrew Stubbs <ams@codesourcery.com>2023-11-10 11:54:59 +0000
commita5922427c29fad177251d89cc946d1c5bfc135eb (patch)
tree7cf8fc82c35aa1ea454ec1cfad53004b84c4f726 /gcc/expr.cc
parente24b0fed9234716c146aaf6f8c1b39170e43a6f3 (diff)
downloadgcc-a5922427c29fad177251d89cc946d1c5bfc135eb.zip
gcc-a5922427c29fad177251d89cc946d1c5bfc135eb.tar.gz
gcc-a5922427c29fad177251d89cc946d1c5bfc135eb.tar.bz2
vect: Don't set excess bits in unform masks
AVX ignores any excess bits in the mask (at least for vector sizes >=8), but AMD GCN magically uses a larger vector than was intended (the smaller sizes are "fake"), leading to wrong-code. This patch fixes amdgcn execution failures in gcc.dg/vect/pr81740-1.c, gfortran.dg/c-interop/contiguous-1.f90, gfortran.dg/c-interop/ff-descriptor-7.f90, and others. gcc/ChangeLog: * expr.cc (store_constructor): Add "and" operation to uniform mask generation.
Diffstat (limited to 'gcc/expr.cc')
-rw-r--r--gcc/expr.cc16
1 files changed, 14 insertions, 2 deletions
diff --git a/gcc/expr.cc b/gcc/expr.cc
index ed4dbb1..3e2a678 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -7470,7 +7470,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
break;
}
/* Use sign-extension for uniform boolean vectors with
- integer modes. */
+ integer modes. Effectively "vec_duplicate" for bitmasks. */
if (!TREE_SIDE_EFFECTS (exp)
&& VECTOR_BOOLEAN_TYPE_P (type)
&& SCALAR_INT_MODE_P (mode)
@@ -7479,7 +7479,19 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
{
rtx op0 = force_reg (TYPE_MODE (TREE_TYPE (elt)),
expand_normal (elt));
- convert_move (target, op0, 0);
+ rtx tmp = gen_reg_rtx (mode);
+ convert_move (tmp, op0, 0);
+
+ /* Ensure no excess bits are set.
+ GCN needs this for nunits < 64.
+ x86 needs this for nunits < 8. */
+ auto nunits = TYPE_VECTOR_SUBPARTS (type).to_constant ();
+ if (maybe_ne (GET_MODE_PRECISION (mode), nunits))
+ tmp = expand_binop (mode, and_optab, tmp,
+ GEN_INT ((1 << nunits) - 1), target,
+ true, OPTAB_DIRECT);
+ if (tmp != target)
+ emit_move_insn (target, tmp);
break;
}