Merge branch 'releases/gcc-15' into devel/omp/gcc-15

Merge up to r15-10483-gcc39aed963b5c6 (5 Nov 2025)
This commit is contained in:
Tobias Burnus 2025-11-05 12:59:58 +01:00
commit 6816d10a43
53 changed files with 1502 additions and 156 deletions

View File

@ -1,3 +1,106 @@
2025-11-03 Jeff Law <jlaw@ventanamicro.com>
Backported from master:
2025-11-01 Jeff Law <jlaw@ventanamicro.com>
PR rtl-optimization/122321
* lra-constraints.cc (update_equiv): Make sure REGNO is in
ira_reg_equiv before trying to update ira_reg_equiv.
2025-11-03 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
Backported from master:
2025-10-26 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
PR target/122270
* config/riscv/riscv-vector-builtins-bases.cc (vset::fold): Use the
unshare_expr for the statement that will be added seperately rather
the one which will be used for the replacement.
2025-11-02 Georg-Johann Lay <avr@gjlay.de>
Backported from master:
2025-11-02 Georg-Johann Lay <avr@gjlay.de>
PR target/122527
* config/avr/avr.cc (avr_load_libgcc_p): Return false if
the address-space is not ADDR_SPACE_FLASH.
(avr_out_lpm_no_lpmx [addr=REG]): Handle sizes of 3 and 4 bytes.
2025-11-02 Georg-Johann Lay <avr@gjlay.de>
Backported from master:
2025-11-02 Georg-Johann Lay <avr@gjlay.de>
PR tree-optimization/118012
PR tree-optimization/122505
* config/avr/avr.md (mulpsi3): Also allow the insn condition
in the case where avropt_pr118012 && !AVR_TINY.
(*mulpsi3): Handle split for the !AVR_HAVE_MUL case.
(*mulpsi3-nomul.libgcc_split, *mulpsi3-nomul.libgcc): New insns.
2025-10-31 Tamar Christina <tamar.christina@arm.com>
Backported from master:
2025-10-27 Tamar Christina <tamar.christina@arm.com>
PR tree-optimization/122408
* tree-vect-slp-patterns.cc (vect_validate_multiplication): Cleanup and
document interface.
(complex_mul_pattern::matches, complex_fms_pattern::matches): Update to
new interface.
2025-10-31 Jinyang He <hejinyang@loongson.cn>
Backported from master:
2025-10-30 Jinyang He <hejinyang@loongson.cn>
Peng Fan <fanpeng@loongson.cn>
* config/loongarch/loongarch.cc
(loongarch_expand_conditional_move): Only allow valid binary
op when optimize conditional move.
2025-10-30 Guo Jie <guojie@loongson.cn>
Backported from master:
2025-10-30 Guo Jie <guojie@loongson.cn>
* config/loongarch/lasx.md (fnma<mode>4): Remove.
* config/loongarch/lsx.md (fnma<mode>4): Remove.
* config/loongarch/simd.md (fnma<mode>4): Simplify and correct.
2025-10-27 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/122394
* tree-ssa-phiopt.cc (spaceship_replacement): Use
build_debug_expr_decl instead of manually building DEBUG_EXPR_DECL
and getting SET_DECL_MODE wrong.
2025-10-27 Jeff Law <jlaw@ventanamicro.com>
Backported from master:
2025-10-13 Jeff Law <jlaw@ventanamicro.com>
PR target/120674
* config/riscv/riscv.cc (riscv_dwarf_poly_indeterminite_value): Do not
set FACTOR to zero, for that case use one instead.
2025-10-27 Tamar Christina <tamar.christina@arm.com>
Backported from master:
2025-10-17 Tamar Christina <tamar.christina@arm.com>
Jennifer Schmitz <jschmitz@nvidia.com>
PR target/121604
* config/aarch64/aarch64-sve-builtins-shapes.cc (apply_predication):
Store gp_index.
(struct pmov_to_vector_lane_def): Mark instruction as has no GP.
* config/aarch64/aarch64-sve-builtins.h (function_instance::gp_value,
function_instance::inactive_values, function_instance::gp_index,
function_shape::has_gp_argument_p): New.
* config/aarch64/aarch64-sve-builtins.cc (gimple_folder::fold_pfalse):
Simplify code and use GP helpers.
2025-10-26 LIU Hao <lh_mouse@126.com>
Backported from master:

View File

@ -1 +1 @@
20251027
20251105

View File

@ -1,3 +1,14 @@
2025-11-04 Bob Duff <duff@adacore.com>
PR ada/118208
* exp_ch5.adb
(Expand_Assign_With_Target_Names.Replace_Target):
Remove code setting Entity to Empty.
* sinfo.ads (Has_Target_Names):
Improve comment: add "@" to clarify what "target name"
means, and remove the content-free phrase "and must
be expanded accordingly."
2025-10-24 Eric Botcazou <ebotcazou@adacore.com>
PR ada/118782

View File

@ -2254,7 +2254,8 @@ package body Exp_Ch5 is
function Replace_Target (N : Node_Id) return Traverse_Result;
-- Replace occurrences of the target name by the proper entity: either
-- the entity of the LHS in simple cases, or the formal of the
-- constructed procedure otherwise.
-- constructed procedure otherwise. Mark all nodes as Analyzed=False
-- so reanalysis will occur.
--------------------
-- Replace_Target --
@ -2264,20 +2265,6 @@ package body Exp_Ch5 is
begin
if Nkind (N) = N_Target_Name then
Rewrite (N, New_Occurrence_Of (Ent, Sloc (N)));
-- The expression will be reanalyzed when the enclosing assignment
-- is reanalyzed, so reset the entity, which may be a temporary
-- created during analysis, e.g. a loop variable for an iterated
-- component association. However, if entity is callable then
-- resolution has established its proper identity (including in
-- rewritten prefixed calls) so we must preserve it.
elsif Is_Entity_Name (N) then
if Present (Entity (N))
and then not Is_Overloadable (Entity (N))
then
Set_Entity (N, Empty);
end if;
end if;
Set_Analyzed (N, False);

View File

@ -1477,7 +1477,7 @@ package Sinfo is
-- Has_Target_Names
-- Present in assignment statements. Indicates that the RHS contains
-- target names (see AI12-0125-3) and must be expanded accordingly.
-- target names ("@" -- see AI12-0125-3).
-- Has_Wide_Character
-- Present in string literals, set if any wide character (i.e. character

View File

@ -21,7 +21,10 @@
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "basic-block.h"
#include "tree.h"
#include "function.h"
#include "gimple.h"
#include "rtl.h"
#include "tm_p.h"
#include "memmodel.h"
@ -68,23 +71,36 @@ za_group_is_pure_overload (const function_group_info &group)
types in ARGUMENT_TYPES. RETURN_TYPE is the type returned by the
function. */
static void
apply_predication (const function_instance &instance, tree return_type,
apply_predication (function_instance &instance, tree return_type,
vec<tree> &argument_types)
{
/* Initially mark the function as not being predicated. */
instance.gp_index = -1;
/* There are currently no SME ZA instructions that have both merging and
unpredicated forms, so for simplicity, the predicates are always included
in the original format string. */
if (instance.pred != PRED_none && instance.pred != PRED_za_m)
{
argument_types.quick_insert (0, instance.gp_type ());
instance.gp_index = 0;
/* For unary merge operations, the first argument is a vector with
the same type as the result. For unary_convert_narrowt it also
provides the "bottom" half of active elements, and is present
for all types of predication. */
auto nargs = argument_types.length () - 1;
if (instance.shape->has_merge_argument_p (instance, nargs))
{
argument_types.quick_insert (0, return_type);
instance.gp_index = 1;
}
}
/* In this case the predicate type we added above is a non-governing
predicate operand (and there is no GP), so update the gp_index value
accordingly. */
if (!instance.shape->has_gp_argument_p (instance))
instance.gp_index = -1;
}
/* Parse and move past an element type in FORMAT and return it as a type
@ -3301,6 +3317,14 @@ struct pmov_to_vector_lane_def : public overloaded_base<0>
but it doesn't currently have the necessary information. */
return c.require_immediate_range (1, 1, bytes - 1);
}
/* This function has a predicate argument, and is a merging instruction, but
the predicate is not a GP. */
bool
has_gp_argument_p (const function_instance &) const override
{
return false;
}
};
SHAPE (pmov_to_vector_lane)

View File

