aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/config/loongarch/lasx.md42
-rw-r--r--gcc/config/loongarch/loongarch-protos.h1
-rw-r--r--gcc/config/loongarch/loongarch.cc48
-rw-r--r--gcc/config/loongarch/predicates.md16
-rw-r--r--gcc/doc/extend.texi7
-rw-r--r--gcc/fortran/ChangeLog10
-rw-r--r--gcc/fortran/trans-expr.cc24
-rw-r--r--gcc/fortran/trans-intrinsic.cc22
-rw-r--r--gcc/jit/jit-recording.cc4
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c4
-rw-r--r--gcc/testsuite/gcc.target/loongarch/lasx-reduc-1.c17
-rw-r--r--gcc/testsuite/gfortran.dg/is_contiguous_5.f90126
15 files changed, 334 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 59534a0..8bdba01 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2025-10-25 Sam James <sam@gentoo.org>
+
+ * doc/extend.texi (nocf_check): Fix syntax errors in example.
+
+2025-10-25 Jiahao Xu <xujiahao@loongson.cn>
+
+ * config/loongarch/lasx.md (vec_extract<mode><lasxhalf>): New define_expand.
+ (vec_extract_lo_<mode>): New define_insn_and_split.
+ (vec_extract_hi_<mode>): New define_insn.
+ * config/loongarch/loongarch-protos.h (loongarch_check_vect_par_cnst_half)
+ New function prototype.
+ * config/loongarch/loongarch.cc (loongarch_split_reduction):
+ Implement TARGET_VECTORIZE_SPLIT_REDUCTION.
+ (loongarch_check_vect_par_cnst_half): New function.
+ * config/loongarch/predicates.md
+ (vect_par_cnst_low_half): New predicate.
+ (vect_par_cnst_high_half): New predicate.
+
2025-10-24 Andrew MacLeod <amacleod@redhat.com>
PR tree-optimization/114025
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 8135eec..8a8350a 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20251025
+20251026
diff --git a/gcc/config/loongarch/lasx.md b/gcc/config/loongarch/lasx.md
index 3d71f30..eed4d2b 100644
--- a/gcc/config/loongarch/lasx.md
+++ b/gcc/config/loongarch/lasx.md
@@ -633,6 +633,48 @@
[(set_attr "move_type" "fmove")
(set_attr "mode" "<UNITMODE>")])
+(define_expand "vec_extract<mode><lasxhalf>"
+ [(match_operand:<VHMODE256_ALL> 0 "register_operand")
+ (match_operand:LASX 1 "register_operand")
+ (match_operand 2 "const_0_or_1_operand")]
+ "ISA_HAS_LASX"
+{
+ if (INTVAL (operands[2]))
+ {
+ operands[2] = loongarch_lsx_vec_parallel_const_half (<MODE>mode, true);
+ emit_insn (gen_vec_extract_hi_<mode> (operands[0], operands[1],
+ operands[2]));
+ }
+ else
+ {
+ operands[2] = loongarch_lsx_vec_parallel_const_half (<MODE>mode, false);
+ emit_insn (gen_vec_extract_lo_<mode> (operands[0], operands[1],
+ operands[2]));
+ }
+ DONE;
+})
+
+(define_insn_and_split "vec_extract_lo_<mode>"
+ [(set (match_operand:<VHMODE256_ALL> 0 "register_operand" "=f")
+ (vec_select:<VHMODE256_ALL>
+ (match_operand:LASX 1 "register_operand" "f")
+ (match_operand:LASX 2 "vect_par_cnst_low_half")))]
+ "ISA_HAS_LASX"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+ "operands[1] = gen_lowpart (<VHMODE256_ALL>mode, operands[1]);")
+
+(define_insn "vec_extract_hi_<mode>"
+ [(set (match_operand:<VHMODE256_ALL> 0 "register_operand" "=f")
+ (vec_select:<VHMODE256_ALL>
+ (match_operand:LASX 1 "register_operand" "f")
+ (match_operand:LASX 2 "vect_par_cnst_high_half")))]
+ "ISA_HAS_LASX"
+ "xvpermi.d\t%u0,%u1,0xe"
+ [(set_attr "move_type" "fmove")
+ (set_attr "mode" "<MODE>")])
+
(define_expand "vec_perm<mode>"
[(match_operand:LASX 0 "register_operand")
(match_operand:LASX 1 "register_operand")
diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h
index 6139af4..6ecbe27 100644
--- a/gcc/config/loongarch/loongarch-protos.h
+++ b/gcc/config/loongarch/loongarch-protos.h
@@ -121,6 +121,7 @@ extern bool loongarch_const_vector_same_int_p (rtx, machine_mode,
extern bool loongarch_const_vector_shuffle_set_p (rtx, machine_mode);
extern bool loongarch_const_vector_bitimm_set_p (rtx, machine_mode);
extern bool loongarch_const_vector_bitimm_clr_p (rtx, machine_mode);
+extern bool loongarch_check_vect_par_cnst_half (rtx, machine_mode, bool);
extern rtx loongarch_const_vector_vrepli (rtx, machine_mode);
extern rtx loongarch_lsx_vec_parallel_const_half (machine_mode, bool);
extern rtx loongarch_gen_const_int_vector (machine_mode, HOST_WIDE_INT);
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 3fe8c76..c782cac 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -1846,6 +1846,37 @@ loongarch_const_vector_shuffle_set_p (rtx op, machine_mode mode)
return true;
}
+/* Check if OP is a PARALLEL RTX with CONST_INT elements representing
+ the HIGH (high_p == TRUE) or LOW (high_p == FALSE) half of a vector
+ for mode MODE. Returns true if the pattern matches, false otherwise. */
+
+bool
+loongarch_check_vect_par_cnst_half (rtx op, machine_mode mode, bool high_p)
+{
+ int nunits = XVECLEN (op, 0);
+ int nelts = GET_MODE_NUNITS (mode);
+
+ if (!known_eq (nelts, nunits * 2))
+ return false;
+
+ rtx first = XVECEXP (op, 0, 0);
+ if (!CONST_INT_P (first))
+ return false;
+
+ int base = high_p ? nelts / 2 : 0;
+ if (INTVAL (first) != base)
+ return false;
+
+ for (int i = 1; i < nunits; i++)
+ {
+ rtx elem = XVECEXP (op, 0, i);
+ if (!CONST_INT_P (elem) || INTVAL (elem) != INTVAL (first) + i)
+ return false;
+ }
+
+ return true;
+}
+
rtx
loongarch_const_vector_vrepli (rtx x, machine_mode mode)
{
@@ -4143,6 +4174,19 @@ loongarch_rtx_costs (rtx x, machine_mode mode, int outer_code,
}
}
+/* All CPUs prefer to avoid cross-lane operations so perform reductions
+ upper against lower halves up to LSX reg size. */
+
+machine_mode
+loongarch_split_reduction (machine_mode mode)
+{
+ if (LSX_SUPPORTED_MODE_P (mode))
+ return mode;
+
+ return mode_for_vector (as_a <scalar_mode> (GET_MODE_INNER (mode)),
+ GET_MODE_NUNITS (mode) / 2).require ();
+}
+
/* Implement targetm.vectorize.builtin_vectorization_cost. */
static int
@@ -11397,6 +11441,10 @@ loongarch_can_inline_p (tree caller, tree callee)
#define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES \
loongarch_autovectorize_vector_modes
+#undef TARGET_VECTORIZE_SPLIT_REDUCTION
+#define TARGET_VECTORIZE_SPLIT_REDUCTION \
+ loongarch_split_reduction
+
#undef TARGET_OPTAB_SUPPORTED_P
#define TARGET_OPTAB_SUPPORTED_P loongarch_optab_supported_p
diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md
index fd2d7b9..34cf74d 100644
--- a/gcc/config/loongarch/predicates.md
+++ b/gcc/config/loongarch/predicates.md
@@ -699,3 +699,19 @@
return true;
})
+
+;; PARALLEL for a vec_select that selects the low half
+;; elements of a vector of MODE.
+(define_special_predicate "vect_par_cnst_low_half"
+ (match_code "parallel")
+{
+ return loongarch_check_vect_par_cnst_half (op, mode, false);
+})
+
+;; PARALLEL for a vec_select that selects the high half
+;; elements of a vector of MODE.
+(define_special_predicate "vect_par_cnst_high_half"
+ (match_code "parallel")
+{
+ return loongarch_check_vect_par_cnst_half (op, mode, true);;
+})
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index fb117f5..882c082 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -6896,15 +6896,14 @@ compiler checks for @code{nocf_check} attribute mismatch and reports
a warning in case of mismatch.
@smallexample
-@{
-int foo (void) __attribute__(nocf_check);
-void (*foo1)(void) __attribute__(nocf_check);
+int foo (void) __attribute__((nocf_check));
+void (*foo1)(void) __attribute__((nocf_check));
void (*foo2)(void);
/* foo's address is assumed to be valid. */
int
foo (void)
-
+@{
/* This call site is not checked for control-flow
validity. */
(*foo1)();
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 7ca0cb0..bf5bcd63 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,13 @@
+2025-10-25 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/114023
+ * trans-expr.cc (gfc_trans_pointer_assignment): Always set dtype
+ when remapping a pointer. For unlimited polymorphic LHS use
+ elem_len from RHS.
+ * trans-intrinsic.cc (gfc_conv_is_contiguous_expr): Extend inline
+ generated code for IS_CONTIGUOUS for pointer arguments to detect
+ when span differs from the element size.
+
2025-10-24 Harald Anlauf <anlauf@gmx.de>
PR fortran/122386
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 21f256b..67b60c7 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -11344,21 +11344,33 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
int dim;
gcc_assert (remap->u.ar.dimen == expr1->rank);
+ /* Always set dtype. */
+ tree dtype = gfc_conv_descriptor_dtype (desc);
+ tmp = gfc_get_dtype (TREE_TYPE (desc));
+ gfc_add_modify (&block, dtype, tmp);
+
+ /* For unlimited polymorphic LHS use elem_len from RHS. */
+ if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
+ {
+ tree elem_len;
+ tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
+ elem_len = fold_convert (gfc_array_index_type, tmp);
+ elem_len = gfc_evaluate_now (elem_len, &block);
+ tmp = gfc_conv_descriptor_elem_len (desc);
+ gfc_add_modify (&block, tmp,
+ fold_convert (TREE_TYPE (tmp), elem_len));
+ }
+
if (rank_remap)
{
/* Do rank remapping. We already have the RHS's descriptor
converted in rse and now have to build the correct LHS
descriptor for it. */
- tree dtype, data, span;
+ tree data, span;
tree offs, stride;
tree lbound, ubound;
- /* Set dtype. */
- dtype = gfc_conv_descriptor_dtype (desc);
- tmp = gfc_get_dtype (TREE_TYPE (desc));
- gfc_add_modify (&block, dtype, tmp);
-
/* Copy data pointer. */
data = gfc_conv_descriptor_data_get (rse.expr);
gfc_conv_descriptor_data_set (&block, desc, data);
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 05017d0..89a03d8 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -2316,10 +2316,14 @@ gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
int i;
tree fncall0;
gfc_array_spec *as;
+ gfc_symbol *sym = NULL;
if (arg->ts.type == BT_CLASS)
gfc_add_class_array_ref (arg);
+ if (arg->expr_type == EXPR_VARIABLE)
+ sym = arg->symtree->n.sym;
+
ss = gfc_walk_expr (arg);
gcc_assert (ss != gfc_ss_terminator);
gfc_init_se (&argse, NULL);
@@ -2342,7 +2346,7 @@ gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
fncall0 = build_call_expr_loc (input_location,
gfor_fndecl_is_contiguous0, 1, desc);
se->expr = fncall0;
- se->expr = convert (logical_type_node, se->expr);
+ se->expr = convert (boolean_type_node, se->expr);
}
else
{
@@ -2374,6 +2378,22 @@ gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
}
se->expr = cond;
}
+
+ /* A pointer that does not have the CONTIGUOUS attribute needs to be checked
+ if it points to an array whose span differs from the element size. */
+ if (as && sym && IS_POINTER(sym) && !sym->attr.contiguous)
+ {
+ tree span = gfc_conv_descriptor_span_get (desc);
+ tmp = fold_convert (TREE_TYPE (span),
+ gfc_conv_descriptor_elem_len (desc));
+ cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ span, tmp);
+ se->expr = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
+ boolean_type_node, cond,
+ convert (boolean_type_node, se->expr));
+ }
+
+ gfc_free_ss_chain (ss);
}
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 6816a71..5c641f6 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -3430,7 +3430,7 @@ recording::string *
recording::array_type::make_debug_string ()
{
return string::from_printf (m_ctxt,
- "%s[%ld]",
+ "%s[%" PRIu64 "]",
m_element_type->get_debug_string (),
m_num_elements);
}
@@ -3446,7 +3446,7 @@ recording::array_type::write_reproducer (reproducer &r)
" gcc_jit_context_new_array_type_u64 (%s,\n"
" %s, /* gcc_jit_location *loc */\n"
" %s, /* gcc_jit_type *element_type */\n"
- " %li); /* int num_elements */\n",
+ " %" PRIu64 "); /* int num_elements */\n",
id,
r.get_identifier (get_context ()),
r.get_identifier (m_loc),
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4b9bd57..d6a2cf4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2025-10-25 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/114023
+ * gfortran.dg/is_contiguous_5.f90: New test.
+
+2025-10-25 Jiahao Xu <xujiahao@loongson.cn>
+
+ * gcc.target/loongarch/lasx-reduc-1.c: New test.
+
2025-10-24 Andrew MacLeod <amacleod@redhat.com>
* gcc.dg/pr110405.c: New.
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c b/gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c
index 90c5ac9..da4b7aa 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c
@@ -7,7 +7,7 @@
/*
** foo:
-** movi d([0-9]+), #0
+** movi? [vdz]([0-9]+)\.?b?, #0
** movprfx z0\.b, p0/z, z0\.b
** usqadd z0\.b, p0/m, z0\.b, z\1\.b
** ret
@@ -19,7 +19,7 @@ svuint8_t foo (svbool_t pg, svuint8_t op1)
/*
** bar:
-** movi d([0-9]+), #0
+** movi? [vdz]([0-9]+)\.?b?, #0
** movprfx z0\.b, p0/z, z0\.b
** suqadd z0\.b, p0/m, z0\.b, z\1\.b
** ret
diff --git a/gcc/testsuite/gcc.target/loongarch/lasx-reduc-1.c b/gcc/testsuite/gcc.target/loongarch/lasx-reduc-1.c
new file mode 100644
index 0000000..e449259
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/lasx-reduc-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -funsafe-math-optimizations -mlasx -fno-unroll-loops -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_PLUS" 4 "optimized" } } */
+
+#define DEFINE_SUM_FUNCTION(T, FUNC_NAME, SIZE) \
+T FUNC_NAME(const T arr[]) { \
+ arr = __builtin_assume_aligned(arr, 64); \
+ T sum = 0; \
+ for (int i = 0; i < SIZE; i++) \
+ sum += arr[i]; \
+ return sum; \
+}
+
+DEFINE_SUM_FUNCTION (int, sum_int_1040, 1028)
+DEFINE_SUM_FUNCTION (float, sum_float_1040, 1028)
+DEFINE_SUM_FUNCTION (long, sum_long_1040, 1026)
+DEFINE_SUM_FUNCTION (double, sum_double_1040, 1026)
diff --git a/gcc/testsuite/gfortran.dg/is_contiguous_5.f90 b/gcc/testsuite/gfortran.dg/is_contiguous_5.f90
new file mode 100644
index 0000000..091e43b5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/is_contiguous_5.f90
@@ -0,0 +1,126 @@
+! { dg-do run }
+! PR fortran/114023 - IS_CONTIGUOUS and pointers to non-contiguous targets
+!
+! Based on testcase by Federico Perini
+
+program main
+ implicit none
+ complex, parameter :: cvals(*) = [(1,-1),(2,-2),(3,-3)]
+ complex , target :: cref(size(cvals)) = cvals ! Reference
+ complex, allocatable, target :: carr(:) ! Test
+
+ type cx
+ real :: re, im
+ end type cx
+ type(cx), parameter :: tvals(*) = [cx(1,-1),cx(2,-2),cx(3,-3)]
+ real, parameter :: expect(*) = tvals% re
+ type(cx) , target :: tref(size(cvals)) = tvals ! Reference
+ type(cx), allocatable, target :: tarr(:)
+
+ real, pointer :: rr1(:), rr2(:), rr3(:), rr4(:)
+ class(*), pointer :: cp1(:), cp2(:), cp3(:), cp4(:)
+
+ carr = cvals
+ tarr = tvals
+
+ if (any (expect /= [1,2,3])) error stop 90
+
+ ! REAL pointer to non-contiguous effective target
+ rr1(1:3) => cref%re
+ rr2 => cref%re
+ rr3(1:3) => carr%re
+ rr4 => carr%re
+
+ if (is_contiguous (rr1)) stop 1
+ if (my_contiguous_real (rr1)) stop 2
+ if (is_contiguous (cref(1:3)%re)) stop 3
+! if (my_contiguous_real (cref(1:3)%re)) stop 4 ! pr122397
+
+ if (is_contiguous (rr3)) stop 6
+ if (my_contiguous_real (rr3)) stop 7
+ if (is_contiguous (carr(1:3)%re)) stop 8
+! if (my_contiguous_real (carr(1:3)%re)) stop 9
+
+ if (is_contiguous (rr2)) stop 11
+ if (my_contiguous_real (rr2)) stop 12
+ if (is_contiguous (cref%re)) stop 13
+! if (my_contiguous_real (cref%re)) stop 14
+
+ if (is_contiguous (rr4)) stop 16
+ if (my_contiguous_real (rr4)) stop 17
+ if (is_contiguous (carr%re)) stop 18
+! if (my_contiguous_real (carr%re)) stop 19
+
+ rr1(1:3) => tref%re
+ rr2 => tref%re
+ rr3(1:3) => tarr%re
+ rr4 => tarr%re
+
+ if (is_contiguous (rr1)) stop 21
+ if (my_contiguous_real (rr1)) stop 22
+ if (is_contiguous (tref(1:3)%re)) stop 23
+! if (my_contiguous_real (tref(1:3)%re)) stop 24
+
+ if (is_contiguous (rr3)) stop 26
+ if (my_contiguous_real (rr3)) stop 27
+ if (is_contiguous (tarr(1:3)%re)) stop 28
+! if (my_contiguous_real (tarr(1:3)%re)) stop 29
+
+ if (is_contiguous (rr2)) stop 31
+ if (my_contiguous_real (rr2)) stop 32
+ if (is_contiguous (tref%re)) stop 33
+! if (my_contiguous_real (tref%re)) stop 34
+
+ if (is_contiguous (rr4)) stop 36
+ if (my_contiguous_real (rr4)) stop 37
+ if (is_contiguous (tarr%re)) stop 38
+! if (my_contiguous_real (tarr%re)) stop 39
+
+ ! Unlimited polymorphic pointer to non-contiguous effective target
+ cp1(1:3) => cref%re
+ cp2 => cref%re
+ cp3(1:3) => carr%re
+ cp4 => carr%re
+
+ if (is_contiguous (cp1)) stop 41
+ if (my_contiguous_poly (cp1)) stop 42
+ if (is_contiguous (cp2)) stop 43
+ if (my_contiguous_poly (cp2)) stop 44
+ if (is_contiguous (cp3)) stop 45
+ if (my_contiguous_poly (cp3)) stop 46
+ if (is_contiguous (cp4)) stop 47
+ if (my_contiguous_poly (cp4)) stop 48
+
+ cp1(1:3) => tref%re
+ cp2 => tref%re
+ cp3(1:3) => tarr%re
+ cp4 => tarr%re
+
+ if (is_contiguous (cp1)) stop 51
+ if (my_contiguous_poly (cp1)) stop 52
+ if (is_contiguous (cp2)) stop 53
+ if (my_contiguous_poly (cp2)) stop 54
+ if (is_contiguous (cp3)) stop 55
+ if (my_contiguous_poly (cp3)) stop 56
+ if (is_contiguous (cp4)) stop 57
+ if (my_contiguous_poly (cp4)) stop 58
+
+ deallocate (carr, tarr)
+contains
+ pure logical function my_contiguous_real (x) result (res)
+ real, pointer, intent(in) :: x(:)
+ res = is_contiguous (x)
+ if (any (x /= expect)) error stop 97
+ end function my_contiguous_real
+
+ pure logical function my_contiguous_poly (x) result (res)
+ class(*), pointer, intent(in) :: x(:)
+ res = is_contiguous (x)
+ select type (x)
+ type is (real)
+ if (any (x /= expect)) error stop 98
+ class default
+ error stop 99
+ end select
+ end function my_contiguous_poly
+end