Jason Merrill [Tue, 21 Nov 2023 23:22:53 +0000 (18:22 -0500)]
c++: start_preparsed_function tweak
In review of the deducing 'this' patch, it came up that the logic in
start_preparsed_function around the ctype variable was convoluted, being
set for non-static member functions and friends, but not for static member
functions. Let's set it for any member function, and not rely on it to
decide whether to set up 'this'.
where the expression is ((1 << R3) + R10), which does not match a valid
machine addressing mode. Consequently `print_operand_address' chokes.
This can be reduced to the testcase included, where it triggers the same
ICE in `p'. Preincrements are required so that their results land in
registers and consequently an indexed addressing mode is tried or
otherwise doing operations piecemeal on stack-based function arguments
as direct input operands turns out more profitable in terms of RTX costs
and the ICE is avoided.
The ultimate cause has been commit c605a8bf9270 ("VAX: Accept ASHIFT in
address expressions"), where a shift of an immediate value by a register
has been mistakenly allowed as an index expression as if the shift
operation was commutative such as multiplication is. So with ASHIFT the
scaler in an index expression has to be the right-hand operand, and the
backend has to enforce that, whereas with MULT the scaler can be either
operand.
Fix this by only accepting the index scaler as the RHS operand to
ASHIFT.
gcc/
PR target/111815
* config/vax/vax.cc (index_term_p): Only accept the index scaler
as the RHS operand to ASHIFT.
gcc/testsuite/
PR target/111815
* gcc.dg/torture/pr111815.c: New test.
RISC-V/testsuite: Add branchless cases for FP NE cond-add operation
Verify, for the generic floating-point NE conditional-add operation,
that if-conversion triggers via `noce_try_addcc' at `-mbranch-cost=3'
setting, which makes branchless code sequences emitted by if-conversion
cheaper than their original branched equivalents, and that extraneous
instructions such as SNEZ, etc. are not present in output.
The reason to XFAIL the SImode test for RV64 targets is GCC thinks it
has to sign-extend addends, which causes if-conversion to give up.
gcc/testsuite/
* gcc.target/riscv/adddifne.c: New test.
* gcc.target/riscv/addsifne.c: New test.
RISC-V/testsuite: Add branched cases for FP NE cond-add operation
Verify, for the generic floating-point NE conditional-add operation,
that if-conversion does *not* trigger at `-mbranch-cost=2' setting,
which makes original branched code sequences cheaper than their
branchless equivalents if-conversion would emit.
gcc/testsuite/
* gcc.target/riscv/adddibfne.c: New test.
* gcc.target/riscv/addsibfne.c: New test.
RISC-V/testsuite: Add branched cases for FP NE cond-move operations
Verify, for the floating-point NE conditional-move operation, that
if-conversion triggers via `noce_try_cmove' at the respective
sufficiently high `-mbranch-cost=' settings that make branchless code
sequences produced by if-conversion cheaper than their original branched
equivalents, and that extraneous instructions such as SNEZ, etc. are not
present in output.
gcc/testsuite/
* gcc.target/riscv/movdifeq-sfb.c: New test.
* gcc.target/riscv/movdifeq-thead.c: New test.
* gcc.target/riscv/movdifeq-ventana.c: New test.
* gcc.target/riscv/movdifeq-zicond.c: New test.
* gcc.target/riscv/movdifeq.c: New test.
* gcc.target/riscv/movsifeq-sfb.c: New test.
* gcc.target/riscv/movsifeq-thead.c: New test.
* gcc.target/riscv/movsifeq-ventana.c: New test.
* gcc.target/riscv/movsifeq-zicond.c: New test.
* gcc.target/riscv/movsifeq.c: New test.
RISC-V/testsuite: Add branched cases for FP NE cond-move operations
Verify, for generic, Ventana and Zicond targets and the floating-point
NE conditional-move operation, that if-conversion does *not* trigger at
the respective sufficiently low `-mbranch-cost=' settings that make
original branched code sequences cheaper than their branchless
equivalents if-conversion would emit.
gcc/testsuite/
* gcc.target/riscv/movdibfeq-ventana.c: New test.
* gcc.target/riscv/movdibfeq-zicond.c: New test.
* gcc.target/riscv/movdibfeq.c: New test.
* gcc.target/riscv/movsibfeq-ventana.c: New test.
* gcc.target/riscv/movsibfeq-zicond.c: New test.
* gcc.target/riscv/movsibfeq.c: New test.
RISC-V: Handle FP NE operator via inversion in cond-operation expansion
We have no FNE.fmt machine instructions, but we can emulate them for the
purpose of conditional-move and conditional-add operations by using the
respective FEQ.fmt instruction and then swapping the data input operands
or complementing the mask for the conditional addend respectively, so
update our handlers accordingly.
gcc/
* config/riscv/riscv-protos.h (riscv_expand_float_scc): Add
`invert_ptr' parameter.
* config/riscv/riscv.cc (riscv_emit_float_compare): Add NE
inversion handling.
(riscv_expand_float_scc): Pass `invert_ptr' through to
`riscv_emit_float_compare'.
(riscv_expand_conditional_move): Pass `&invert' to
`riscv_expand_float_scc'.
* config/riscv/riscv.md (add<mode>cc): Likewise.
RISC-V/testsuite: Add branchless cases for generic FP cond adds
Verify, for generic floating-point conditional-add operations that have
a corresponding conditional-set machine instruction, that if-conversion
triggers via `noce_try_addcc' at `-mbranch-cost=3' setting, which makes
branchless code sequences emitted by if-conversion cheaper than their
original branched equivalents, and that extraneous instructions such as
SNEZ, etc. are not present in output.
The reason to XFAIL SImode tests for RV64 targets is the compiler thinks
it has to sign-extend addends, which causes if-conversion to give up.
gcc/testsuite/
* gcc.target/riscv/adddifeq.c: New test.
* gcc.target/riscv/adddifge.c: New test.
* gcc.target/riscv/adddifgt.c: New test.
* gcc.target/riscv/adddifle.c: New test.
* gcc.target/riscv/adddiflt.c: New test.
* gcc.target/riscv/addsifeq.c: New test.
* gcc.target/riscv/addsifge.c: New test.
* gcc.target/riscv/addsifgt.c: New test.
* gcc.target/riscv/addsifle.c: New test.
* gcc.target/riscv/addsiflt.c: New test.
RISC-V/testsuite: Add branched cases for generic FP cond adds
Verify, for generic floating-point conditional-add operations that have
a corresponding conditional-set machine instruction, that if-conversion
does *not* trigger at `-mbranch-cost=2' setting, which makes original
branched code sequences cheaper than their branchless equivalents
if-conversion would emit. Cover all the relevant floating-point
relational operations to make sure no corner case escapes.
gcc/testsuite/
* gcc.target/riscv/adddibfeq.c: New test.
* gcc.target/riscv/adddibfge.c: New test.
* gcc.target/riscv/adddibfgt.c: New test.
* gcc.target/riscv/adddibfle.c: New test.
* gcc.target/riscv/adddibflt.c: New test.
* gcc.target/riscv/addsibfeq.c: New test.
* gcc.target/riscv/addsibfge.c: New test.
* gcc.target/riscv/addsibfgt.c: New test.
* gcc.target/riscv/addsibfle.c: New test.
* gcc.target/riscv/addsibflt.c: New test.
RISC-V/testsuite: Add branchless cases for generic FP cond moves
Verify, for generic floating-point conditional-move operations that have
a corresponding conditional-set machine instruction, that if-conversion
triggers (via `cond_move_convert_if_block', which doesn't report) at
`-mbranch-cost=5' setting, which makes branchless code sequences emitted
by if-conversion cheaper than their original branched equivalents, and
that extraneous instructions such as SNEZ, etc. are not present in
output.
gcc/testsuite/
* gcc.target/riscv/movdifge.c: New test.
* gcc.target/riscv/movdifgt.c: New test.
* gcc.target/riscv/movdifle.c: New test.
* gcc.target/riscv/movdiflt.c: New test.
* gcc.target/riscv/movdifne.c: New test.
* gcc.target/riscv/movsifge.c: New test.
* gcc.target/riscv/movsifgt.c: New test.
* gcc.target/riscv/movsifle.c: New test.
* gcc.target/riscv/movsiflt.c: New test.
* gcc.target/riscv/movsifne.c: New test.
RISC-V/testsuite: Add branched cases for generic FP cond moves
Verify, for generic floating-point conditional-move operations that have
a corresponding conditional-set machine instruction, that if-conversion
does *not* trigger at `-mbranch-cost=4' setting, which makes original
branched code sequences cheaper than their branchless equivalents
if-conversion would emit. Cover all the relevant floating-point
relational operations to make sure no corner case escapes.
gcc/testsuite/
* gcc.target/riscv/movdibfge.c: New test.
* gcc.target/riscv/movdibfgt.c: New test.
* gcc.target/riscv/movdibfle.c: New test.
* gcc.target/riscv/movdibflt.c: New test.
* gcc.target/riscv/movdibfne.c: New test.
* gcc.target/riscv/movsibfge.c: New test.
* gcc.target/riscv/movsibfgt.c: New test.
* gcc.target/riscv/movsibfle.c: New test.
* gcc.target/riscv/movsibflt.c: New test.
* gcc.target/riscv/movsibfne.c: New test.
RISC-V: Avoid extraneous integer comparison for FP comparisons
We have floating-point coditional-set machine instructions for a subset
of FP comparisons, so avoid going through a comparison against constant
zero in `riscv_expand_float_scc' where not necessary, preventing an
extraneous RTL instruction from being produced that counts against the
cost of the replacement branchless code sequence in if-conversion, e.g.:
lowering the cost of the code sequence produced (even though combine
would swallow the second insn anyway).
We still need to produce a comparison against constant zero where the
instruction following a floating-point coditional-set operation is a
branch, so add canonicalization to `riscv_expand_conditional_branch'
instead.
gcc/
* config/riscv/riscv.cc (riscv_emit_float_compare) <NE>: Handle
separately.
<EQ, LE, LT, GE, GT>: Return operands supplied as is.
(riscv_emit_binary): Call `riscv_emit_binary' directly rather
than going through a temporary register for word-mode targets.
(riscv_expand_conditional_branch): Canonicalize the comparison
if not against constant zero.
RISC-V: Provide FP conditional-branch instructions for if-conversion
Do not expand floating-point conditional-branch RTL instructions right
away that use a comparison operation that is either directly available
as a machine conditional-set instruction or is NE, which can be emulated
by EQ. This is so that if-conversion sees them in their original form
and can produce fewer operations tried in a branchless code sequence
compared to when such an instruction has been already converted to a
sequence of a floating-point conditional-set RTL instruction followed by
an integer conditional-branch RTL instruction. Split any floating-point
conditional-branch RTL instructions still remaining after reload then.
Adjust the testsuite accordingly: since the middle end uses the inverse
condition internally, an inverse conditional-set instruction may make it
to assembly output and also `cond_move_process_if_block' will be used by
if-conversion rather than `noce_process_if_block', because the latter
function not yet been updated to handle inverted conditions.
gcc/
* config/riscv/predicates.md (ne_operator): New predicate.
* config/riscv/riscv.cc (riscv_insn_cost): Handle branches on a
floating-point condition.
* config/riscv/riscv.md (@cbranch<mode>4): Rename expander to...
(@cbranch<ANYF:mode>4): ... this. Only expand the RTX via
`riscv_expand_conditional_branch' for `!signed_order_operator'
operators, otherwise let it through.
(*cbranch<ANYF:mode>4, *cbranch<ANYF:mode>4): New insns and
splitters.
RISC-V: Also allow FP conditions in `riscv_expand_conditional_move'
In `riscv_expand_conditional_move' we only let integer conditions
through at the moment, even though code has already been prepared to
handle floating-point conditions as well.
Lift this restriction and only bail out if a non-word-mode integer
condition has been requested, as we cannot handle this specific case
owing to machine instruction set restriction. We already take care of
the non-integer, non-floating-point case later on.
gcc/
* config/riscv/riscv.cc (riscv_expand_conditional_move): Don't
bail out in floating-point conditions.
RISC-V: Only use SUBREG if applicable in `riscv_expand_float_scc'
A subsequent change to enable the processing of conditional moves on a
floating-point condition by `riscv_expand_conditional_move' will cause
`riscv_expand_float_scc' to be called for word-mode target RTX with RV64
targets. In that case an invalid insn such as:
would be produced, which would crash the compiler later on. Since the
output operand of the SET operation to be produced already has the same
mode as the input operand does, just omit the use of SUBREG and assign
directly.
gcc/
* config/riscv/riscv.cc (riscv_expand_float_scc): Suppress the
use of SUBREG if the conditional-set target is word-mode.
RISC-V/testsuite: Add branchless cases for generic integer cond adds
Verify, for generic integer conditional-add operations, if-conversion
to trigger via `noce_try_addcc' at the respective sufficiently high
`-mbranch-cost=' settings that make branchless code sequences produced
by if-conversion cheaper than their original branched equivalents, and,
where applicable, that extraneous instructions such as SNEZ, etc. are
not present in output. Cover all integer relational operations to make
sure no corner case escapes.
The reason to XFAIL SImode tests for RV64 targets is the compiler thinks
it has to sign-extend addends, which causes if-conversion to give up.
gcc/testsuite/
* gcc.target/riscv/adddieq.c: New test.
* gcc.target/riscv/adddige.c: New test.
* gcc.target/riscv/adddigeu.c: New test.
* gcc.target/riscv/adddigt.c: New test.
* gcc.target/riscv/adddigtu.c: New test.
* gcc.target/riscv/adddile.c: New test.
* gcc.target/riscv/adddileu.c: New test.
* gcc.target/riscv/adddilt.c: New test.
* gcc.target/riscv/adddiltu.c: New test.
* gcc.target/riscv/adddine.c: New test.
* gcc.target/riscv/addsieq.c: New test.
* gcc.target/riscv/addsige.c: New test.
* gcc.target/riscv/addsigeu.c: New test.
* gcc.target/riscv/addsigt.c: New test.
* gcc.target/riscv/addsigtu.c: New test.
* gcc.target/riscv/addsile.c: New test.
* gcc.target/riscv/addsileu.c: New test.
* gcc.target/riscv/addsilt.c: New test.
* gcc.target/riscv/addsiltu.c: New test.
* gcc.target/riscv/addsine.c: New test.
RISC-V/testsuite: Add branched cases for generic integer cond adds
Verify, for generic integer conditional-add operations, if-conversion
*not* to trigger at the respective sufficiently low `-mbranch-cost='
settings that make original branched code sequences cheaper than their
branchless equivalents if-conversion would emit. Cover all integer
relational operations to make sure no corner case escapes.
gcc/testsuite/
* gcc.target/riscv/adddibeq.c: New test.
* gcc.target/riscv/adddibge.c: New test.
* gcc.target/riscv/adddibgeu.c: New test.
* gcc.target/riscv/adddibgt.c: New test.
* gcc.target/riscv/adddibgtu.c: New test.
* gcc.target/riscv/adddible.c: New test.
* gcc.target/riscv/adddibleu.c: New test.
* gcc.target/riscv/adddiblt.c: New test.
* gcc.target/riscv/adddibltu.c: New test.
* gcc.target/riscv/adddibne.c: New test.
* gcc.target/riscv/addsibeq.c: New test.
* gcc.target/riscv/addsibge.c: New test.
* gcc.target/riscv/addsibgeu.c: New test.
* gcc.target/riscv/addsibgt.c: New test.
* gcc.target/riscv/addsibgtu.c: New test.
* gcc.target/riscv/addsible.c: New test.
* gcc.target/riscv/addsibleu.c: New test.
* gcc.target/riscv/addsiblt.c: New test.
* gcc.target/riscv/addsibltu.c: New test.
* gcc.target/riscv/addsibne.c: New test.
RISC-V: Add `addMODEcc' implementation for generic targets
Provide RTL expansion of conditional-add operations for generic targets
using a suitable sequence of base integer machine instructions according
to cost evaluation by if-conversion. Use existing `-mmovcc' command
line option to enable this transformation.
gcc/
* config/riscv/riscv.md (add<mode>cc): New expander.
RISC-V/testsuite: Add branchless cases for generic integer cond moves
Verify, for generic integer conditional-move operations, if-conversion
to trigger via `noce_try_cmove' at the respective sufficiently high
`-mbranch-cost=' settings that make branchless code sequences produced
by if-conversion cheaper than their original branched equivalents, and,
where applicable, that extraneous instructions such as SNEZ, etc. are
not present in output. Cover all integer relational operations to make
sure no corner case escapes.
gcc/testsuite/
* gcc.target/riscv/movdieq.c: New test.
* gcc.target/riscv/movdige.c: New test.
* gcc.target/riscv/movdigeu.c: New test.
* gcc.target/riscv/movdigt.c: New test.
* gcc.target/riscv/movdigtu.c: New test.
* gcc.target/riscv/movdile.c: New test.
* gcc.target/riscv/movdileu.c: New test.
* gcc.target/riscv/movdilt.c: New test.
* gcc.target/riscv/movdiltu.c: New test.
* gcc.target/riscv/movdine.c: New test.
* gcc.target/riscv/movsieq.c: New test.
* gcc.target/riscv/movsige.c: New test.
* gcc.target/riscv/movsigeu.c: New test.
* gcc.target/riscv/movsigt.c: New test.
* gcc.target/riscv/movsigtu.c: New test.
* gcc.target/riscv/movsile.c: New test.
* gcc.target/riscv/movsileu.c: New test.
* gcc.target/riscv/movsilt.c: New test.
* gcc.target/riscv/movsiltu.c: New test.
* gcc.target/riscv/movsine.c: New test.
RISC-V/testsuite: Add branched cases for generic integer cond moves
Verify, for generic integer conditional-move operations, if-conversion
*not* to trigger at the respective sufficiently low `-mbranch-cost='
settings that make original branched code sequences cheaper than their
branchless equivalents if-conversion would emit. Cover all integer
relational operations to make sure no corner case escapes.
gcc/testsuite/
* gcc.target/riscv/movdibeq.c: New test.
* gcc.target/riscv/movdibge.c: New test.
* gcc.target/riscv/movdibgeu.c: New test.
* gcc.target/riscv/movdibgt.c: New test.
* gcc.target/riscv/movdibgtu.c: New test.
* gcc.target/riscv/movdible.c: New test.
* gcc.target/riscv/movdibleu.c: New test.
* gcc.target/riscv/movdiblt.c: New test.
* gcc.target/riscv/movdibltu.c: New test.
* gcc.target/riscv/movdibne.c: New test.
* gcc.target/riscv/movsibeq.c: New test.
* gcc.target/riscv/movsibge.c: New test.
* gcc.target/riscv/movsibgeu.c: New test.
* gcc.target/riscv/movsibgt.c: New test.
* gcc.target/riscv/movsibgtu.c: New test.
* gcc.target/riscv/movsible.c: New test.
* gcc.target/riscv/movsibleu.c: New test.
* gcc.target/riscv/movsiblt.c: New test.
* gcc.target/riscv/movsibltu.c: New test.
* gcc.target/riscv/movsibne.c: New test.
RISC-V: Add `movMODEcc' implementation for generic targets
Provide RTL expansion of conditional-move operations for generic targets
using a suitable sequence of base integer machine instructions according
to cost evaluation by if-conversion. Add `-mmovcc' command line option
to enable this transformation, off by default.
For the generic sequences small immediates as per the `arith_operand'
predicate are cost-equivalent to registers as we can use them as input,
alternative to a register, to the respective AND[I] machine operations,
however we need to reject immediates fulfilling `lui_operand', because
they would require reloading into a register, making the operation more
costly. Therefore add `movcc_operand' predicate and use it accordingly.
There is a need to adjust zbs-bext-02.c, which can also serve as emitted
code example, because with certain compilation options an AND operation
can now legitimately appear in output despite BEXT having been produced
as expected, such as with `-march=rv64gc -O2':
foo:
mv a3,a0
li a5,0
mv a0,a1
li a2,64
li a1,1
.L3:
sll a4,a1,a5
and a4,a4,a3
addiw a5,a5,1
beq a4,zero,.L2
addiw a0,a0,1
.L2:
bne a5,a2,.L3
ret
vs `-march=rv64gc_zbs -O2':
foo:
mv a4,a0
li a5,0
mv a0,a1
li a3,64
.L3:
bext a2,a4,a5
beq a2,zero,.L2
addiw a0,a0,1
.L2:
addiw a5,a5,1
bne a5,a3,.L3
ret
and then with `-march=rv64gc -mmovcc -mbranch-cost=7':
foo:
mv a6,a0
li a4,0
mv a0,a1
li a7,1
li a1,64
.L3:
sll a5,a7,a4
and a5,a5,a6
snez a5,a5
neg a5,a5
not a2,a5
addiw a3,a0,1
and a5,a5,a3
and a0,a2,a0
addiw a4,a4,1
or a0,a5,a0
bne a4,a1,.L3
ret
vs `-march=rv64gc_zbs -mmovcc -mbranch-cost=7':
foo:
mv a6,a0
li a4,0
mv a0,a1
li a1,64
.L3:
bext a5,a6,a4
neg a5,a5
not a2,a5
addiw a3,a0,1
and a5,a5,a3
and a0,a2,a0
addiw a4,a4,1
or a0,a5,a0
bne a4,a1,.L3
ret
However BEXT is supposed to replace an SLL operation so adjust the test
case to reject SLL rather than AND, letting the test case pass even with
`/-mmovcc/-mbranch-cost=7' specified as DejaGNU test flags (and in the
absence of target-specific conditional-move operations enabled either by
default or with other test flags).
gcc/
* config/riscv/predicates.md (movcc_operand): New predicate.
* config/riscv/riscv.cc (riscv_expand_conditional_move): Handle
generic targets.
* config/riscv/riscv.md (mov<mode>cc): Likewise.
* config/riscv/riscv.opt (mmovcc): New option.
* doc/invoke.texi (Option Summary): Document it.
gcc/testsuite/
* gcc.target/riscv/zbs-bext-02.c: Adjust to reject SLL rather
than AND.
RISC-V/testsuite: Add branchless cases for T-Head non-equality cond moves
Verify, for T-Head targets and the non-equality integer conditional-move
operations, that if-conversion triggers via `noce_try_cmove' at
`-mbranch-cost=2' setting, which makes branchless code sequences
produced by if-conversion cheaper than their original branched
equivalents, and that extraneous instructions such as SNEZ, etc. are not
present in output.
gcc/testsuite/
* gcc.target/riscv/movdige-thead.c: New test.
* gcc.target/riscv/movdigeu-thead.c: New test.
* gcc.target/riscv/movdigt-thead.c: New test.
* gcc.target/riscv/movdigtu-thead.c: New test.
* gcc.target/riscv/movdile-thead.c: New test.
* gcc.target/riscv/movdileu-thead.c: New test.
* gcc.target/riscv/movdilt-thead.c: New test.
* gcc.target/riscv/movdiltu-thead.c: New test.
* gcc.target/riscv/movsige-thead.c: New test.
* gcc.target/riscv/movsigeu-thead.c: New test.
* gcc.target/riscv/movsigt-thead.c: New test.
* gcc.target/riscv/movsigtu-thead.c: New test.
* gcc.target/riscv/movsile-thead.c: New test.
* gcc.target/riscv/movsileu-thead.c: New test.
* gcc.target/riscv/movsilt-thead.c: New test.
* gcc.target/riscv/movsiltu-thead.c: New test.
RISC-V/testsuite: Add branched cases for T-Head non-equality cond moves
Verify, for T-Head targets and the non-equality integer conditional-move
operations, that if-conversion does *not* trigger at `-mbranch-cost=1'
setting, which makes original branched code sequences cheaper than their
branchless equivalents if-conversion would emit.
gcc/testsuite/
* gcc.target/riscv/movdibge-thead.c: New test.
* gcc.target/riscv/movdibgeu-thead.c: New test.
* gcc.target/riscv/movdibgt-thead.c: New test.
* gcc.target/riscv/movdibgtu-thead.c: New test.
* gcc.target/riscv/movdible-thead.c: New test.
* gcc.target/riscv/movdibleu-thead.c: New test.
* gcc.target/riscv/movdiblt-thead.c: New test.
* gcc.target/riscv/movdibltu-thead.c: New test.
* gcc.target/riscv/movsibge-thead.c: New test.
* gcc.target/riscv/movsibgeu-thead.c: New test.
* gcc.target/riscv/movsibgt-thead.c: New test.
* gcc.target/riscv/movsibgtu-thead.c: New test.
* gcc.target/riscv/movsible-thead.c: New test.
* gcc.target/riscv/movsibleu-thead.c: New test.
* gcc.target/riscv/movsiblt-thead.c: New test.
* gcc.target/riscv/movsibltu-thead.c: New test.
Code in `riscv_expand_conditional_move' for Ventana and Zicond targets
seems like bolted on as an afterthought rather than properly merged so
as to handle all the cases together.
Fold the existing code pieces together then (observing that for short
forward branch targets no integer comparisons need to be canonicalized),
letting T-Head targets produce branchless sequences for all the integer
comparisons rather than for equality ones only, and preparing for the
handling of floating-point comparisons here across all conditional-move
targets.
gcc/
* config/riscv/riscv.cc (riscv_expand_conditional_move): Unify
conditional-move handling across all the relevant targets.
RISC-V: Also accept constants for T-Head cond-move data input operands
There is no need for the requirement for conditional-move data input
operands to be stricter for T-Head targets than for short forward branch
targets and limit them to registers only. They are keyed according to
the `sfb_alu_operand' predicate, which lets certain constants through.
Such constants are already forced into a register for the `cons' operand
in the analogous short forward branch case and we can force them for the
`alt' operand and T-Head as well. This enables more opportunities for a
branchless sequence to be produced.
gcc/
* config/riscv/riscv.cc (riscv_expand_conditional_move): Also
accept constants for T-Head data input operands.
RISC-V: Also accept constants for T-Head cond-move comparison operands
There is no need for the requirement for conditional-move comparison
operands to be stricter for T-Head targets than for other targets and
limit them to registers only. Constants will be reloaded if required
just as with branches or other-target conditional-move operations and
there is no extra overhead specific to the T-Head case. This enables
more opportunities for a branchless sequence to be produced.
gcc/
* config/riscv/riscv.cc (riscv_expand_conditional_move): Also
accept constants for T-Head comparison operands.
RISC-V/testsuite: Add branchless cases for equality cond-move operations
Verify, for Ventana and Zicond targets and the equality conditional-move
operations, that if-conversion triggers via `noce_try_cmove' at the
respective sufficiently high `-mbranch-cost=' settings that make
branchless code sequences produced by if-conversion cheaper than their
original branched equivalents, and that extraneous instructions such as
SNEZ, etc. are not present in output.
gcc/testsuite/
* gcc.target/riscv/movdieq-ventana.c: New test.
* gcc.target/riscv/movdieq-zicond.c: New test.
* gcc.target/riscv/movdine-ventana.c: New test.
* gcc.target/riscv/movdine-zicond.c: New test.
* gcc.target/riscv/movsieq-ventana.c: New test.
* gcc.target/riscv/movsieq-zicond.c: New test.
* gcc.target/riscv/movsine-ventana.c: New test.
* gcc.target/riscv/movsine-zicond.c: New test.
RISC-V/testsuite: Add branched cases for equality cond-move operations
Verify, for Ventana and Zicond targets and the equality conditional-move
operations, that if-conversion does *not* trigger at the respective
sufficiently low `-mbranch-cost=' settings that make original branched
code sequences cheaper than their branchless equivalents if-conversion
would emit.
gcc/testsuite/
* gcc.target/riscv/movdibeq-ventana.c: New test.
* gcc.target/riscv/movdibeq-zicond.c: New test.
* gcc.target/riscv/movdibne-ventana.c: New test.
* gcc.target/riscv/movdibne-zicond.c: New test.
* gcc.target/riscv/movsibeq-ventana.c: New test.
* gcc.target/riscv/movsibeq-zicond.c: New test.
* gcc.target/riscv/movsibne-ventana.c: New test.
* gcc.target/riscv/movsibne-zicond.c: New test.
RISC-V: Avoid extraneous EQ or NE operation in cond-move expansion
In the non-zero case there is no need for the conditional value used by
Ventana and Zicond integer conditional operations to be specifically 1.
Regardless we canonicalize it by producing an extraneous conditional-set
operation, such as with the sequence below:
where insn 23 can well be removed without changing the semantics of the
sequence. This is actually fixed up later on by combine and the insn
does not make it to output meaning no SNEZ (or SEQZ in the reverse case)
appears in the assembly produced, however it counts towards the cost of
the sequence calculated by if-conversion, raising the trigger level for
the branchless sequence to be chosen. Arguably to emit this extraneous
operation it can be also considered rather sloppy of our backend's.
Remove the check for operand 1 being constant 0 in the Ventana/Zicond
case for equality comparisons then, observing that `riscv_zero_if_equal'
called via `riscv_emit_int_compare' will canonicalize the comparison if
required, removing the extraneous insn from output:
Adjust branch costs across the test cases affected accordingly.
gcc/
* config/riscv/riscv.cc (riscv_expand_conditional_move): Remove
the check for operand 1 being constant 0 in the Ventana/Zicond
case for equality comparisons.
RISC-V/testsuite: Add branchless cases for GEU and LEU cond-move operations
Verify, for Ventana and Zicond targets and the GEU and LEU
conditional-move operations, that if-conversion triggers via
`noce_try_cmove' at `-mbranch-cost=4' setting, which makes branchless
code sequences produced by if-conversion cheaper than their original
branched equivalents, and that extraneous instructions such as SEQZ,
etc. are not present in output.
gcc/testsuite/
* gcc.target/riscv/movdigtu-ventana.c: New test.
* gcc.target/riscv/movdigtu-zicond.c: New test.
* gcc.target/riscv/movdiltu-ventana.c: New test.
* gcc.target/riscv/movdiltu-zicond.c: New test.
* gcc.target/riscv/movsigtu-ventana.c: New test.
* gcc.target/riscv/movsigtu-zicond.c: New test.
* gcc.target/riscv/movsiltu-ventana.c: New test.
* gcc.target/riscv/movsiltu-zicond.c: New test.
RISC-V/testsuite: Add branched cases for GEU and LEU cond-move operations
Verify, for Ventana and Zicond targets and the GEU and LEU
conditional-move operations, that if-conversion does *not* trigger at
`-mbranch-cost=3' setting, which makes original branched code sequences
cheaper than their branchless equivalents if-conversion would emit.
gcc/testsuite/
* gcc.target/riscv/movdibgtu-ventana.c: New test.
* gcc.target/riscv/movdibgtu-zicond.c: New test.
* gcc.target/riscv/movdibltu-ventana.c: New test.
* gcc.target/riscv/movdibltu-zicond.c: New test.
* gcc.target/riscv/movsibgtu-ventana.c: New test.
* gcc.target/riscv/movsibgtu-zicond.c: New test.
* gcc.target/riscv/movsibltu-ventana.c: New test.
* gcc.target/riscv/movsibltu-zicond.c: New test.
RISC-V: Also invert the cond-move condition for GEU and LEU
Update `riscv_expand_conditional_move' and handle the missing GEU and
LEU operators there, avoiding an extraneous conditional set operation,
such as with this output:
sgtu a0,a0,a1
seqz a1,a0
czero.eqz a3,a3,a1
czero.nez a1,a2,a1
or a0,a1,a3
produced when optimizing for Zicond targets from:
int
movsigtu (int w, int x, int y, int z)
{
return w > x ? y : z;
}
These operators can be inverted producing optimal code such as this:
sgtu a1,a0,a1
czero.nez a3,a3,a1
czero.eqz a1,a2,a1
or a0,a1,a3
which this change causes to happen.
gcc/
* config/riscv/riscv.cc (riscv_expand_conditional_move): Also
invert the condition for GEU and LEU.
RISC-V/testsuite: Add branchless cases for FP cond-move operations
Verify, for short forward branch, T-Head, Ventana and Zicond targets and
the ordered floating-point conditional-move operations that already work
as expected, that if-conversion triggers via `noce_try_cmove' at the
respective sufficiently high `-mbranch-cost=' settings that make
branchless code sequences produced by if-conversion cheaper than their
original branched equivalents, and that extraneous instructions such as
SNEZ, etc. are not present in output. Cover all ordered floating-point
relational operations to make sure no corner case escapes.
gcc/testsuite/
* gcc.target/riscv/movdifge-sfb.c: New test.
* gcc.target/riscv/movdifge-thead.c: New test.
* gcc.target/riscv/movdifge-ventana.c: New test.
* gcc.target/riscv/movdifge-zicond.c: New test.
* gcc.target/riscv/movdifgt-sfb.c: New test.
* gcc.target/riscv/movdifgt-thead.c: New test.
* gcc.target/riscv/movdifgt-ventana.c: New test.
* gcc.target/riscv/movdifgt-zicond.c: New test.
* gcc.target/riscv/movdifle-sfb.c: New test.
* gcc.target/riscv/movdifle-thead.c: New test.
* gcc.target/riscv/movdifle-ventana.c: New test.
* gcc.target/riscv/movdifle-zicond.c: New test.
* gcc.target/riscv/movdiflt-sfb.c: New test.
* gcc.target/riscv/movdiflt-thead.c: New test.
* gcc.target/riscv/movdiflt-ventana.c: New test.
* gcc.target/riscv/movdiflt-zicond.c: New test.
* gcc.target/riscv/movdifne-sfb.c: New test.
* gcc.target/riscv/movdifne-thead.c: New test.
* gcc.target/riscv/movdifne-ventana.c: New test.
* gcc.target/riscv/movdifne-zicond.c: New test.
* gcc.target/riscv/movsifge-sfb.c: New test.
* gcc.target/riscv/movsifge-thead.c: New test.
* gcc.target/riscv/movsifge-ventana.c: New test.
* gcc.target/riscv/movsifge-zicond.c: New test.
* gcc.target/riscv/movsifgt-sfb.c: New test.
* gcc.target/riscv/movsifgt-thead.c: New test.
* gcc.target/riscv/movsifgt-ventana.c: New test.
* gcc.target/riscv/movsifgt-zicond.c: New test.
* gcc.target/riscv/movsifle-sfb.c: New test.
* gcc.target/riscv/movsifle-thead.c: New test.
* gcc.target/riscv/movsifle-ventana.c: New test.
* gcc.target/riscv/movsifle-zicond.c: New test.
* gcc.target/riscv/movsiflt-sfb.c: New test.
* gcc.target/riscv/movsiflt-thead.c: New test.
* gcc.target/riscv/movsiflt-ventana.c: New test.
* gcc.target/riscv/movsiflt-zicond.c: New test.
* gcc.target/riscv/movsifne-sfb.c: New test.
* gcc.target/riscv/movsifne-thead.c: New test.
* gcc.target/riscv/movsifne-ventana.c: New test.
* gcc.target/riscv/movsifne-zicond.c: New test.
RISC-V/testsuite: Add branched cases for FP cond-move operations
Verify, for Ventana and Zicond targets and the ordered floating-point
conditional-move operations that already work as expected, that
if-conversion does *not* trigger at `-mbranch-cost=2' setting, which
makes original branched code sequences cheaper than their branchless
equivalents if-conversion would emit. Cover all ordered floating-point
relational operations to make sure no corner case escapes.
gcc/testsuite/
* gcc.target/riscv/movdibfge-ventana.c: New test.
* gcc.target/riscv/movdibfge-zicond.c: New test.
* gcc.target/riscv/movdibfgt-ventana.c: New test.
* gcc.target/riscv/movdibfgt-zicond.c: New test.
* gcc.target/riscv/movdibfle-ventana.c: New test.
* gcc.target/riscv/movdibfle-zicond.c: New test.
* gcc.target/riscv/movdibflt-ventana.c: New test.
* gcc.target/riscv/movdibflt-zicond.c: New test.
* gcc.target/riscv/movdibfne-ventana.c: New test.
* gcc.target/riscv/movdibfne-zicond.c: New test.
* gcc.target/riscv/movsibfge-ventana.c: New test.
* gcc.target/riscv/movsibfge-zicond.c: New test.
* gcc.target/riscv/movsibfgt-ventana.c: New test.
* gcc.target/riscv/movsibfgt-zicond.c: New test.
* gcc.target/riscv/movsibfle-ventana.c: New test.
* gcc.target/riscv/movsibfle-zicond.c: New test.
* gcc.target/riscv/movsibflt-ventana.c: New test.
* gcc.target/riscv/movsibflt-zicond.c: New test.
* gcc.target/riscv/movsibfne-ventana.c: New test.
* gcc.target/riscv/movsibfne-zicond.c: New test.
RISC-V/testsuite: Add branchless cases for integer cond-move operations
Verify, for T-Head, Ventana and Zicond targets and the integer
conditional-move operations that already work as expected, if-conversion
to trigger via `noce_try_cmove' at the respective sufficiently high
`-mbranch-cost=' settings that make branchless code sequences produced
by if-conversion cheaper than their original branched equivalents, and
that extraneous instructions such as SNEZ, etc. are not present in
output. Cover all integer relational operations to make sure no corner
case escapes.
gcc/testsuite/
* gcc.target/riscv/movdieq-thead.c: New test.
* gcc.target/riscv/movdige-ventana.c: New test.
* gcc.target/riscv/movdige-zicond.c: New test.
* gcc.target/riscv/movdigeu-ventana.c: New test.
* gcc.target/riscv/movdigeu-zicond.c: New test.
* gcc.target/riscv/movdigt-ventana.c: New test.
* gcc.target/riscv/movdigt-zicond.c: New test.
* gcc.target/riscv/movdile-ventana.c: New test.
* gcc.target/riscv/movdile-zicond.c: New test.
* gcc.target/riscv/movdileu-ventana.c: New test.
* gcc.target/riscv/movdileu-zicond.c: New test.
* gcc.target/riscv/movdilt-ventana.c: New test.
* gcc.target/riscv/movdilt-zicond.c: New test.
* gcc.target/riscv/movdine-thead.c: New test.
* gcc.target/riscv/movsieq-thead.c: New test.
* gcc.target/riscv/movsige-ventana.c: New test.
* gcc.target/riscv/movsige-zicond.c: New test.
* gcc.target/riscv/movsigeu-ventana.c: New test.
* gcc.target/riscv/movsigeu-zicond.c: New test.
* gcc.target/riscv/movsigt-ventana.c: New test.
* gcc.target/riscv/movsigt-zicond.c: New test.
* gcc.target/riscv/movsile-ventana.c: New test.
* gcc.target/riscv/movsile-zicond.c: New test.
* gcc.target/riscv/movsileu-ventana.c: New test.
* gcc.target/riscv/movsileu-zicond.c: New test.
* gcc.target/riscv/movsilt-ventana.c: New test.
* gcc.target/riscv/movsilt-zicond.c: New test.
* gcc.target/riscv/movsine-thead.c: New test.
RISC-V/testsuite: Add branched cases for integer cond-move operations
Verify, for T-Head, Ventana and Zicond targets and the integer
conditional-move operations that already work as expected, that
if-conversion does *not* trigger at the respective sufficiently low
`-mbranch-cost=' settings that make original branched code sequences
cheaper than their branchless equivalents if-conversion would emit.
Cover all integer relational operations to make sure no corner case
escapes.
The reason to XFAIL movdibne-thead.c and movsibne-thead.c is the
branchless T-Head sequence:
sub a1,a0,a1
th.mveqz a2,a3,a1
mv a0,a2
ret
produced rather than its original branched counterpart:
beq a0,a1,.L3
mv a0,a2
ret
.L3:
mv a0,a3
ret
at `-mbranch-cost=1', even though under this setting the latter sequence
is obviously cheaper performance-wise. This is because the final move
instruction in the branchless sequence is not counted towards its cost
and consequently the cost of both sequences works out at 8 each, making
if-conversion prefer the branchless variant. Use the XFAIL mark to keep
track of these cases for future consideration.
gcc/testsuite/
* gcc.target/riscv/movdibeq-thead.c: New test.
* gcc.target/riscv/movdibge-ventana.c: New test.
* gcc.target/riscv/movdibge-zicond.c: New test.
* gcc.target/riscv/movdibgeu-ventana.c: New test.
* gcc.target/riscv/movdibgeu-zicond.c: New test.
* gcc.target/riscv/movdibgt-ventana.c: New test.
* gcc.target/riscv/movdibgt-zicond.c: New test.
* gcc.target/riscv/movdible-ventana.c: New test.
* gcc.target/riscv/movdible-zicond.c: New test.
* gcc.target/riscv/movdibleu-ventana.c: New test.
* gcc.target/riscv/movdibleu-zicond.c: New test.
* gcc.target/riscv/movdiblt-ventana.c: New test.
* gcc.target/riscv/movdiblt-zicond.c: New test.
* gcc.target/riscv/movdibne-thead.c: New test.
* gcc.target/riscv/movsibeq-thead.c: New test.
* gcc.target/riscv/movsibge-ventana.c: New test.
* gcc.target/riscv/movsibge-zicond.c: New test.
* gcc.target/riscv/movsibgeu-ventana.c: New test.
* gcc.target/riscv/movsibgeu-zicond.c: New test.
* gcc.target/riscv/movsibgt-ventana.c: New test.
* gcc.target/riscv/movsibgt-zicond.c: New test.
* gcc.target/riscv/movsible-ventana.c: New test.
* gcc.target/riscv/movsible-zicond.c: New test.
* gcc.target/riscv/movsibleu-ventana.c: New test.
* gcc.target/riscv/movsibleu-zicond.c: New test.
* gcc.target/riscv/movsiblt-ventana.c: New test.
* gcc.target/riscv/movsiblt-zicond.c: New test.
* gcc.target/riscv/movsibne-thead.c: New test.
RISC-V: Rework branch costing model for if-conversion
The generic branch costing model for if-conversion assumes a fixed cost
of COSTS_N_INSNS (2) for a conditional branch, and that one half of that
cost comes from a preceding condition-set instruction, such as with
MODE_CC targets, and then the other half of that cost is for the actual
branch instruction. This is hardcoded for `if_info.original_cost' in
`noce_find_if_block' and regardless of the cost set for branches via
BRANCH_COST.
Then `default_max_noce_ifcvt_seq_cost' instructs if-conversion to prefer
a branchless sequence as costly as high as triple the BRANCH_COST value
set. This is apparently to make up for the inability to accurately
guess the branch penalty.
Consequently for the BRANCH_COST of 3 we commonly set for tuning,
if-conversion will consider branchless sequences costing 3 * 3 - 2 = 7
instruction units more than a corresponding branch sequence. For the
BRANCH_COST of 4 such as with `sifive-7-series' tuning this is even
worse, at 3 * 4 - 2 = 10. Effectively it means a branchless sequence
will always be chosen if available, even a very inefficient one.
Rework the branch costing model to better match our architecture,
observing in particular that we have no preparatory instructions for
branches so that the cost of a branch is naked BRANCH_COST plus any
extra overhead the processing of a branch's source RTX might incur.
Provide TARGET_INSN_COST and TARGET_MAX_NOCE_IFCVT_SEQ_COST handlers
than that return suitable cost based on BRANCH_COST. The latter hook
usually returns a value that is lower than the cost of the corresponding
branched sequence. This is because we don't really want to produce a
branchless sequence that is more expensive than the original branched
sequence. If this turns out too conservative for some corner case, then
this choice might be revisited.
Then we don't want to fiddle with `noce_find_if_block' without a lot of
cross-target verification, so add TARGET_NOCE_CONVERSION_PROFITABLE_P
defined such that it subtracts the fixed COSTS_N_INSNS (2) cost from the
cost of the original branched sequence supplied and instead adds actual
branch cost calculated from the conditional branch instruction used. It
is then further tweaked according to simple analysis of the replacement
branchless sequence produced so as to cancel the cost of an extraneous
zero extend operation produced by `noce_try_store_flag_mask' as observed
with gcc/testsuite/gcc.target/riscv/pr105314.c.
Tweak the testsuite accordingly and set `-mbranch-cost=' explicitly for
the relevant cases so that the expected if-conversion transformation is
made regardless of the default BRANCH_COST value of tuning in effect.
Some of these settings will be lowered later on as deficiencies in
branchless sequence generation have been fixed that lower their cost
calculated by if-conversion.
gcc/
* config/riscv/riscv.cc (riscv_insn_cost): New function.
(riscv_max_noce_ifcvt_seq_cost): Likewise.
(riscv_noce_conversion_profitable_p): Likewise.
(TARGET_INSN_COST): New macro.
(TARGET_MAX_NOCE_IFCVT_SEQ_COST): New macro.
(TARGET_NOCE_CONVERSION_PROFITABLE_P): New macro.
RISC-V: Fix `mode' usage in `riscv_expand_conditional_move'
In `riscv_expand_conditional_move' `mode' is initialized right away from
`GET_MODE (dest)', so remove needless references that refrain from using
the local variable.
gcc/
* config/riscv/riscv.cc (riscv_expand_conditional_move): Use
`mode' for `GET_MODE (dest)' throughout.
RISC-V: Sanitise NEED_EQ_NE_P case with `riscv_emit_int_compare'
For the NEED_EQ_NE_P `riscv_emit_int_compare' is documented to only emit
EQ or NE comparisons against zero, however it does not catch incorrect
use where a non-equality comparison has been requested and falls through
to the general case then. Add a safety guard to catch such a case then.
Arguably the NEED_EQ_NE_P case would best be moved into a function of
its own, but let's leave it for a separate cleanup.
gcc/
* config/riscv/riscv.cc (riscv_emit_int_compare): Bail out if
NEED_EQ_NE_P but the comparison is neither EQ nor NE.
RISC-V/testsuite: Add cases for integer SFB cond-move operations
Verify, for short forward branch targets and the conditional-move
operations that already work as expected, that if-conversion triggers
via `noce_try_cmove' already at `-mbranch-cost=1' and that extraneous
instructions such as SNEZ, etc. are not present in output. Cover all
integer relational operations to make sure no corner case escapes.
gcc/testsuite/
* gcc.target/riscv/movdieq-sfb.c: New test.
* gcc.target/riscv/movdige-sfb.c: New test.
* gcc.target/riscv/movdigeu-sfb.c: New test.
* gcc.target/riscv/movdigt-sfb.c: New test.
* gcc.target/riscv/movdigtu-sfb.c: New test.
* gcc.target/riscv/movdile-sfb.c: New test.
* gcc.target/riscv/movdileu-sfb.c: New test.
* gcc.target/riscv/movdilt-sfb.c: New test.
* gcc.target/riscv/movdiltu-sfb.c: New test.
* gcc.target/riscv/movdine-sfb.c: New test.
* gcc.target/riscv/movsieq-sfb.c: New test.
* gcc.target/riscv/movsige-sfb.c: New test.
* gcc.target/riscv/movsigeu-sfb.c: New test.
* gcc.target/riscv/movsigt-sfb.c: New test.
* gcc.target/riscv/movsigtu-sfb.c: New test.
* gcc.target/riscv/movsile-sfb.c: New test.
* gcc.target/riscv/movsileu-sfb.c: New test.
* gcc.target/riscv/movsilt-sfb.c: New test.
* gcc.target/riscv/movsiltu-sfb.c: New test.
* gcc.target/riscv/movsine-sfb.c: New test.
testsuite: Add cases for conditional-move and conditional-add operations
Add generic execution tests for expressions that are expected to expand
to conditional-move and conditional-add operations where supported. To
ensure no corner case escapes all relational operators are extensively
covered for integer comparisons and all ordered operators are covered
for floating-point comparisons. Unordered operators are not covered at
this point as they'd require a different input data set.
gcc/testsuite/
* gcc.dg/torture/addieq.c: New test.
* gcc.dg/torture/addifeq.c: New test.
* gcc.dg/torture/addifge.c: New test.
* gcc.dg/torture/addifgt.c: New test.
* gcc.dg/torture/addifle.c: New test.
* gcc.dg/torture/addiflt.c: New test.
* gcc.dg/torture/addifne.c: New test.
* gcc.dg/torture/addige.c: New test.
* gcc.dg/torture/addigeu.c: New test.
* gcc.dg/torture/addigt.c: New test.
* gcc.dg/torture/addigtu.c: New test.
* gcc.dg/torture/addile.c: New test.
* gcc.dg/torture/addileu.c: New test.
* gcc.dg/torture/addilt.c: New test.
* gcc.dg/torture/addiltu.c: New test.
* gcc.dg/torture/addine.c: New test.
* gcc.dg/torture/addleq.c: New test.
* gcc.dg/torture/addlfeq.c: New test.
* gcc.dg/torture/addlfge.c: New test.
* gcc.dg/torture/addlfgt.c: New test.
* gcc.dg/torture/addlfle.c: New test.
* gcc.dg/torture/addlflt.c: New test.
* gcc.dg/torture/addlfne.c: New test.
* gcc.dg/torture/addlge.c: New test.
* gcc.dg/torture/addlgeu.c: New test.
* gcc.dg/torture/addlgt.c: New test.
* gcc.dg/torture/addlgtu.c: New test.
* gcc.dg/torture/addlle.c: New test.
* gcc.dg/torture/addlleu.c: New test.
* gcc.dg/torture/addllt.c: New test.
* gcc.dg/torture/addlltu.c: New test.
* gcc.dg/torture/addlne.c: New test.
* gcc.dg/torture/movieq.c: New test.
* gcc.dg/torture/movifeq.c: New test.
* gcc.dg/torture/movifge.c: New test.
* gcc.dg/torture/movifgt.c: New test.
* gcc.dg/torture/movifle.c: New test.
* gcc.dg/torture/moviflt.c: New test.
* gcc.dg/torture/movifne.c: New test.
* gcc.dg/torture/movige.c: New test.
* gcc.dg/torture/movigeu.c: New test.
* gcc.dg/torture/movigt.c: New test.
* gcc.dg/torture/movigtu.c: New test.
* gcc.dg/torture/movile.c: New test.
* gcc.dg/torture/movileu.c: New test.
* gcc.dg/torture/movilt.c: New test.
* gcc.dg/torture/moviltu.c: New test.
* gcc.dg/torture/movine.c: New test.
* gcc.dg/torture/movleq.c: New test.
* gcc.dg/torture/movlfeq.c: New test.
* gcc.dg/torture/movlfge.c: New test.
* gcc.dg/torture/movlfgt.c: New test.
* gcc.dg/torture/movlfle.c: New test.
* gcc.dg/torture/movlflt.c: New test.
* gcc.dg/torture/movlfne.c: New test.
* gcc.dg/torture/movlge.c: New test.
* gcc.dg/torture/movlgeu.c: New test.
* gcc.dg/torture/movlgt.c: New test.
* gcc.dg/torture/movlgtu.c: New test.
* gcc.dg/torture/movlle.c: New test.
* gcc.dg/torture/movlleu.c: New test.
* gcc.dg/torture/movllt.c: New test.
* gcc.dg/torture/movlltu.c: New test.
* gcc.dg/torture/movlne.c: New test.
Robin Dapp [Tue, 21 Nov 2023 11:51:12 +0000 (12:51 +0100)]
vect: Allow reduc_index != 1 for COND_OPs.
In PR112406 Tamar found another problem with COND_OP reductions.
I wrongly assumed that the reduction variable will always remain in
operand 1, just as we create the COND_OP in ifcvt. But of course,
addition being commutative, we are free to swap operand 1 and 2 and we
end up with e.g.
Robin Dapp [Mon, 20 Nov 2023 15:19:46 +0000 (16:19 +0100)]
RISC-V: testsuite: Add rv64 requirement for bug-9 and bug-14.
This adds an effective target requirement to compile the tests. Since
we disabled 64-bit indices on rv32 targets those tests should be
unsupported on rv32.
Patrick O'Neill [Thu, 2 Nov 2023 17:20:43 +0000 (10:20 -0700)]
gfortran: Rely on dg-do-what-default to avoid running pr85853.f90, pr107254.f90 and vect-alias-check-1.F90 on non-vector targets
Testcases in gfortran.dg/vect/vect.exp rely on
check_vect_support_and_set_flags to set dg-do-what-default and avoid
running vector tests on non-vector targets. The three testcases in this
patch overwrite the default with dg-do run which causes issues
for non-vector targets.
Removing the dg-do run directive resolves this issue for non-vector
targets (while still running the tests on vector targets).
Jonathan Wakely [Tue, 21 Nov 2023 11:49:22 +0000 (11:49 +0000)]
libstdc++: Do not declare strtok for C++26 freestanding (P2937R0)
This was recently approved for C++26.
We should define the __cpp_lib_freestanding_cstring macro in <string.h>
as well as <cstring>, but we do not currently install our own <string.h>
for most targets.
libstdc++-v3/ChangeLog:
* include/bits/version.def (freestanding_cstring): Add.
* include/bits/version.h: Regenerate.
* include/c_compatibility/string.h (strtok): Do not declare for
C++26 freestanding.
* include/c_global/cstring (strtok): Likewise.
* testsuite/21_strings/headers/cstring/version.cc: New test.
Jonathan Wakely [Mon, 20 Nov 2023 21:39:58 +0000 (21:39 +0000)]
libstdc++: Add freestanding feature test macros (P2407R5)
This C++26 change makes several classes "partially freestanding", but we
already fully supported them in freestanding mode. All we need to do is
define the new feature test macros and add tests for them.
libstdc++-v3/ChangeLog:
* include/bits/version.def (freestanding_algorithm)
(freestanding_array, freestanding_optional)
(freestanding_string_view, freestanding_variant): Add.
* include/bits/version.h: Regenerate.
* include/std/algorithm (__glibcxx_want_freestanding_algorithm):
Define.
* include/std/array (__glibcxx_want_freestanding_array):
Define.
* include/std/optional (__glibcxx_want_freestanding_optional):
Define.
* include/std/string_view
(__glibcxx_want_freestanding_string_view): Define.
* include/std/variant (__glibcxx_want_freestanding_variant):
Define.
* testsuite/20_util/optional/version.cc: Add checks for
__cpp_lib_freestanding_optional.
* testsuite/20_util/variant/version.cc: Add checks for
__cpp_lib_freestanding_variant.
* testsuite/23_containers/array/tuple_interface/get_neg.cc:
Adjust dg-error line numbers.
* testsuite/21_strings/basic_string_view/requirements/version.cc:
New test.
* testsuite/23_containers/array/requirements/version.cc: New
test.
* testsuite/25_algorithms/fill_n/requirements/version.cc: New
test.
* testsuite/25_algorithms/swap_ranges/requirements/version.cc:
New test.
Jonathan Wakely [Sat, 18 Nov 2023 21:07:47 +0000 (21:07 +0000)]
libstdc++: Add std::span::at for C++26 (P2821R5)
Also define the new feature test macros from P2833R2, indicating that
std::span and std::expected are supported for freestanding mode.
libstdc++-v3/ChangeLog:
* include/bits/version.def (freestanding_expected): New macro.
(span): Add C++26 value.
* include/bits/version.h: Regenerate.
* include/std/expected (__glibcxx_want_freestanding_expected):
Define.
* include/std/span (span::at): New member function.
* testsuite/20_util/expected/version.cc: Add checks for
__cpp_lib_freestanding_expected.
* testsuite/23_containers/span/2.cc: Moved to...
* testsuite/23_containers/span/version.cc: ...here. Add checks
for __cpp_lib_span in <span> as well as in <version>.
* testsuite/23_containers/span/1.cc: Removed.
* testsuite/23_containers/span/at.cc: New test.
Jonathan Wakely [Sat, 18 Nov 2023 21:09:53 +0000 (21:09 +0000)]
libstdc++: Fix std::tr2::dynamic_bitset support for alternate characters
libstdc++-v3/ChangeLog:
* include/tr2/dynamic_bitset (dynamic_bitset): Pass zero and one
characters to _M_copy_from_string.
* testsuite/tr2/dynamic_bitset/string.cc: New test.
This patch adds a target-independent aligned_register_operand
predicate, for use with register constraints that use filters
to impose an alignment. The definition deliberately jetisons
some of the historical baggage in general_operand.
gcc/
* common.md (aligned_register_operand): New predicate.
This patch makes IRA apply register filters when picking hard registers.
All the new code should be optimised away on targets that don't use
register filters. On targets that do use them, the new register_filters
bitfield is expected to be only a handful of bits.
Information about register filters is recorded in process_bb_node_lives.
The information isn't really related to liveness, but it's a convenient
point because (a) we've already built the allocno structures and
(b) we've already extracted the insn and preprocessed the constraints.
gcc/
* ira-int.h (ira_allocno): Add a register_filters field.
(ALLOCNO_REGISTER_FILTERS): New macro.
(ALLOCNO_SET_REGISTER_FILTERS): Likewise.
* ira-build.cc (ira_create_allocno): Initialize register_filters.
(create_cap_allocno): Propagate register_filters.
(propagate_allocno_info): Likewise.
(propagate_some_info_from_allocno): Likewise.
* ira-lives.cc (process_register_constraint_filters): New function.
(process_bb_node_lives): Use it to record register filter
information.
* ira-color.cc (assign_hard_reg): Check register filters.
(improve_allocation, fast_allocation): Likewise.
This patch makes LRA apply register filters. This plus the recog
change is enough for correct code generation, but a follow-on IRA
patch improves the allocation.
All the new code should be optimised away on targets that don't
use register filters. That's because get_register_filter just
wraps "return nullptr" on those targets.
The main (but simplest) part of this patch makes constrain_operands
take register filters into account.
The rest of the patch adds register filter information to
operand_alternative. Generally, if two register constraints
have different register filters, it's better if they're in separate
alternatives. However, the syntax doesn't enforce that, and we can't
assert it due to inline asms. So it's a choice between (a) adding
code to enforce consistent filters or (b) dealing with mixes of filters
in a conservatively correct way (in the sense of not allowing invalid
operands). The latter seems much easier.
The patch therefore adds a mask of the filters that apply
to at least one constraint in a given operand alternative.
A register is OK if it passes all of the filters in the mask.
gcc/
* recog.h (operand_alternative): Add a register_filters field.
(alternative_register_filters): New function.
* recog.cc (preprocess_constraints): Calculate the filters field.
(constrain_operands): Check register filters.
Add register filter operand to define_register_constraint
The main way of enforcing registers to be aligned is through
HARD_REGNO_MODE_OK. But this is a global property that applies
to all operands. A given (regno, mode) pair is either globally
valid or globally invalid.
This patch instead adds a way of specifying that individual operands
must be aligned. More generally, it allows constraints to specify
a C++ condition that the operand's REGNO must satisfy. The condition
must be invariant for a given set of target options, so that it can
be precomputed and cached as a HARD_REG_SET.
This information will be used in very compile-time-sensitive
parts of the compiler. A lot of the complication is in allowing
the information to be stored and tested without much memory cost,
and without impacting targets that don't use the feature.
Specifically:
- Constraints are encouraged to test the absolute REGNO rather than
an offset from the start of the containing class. For example,
all constraints for even registers should use the same condition,
such as "regno % 2 == 0". This requires the classes to start at
even register boundaries, but that's already an implicit
requirement due to things like the ira-costs.cc code that begins:
/* Some targets allow pseudos to be allocated to unaligned sequences
of hard registers. However, selecting an unaligned sequence can
unnecessarily restrict later allocations. So increase the cost of
unaligned hard regs to encourage the use of aligned hard regs. */
- Each unique condition is given a "filter identifier".
- The total number of filters is given by NUM_REGISTER_FILTERS,
defined automatically in insn-config.h. Structures can therefore use
a bitfield of NUM_REGISTER_FILTERS to represent a mask of filters.
- There is a new target global, target_constraints, that caches the
HARD_REG_SET for each filter.
- There is a function for looking up the HARD_REG_SET filter for a given
constraint and one for looking up the filter id. Both simply return
a constant on targets that don't use the feature.
- There are functions for testing a register against a specific filter,
or against a mask of filters.
This patch just adds the information. Later ones make use of it.
gcc/
* rtl.def (DEFINE_REGISTER_CONSTRAINT): Add an optional filter
operand.
* doc/md.texi (define_register_constraint): Document it.
* doc/tm.texi.in: Reference it in discussion about aligned registers.
* doc/tm.texi: Regenerate.
* gensupport.h (register_filters, get_register_filter_id): Declare.
* gensupport.cc (register_filter_map, register_filters): New variables.
(get_register_filter_id): New function.
(process_define_register_constraint): Likewise.
(process_rtx): Pass define_register_constraints to
process_define_register_constraint.
* genconfig.cc (main): Emit a definition of NUM_REGISTER_FILTERS.
* genpreds.cc (constraint_data): Add a filter field.
(add_constraint): Update accordingly.
(process_define_register_constraint): Pass the filter operand.
(write_init_reg_class_start_regs): New function.
(write_get_register_filter): Likewise.
(write_get_register_filter_id): Likewise.
(write_tm_preds_h): Write a definition of target_constraints,
plus helpers to test its contents. Write the get_register_filter*
functions.
(write_insn_preds_c): Write init_reg_class_start_regs.
* reginfo.cc (init_reg_class_start_regs): Declare.
(init_reg_sets): Call it.
* target-globals.h (this_target_constraints): Declare.
(target_globals): Add a constraints field.
(restore_target_globals): Update accordingly.
* target-globals.cc: Include tm_p.h.
(default_target_globals): Initialize the constraints field.
(save_target_globals): Handle the constraints field.
(target_globals::~target_globals): Likewise.
For vec_pack_trunc patterns there can be an ambiguity for the
source mode for BFmode vs HFmode. The vectorizer checks
the insns operand mode for this, the following makes forwprop
do the same. That of course doesn't help if the target supports
both conversions.
PR tree-optimization/112623
* tree-ssa-forwprop.cc (simplify_vector_constructor):
Check the source mode of the insn for vector pack/unpacks.
Richard Biener [Tue, 21 Nov 2023 08:50:54 +0000 (09:50 +0100)]
Move VF based dependence check
The following moves the check whether the maximum vectorization
factor determined by data dependence analysis is in conflict with
the chosen vectorization factor to after the point where we applied
both the SLP and the unrolling adjustment to the vectorization
factor. We check the latter before applying unrolling, but the
SLP adjustment can result in both missed optimization and wrong-code.
* tree-vect-loop.cc (vect_analyze_loop_2): Move check
of VF against max_vf until VF is final.
Jan Hubicka [Tue, 21 Nov 2023 14:17:16 +0000 (15:17 +0100)]
optimize std::vector::push_back
this patch speeds up the push_back at -O3 significantly by making the
reallocation to be inlined by default. _M_realloc_insert is general
insertion that takes iterator pointing to location where the value
should be inserted. As such it contains code to move other entries around
that is quite large.
Since appending to the end of array is common operation, I think we should
have specialized code for that. Sadly it is really hard to work out this
from IPA passes, since we basically care whether the iterator points to
the same place as the end pointer, which are both passed by reference.
This is inter-procedural value numbering that is quite out of reach.
I also added extra check making it clear that the new length of the vector
is non-zero. This saves extra conditionals. Again it is quite hard case
since _M_check_len seem to be able to return 0 if its parameter is 0.
This never happens here, but we are not able to propagate this early nor
at IPA stage.
libstdc++-v3/ChangeLog:
PR libstdc++/110287
PR middle-end/109811
PR middle-end/109849
* include/bits/stl_vector.h (_M_realloc_append): New member function.
(push_back): Use it.
* include/bits/vector.tcc: (emplace_back): Use it.
(_M_realloc_insert): Let compiler know that new vector size is non-zero.
(_M_realloc_append): New member function.
Tamar Christina [Tue, 21 Nov 2023 13:21:39 +0000 (13:21 +0000)]
AArch64: only emit mismatch error when features would be disabled.
At the moment we emit a warning whenever you specify both -march and -mcpu
and the architecture of them differ. The idea originally was that the user may
not be aware of this change.
However this has a few problems:
1. Architecture revisions is not an observable part of the architecture,
extensions are. Starting with GCC 14 we have therefore relaxed the rule that
all extensions can be enabled at any architecture level. Therefore it's
incorrect, or at least not useful to keep the check on architecture.
2. It's problematic in Makefiles and other build systems, where you want to
for certain files enable CPU specific builds. i.e. you may be by default
building for -march=armv8-a but for some file for -mcpu=neoverse-n1. Since
there's no easy way to remove the earlier options we end up warning and
there's no way to disable just this warning. Build systems compiling with
-Werror face an issue in this case that compiling with GCC is needlessly
hard.
3. It doesn't actually warn for cases that may lead to issues, so e.g.
-march=armv8.2-a+sve -mcpu=neoverse-n1 does not give a warning that SVE would
be disabled.
For this reason I have one of two proposals:
1. Just remove this warning all together.
2. Rework the warning based on extensions and only warn when features would be
disabled by the presence of the -mcpu. This is the approach this patch has
taken.
As examples:
> aarch64-none-linux-gnu-gcc -march=armv8.2-a+sve -mcpu=neoverse-n1
cc1: warning: switch ‘-mcpu=neoverse-n1’ conflicts with ‘-march=armv8.2-a+sve’ switch and resulted in options +crc+sve+norcpc+nodotprod being added .arch armv8.2-a+crc+sve
The one remaining issue here is that if both -march and -mcpu are specified we
pick the -march. This is not particularly obvious and for the use case to be
more useful I think it makes sense to pick the CPU's arch?
I did not make that change in the patch as it changes semantics.
Note that I can't write a test for this because dg-warning expects warnings to
be at a particular line and doesn't support warnings at the "global" level.
Tamar Christina [Tue, 21 Nov 2023 13:20:39 +0000 (13:20 +0000)]
AArch64: Add new generic-armv8-a CPU and make it the default.
This patch adds a new generic scheduling model "generic-armv8-a" and makes it
the default for all Armv8 architectures.
-mcpu=generic and -mtune=generic is kept around for those that really want the
previous cost model.
This shows on SPECCPU 2017 the following:
generic: SPECINT 1.0% improvement in geomean, SPECFP -0.6%. The SPECFP is due
to fotonik3d_r where we vectorize an FP calculation that only ever
needs one lane of the result. This I believe is a generic costing bug
but at the moment we can't change costs of FP and INT independently.
So will defer updating that cost to stage3 after Richard's other
costing updates land.
generic SVE: SPECINT 1.1% improvement in geomean, SPECFP 0.7% improvement.
gcc/ChangeLog:
PR target/111370
* config/aarch64/aarch64-arches.def (armv8-9, armv8-a, armv8.1-a,
armv8.2-a, armv8.3-a, armv8.4-a, armv8.5-a, armv8.6-a, armv8.7-a,
armv8.8-a): Update to generic_armv8_a.
* config/aarch64/aarch64-cores.def (generic-armv8-a): New.
* config/aarch64/aarch64-tune.md: Regenerate.
* config/aarch64/aarch64.cc: Include generic_armv8_a.h
* config/aarch64/aarch64.h (TARGET_CPU_DEFAULT): Change to
TARGET_CPU_generic_armv8_a.
* config/aarch64/tuning_models/generic_armv8_a.h: New file.
Tamar Christina [Tue, 21 Nov 2023 13:19:36 +0000 (13:19 +0000)]
AArch64: Refactor costs models to different files.
This patch series attempts to move the generic cost model in AArch64 to a new
and modern generic standard. The current standard is quite old and generates
very suboptimal code out of the box for user of GCC.
The goal is for the new cost model to be beneficial on newer/current Arm
Microarchitectures while not being too negative for older ones.
It does not change any core specific optimization. The final changes reflect
both performance optimizations and size optimizations.
This first patch just re-organizes the cost structures to their own files.
The AArch64.cc file has gotten very big and it's hard to follow.
No functional changes are expected from this change. Note that since all the
structures have private visibility I've put them in header files instead.
gcc/ChangeLog:
PR target/111370
* config/aarch64/aarch64.cc (generic_addrcost_table,
exynosm1_addrcost_table,
xgene1_addrcost_table,
thunderx2t99_addrcost_table,
thunderx3t110_addrcost_table,
tsv110_addrcost_table,
qdf24xx_addrcost_table,
a64fx_addrcost_table,
neoversev1_addrcost_table,
neoversen2_addrcost_table,
neoversev2_addrcost_table,
generic_regmove_cost,
cortexa57_regmove_cost,
cortexa53_regmove_cost,
exynosm1_regmove_cost,
thunderx_regmove_cost,
xgene1_regmove_cost,
qdf24xx_regmove_cost,
thunderx2t99_regmove_cost,
thunderx3t110_regmove_cost,
tsv110_regmove_cost,
a64fx_regmove_cost,
neoversen2_regmove_cost,
neoversev1_regmove_cost,
neoversev2_regmove_cost,
generic_vector_cost,
a64fx_vector_cost,
qdf24xx_vector_cost,
thunderx_vector_cost,
tsv110_vector_cost,
cortexa57_vector_cost,
exynosm1_vector_cost,
xgene1_vector_cost,
thunderx2t99_vector_cost,
thunderx3t110_vector_cost,
ampere1_vector_cost,
generic_branch_cost,
generic_tunings,
cortexa35_tunings,
cortexa53_tunings,
cortexa57_tunings,
cortexa72_tunings,
cortexa73_tunings,
exynosm1_tunings,
thunderxt88_tunings,
thunderx_tunings,
tsv110_tunings,
xgene1_tunings,
emag_tunings,
qdf24xx_tunings,
saphira_tunings,
thunderx2t99_tunings,
thunderx3t110_tunings,
neoversen1_tunings,
ampere1_tunings,
ampere1a_tunings,
neoversev1_vector_cost,
neoversev1_tunings,
neoverse512tvb_vector_cost,
neoverse512tvb_tunings,
neoversen2_vector_cost,
neoversen2_tunings,
neoversev2_vector_cost,
neoversev2_tunings
a64fx_tunings): Split into own files.
* config/aarch64/tuning_models/a64fx.h: New file.
* config/aarch64/tuning_models/ampere1.h: New file.
* config/aarch64/tuning_models/ampere1a.h: New file.
* config/aarch64/tuning_models/cortexa35.h: New file.
* config/aarch64/tuning_models/cortexa53.h: New file.
* config/aarch64/tuning_models/cortexa57.h: New file.
* config/aarch64/tuning_models/cortexa72.h: New file.
* config/aarch64/tuning_models/cortexa73.h: New file.
* config/aarch64/tuning_models/emag.h: New file.
* config/aarch64/tuning_models/exynosm1.h: New file.
* config/aarch64/tuning_models/generic.h: New file.
* config/aarch64/tuning_models/neoverse512tvb.h: New file.
* config/aarch64/tuning_models/neoversen1.h: New file.
* config/aarch64/tuning_models/neoversen2.h: New file.
* config/aarch64/tuning_models/neoversev1.h: New file.
* config/aarch64/tuning_models/neoversev2.h: New file.
* config/aarch64/tuning_models/qdf24xx.h: New file.
* config/aarch64/tuning_models/saphira.h: New file.
* config/aarch64/tuning_models/thunderx.h: New file.
* config/aarch64/tuning_models/thunderx2t99.h: New file.
* config/aarch64/tuning_models/thunderx3t110.h: New file.
* config/aarch64/tuning_models/thunderxt88.h: New file.
* config/aarch64/tuning_models/tsv110.h: New file.
* config/aarch64/tuning_models/xgene1.h: New file.
Tamar Christina [Tue, 21 Nov 2023 13:17:17 +0000 (13:17 +0000)]
AArch64: Add pattern for unsigned widenings (uxtl) to zip{1,2}
This changes unpack instructions to use zip{1,2} when doing a zero-extending
widening operation. Permutes generally have a higher throughput than the
widening operations. Zeros are shuffled into the top half of the registers.
The testcase
void d2 (unsigned * restrict a, unsigned short *b, int n)
{
for (int i = 0; i < (n & -8); i++)
a[i] = b[i];
}
* gcc.target/aarch64/simd/vmovl_high_1.c: Update codegen.
* gcc.target/aarch64/uxtl-combine-1.c: New test.
* gcc.target/aarch64/uxtl-combine-2.c: New test.
* gcc.target/aarch64/uxtl-combine-3.c: New test.
* gcc.target/aarch64/uxtl-combine-4.c: New test.
* gcc.target/aarch64/uxtl-combine-5.c: New test.
* gcc.target/aarch64/uxtl-combine-6.c: New test.
This seems to be because the vectorizer thinks the vector transfers are free:
x1_4 + x2_6 1 times vector_stmt costs 0 in body
x1_4 + x2_6 1 times vec_to_scalar costs 0 in body
This happens because the stmt it's using to get the cost of register transfers
for the given type happens to be one feeding into a MUL. we incorrectly
discount the + for the register transfer.
This is fixed by guarding the check for aarch64_multiply_add_p with a kind
check and only do it for scalar_stmt and vector_stmt.
I'm sending this separate to my patch series but it's required for it.
It also seems to fix overvectorization cases in fotonik3d_r in SPECCPU 2017.
Sebastian Huber [Mon, 20 Nov 2023 14:26:38 +0000 (15:26 +0100)]
gcov: Fix integer types in gen_counter_update()
This change fixes issues like this:
gcc.dg/gomp/pr27573.c: In function ‘main._omp_fn.0’:
gcc.dg/gomp/pr27573.c:19:1: error: non-trivial conversion in ‘ssa_name’
19 | }
| ^
long int
long unsigned int
# .MEM_19 = VDEF <.MEM_18>
__gcov7.main._omp_fn.0[0] = PROF_time_profile_12;
during IPA pass: profile
gcc.dg/gomp/pr27573.c:19:1: internal compiler error: verify_gimple failed
gcc/ChangeLog:
PR middle-end/112634
* tree-profile.cc (gen_assign_counter_update): Cast the unsigned result type of
__atomic_add_fetch() to the signed counter type.
(gen_counter_update): Fix formatting.
Eric Botcazou [Fri, 20 Oct 2023 08:26:23 +0000 (10:26 +0200)]
ada: Fix issue with indefinite vector of overaligned unconstrained array
The problem is that the aligning machinery is not consistently triggered,
depending on whether a constrained view or the nominal unconstrained view
of the element type is used to perform the allocations and deallocations.
gcc/ada/
* gcc-interface/decl.cc (gnat_to_gnu_entity) <E_Array_Subtype>: Put
the alignment directly on the type in the constrained case too.
* gcc-interface/utils.cc (maybe_pad_type): For an array type, take
the alignment of the element type as the original alignment.
Gary Dismukes [Thu, 2 Nov 2023 23:36:12 +0000 (23:36 +0000)]
ada: Compiler crash on container aggregate with loop_parameter_specifications
The compiler crashes on a container aggregate with more than one
iterated_element_association given by a loop_parameter_specification.
In such a case, the tree contains N_Iterated_Component_Association
nodes rather than N_Iterated_Element_Association nodes, and the code
for handling those needs to obtain the bounds from the Discrete_Choices
field of each N_Iterated_Component_Association rather than assuming
that the association has a normal list of choices.
gcc/ada/
* sem_aggr.adb (Resolve_Container_Aggregate): In the case where Comp
is an N_Iterated_Component_Association, pick up Discrete_Choices rather
than Choices.
Eric Botcazou [Thu, 2 Nov 2023 14:05:06 +0000 (15:05 +0100)]
ada: Another couple of cleanups in the finalization machinery
For package specs and bodies that need finalizers, Build_Finalizer is
invoked from the Standard scope so it needs to adjust the scope stack
before creating new objects; this changes it to do so only once.
For other kinds of scopes, it is invoked from Expand_Cleanup_Actions,
which assumes that the correct scope is already on the stack; that's
why Cleanup_Scopes adjusts the scope stack explicitly, but it should
use Pop_Scope instead of End_Scope to do it.
gcc/ada/
* exp_ch7.adb (Build_Finalizer): For package specs and bodies, push
and pop the specs onto the scope stack only once.
* inline.adb (Cleanup_Scopes): Call Pop_Scope instead of End_Scope.
Steve Baird [Wed, 1 Nov 2023 21:39:35 +0000 (14:39 -0700)]
ada: Deep delta aggregates in postconditions
Fix a bug in handling array-valued deep delta aggregates occurring in
postconditions. The bug could result in a spurious compilation failure.
gcc/ada/
* sem_aggr.adb (Resolve_Delta_Array_Aggregate): In the case of a
deep delta choice, the expected type for the expression will
typically not be the component type of the array type, so a call
to Analyze_And_Resolve that assumes otherwise would be an error.
It turns out that such a call, while wrong, is usually harmless
because the expression has already been marked as analyzed. This
doesn't work if the aggregate occurs in a postcondition and, in
any case, we don't want to rely on this. So do not perform the
call in the deep case.
Eric Botcazou [Tue, 31 Oct 2023 16:49:47 +0000 (17:49 +0100)]
ada: Small consistency fix for -gnatwv warning
The goal is to arrange for the warning to be issued consistently between
objects whose address is taken and objects whose address is not taken.
gcc/ada/
* sem_warn.adb (Check_References.Type_OK_For_No_Value_Assigned):
New predicate.
(Check_References): For Warn_On_No_Value_Assigned, use the same test
on the type in the address-not-taken and default cases.
Gary Dismukes [Tue, 31 Oct 2023 19:50:46 +0000 (19:50 +0000)]
ada: Compiler error reporting illegal prefix on legal loop iterator with "in"
During semantic analysis, the compiler fails to determine the cursor type
in the case of a generalized iterator loop with "in", in the case where the
iterator type has a parent type that is a controlled type (for example) and
its ancestor iterator interface type is given after as a progenitor. It also
improperly determines the ancestor interface type during expansion (within
Expand_Iterator_Loop_Over_Container), for both "in" and "of" iterator forms.
The FE was assuming that the iterator interface is simply the parent type
of the iterator type, but that type can occur later in the interface list,
or be inherited. A new function is added that properly locates a type's
iterator interface ancestor, if any, and is called for analysis and expansion.
gcc/ada/
* exp_ch5.adb (Expand_Iterator_Loop_Over_Container): Retrieve the
iteration type's iteration interface progenitor via
Iterator_Interface_Ancestor, in the case of both "in" and "of"
iterators. Narrow the scope of Pack, so it's declared and
initialized only within the code related to "of" iterators, and
change its name to Cont_Type_Pack. Adjust comments.
* sem_ch5.adb (Get_Cursor_Type): In the case of a derived type,
retrieve the iteration type's iterator interface progenitor (if it
exists) via Iterator_Interface_Ancestor rather than assuming that
the parent type is the interface progenitor.
* sem_util.ads (Iterator_Interface_Ancestor): New function.
* sem_util.adb (Iterator_Interface_Ancestor): New function
returning a type's associated iterator interface type, if any, by
collecting and traversing the type's interfaces.
Eric Botcazou [Tue, 31 Oct 2023 16:27:15 +0000 (17:27 +0100)]
ada: Fix internal error on 'Address of task component
This happens when the prefix of the selected component is of an access type,
i.e. there is an implicit dereference. because the prefix is not resolved.
gcc/ada/
* sem_attr.adb (Resolve_Attribute) <Attribute_Address>: Remove the
bypass for prefixes with task type.
Eric Botcazou [Fri, 27 Oct 2023 09:34:31 +0000 (11:34 +0200)]
ada: Further cleanup in finalization machinery
The bodies of generic units are instantiated separately by GNAT at the end
of the processing of the compilation unit. This requires the deferral of
the generation of cleanups and finalization actions in enclosing scopes,
except for instantiations in generic units where they are not generated.
The criterion used to detect this latter case is Inside_A_Generic, but this
global variable is not properly updated during the instantiation of generic
bodies, leading to problems with nested instantiations, so it is changed to
Expander_Active instead. As a matter of fact, the exact same idiom is used
a few lines above to clear the Needs_Body variable.
gcc/ada/
* sem_ch12.adb (Analyze_Package_Instantiation): Test Expander_Active
to detect generic contexts for the generation of cleanup actions.
Justin Squirek [Fri, 27 Oct 2023 00:08:07 +0000 (00:08 +0000)]
ada: Fix string indexing within GNAT.Calendar.Time_IO.Value
The patch fixes an issue in the compiler whereby calls to
GNAT.Calendar.Time_IO.Value where the actual for formal String Date with
indexing starting at any value besides one would result in a spurious runtime
exception.
gcc/ada/
* libgnat/g-catiio.adb (Value): Modify conditionals to use 'Last
instead of 'Length
Eric Botcazou [Tue, 24 Oct 2023 07:50:25 +0000 (09:50 +0200)]
ada: Further cleanup in finalization machinery
This removes the specific treatment of transient scopes in initialization
procedures, which is obsolete.
gcc/ada/
* exp_aggr.adb (Convert_To_Assignments): Do not treat initialization
procedures specially when it comes to creating a transient scope.
* exp_ch7.adb (Build_Finalizer.Process_Declarations): Likewise.
* exp_util.adb (Requires_Cleanup_Actions): Likewise.
Doug Rupp [Thu, 12 Oct 2023 19:31:46 +0000 (12:31 -0700)]
ada: Use CLOCK_MONOTONIC on VxWorks
The monotonic clock keeps track of the time that has elapsed since
system startup; that is, the value returned by clock_gettime() is the
amount of time (in seconds and nanoseconds) that has passed since the
system booted. The monotonic clock cannot be reset. As a result,
time interval measurements made relative to the monotonic clock are
not subject to errors resulting from the clock time being unexpectedly
adjusted between the interval start and end.
gcc/ada/
* s-oscons-tmplt.c: #define CLOCK_RT_Ada "CLOCK_MONOTONIC" for
__vxworks
Steve Baird [Fri, 22 Sep 2023 18:54:13 +0000 (11:54 -0700)]
ada: Deep delta aggregates
Add support for "deep" delta aggregates, a GNAT-defined language extension
conditionally enabled via the -gnatX0 switch. In a deep delta aggregate, a
delta choice may specify a subcomponent (as opposed to just a component).
gcc/ada/
* par.adb: Add new Boolean variable Inside_Delta_Aggregate.
* par-ch4.adb (P_Simple_Expression): Add support for a deep delta
aggregate choice. We turn a sequence of selectors into a peculiar
tree. We build a component (Indexed or Selected) whose prefix is
another such component, etc. The leftmost prefix at the bottom of
the tree has a "name" which is the first selector, without any
further prefix. For something like "with delta (1)(2) => 3" where
the type of the aggregate is an array of arrays of integers, we'll
build an N_Indexed_Component whose prefix is an integer literal 1.
This is consistent with the trees built for "regular"
(Ada-defined) delta aggregates.
* sem_aggr.adb (Is_Deep_Choice, Is_Root_Prefix_Of_Deep_Choice):
New queries.
(Resolve_Deep_Delta_Assoc): new procedure.
(Resolve_Delta_Array_Aggregate): call Resolve_Deep_Delta_Assoc in
deep case.
(Resolve_Delta_Record_Aggregate): call Resolve_Deep_Delta_Assoc in
deep case.
(Get_Component_Type): new function replaces old Get_Component
function.
* sem_aggr.ads (Is_Deep_Choice, Is_Root_Prefix_Of_Deep_Choice):
New queries.
* exp_aggr.adb (Expand_Delta_Array_Aggregate): add nested function
Make_Array_Delta_Assignment_LHS; call it instead of
Make_Indexed_Component.
(Expand_Delta_Record_Aggregate): add nested function
Make_Record_Delta_Assignment_LHS; call it instead of
Make_Selected_Component.
* exp_spark.adb (Expand_SPARK_Delta_Or_Update): Insert range
checks for indexes in deep delta aggregates.