@ -3630,24 +3630,22 @@ gimple_folder::redirect_pred_x ()
gimple *
gimple_folder::fold_pfalse ()
{
if (pred == PRED_none)
tree gp = gp_value (call);
/* If there isn't a GP then we can't do any folding as the instruction isn't
predicated. */
if (!gp)
return nullptr;
tree arg0 = gimple_call_arg (call, 0);
if (pred == PRED_m)
{
/* Unary function shapes with _m predication are folded to the
inactive vector (arg0), while other function shapes are folded
to op1 (arg1). */
tree arg1 = gimple_call_arg (call, 1);
if (is_pfalse (arg1))
return fold_call_to (arg0);
if (is_pfalse (arg0))
return fold_call_to (arg1);
tree val = inactive_values (call);
if (is_pfalse (gp))
return fold_call_to (val);
return nullptr;
}
if ((pred == PRED_x || pred == PRED_z) && is_pfalse (arg0))
if ((pred == PRED_x || pred == PRED_z) && is_pfalse (gp))
return fold_call_to (build_zero_cst (TREE_TYPE (lhs)));
if (pred == PRED_implicit && is_pfalse (arg0))
if (pred == PRED_implicit && is_pfalse (gp))
{
unsigned int flags = call_properties ();
/* Folding to lhs = {0, ...} is not appropriate for intrinsics with

View File

@ -402,6 +402,8 @@ public:
bool could_trap_p () const;
vector_type_index gp_type_index () const;
tree gp_value (gcall *) const;
tree inactive_values (gcall *) const;
tree gp_type () const;
unsigned int vectors_per_tuple () const;
@ -435,6 +437,7 @@ public:
group_suffix_index group_suffix_id;
predication_index pred;
fpm_mode_index fpm_mode;
int gp_index;
};
class registered_function;
@ -800,6 +803,8 @@ public:
virtual bool has_merge_argument_p (const function_instance &,
unsigned int) const;
virtual bool has_gp_argument_p (const function_instance &) const;
virtual bool explicit_type_suffix_p (unsigned int) const = 0;
/* True if the group suffix is present in overloaded names.
@ -948,6 +953,33 @@ function_instance::gp_type () const
return acle_vector_types[0][gp_type_index ()];
}
/* Return the tree value that should be used as the governing predicate of
this function. If none then return NULL_TREE. */
inline tree
function_instance::gp_value (gcall *call) const
{
if (gp_index < 0)
return NULL_TREE;
return gimple_call_arg (call, gp_index);
}
/* Return the tree value that should be used for the inactive lanes should this
function be a predicated function with a gp. Otherwise return NULL_TREE. */
inline tree
function_instance::inactive_values (gcall *call) const
{
if (gp_index < 0)
return NULL_TREE;
/* Function is unary with m predicate. */
if (gp_index == 1)
return gimple_call_arg (call, 0);
/* Else the inactive values are the next element. */
return gimple_call_arg (call, 1);
}
/* If the function operates on tuples of vectors, return the number
of vectors in the tuples, otherwise return 1. */
inline unsigned int
@ -1122,6 +1154,14 @@ function_shape::has_merge_argument_p (const function_instance &instance,
return nargs == 1 && instance.pred == PRED_m;
}
/* Return true if INSTANCE has an predicate argument that can be used as the global
predicate. */
inline bool
function_shape::has_gp_argument_p (const function_instance &instance) const
{
return instance.pred != PRED_none;
}
/* Return the mode of the result of a call. */
inline machine_mode
function_expander::result_mode () const

View File

@ -3293,7 +3293,8 @@ avr_load_libgcc_p (rtx op)
return (n_bytes > 2
&& !AVR_HAVE_LPMX
&& avr_mem_flash_p (op));
&& avr_mem_flash_p (op)
&& MEM_ADDR_SPACE (op) == ADDR_SPACE_FLASH);
}
@ -3645,6 +3646,46 @@ avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
avr_asm_len ("sbiw %2,1", xop, plen, 1);
break; /* 2 */
/* cases 3 and 4 are only needed with ELPM but no ELPMx. */
case 3:
if (REGNO (dest) == REG_Z - 2
&& !reg_unused_after (insn, all_regs_rtx[REG_31]))
avr_asm_len ("push r31", xop, plen, 1);
avr_asm_len ("%4lpm $ mov %A0,%3 $ adiw %2,1", xop, plen, 3);
avr_asm_len ("%4lpm $ mov %B0,%3 $ adiw %2,1", xop, plen, 3);
avr_asm_len ("%4lpm $ mov %C0,%3", xop, plen, 2);
if (REGNO (dest) == REG_Z - 2)
{
if (!reg_unused_after (insn, all_regs_rtx[REG_31]))
avr_asm_len ("pop r31", xop, plen, 1);
}
else if (!reg_unused_after (insn, addr))
avr_asm_len ("sbiw %2,2", xop, plen, 1);
break; /* 3 */
case 4:
avr_asm_len ("%4lpm $ mov %A0,%3 $ adiw %2,1", xop, plen, 3);
avr_asm_len ("%4lpm $ mov %B0,%3 $ adiw %2,1", xop, plen, 3);
if (REGNO (dest) != REG_Z - 2)
{
avr_asm_len ("%4lpm $ mov %C0,%3 $ adiw %2,1", xop, plen, 3);
avr_asm_len ("%4lpm $ mov %D0,%3", xop, plen, 2);
if (!reg_unused_after (insn, addr))
avr_asm_len ("sbiw %2,3", xop, plen, 1);
}
else
{
avr_asm_len ("%4lpm $ push %3 $ adiw %2,1", xop, plen, 3);
avr_asm_len ("%4lpm $ mov %D0,%3", xop, plen, 2);
avr_asm_len ("pop $C0", xop, plen, 1);
}
break; /* 4 */
}
break; /* REG */

View File

