#include "tree-pass.h"
#include "df.h"
#include "rtl-ssa.h"
+#include "rtl-iter.h"
#include "cfgcleanup.h"
#include "insn-attr.h"
#include "tm-constrs.h"
&& def1->insn ()->compare_with (insn) >= 0)
return NULL_RTX;
}
+ else
+ {
+ /* If the use is in a subreg e.g. in a store it is possible that
+ we punned the vector mode with a larger mode like
+ (subreg:V1SI (reg:V4QI 123)).
+ For an AVL of 1 that means we actually store one SImode
+ element and not 1 QImode elements. But the latter is what we
+ would propagate if we took the AVL operand literally.
+ Instead we scale it by the ratio of inner and outer mode
+ (4 in the example above). */
+ int factor = 1;
+ if (use->includes_subregs ())
+ {
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, use_insn->rtl (), NONCONST)
+ {
+ const_rtx x = *iter;
+ if (x
+ && SUBREG_P (x)
+ && REG_P (SUBREG_REG (x))
+ && REGNO (SUBREG_REG (x)) == use->regno ()
+ && known_eq (GET_MODE_SIZE (use->mode ()),
+ GET_MODE_SIZE (GET_MODE (x))))
+ {
+ if (can_div_trunc_p (GET_MODE_NUNITS (use->mode ()),
+ GET_MODE_NUNITS (GET_MODE (x)),
+ &factor))
+ {
+ gcc_assert (factor > 0);
+ break;
+ }
+ else
+ return NULL_RTX;
+ }
+ }
+ }
+
+ if (factor > 1)
+ new_use_avl = GEN_INT (INTVAL (new_use_avl) * factor);
+ }
if (!use_avl)
use_avl = new_use_avl;
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcbv_zvl256b -mabi=lp64d -O3 -mrvv-vector-bits=zvl --param=riscv-autovec-mode=V4QI -mtune=generic-ooo -fdump-rtl-avlprop-all" } */
+
+typedef unsigned char uint8_t;
+typedef short int16_t;
+
+#define FDEC_STRIDE 32
+
+static inline uint8_t x264_clip_uint8( int x )
+{
+ return x;
+}
+
+void
+x264_add4x4_idct (uint8_t *p_dst, int16_t d[16])
+{
+ for( int y = 0; y < 4; y++ )
+ {
+ for( int x = 0; x < 4; x++ )
+ p_dst[x] = x264_clip_uint8( p_dst[x] + d[y*4+x] );
+ p_dst += FDEC_STRIDE;
+ }
+}
+
+/* { dg-final { scan-rtl-dump "Propagating AVL: \\(const_int 4" "avlprop" } } */
+/* { dg-final { scan-rtl-dump-not "Propagating AVL: \\(const_int 1" "avlprop" } } */