@ -4091,9 +4091,17 @@
(match_operand:PSI 2 "nonmemory_operand" "")))
(clobber (reg:HI 26))
(clobber (reg:DI 18))])]
"AVR_HAVE_MUL"
"AVR_HAVE_MUL
|| (avropt_pr118012
/* AVR_TINY passes args on the stack, so we cannot work
around PR118012 like this. */
&& ! AVR_TINY)"
{
if (s8_operand (operands[2], PSImode))
if (!AVR_HAVE_MUL)
{
operands[2] = force_reg (PSImode, operands[2]);
}
else if (s8_operand (operands[2], PSImode))
{
rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1]));
@ -4198,7 +4206,9 @@
(match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn")))
(clobber (reg:HI 26))
(clobber (reg:DI 18))]
"AVR_HAVE_MUL && !reload_completed"
"!reload_completed
&& (AVR_HAVE_MUL
|| (avropt_pr118012 && !AVR_TINY))"
{ gcc_unreachable(); }
"&& 1"
[(set (reg:PSI 18)
@ -4208,13 +4218,30 @@
(parallel [(set (reg:PSI 22)
(mult:PSI (reg:PSI 22)
(reg:PSI 18)))
(clobber (reg:QI 21))
(clobber (reg:QI 25))
(clobber (reg:HI 26))])
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (match_dup 5))])
(set (match_dup 0)
(reg:PSI 22))]
{
if (s8_operand (operands[2], PSImode))
if (AVR_HAVE_MUL)
{
operands[3] = gen_rtx_REG (QImode, REG_21);
operands[4] = gen_rtx_REG (QImode, REG_25);
operands[5] = gen_rtx_REG (HImode, REG_26);
}
else
{
operands[3] = gen_rtx_REG (SImode, REG_18);
operands[4] = gen_rtx_SCRATCH (QImode);
operands[5] = gen_rtx_SCRATCH (HImode);
}
if (!AVR_HAVE_MUL)
{
operands[2] = force_reg (PSImode, operands[2]);
}
else if (s8_operand (operands[2], PSImode))
{
rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode));
emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1]));
@ -4273,6 +4300,37 @@
"%~call __mulpsi3"
[(set_attr "type" "xcall")])
(define_insn_and_split "*mulpsi3-nomul.libgcc_split"
[(set (reg:PSI 22)
(mult:PSI (reg:PSI 22)
(reg:PSI 18)))
(clobber (reg:SI 18))
(clobber (scratch:QI))
(clobber (scratch:HI))]
"!AVR_HAVE_MUL && avropt_pr118012 && !AVR_TINY"
"#"
"&& reload_completed"
[(parallel [(set (reg:PSI 22)
(mult:PSI (reg:PSI 22)
(reg:PSI 18)))
(clobber (reg:SI 18))
(clobber (scratch:QI))
(clobber (scratch:HI))
(clobber (reg:CC REG_CC))])])
(define_insn "*mulpsi3-nomul.libgcc"
[(set (reg:PSI 22)
(mult:PSI (reg:PSI 22)
(reg:PSI 18)))
(clobber (reg:SI 18))
(clobber (scratch:QI))
(clobber (scratch:HI))
(clobber (reg:CC REG_CC))]
"reload_completed
&& !AVR_HAVE_MUL && avropt_pr118012 && !AVR_TINY"
"%~call __mulpsi3"
[(set_attr "type" "xcall")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 24-bit signed/unsigned division and modulo.

View File

@ -993,16 +993,6 @@
[(set_attr "type" "simd_fmadd")
(set_attr "mode" "<MODE>")])
(define_insn "fnma<mode>4"
[(set (match_operand:FLASX 0 "register_operand" "=f")
(fma:FLASX (neg:FLASX (match_operand:FLASX 1 "register_operand" "f"))
(match_operand:FLASX 2 "register_operand" "f")
(match_operand:FLASX 3 "register_operand" "0")))]
"ISA_HAS_LASX"
"xvfnmsub.<flasxfmt>\t%u0,%u1,%u2,%u0"
[(set_attr "type" "simd_fmadd")
(set_attr "mode" "<MODE>")])
(define_expand "sqrt<mode>2"
[(set (match_operand:FLASX 0 "register_operand")
(sqrt:FLASX (match_operand:FLASX 1 "register_operand")))]

View File

@ -5437,12 +5437,32 @@ loongarch_expand_conditional_move (rtx *operands)
}
}
auto is_binary_op_0_keep_orig = [](enum rtx_code code)
{
switch (code)
{
case PLUS:
case MINUS:
case IOR:
case XOR:
case ROTATE:
case ROTATERT:
case ASHIFT:
case ASHIFTRT:
case LSHIFTRT:
return true;
default:
return false;
}
};
/* Check if the optimization conditions are met. */
if (value_if_true_insn
&& value_if_false_insn
/* Make sure that value_if_false and var are the same. */
&& BINARY_P (value_if_true_insn_src
/* Make sure that the orig value OP 0 keep orig. */
&& (value_if_true_insn_src
= SET_SRC (single_set (value_if_true_insn)))
&& is_binary_op_0_keep_orig ( GET_CODE (value_if_true_insn_src))
/* Make sure that both value_if_true and value_if_false
has the same var. */
&& rtx_equal_p (XEXP (value_if_true_insn_src, 0),

View File

@ -852,16 +852,6 @@
[(set_attr "type" "simd_fmadd")
(set_attr "mode" "<MODE>")])
(define_insn "fnma<mode>4"
[(set (match_operand:FLSX 0 "register_operand" "=f")
(fma:FLSX (neg:FLSX (match_operand:FLSX 1 "register_operand" "f"))
(match_operand:FLSX 2 "register_operand" "f")
(match_operand:FLSX 3 "register_operand" "0")))]
"ISA_HAS_LSX"
"vfnmsub.<flsxfmt>\t%w0,%w1,%w2,%w0"
[(set_attr "type" "simd_fmadd")
(set_attr "mode" "<MODE>")])
(define_expand "sqrt<mode>2"
[(set (match_operand:FLSX 0 "register_operand")
(sqrt:FLSX (match_operand:FLSX 1 "register_operand")))]

View File

@ -431,6 +431,17 @@
[(set_attr "type" "simd_int_arith")
(set_attr "mode" "<MODE>")])
;; <x>vfnmsub.{s/d}
(define_insn "fnma<mode>4"
[(set (match_operand:FVEC 0 "register_operand" "=f")
(fma:FVEC (neg:FVEC (match_operand:FVEC 1 "register_operand" "f"))
(match_operand:FVEC 2 "register_operand" "f")
(match_operand:FVEC 3 "register_operand" "f")))]
"!HONOR_SIGNED_ZEROS (<MODE>mode)"
"<x>vfnmsub.<simdfmt>\t%<wu>0,%<wu>1,%<wu>2,%<wu>3"
[(set_attr "type" "simd_fmadd")
(set_attr "mode" "<MODE>")])
;; <x>vfcmp.*.{s/d} with defined RTX code
;; There are no fcmp.{sugt/suge/cgt/cge}.{s/d} menmonics in GAS, so we have
;; to reverse the operands ourselves :(.

View File

@ -1792,12 +1792,13 @@ public:
The fold routines expect the replacement statement to have the
same lhs as the original call, so return the copy statement
rather than the field update. */
gassign *copy = gimple_build_assign (unshare_expr (f.lhs), rhs_tuple);
gassign *copy = gimple_build_assign (f.lhs, rhs_tuple);
/* Get a reference to the individual vector. */
tree field = tuple_type_field (TREE_TYPE (f.lhs));
tree lhs_array
= build3 (COMPONENT_REF, TREE_TYPE (field), f.lhs, field, NULL_TREE);
= build3 (COMPONENT_REF, TREE_TYPE (field), unshare_expr (f.lhs),
field, NULL_TREE);
tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector), lhs_array,
index, NULL_TREE, NULL_TREE);
gassign *update = gimple_build_assign (lhs_vector, rhs_vector);

View File

@ -11809,6 +11809,13 @@ riscv_dwarf_poly_indeterminate_value (unsigned int i, unsigned int *factor,
*/
gcc_assert (i == 1);
*factor = BYTES_PER_RISCV_VECTOR.coeffs[1];
/* The factor will be zero if vector is not enabled. That ultimately
causes problems in the dwarf2 emitter as the factor is used for
a division, causing a divide by zero. */
if (*factor == 0)
*factor = 1;
*offset = 1;
return RISCV_DWARF_VLENB;
}

View File

@ -1,3 +1,66 @@
2025-11-04 Nathaniel Shead <nathanieloshead@gmail.com>
Backported from master:
2025-11-04 Nathaniel Shead <nathanieloshead@gmail.com>
PR c++/122253
* decl2.cc (min_vis_expr_r): Don't mark no-linkage declarations
as VISIBILITY_ANON.
2025-11-02 Nathaniel Shead <nathanieloshead@gmail.com>
Backported from master:
2025-11-02 Nathaniel Shead <nathanieloshead@gmail.com>
PR c++/122421
* module.cc (trees_in::read_var_def): Don't handle class-scope
variables anymore.
(trees_in::read_class_def): Handle them here instead.
2025-11-01 Nathaniel Shead <nathanieloshead@gmail.com>
Backported from master:
2025-11-01 Nathaniel Shead <nathanieloshead@gmail.com>
PR c++/122381
* module.cc (trees_out::core_vals): Write BASELINK_OPTYPE (aka
TREE_CHAIN).
(trees_in::core_vals): Read it.
2025-10-28 Patrick Palka <ppalka@redhat.com>
Backported from master:
2025-10-14 Patrick Palka <ppalka@redhat.com>
PR c++/122192
* parser.cc (cp_parser_mem_initializer_id): Pass class_type
instead of typename_type to cp_parser_class_name in the
nested-name-specifier case.
2025-10-28 Patrick Palka <ppalka@redhat.com>
Backported from master:
2025-10-10 Patrick Palka <ppalka@redhat.com>
PR c++/122192
* decl.cc (make_typename_type): Document base-specifier as
another type-only lookup case.
* parser.cc (cp_parser_class_name): Propagate tag_type to
make_typename_type instead of hardcoding typename_type.
(cp_parser_base_specifier): Pass class_type instead of
typename_type as tag_type to cp_parser_class_name.
2025-10-28 Nathaniel Shead <nathanieloshead@gmail.com>
Backported from master:
2025-10-27 Nathaniel Shead <nathanieloshead@gmail.com>
PR c++/122310
* module.cc (get_keyed_decl_scope): New function.
(trees_out::get_merge_kind): Use it.
(trees_out::key_mergeable): Use it.
(maybe_key_decl): Key to the containing type for all members.
2025-10-14 Jason Merrill <jason@redhat.com>
Backported from master:

View File

@ -4546,7 +4546,9 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
- the tag corresponds to a class-key or 'enum' so
[basic.lookup.elab] applies, or
- the tag corresponds to scope_type or tf_qualifying_scope is
set so [basic.lookup.qual]/1 applies.
set so [basic.lookup.qual]/1 applies, or
- we're inside a base-specifier so [class.derived.general]/2 applies;
the tag will already be class_type in that case.
TODO: If we'd set/track the scope_type tag thoroughly on all
TYPENAME_TYPEs that are followed by :: then we wouldn't need the
tf_qualifying_scope flag. */

View File

@ -2867,7 +2867,12 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void *data)
break;
}
addressable:
if (! TREE_PUBLIC (t))
if (decl_linkage (t) == lk_none)
tpvis = type_visibility (TREE_TYPE (t));
/* Decls that have had their visibility constrained will report
as external linkage, but we still want to transitively constrain
if we refer to them, so just check TREE_PUBLIC instead. */
else if (!TREE_PUBLIC (t))
tpvis = VISIBILITY_ANON;
else
tpvis = DECL_VISIBILITY (t);

View File

@ -2789,6 +2789,8 @@ vec<tree, va_heap, vl_embed> *post_load_decls;
typedef hash_map<tree, auto_vec<tree>> keyed_map_t;
static keyed_map_t *keyed_table;
static tree get_keyed_decl_scope (tree);
/* Instantiations of temploid friends imported from another module
need to be attached to the same module as the temploid. This maps
these decls to the temploid they are instantiated from, as there is
@ -6688,6 +6690,7 @@ trees_out::core_vals (tree t)
WT (((lang_tree_node *)t)->baselink.binfo);
WT (((lang_tree_node *)t)->baselink.functions);
WT (((lang_tree_node *)t)->baselink.access_binfo);
WT (((lang_tree_node *)t)->baselink.common.chain);
break;
case CONSTRAINT_INFO:
@ -7257,6 +7260,7 @@ trees_in::core_vals (tree t)
RT (((lang_tree_node *)t)->baselink.binfo);
RTU (((lang_tree_node *)t)->baselink.functions);
RT (((lang_tree_node *)t)->baselink.access_binfo);
RT (((lang_tree_node *)t)->baselink.common.chain);
break;
case CONSTRAINT_INFO:
@ -11275,19 +11279,11 @@ trees_out::get_merge_kind (tree decl, depset *dep)
if (DECL_IMPLICIT_TYPEDEF_P (STRIP_TEMPLATE (decl))
&& LAMBDA_TYPE_P (TREE_TYPE (decl)))
{
if (tree scope = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (decl)))
{
/* Lambdas attached to fields are keyed to its class. */
if (TREE_CODE (scope) == FIELD_DECL)
scope = TYPE_NAME (DECL_CONTEXT (scope));
if (DECL_LANG_SPECIFIC (scope)
&& DECL_MODULE_KEYED_DECLS_P (scope))
{
if (get_keyed_decl_scope (decl))
mk = MK_keyed;
break;
}
}
/* Lambdas not attached to any mangling scope are TU-local. */
else
/* Lambdas not attached to any mangling scope are TU-local
and so cannot be deduplicated. */
mk = MK_unique;
break;
}
@ -11589,16 +11585,9 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
case MK_keyed:
{
gcc_checking_assert (LAMBDA_TYPE_P (TREE_TYPE (inner)));
tree scope = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (inner));
gcc_checking_assert (TREE_CODE (scope) == VAR_DECL
|| TREE_CODE (scope) == FIELD_DECL
|| TREE_CODE (scope) == PARM_DECL
|| TREE_CODE (scope) == TYPE_DECL
|| TREE_CODE (scope) == CONCEPT_DECL);
/* Lambdas attached to fields are keyed to the class. */
if (TREE_CODE (scope) == FIELD_DECL)
scope = TYPE_NAME (DECL_CONTEXT (scope));
tree scope = get_keyed_decl_scope (inner);
gcc_checking_assert (scope);
auto *root = keyed_table->get (scope);
unsigned ix = root->length ();
/* If we don't find it, we'll write a really big number
@ -12859,12 +12848,11 @@ trees_in::read_var_def (tree decl, tree maybe_template)
if (DECL_EXPLICIT_INSTANTIATION (decl)
&& !DECL_EXTERNAL (decl))
setup_explicit_instantiation_definition_linkage (decl);
if (DECL_IMPLICIT_INSTANTIATION (decl)
/* Class static data members are handled in read_class_def. */
if (!DECL_CLASS_SCOPE_P (decl)
&& (DECL_IMPLICIT_INSTANTIATION (decl)
|| (DECL_EXPLICIT_INSTANTIATION (decl)
&& !DECL_EXTERNAL (decl))
|| (DECL_CLASS_SCOPE_P (decl)
&& !DECL_VTABLE_OR_VTT_P (decl)
&& !DECL_TEMPLATE_INFO (decl)))
&& !DECL_EXTERNAL (decl))))
note_vague_linkage_variable (decl);
}
if (!dyn_init)
@ -13278,6 +13266,10 @@ trees_in::read_class_def (tree defn, tree maybe_template)
DECL_ACCESS (d) = tree_cons (type, access, list);
}
}
if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (maybe_template) != TEMPLATE_DECL)
note_vague_linkage_variable (decl);
}
}
@ -20916,9 +20908,21 @@ maybe_key_decl (tree ctx, tree decl)
&& TREE_CODE (ctx) != CONCEPT_DECL)
return;
/* For fields, key it to the containing type to handle deduplication
correctly. */
if (TREE_CODE (ctx) == FIELD_DECL)
/* For members, key it to the containing type to handle deduplication
correctly. For fields, this is necessary as FIELD_DECLs have no
dep and so would only be streamed after the lambda type, defeating
our ability to merge them.
Other class-scope key decls might depend on the type of the lambda
but be within the same cluster; we need to ensure that we never
first see the key decl while streaming the lambda type as merging
would then fail when comparing the partially-streamed lambda type
of the key decl with the existing (PR c++/122310).
Perhaps sort_cluster can be adjusted to handle this better, but
this is a simple workaround (and might down on the number of
entries in keyed_table as a bonus). */
while (DECL_CLASS_SCOPE_P (ctx))
ctx = TYPE_NAME (DECL_CONTEXT (ctx));
if (!keyed_table)
@ -20933,6 +20937,30 @@ maybe_key_decl (tree ctx, tree decl)
vec.safe_push (decl);
}
/* Find the scope that the lambda DECL is keyed to, if any. */
static tree
get_keyed_decl_scope (tree decl)
{
gcc_checking_assert (LAMBDA_TYPE_P (TREE_TYPE (decl)));
tree scope = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (decl));
if (!scope)
return NULL_TREE;
gcc_checking_assert (TREE_CODE (scope) == VAR_DECL
|| TREE_CODE (scope) == FIELD_DECL
|| TREE_CODE (scope) == PARM_DECL
|| TREE_CODE (scope) == TYPE_DECL
|| TREE_CODE (scope) == CONCEPT_DECL);
while (DECL_CLASS_SCOPE_P (scope))
scope = TYPE_NAME (DECL_CONTEXT (scope));
gcc_checking_assert (DECL_LANG_SPECIFIC (scope)
&& DECL_MODULE_KEYED_DECLS_P (scope));
return scope;
}
/* DECL is an instantiated friend that should be attached to the same
module that ORIG is. */

View File

@ -18509,7 +18509,7 @@ cp_parser_mem_initializer_id (cp_parser* parser)
return cp_parser_class_name (parser,
/*typename_keyword_p=*/true,
/*template_keyword_p=*/template_p,
typename_type,
class_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);
@ -27809,8 +27809,7 @@ cp_parser_class_name (cp_parser *parser,
/* If this is a typename, create a TYPENAME_TYPE. */
if (typename_p && decl != error_mark_node)
{
decl = make_typename_type (scope, decl, typename_type,
/*complain=*/tf_error);
decl = make_typename_type (scope, decl, tag_type, /*complain=*/tf_error);
if (decl != error_mark_node)
decl = TYPE_NAME (decl);
}
@ -30203,7 +30202,7 @@ cp_parser_base_specifier (cp_parser* parser)
type = cp_parser_class_name (parser,
class_scope_p,
template_p,
typename_type,
class_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);

View File

@ -1,3 +1,26 @@
2025-11-01 Harald Anlauf <anlauf@gmx.de>
Backported from master:
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-11-01 Harald Anlauf <anlauf@gmx.de>
Backported from master:
2025-10-24 Harald Anlauf <anlauf@gmx.de>
PR fortran/122386
* dependency.cc (gfc_ref_needs_temporary_p): Revert r16-518.
* trans-intrinsic.cc (gfc_conv_intrinsic_transfer): Force temporary
for SOURCE not being a simply-contiguous array.
2025-10-25 Harald Anlauf <anlauf@gmx.de>
Backported from master:

View File

@ -944,12 +944,8 @@ gfc_ref_needs_temporary_p (gfc_ref *ref)
types), not in characters. */
return subarray_p;
case REF_INQUIRY:
/* Within an array reference, inquiry references of complex
variables generally need a temporary. */
return subarray_p;
case REF_COMPONENT:
case REF_INQUIRY:
break;
}

View File

@ -11232,21 +11232,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);

View File

@ -2315,10 +2315,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);
@ -2341,7 +2345,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
{
@ -2373,6 +2377,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);
}
@ -8541,13 +8561,18 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
}
else
{
bool simply_contiguous = gfc_is_simply_contiguous (arg->expr,
false, true);
argse.want_pointer = 0;
/* A non-contiguous SOURCE needs packing. */
if (!simply_contiguous)
argse.force_tmp = 1;
gfc_conv_expr_descriptor (&argse, arg->expr);
source = gfc_conv_descriptor_data_get (argse.expr);
source_type = gfc_get_element_type (TREE_TYPE (argse.expr));
/* Repack the source if not simply contiguous. */
if (!gfc_is_simply_contiguous (arg->expr, false, true))
if (!simply_contiguous)
{
tmp = gfc_build_addr_expr (NULL_TREE, argse.expr);

View File

@ -522,6 +522,11 @@ update_equiv (int regno)
{
rtx x;
/* If REGNO is beyond the length of the equivalence array structure,
then there's nothing to update. */
if (regno >= ira_reg_equiv_len)
return;
if ((x = ira_reg_equiv[regno].memory) != NULL_RTX)
ira_reg_equiv[regno].memory
= simplify_replace_fn_rtx (x, NULL_RTX, loc_equivalence_callback,

View File

@ -1,3 +1,145 @@
2025-11-04 Nathaniel Shead <nathanieloshead@gmail.com>
Backported from master:
2025-11-04 Nathaniel Shead <nathanieloshead@gmail.com>
PR c++/122253
* g++.dg/modules/internal-16.C: New test.
2025-11-03 Jeff Law <jlaw@ventanamicro.com>
Backported from master:
2025-11-01 Jeff Law <jlaw@ventanamicro.com>
PR rtl-optimization/122321
* gcc.target/riscv/rvv/autovec/pr122321.c: New test.
2025-11-03 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
Backported from master:
2025-10-26 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
PR target/122270
* gcc.target/riscv/rvv/base/pr122270-1.c: New test.
2025-11-02 Nathaniel Shead <nathanieloshead@gmail.com>
Backported from master:
2025-11-02 Nathaniel Shead <nathanieloshead@gmail.com>
PR c++/122421
* g++.dg/modules/inst-6_a.C: New test.
* g++.dg/modules/inst-6_b.C: New test.
2025-11-01 Harald Anlauf <anlauf@gmx.de>
Backported from master:
2025-10-25 Harald Anlauf <anlauf@gmx.de>
PR fortran/114023
* gfortran.dg/is_contiguous_5.f90: New test.
2025-11-01 Harald Anlauf <anlauf@gmx.de>
Backported from master:
2025-10-24 Harald Anlauf <anlauf@gmx.de>
PR fortran/122386
* gfortran.dg/transfer_array_subref_2.f90: New test.
2025-11-01 Nathaniel Shead <nathanieloshead@gmail.com>
Backported from master:
2025-11-01 Nathaniel Shead <nathanieloshead@gmail.com>
PR c++/122381
* g++.dg/modules/convop-2_a.H: New test.
* g++.dg/modules/convop-2_b.C: New test.
2025-10-31 Tamar Christina <tamar.christina@arm.com>
Backported from master:
2025-10-27 Tamar Christina <tamar.christina@arm.com>
PR tree-optimization/122408
* gfortran.target/aarch64/pr122408_1.f90: New test.
* gfortran.target/aarch64/pr122408_2.f90: New test.
2025-10-31 Jinyang He <hejinyang@loongson.cn>
Backported from master:
2025-10-30 Jinyang He <hejinyang@loongson.cn>
Peng Fan <fanpeng@loongson.cn>
* gcc.target/loongarch/conditional-move-opt-1.c: Remove mul.
* gcc.target/loongarch/conditional-move-opt-2.c: Remove and.
* gcc.target/loongarch/conditional-move-opt-3.c: New test.
2025-10-30 Guo Jie <guojie@loongson.cn>
Backported from master:
2025-10-30 Guo Jie <guojie@loongson.cn>
* gcc.target/loongarch/fnmam4-vec.c: New test.
2025-10-28 Patrick Palka <ppalka@redhat.com>
Backported from master:
2025-10-14 Patrick Palka <ppalka@redhat.com>
PR c++/122192
* g++.dg/template/dependent-base6.C: Verify mem-initializer-id
qualified name lookup is type-only too.
2025-10-28 Patrick Palka <ppalka@redhat.com>
Backported from master:
2025-10-10 Patrick Palka <ppalka@redhat.com>
PR c++/122192
* g++.dg/template/dependent-base6.C: New test.
2025-10-28 Nathaniel Shead <nathanieloshead@gmail.com>
Backported from master:
2025-10-27 Nathaniel Shead <nathanieloshead@gmail.com>
PR c++/122310
* g++.dg/modules/lambda-12.h: New test.
* g++.dg/modules/lambda-12_a.H: New test.
* g++.dg/modules/lambda-12_b.C: New test.
2025-10-27 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/122394
* g++.dg/opt/pr122394.C: New test.
2025-10-27 Jeff Law <jlaw@ventanamicro.com>
Backported from master:
2025-10-13 Jeff Law <jlaw@ventanamicro.com>
PR target/120674
* gcc.target/riscv/pr120674.c: New test.
2025-10-27 Tamar Christina <tamar.christina@arm.com>
Backported from master:
2025-10-17 Tamar Christina <tamar.christina@arm.com>
Jennifer Schmitz <jschmitz@nvidia.com>
PR target/121604
* gcc.target/aarch64/sve/pr121604_brk.c: New test.
* gcc.target/aarch64/sve2/pr121604_pmov.c: New test.
2025-10-27 H.J. Lu <hjl.tools@gmail.com>
Backported from master:
2025-10-27 H.J. Lu <hjl.tools@gmail.com>
PR target/122323
* gcc.target/i386/builtin-copysign-8b.c: Add -mtune=generic.
2025-10-26 Alexandre Oliva <oliva@adacore.com>
Backported from master:

View File

@ -0,0 +1,10 @@
// PR c++/122381
// { dg-additional-options "-fmodule-header" }
// { dg-module-cmi {} }
template <typename T> struct color_ref {
operator int() const { return 0; }
int foo(color_ref x) {
return x.operator int();
}
};

View File

@ -0,0 +1,5 @@
// PR c++/122381
// { dg-additional-options "-fmodules" }
import "convop-2_a.H";
template struct color_ref<int>;

View File

@ -0,0 +1,14 @@
// PR c++/122421
// { dg-additional-options "-fmodules" }
// { dg-module-cmi M }
export module M;
export template <typename T> struct Type {
static const int arr[3];
};
extern template const int Type<double>::arr[3];
template <typename T> const int Type<T>::arr[] = { 42, 43, 44 };
export Type<int> ti;

View File

@ -0,0 +1,12 @@
// PR c++/122421
// { dg-additional-options "-fmodules" }
import M;
int main() {
const int& a = Type<int>::arr[0];
const int& b = Type<double>::arr[0];
}
// { dg-final { scan-assembler {_ZNW1M4TypeIiE3arrE:} } }
// { dg-final { scan-assembler-not {_ZNW1M4TypeIdE3arrE:} } }

View File

@ -0,0 +1,30 @@
// PR c++/122253
// { dg-additional-options "-fmodules -Wtemplate-names-tu-local" }
export module M;
template <int> struct ic {};
struct S {
constexpr operator int() const { return 5; }
constexpr int operator&() const { return 8; }
};
template <typename T> inline void a(T) {
T a;
static T b;
ic<a>{};
ic<b>{};
ic<&a>{};
ic<&b>{};
}
template <typename T> inline auto b(T x) {
return [&](auto y) {
return [=](auto z) {
return ic<(int)x + (int)&y + (int)z>{};
};
};
}
template void a(S);
ic<5 + 8 + 5> x = b(S{})(S{})(S{});

View File

@ -0,0 +1,27 @@
// PR c++/122310
struct Foo {
constexpr static inline auto do_nothing = [](auto && ...){};
using TNothing = decltype(do_nothing);
};
template <typename T>
struct X {
struct Inner {
union MoreInner {
static constexpr auto x = []{};
#if __cplusplus >= 202002L
static decltype([]{}) y;
#endif
};
};
using A = decltype(Inner::MoreInner::x);
#if __cplusplus >= 202002L
using B = decltype(Inner::MoreInner::y);
#endif
};
inline X<int>::A* a{};
#if __cplusplus >= 202002L
inline X<int>::B* b{};
#endif

View File

@ -0,0 +1,5 @@
// PR c++/122310
// { dg-additional-options "-fmodule-header" }
// { dg-module-cmi {} }
#include "lambda-12.h"

View File

@ -0,0 +1,5 @@
// PR c++/122310
// { dg-additional-options "-fmodules -fno-module-lazy" }
#include "lambda-12.h"
import "lambda-12_a.H";

View File

@ -0,0 +1,20 @@
// PR tree-optimization/122394
// { dg-do compile { target c++23 } }
// { dg-options "-O1 -g" }
#include <compare>
struct A {
friend auto operator<=> (A, A) = default;
double a;
};
void foo ();
A b, c;
void
bar ()
{
bool d = c >= b;
if (d)
foo ();
}

View File

@ -0,0 +1,14 @@
// PR c++/122192
// Verify name lookup within a base-specifier is type-only.
struct A {
int B;
struct B { };
};
struct S1 : A::B { }; // OK
template<class T> struct S2 : T::B { // OK, used to fail
S2() : T::B() { } // Also OK
};
template struct S2<A>;

View File

@ -0,0 +1,25 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { check-function-bodies "**" "" "" } } */
#include <arm_sve.h>
/*
** foo:
** ptrue p0\.b, all
** brkb p0\.b, p0/z, p0\.b
** ret
*/
svbool_t foo () {
return svbrkb_b_m (svpfalse (), svptrue_b8 (), svptrue_b8 ());
}
/*
** bar:
** ptrue p0\.b, all
** brka p0\.b, p0/z, p0\.b
** ret
*/
svbool_t bar () {
return svbrka_b_m (svpfalse (), svptrue_b8 (), svptrue_b8 ());
}

View File

@ -0,0 +1,16 @@
/* { dg-do compile } */
/* { dg-options "-O2 -march=armv8.2-a+sve2p1" } */
/* { dg-final { check-function-bodies "**" "" "" } } */
#include <arm_sve.h>
/*
** f:
** pfalse p([0-7]+)\.b
** mov z0\.b, #-1
** pmov z0\[1\], p\1\.d
** ret
*/
svuint64_t f () {
return svpmov_lane_u64_m (svdup_u64 (~0UL), svpfalse (), 1);
}

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mno-avx512f -mavx" } */
/* { dg-options "-O2 -mno-avx512f -mavx -mtune=generic" } */
/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
/* { dg-final { check-function-bodies "**" "" "" { target { ! ia32 } } {^\t?\.} } } */

View File

@ -27,7 +27,7 @@ void
test_lt ()
{
if (lm < ln)
lr *= (1 << 16);
lr += (1 << 16);
lr += lm;
}
@ -35,7 +35,7 @@ void
test_le ()
{
if (lm <= ln)
lr = lm * ((long)1 << 32);
lr = lm + ((long)1 << 32);
else
lr = lm;
lr += lm;

View File

@ -29,7 +29,7 @@ void
test_lez ()
{
if (lm <= 0)
lr &= (1 << 16);
lr |= (1 << 16);
lr += lm;
}

View File

@ -0,0 +1,14 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler "maskeqz" } } */
/* { dg-final { scan-assembler "masknez" } } */
extern long lm, ln, lr;
void
test_and ()
{
if (lm < 0)
lr &= (1 << 16);
lr += lm;
}

View File

@ -0,0 +1,14 @@
/* { dg-do compile } */
/* { dg-options "-Ofast -mlasx -ftree-vectorize" } */
/* { dg-require-effective-target loongarch_asx } */
void
foo (float *u, float x, float *y, float z)
{
int i;
for (i = 0; i < 1024; i++)
*(u++) = (x - y[i] * z);
}
/* { dg-final { scan-assembler-not "\tvori.b"} } */
/* { dg-final { scan-assembler-not "\txvori.b"} } */

View File

@ -0,0 +1,6 @@
/* { dg-do compile } */
/* { dg-additional-options "-g -w -march=rv32gcv -mabi=ilp32" { target rv32 } } */
/* { dg-additional-options "-g -w -march=rv64gcv -mabi=lp64d" { target rv64 } } */
#pragma riscv intrinsic "vector"
void GB_AxB_saxpy5_unrolled_rvv() { vfloat64m8_t vc; }

View File

@ -0,0 +1,150 @@
/* { dg-do compile } */
/* { dg-options "-march=rv64gcv -mabi=lp64d -w -O0" { target rv64 } } */
/* { dg-options "-march=rv32gcv -mabi=ilp32 -w -O0" { target rv32 } } */
typedef int a;
typedef signed char b;
typedef char c;
typedef short d;
typedef unsigned short e;
typedef a f;
typedef unsigned g;
typedef long h;
h j, k, l, m, n, o;
int p, q, r, s;
short t;
volatile a u;
a v[];
char w, x;
a *y, *z;
a **aa;
__attribute__((always_inline)) b __attribute__((vector_size(16)))
ab(f __attribute__((vector_size(8 * sizeof(f)))), d ac,
d __attribute__((vector_size(2 * sizeof(d)))), d) {
return __builtin_shufflevector(
(b __attribute__((vector_size(16)))) __builtin_convertvector(
(d __attribute__((vector_size(16 *sizeof(d))))){
ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac},
c __attribute__((vector_size(16)))) |
__builtin_convertvector(
(d __attribute__((vector_size(16 *sizeof(d))))){
ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac},
c __attribute__((vector_size(16)))),
__builtin_convertvector(
(d __attribute__((vector_size(16 *sizeof(d))))){
ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac},
b __attribute__((vector_size(16)))),
3, 21, 0, 2, 2, 7, 1, 8, 4, 0, 8, 0, 8, 9, 5, 6);
}
__attribute__((always_inline)) g
ad(d ae, h __attribute__((vector_size(32 * sizeof(h))))) {
g f = 6318;
return (8 ? ae / 786856318u : 0) & ae;
}
a(af)(a, int);
void(ag)(long);
char(ah)(char, char);
char(ai)(char);
short(aj)(short, short);
int ak(long, int *, int *, char, int);
void al(signed, a *, int *, long);
char am(int *, short, short);
void an(int *, long, int);
void ao(int, int *, a *);
a ap() {
int *aq, *ar, *as;
short at;
char au, av, aw = 2;
long ax, ay, az = j;
int ba, i;
g __attribute__((vector_size(16 * sizeof(g)))) bb = {80};
b __attribute__((vector_size(4))) bc = {6};
int bd[1];
char *be = &w;
int bf, bg = q;
a **bh[] = {
&y, &z, &z, &y, &y, &y, &y, &y, &z, &z, &y, &z, &y, &y, &y, &y, &z, &y,
&z, &y, &y, &y, &z, &z, &z, &y, &z, &z, &z, &y, &z, &z, &y, &z, &z, &y,
&z, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z, &z, &y, &y, 0, &z, 0,
&z, 0, &y, &z, &z, 0, &z, 0, &z, &z, &z, &y, &z, &z, &y, &z, &z, &y,
0, &z, 0, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z, &z, &y, &y, 0,
&z, 0, &z, 0, &y, &z, &z, 0, &z, 0, &z, &z, &z, &y, &z, &z, &y, &z,
&z, &y, 0, &z, 0, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z, &z, &y,
&y, 0, &z, 0, &z, 0, &y, &z, &z, 0, &z, 0, &z, &z, &z, &y, &z, &z,
&y, &z, &z, &y, 0, &z, 0, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z,
&z, &y, &y, 0, &z, 0, &z, 0, &y, &z, &z, 0, 0, &z, 0, &z, &z, &z,
&y, &z, &z, &y, &z, &z, &y, 0, &z, 0, 0, &z, &z};
for (; i; i++)
bd[i] = p;
h __attribute__((vector_size(32 * sizeof(h))))
bi = {2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681,
2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681,
2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681},
bj = __builtin_convertvector(
(c __attribute__((vector_size(32)))){
aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw,
aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw},
h __attribute__((vector_size(32 * sizeof(h))))),
bk = __builtin_convertvector(
__builtin_shufflevector(bb, bb, 4, 8, 7, 9, 1, 10, 4, 7, 0, 4, 3, 5, 6, 7,
6, 2, 2, 20, 6, 4, 7, 7, 9, 7, 4, 9, 8, 6, 1, 0,
6, 9),
h __attribute__((vector_size(32 * sizeof(h)))));
bb = __builtin_convertvector(
ab(__builtin_shufflevector(
__builtin_shufflevector(
__builtin_convertvector(
__builtin_shufflevector(bb, bb, 1, 31, 8, 2, 3, 7, 4, 0, 7,
3, 4, 6, 7, 1, 9, 3, 8, 7, 1, 8, 5,
3, 9, 9, 0, 3, 2, 8, 5, 2, 5, 3),
f __attribute__((vector_size(32 * sizeof(f))))),
(f __attribute__((vector_size(32 * sizeof(f))))){
800761418310502961587690471176286910032020044212442466872080013589354162852207417903424527024812447907811618435019152886919380169872910001752451018659493155196043018716516518746289614523948734758456011127254301274351182132760058399143431214610613191313926994549901191890929084305862034120561651877003645},
32, 44),
(f __attribute__((vector_size(2 * sizeof(f))))){o}, 1, 0, 3, 0, 2,
1, 3, 3),
ad(__builtin_clzg((g)aw, (f)bb[9]),
(h __attribute__((vector_size(32 * sizeof(h))))){
bi[0] ?: bk[0], bi[1] ? 1 : bk[1], bi[2] ? 2 : bk[2],
bi[3] ? 3 : bk[3], bi[4] ? 4 : bk[4], bi[5] ? 5 : bk[5],
bi[6] ? 6 : bk[6], bi[7] ? 7 : bk[7], bi[8] ? 8 : bk[8],
bi[9] ? 9 : bk[9], bi[0] ? 10 : bk[0], bi[1] ? 1 : bk[1],
bi[2] ? 2 : bk[2], bi[3] ? 3 : bk[3], bi[4] ? 4 : bk[4],
bi[5] ? 5 : bk[5], bi[6] ? 6 : bk[6], bi[7] ? 7 : bk[7],
bi[8] ? 8 : bk[8], bi[9] ? 9 : bk[9], bi[0] ? 20 : bk[0],
bi[1] ? 1 : bk[1], bi[2] ? 2 : bk[2], bi[3] ? 3 : bk[3],
bi[4] ? bj[4] : 4, bi[5] ?: 5, bi[6] ?: 6,
bi[7] ? 0 : 7, bi[8] ?: 8, bi[9] ? 0 : 9,
bi[0] ? 0 : 30, bi[1] ?: 1}),
(d __attribute__((vector_size(2 * sizeof(d)))))
__builtin_shufflevector(
__builtin_convertvector(
__builtin_shufflevector(bb, bb, 2, 7, 21, 6),
e __attribute__((vector_size(4 * sizeof(e))))),
__builtin_convertvector(
(c __attribute__((vector_size(4)))){aw, aw},
e __attribute__((vector_size(4 * sizeof(e))))),
5, 1) +
(__builtin_convertvector(
__builtin_shufflevector(bb, bb, 4, 5),
e __attribute__((vector_size(2 * sizeof(e))))) <=
__builtin_convertvector(
(c __attribute__((vector_size(2)))){aw},
e __attribute__((vector_size(2 * sizeof(e)))))),
n ? bb[5] << n : aw),
g __attribute__((vector_size(16 * sizeof(g)))));
ag(aw & t);
at = aj(aw, v[1]);
au = ah(at, aw);
ba = af((1 == ax != aw) <= aw <= au, aw);
ao(0, &bd[0], &r);
o = ay;
an(aq, aw, k);
av = am(ar, l, k);
*be = ai(*be);
al(x, as, &bd[0], aw);
bg = ak(u, &s, &bf, aw, aw);
as = *aa;
return m;
}

View File

@ -0,0 +1,10 @@
/* { dg-options "" } */
/* { dg-do compile } */
/* { dg-add-options riscv_v } */
/* PR target/122270 */
#include "riscv_vector.h"
void a(vfloat32m1_t b, vfloat32m1x4_t *c) {
*c = __riscv_vset_v_f32m1_f32m1x4(*c, 3, b);
}

View File

@ -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

View File

@ -0,0 +1,52 @@
! { dg-do run }
! { dg-additional-options "-O2 -fdump-tree-optimized" }
!
! PR fortran/122386 - passing of component ref of nested DT array to TRANSFER
program main
implicit none
integer, parameter :: dp = 4
type cx
real(dp) :: re, im
end type cx
type complex_wrap1
type(cx) :: z(2)
end type complex_wrap1
type complex_wrap2
type(cx), dimension(:), allocatable :: z
end type complex_wrap2
type(complex_wrap1) :: x = complex_wrap1([cx(1,2), cx(3,4)])
type(complex_wrap2) :: w
w%z = x%z
! The following statements should get optimized away...
if (size (transfer ( x%z%re ,[1.0_dp])) /= 2) error stop 1
if (size (transfer ((x%z%re),[1.0_dp])) /= 2) error stop 2
if (size (transfer ([x%z%re],[1.0_dp])) /= 2) error stop 3
if (size (transfer ( x%z%im ,[1.0_dp])) /= 2) error stop 4
if (size (transfer ((x%z%im),[1.0_dp])) /= 2) error stop 5
if (size (transfer ([x%z%im],[1.0_dp])) /= 2) error stop 6
! ... while the following may not:
if (any (transfer ( x%z%re ,[1.0_dp]) /= x%z%re)) stop 7
if (any (transfer ( x%z%im ,[1.0_dp]) /= x%z%im)) stop 8
if (size (transfer ( w%z%re ,[1.0_dp])) /= 2) stop 11
if (size (transfer ((w%z%re),[1.0_dp])) /= 2) stop 12
if (size (transfer ([w%z%re],[1.0_dp])) /= 2) stop 13
if (size (transfer ( w%z%im ,[1.0_dp])) /= 2) stop 14
if (size (transfer ((w%z%im),[1.0_dp])) /= 2) stop 15
if (size (transfer ([w%z%im],[1.0_dp])) /= 2) stop 16
if (any (transfer ( w%z%re ,[1.0_dp]) /= x%z%re)) stop 17
if (any (transfer ( w%z%im ,[1.0_dp]) /= x%z%im)) stop 18
deallocate (w%z)
end program main
! { dg-final { scan-tree-dump-not "_gfortran_error_stop_numeric" "optimized" } }

View File

@ -0,0 +1,61 @@
! { dg-do compile }
! { dg-additional-options "-O2 -march=armv8.3-a" }
subroutine c_add_ab(n, a, c, b) ! C += A * B
use iso_fortran_env, only: real64
implicit none
!GCC$ ATTRIBUTES noinline :: c_add_ab
integer, intent(in) :: n
complex(real64), intent(in) :: a
complex(real64), intent(inout) :: c(*)
complex(real64), intent(in) :: b(*)
integer :: k
do k = 1, n
c(k) = c(k) + a * b(k)
end do
end subroutine c_add_ab
subroutine c_sub_ab(n, a, c, b) ! C -= A * B
use iso_fortran_env, only: real64
implicit none
!GCC$ ATTRIBUTES noinline :: c_sub_ab
integer, intent(in) :: n
complex(real64), intent(in) :: a
complex(real64), intent(inout) :: c(*)
complex(real64), intent(in) :: b(*)
integer :: k
do k = 1, n
c(k) = c(k) - a * b(k)
end do
end subroutine c_sub_ab
subroutine c_add_a_conjb(n, a, c, b) ! C += A * conj(B)
use iso_fortran_env, only: real64
implicit none
!GCC$ ATTRIBUTES noinline :: c_add_a_conjb
integer, intent(in) :: n
complex(real64), intent(in) :: a
complex(real64), intent(inout) :: c(*)
complex(real64), intent(in) :: b(*)
integer :: k
do k = 1, n
c(k) = c(k) + a * conjg(b(k))
end do
end subroutine c_add_a_conjb
subroutine c_sub_a_conjb(n, a, c, b) ! C -= A * conj(B)
use iso_fortran_env, only: real64
implicit none
!GCC$ ATTRIBUTES noinline :: c_sub_a_conjb
integer, intent(in) :: n
complex(real64), intent(in) :: a
complex(real64), intent(inout) :: c(*)
complex(real64), intent(in) :: b(*)
integer :: k
do k = 1, n
c(k) = c(k) - a * conjg(b(k))
end do
end subroutine c_sub_a_conjb
! { dg-final { scan-assembler-times {fcmla\s+v[0-9]+.2d, v[0-9]+.2d, v[0-9]+.2d, #0} 2 } }
! { dg-final { scan-assembler-times {fcmla\s+v[0-9]+.2d, v[0-9]+.2d, v[0-9]+.2d, #270} 2 } }

View File

@ -0,0 +1,140 @@
! { dg-do run }
! { dg-additional-options "-O2" }
! { dg-additional-options "-O2 -march=armv8.3-a" { target arm_v8_3a_complex_neon_hw } }
module util
use iso_fortran_env, only: real64, int64
implicit none
contains
pure logical function bitwise_eq(x, y)
complex(real64), intent(in) :: x, y
integer(int64) :: xr, xi, yr, yi
xr = transfer(real(x,kind=real64), 0_int64)
xi = transfer(aimag(x), 0_int64)
yr = transfer(real(y,kind=real64), 0_int64)
yi = transfer(aimag(y), 0_int64)
bitwise_eq = (xr == yr) .and. (xi == yi)
end function bitwise_eq
subroutine check_equal(tag, got, ref, nfail)
character(*), intent(in) :: tag
complex(real64), intent(in) :: got(:), ref(:)
integer, intent(inout) :: nfail
integer :: i
do i = 1, size(got)
if (.not. bitwise_eq(got(i), ref(i))) then
nfail = nfail + 1
write(*,'(A,": mismatch at i=",I0, " got=",2ES16.8," ref=",2ES16.8)') &
trim(tag), i, real(got(i)), aimag(got(i)), real(ref(i)), aimag(ref(i))
end if
end do
end subroutine check_equal
end module util
module fcmla_ops
use iso_fortran_env, only: real64
implicit none
contains
subroutine c_add_ab(n, a, c, b) ! C += A * B
!GCC$ ATTRIBUTES noinline :: c_add_ab
integer, intent(in) :: n
complex(real64), intent(in) :: a
complex(real64), intent(inout) :: c(*)
complex(real64), intent(in) :: b(*)
integer :: k
do k = 1, n
c(k) = c(k) + a * b(k)
end do
end subroutine c_add_ab
subroutine c_sub_ab(n, a, c, b) ! C -= A * B
!GCC$ ATTRIBUTES noinline :: c_sub_ab
integer, intent(in) :: n
complex(real64), intent(in) :: a
complex(real64), intent(inout) :: c(*)
complex(real64), intent(in) :: b(*)
integer :: k
do k = 1, n
c(k) = c(k) - a * b(k)
end do
end subroutine c_sub_ab
subroutine c_add_a_conjb(n, a, c, b) ! C += A * conj(B)
!GCC$ ATTRIBUTES noinline :: c_add_a_conjb
integer, intent(in) :: n
complex(real64), intent(in) :: a
complex(real64), intent(inout) :: c(*)
complex(real64), intent(in) :: b(*)
integer :: k
do k = 1, n
c(k) = c(k) + a * conjg(b(k))
end do
end subroutine c_add_a_conjb
subroutine c_sub_a_conjb(n, a, c, b) ! C -= A * conj(B)
!GCC$ ATTRIBUTES noinline :: c_sub_a_conjb
integer, intent(in) :: n
complex(real64), intent(in) :: a
complex(real64), intent(inout) :: c(*)
complex(real64), intent(in) :: b(*)
integer :: k
do k = 1, n
c(k) = c(k) - a * conjg(b(k))
end do
end subroutine c_sub_a_conjb
end module fcmla_ops
program fcmla_accum_pairs
use iso_fortran_env, only: real64
use util
use fcmla_ops
implicit none
integer, parameter :: n = 4
complex(real64) :: a, b(n), c0(n)
complex(real64) :: c_add_ab_got(n), c_add_ab_ref(n)
complex(real64) :: c_sub_ab_got(n), c_sub_ab_ref(n)
complex(real64) :: c_add_conjb_got(n), c_add_conjb_ref(n)
complex(real64) :: c_sub_conjb_got(n), c_sub_conjb_ref(n)
integer :: i, fails
! Constants (include a signed-zero lane)
a = cmplx( 2.0_real64, -3.0_real64, kind=real64)
b(1) = cmplx( 1.5_real64, -2.0_real64, kind=real64)
b(2) = cmplx(-4.0_real64, 5.0_real64, kind=real64)
b(3) = cmplx(-0.0_real64, 0.0_real64, kind=real64)
b(4) = cmplx( 0.25_real64, 3.0_real64, kind=real64)
c0(1) = cmplx( 1.0_real64, -2.0_real64, kind=real64)
c0(2) = cmplx( 3.0_real64, -4.0_real64, kind=real64)
c0(3) = cmplx(-5.0_real64, 6.0_real64, kind=real64)
c0(4) = cmplx( 0.0_real64, 0.0_real64, kind=real64)
! Run each form
c_add_ab_got = c0; call c_add_ab (n, a, c_add_ab_got, b)
c_sub_ab_got = c0; call c_sub_ab (n, a, c_sub_ab_got, b)
c_add_conjb_got = c0; call c_add_a_conjb(n, a, c_add_conjb_got, b)
c_sub_conjb_got = c0; call c_sub_a_conjb(n, a, c_sub_conjb_got, b)
! Scalar references
do i = 1, n
c_add_ab_ref(i) = c0(i) + a * b(i)
c_sub_ab_ref(i) = c0(i) - a * b(i)
c_add_conjb_ref(i) = c0(i) + a * conjg(b(i))
c_sub_conjb_ref(i) = c0(i) - a * conjg(b(i))
end do
! Bitwise checks
fails = 0
call check_equal("C += A*B ", c_add_ab_got, c_add_ab_ref, fails)
call check_equal("C -= A*B ", c_sub_ab_got, c_sub_ab_ref, fails)
call check_equal("C += A*conj(B) ", c_add_conjb_got, c_add_conjb_ref, fails)
call check_equal("C -= A*conj(B) ", c_sub_conjb_got, c_sub_conjb_ref, fails)
if (fails == 0) then
stop 0
else
stop 1
end if
end program fcmla_accum_pairs

View File

@ -2995,10 +2995,8 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
if (has_cast_debug_uses
|| (HONOR_NANS (TREE_TYPE (lhs1)) && !is_cast))
{
tree temp3 = make_node (DEBUG_EXPR_DECL);
DECL_ARTIFICIAL (temp3) = 1;
TREE_TYPE (temp3) = TREE_TYPE (orig_use_lhs);
SET_DECL_MODE (temp3, TYPE_MODE (type));
tree temp3
= build_debug_expr_decl (TREE_TYPE (orig_use_lhs));
if (has_cast_debug_uses)
t = fold_convert (TREE_TYPE (temp3), temp2);
else

View File

@ -847,15 +847,23 @@ compatible_complex_nodes_p (slp_compat_nodes_map_t *compat_cache,
return true;
}
/* Check to see if the oprands to two multiplies, 2 each in LEFT_OP and
RIGHT_OP match a complex multiplication or complex multiply-and-accumulate
or complex multiply-and-subtract pattern. Do this using the permute cache
PERM_CACHE and the combination compatibility list COMPAT_CACHE. If
the operation is successful the macthing operands are returned in OPS and
_STATUS indicates if the operation matched includes a conjugate of one of the
operands. If the operation succeeds True is returned, otherwise False and
the values in ops are meaningless. */
static inline bool
vect_validate_multiplication (slp_tree_to_load_perm_map_t *perm_cache,
slp_compat_nodes_map_t *compat_cache,
vec<slp_tree> &left_op,
vec<slp_tree> &right_op,
bool subtract,
const vec<slp_tree> &left_op,
const vec<slp_tree> &right_op,
bool subtract, vec<slp_tree> &ops,
enum _conj_status *_status)
{
auto_vec<slp_tree> ops;
enum _conj_status stats = CONJ_NONE;
/* The complex operations can occur in two layouts and two permute sequences
@ -886,31 +894,31 @@ vect_validate_multiplication (slp_tree_to_load_perm_map_t *perm_cache,
bool neg0 = vect_match_expression_p (right_op[0], NEGATE_EXPR);
bool neg1 = vect_match_expression_p (right_op[1], NEGATE_EXPR);
/* Create the combined inputs after remapping and flattening. */
ops.create (4);
ops.safe_splice (left_op);
ops.safe_splice (right_op);
/* Determine which style we're looking at. We only have different ones
whenever a conjugate is involved. */
if (neg0 && neg1)
;
else if (neg0)
{
right_op[0] = SLP_TREE_CHILDREN (right_op[0])[0];
ops[2] = SLP_TREE_CHILDREN (right_op[0])[0];
stats = CONJ_FST;
if (subtract)
perm = 0;
}
else if (neg1)
{
right_op[1] = SLP_TREE_CHILDREN (right_op[1])[0];
ops[3] = SLP_TREE_CHILDREN (right_op[1])[0];
stats = CONJ_SND;
perm = 1;
}
*_status = stats;
/* Flatten the inputs after we've remapped them. */
ops.create (4);
ops.safe_splice (left_op);
ops.safe_splice (right_op);
/* Extract out the elements to check. */
slp_tree op0 = ops[styles[style][0]];
slp_tree op1 = ops[styles[style][1]];
@ -1073,15 +1081,16 @@ complex_mul_pattern::matches (complex_operation_t op,
return IFN_LAST;
enum _conj_status status;
auto_vec<slp_tree> res_ops;
if (!vect_validate_multiplication (perm_cache, compat_cache, left_op,
right_op, false, &status))
right_op, false, res_ops, &status))
{
/* Try swapping the order and re-trying since multiplication is
commutative. */
std::swap (left_op[0], left_op[1]);
std::swap (right_op[0], right_op[1]);
if (!vect_validate_multiplication (perm_cache, compat_cache, left_op,
right_op, false, &status))
right_op, false, res_ops, &status))
return IFN_LAST;
}
@ -1109,24 +1118,24 @@ complex_mul_pattern::matches (complex_operation_t op,
if (add0)
ops->quick_push (add0);
complex_perm_kinds_t kind = linear_loads_p (perm_cache, left_op[0]);
complex_perm_kinds_t kind = linear_loads_p (perm_cache, res_ops[0]);
if (kind == PERM_EVENODD || kind == PERM_TOP)
{
ops->quick_push (left_op[1]);
ops->quick_push (right_op[1]);
ops->quick_push (left_op[0]);
ops->quick_push (res_ops[1]);
ops->quick_push (res_ops[3]);
ops->quick_push (res_ops[0]);
}
else if (kind == PERM_EVENEVEN && status != CONJ_SND)
{
ops->quick_push (left_op[0]);
ops->quick_push (right_op[0]);
ops->quick_push (left_op[1]);
ops->quick_push (res_ops[0]);
ops->quick_push (res_ops[2]);
ops->quick_push (res_ops[1]);
}
else
{
ops->quick_push (left_op[0]);
ops->quick_push (right_op[1]);
ops->quick_push (left_op[1]);
ops->quick_push (res_ops[0]);
ops->quick_push (res_ops[3]);
ops->quick_push (res_ops[1]);
}
return ifn;
@ -1298,15 +1307,17 @@ complex_fms_pattern::matches (complex_operation_t op,
return IFN_LAST;
enum _conj_status status;
auto_vec<slp_tree> res_ops;
if (!vect_validate_multiplication (perm_cache, compat_cache, right_op,
left_op, true, &status))
left_op, true, res_ops, &status))
{
/* Try swapping the order and re-trying since multiplication is
commutative. */
std::swap (left_op[0], left_op[1]);
std::swap (right_op[0], right_op[1]);
auto_vec<slp_tree> res_ops;
if (!vect_validate_multiplication (perm_cache, compat_cache, right_op,
left_op, true, &status))
left_op, true, res_ops, &status))
return IFN_LAST;
}
@ -1321,20 +1332,20 @@ complex_fms_pattern::matches (complex_operation_t op,
ops->truncate (0);
ops->create (4);
complex_perm_kinds_t kind = linear_loads_p (perm_cache, right_op[0]);
complex_perm_kinds_t kind = linear_loads_p (perm_cache, res_ops[2]);
if (kind == PERM_EVENODD)
{
ops->quick_push (l0node[0]);
ops->quick_push (right_op[0]);
ops->quick_push (right_op[1]);
ops->quick_push (left_op[1]);
ops->quick_push (res_ops[2]);
ops->quick_push (res_ops[3]);
ops->quick_push (res_ops[1]);
}
else
{
ops->quick_push (l0node[0]);
ops->quick_push (right_op[1]);
ops->quick_push (right_op[0]);
ops->quick_push (left_op[0]);
ops->quick_push (res_ops[3]);
ops->quick_push (res_ops[2]);
ops->quick_push (res_ops[0]);
}
return ifn;