Commit beed8fc0 by Alexandre Oliva Committed by Alexandre Oliva

Introduce H8SX support.

* expr.c (expand_strcpy): Renamed and moved to...
* builtins.c (expand_movstr): ... here.  Tweak.
(expand_builtin_strcpy): Adjust.  Use movstr if len can't be
computed or has side effects.
(expand_builtin_stpcpy): Likewise.  Use strcpy if return value is
unused, or if mempcpy fails.  Adjust the return value in the
latter case.  Use movstr if everything else fails.
* doc/md.texi (movstr): Document.
(movmemM, clrmemM): Fix explanation of memory block operands.
* config/h8300/h8300.md (stpcpy): Renamed to...
(movstr): ... this.  Adjust.
2004-07-07  Alexandre Oliva  <aoliva@redhat.com>
* config/h8300/h8300.md: Rename movstr*, except for movstrict*, to
movmem* and clrstr* to clrmem*.
2004-06-27  Alexandre Oliva  <aoliva@redhat.com>
* config/h8300/h8300.c (h8300_reg_class_from_letter): Map 'D' to
GENERAL_REGS, always.
(h8300_swap_into_er6, h8300_swap_into_er6): Handle the case of
getting the stack pointer as addr.
* config/h8300/h8300.h (PREDICATE_CODES): Remove constant rtxes
from general_operand_dst.
* config/h8300/h8300.md (movmd_internal_normal): New, normal-mode
variant of...
(movmd_internal): ... this.  Add modes to operands.  Disparage `D'
instead of requiring it to match only before reload.
(stpcpy_internal_normal): New, normal-mode variant of...
(stpcpy_internal): ... this.  Add modes to operands.  Disparage
`D' instead of requiring it to match only before reload.
* config/h8300/h8300-protos.h (h8300_legitimate_address_p): Add
mode argument.
* config/h8300/h8300.h (GO_IF_LEGITIMATE_ADDRESS): Pass it to...
* config/h8300/h8300.c (h8300_legitimate_address_p): Pass it to
h8300_get_index.
* config/h8300/h8300.md (attr type): Add call.
(attr can_delay): If type is call, set it no.
(call, call_value): Set type to call.
2004-06-21  Alexandre Oliva  <aoliva@redhat.com>
* config/h8300/h8300.md (logicalhi3_sn, logicalsi3_sn): New.
2004-06-16  Alexandre Oliva  <aoliva@redhat.com>
* tree.c (get_narrower): Don't narrow integral types into
non-integral types.
* config/h8300/h8300.c (h8300_expand_epilogue): Initialize
frame_size *before* the first use.
* config/h8300/h8300.md (movstrictqi): Reintroduce post-increment
on input.
(peephole2): Don't widen instructions that push SP.  Move
decrement of SP to the end of all stm-generating peepholes.
2003-07-24  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.md (insv): Prefer to use AND to clear a bitfield
and OR to set it to all ones.
2003-07-24  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.md (can_delay): Default to "no" for bit branches.
(call, call_value): Set can_delay to "no".
2003-07-22  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.md (extzv): Make subreg check more robust.
2003-07-21  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.md (*brabit): Remove.
* config/h8300/h8300.md (*brabc, *brabs): Remove mode from
zero_extract.  Use bit_memory_operand as the predicate for
operand 1 and 'WU' as the constraint.  Check the difference
between the base length and the final one when deciding which
type of branch to use.
2003-07-21  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.md (extzv): Remove mode from operands 0 and 1.
Use convert_move to extend the result for TARGET_H8300SX.  Check
for QImode memory references.  Optimize the case where the
destination is a paradoxical subreg.
2003-07-21  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.md (*movsf_h8sx): Add an r <- G alternative.
* config/h8300/h8300.md (andqi): Remove bclr from h8sx version.
2003-07-21  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.md: Include mova.md
(length_table): Add mova and mova_zero.
* config/h8300/h8300.c (print_operand): Handle '%o'.  Print a length
after all constant addresses for '%R', '%X', '%T' and '%S'.
(h8300_mova_length): New function.
(h8300_insn_length_from_table): Use it to handle mova and mova_zero.
* config/h8300/t-h8300 (mova.md): Generate from genmova.sh.  Add to
dependencies for s-config, etc.
* config/h8300/gemova.sh: New file.
* config/h8300/mova.md: Generated.
2003-07-20  Alexandre Oliva  <aoliva@redhat.com>
* config/h8300/h8300.c (h8300_bitfield_length): New.
(nibble_operand): Adjust.
(h8300_binary_length): Handle conditional binary op.
(h8300_insn_length_from_table): Handle bitfield and bitbranch.
* config/h8300/h8300.h: Change constraints W# and Y# to P#>X and
P#<X, respectively.  The original P is now IP4>X.  Introduced P#>0
and P#<0, unused so far.  W and Y are now prefixes to multi-letter
constraints.  WU is introduced as a variant of U that requires a
mem, and is therefore considered an EXTRA_MEMORY_CONSTRAINT.
* config/h8300/h8300.md (attr type): Added bitbranch.
(attr length_table): Added bitfield and bitbranch.
(attr length): Compute bitbranch length.
(andqi): Separate pattern for H8300SX.  Use bfld for loading the
least-significant bit of a byte.
(brabit, brabc, brabs): New.
(insv, extzv): Emit bfst and bfld on H8300SX.
(bfld, bfst, seq, sne): New.
(bstzhireg, cmpstz, bstz, bistz): New.
(cmpcondbset, condbset, cmpcondbclr, condbclr): New.
(cmpcondbsetreg, condbsetreg, cmpcondbclrreg, condbclrreg): New.
2003-07-11  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.c (h8sx_binary_memory_operator): New function.
(h8sx_unary_memory_operator): New function.
* config/h8300/h8300.h (EXTRA_MEMORY_CONSTRAINT): Disable.
(PREDICATE_CODES): Add h8sx_{unary,binary}_memory_operator.
* config/h8300/h8300.md: Add peepholes to combine reloads and
arithmetic insns.
2003-07-10  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h830.md (cmpqi): Use 'i' rather than 'n' in constraints.
(*cmphi_h8300hs, *addqi3, *addhi3_h8sx, subhi3): Likewise.
(and?i, ior?i, xor?i): Likewise.
2003-07-10  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.c: Move enums and prototypes to head of file.
Various whitespace fixes.
(h8300_constant_length): New function, split out from...
(h8300_displacement_size): ...here.  Rename h8300_displacement_length.
(h8300_classify_operand): Use IN_RANGE.
(h8300_classify_operand): Use h8300_constant_length.
(h8300_short_move_mem_p): Tighten size check.
(h8sx_mergeable_memrefs_p): Tighten equality check.
2003-06-30  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.h (TARGET_CPU_CPP_BUILTINS): Define __H8300SX__
for -msx.
* config/h8300/crti.asm: Use .h8300sx or .h8300sxn for -msx code.
* config/h8300/crtn.asm: Likewise.
* config/h8300/lib1funcs.asm: Likewise.  Use 32-bit pointers
if __H8300SX__ is defined.
2003-06-27  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300-protos.h (h8300_get_index): Add mode parameter.
* config/h8300/h8300.h (GO_IF_LEGITIMATE_ADDRESS): Update accordingly.
(GO_IF_MODE_DEPENDENT_ADDRESS): Treat POST_DEC, PRE_INC and indexed
addresses as mode-dependent.
* config/h8300/h8300.c (print_operand_address): Update call to
h8300_get_index.
(h8300_get_index): Take a mode argument.  Rework to fix an
earlier misunderstanding.
2003-06-26  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.c (zero_extendqisi2): Force the source operand
into a register if TARGET_H8300SX.
(*zero_extendqisi2_h8300hs, *extendqisi2_h8300): Disable for
TARGET_H8300SX.  Also disable related define_splits.
(*zero_extendqisi2_h8sx, *extendqisi2_h8sx): New patterns.
2003-06-23  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.c (h8300_rtx_costs): Add h8sx handling.
2003-06-20  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.h (OK_FOR_Z): New macro.
(EXTRA_CONSTRAINT_STR): Check it.
* config/h8300/h8300.c (h8300_classify_operand): Accept null
class arguments.
(h8300_insn_length_from_table): Handle LENGTH_TABLE_MOV_IMM4.
* config/h8300/h8300.md (length_table): Add mov_imm4.
(movqi, movhi): Add Z <- W4 alternatives to h8sx patterns.
2003-06-20  Richard Sandiford  <rsandifo@redhat.com>
* genattrtab.c (write_eligible_delay): Allow candidate_insn to
be a label.
* config/h8300/h8300.h (DELAY_SLOT_LENGTH): New macro.
* config/h8300/h8300.c (h8300_reorg): New function.
(TARGET_MACHINE_DEPENDENT_REORG): Define.
* config/h8300/h8300.md (length): Subtract the length of the
delay slot from (pc) when checking the range of forward branches.
(delay_slot, can_delay): New attributes.
(define_delay): Add bra/s handling.
(movmd_internal, return_h8sx, *return_1): Set can_delay to no.
(jump): Add delayed-branch handling.
2003-06-17  Richard Sandiford  <rsandifo@redhat.com>
* expr.c (expand_strcpy): New function.
* builtins.c (expand_builtin_strcpy): Fall back on expand_strcpy.
(expand_builtin_stpcpy): Likewise.
* config/h8300/h8300-protos.h (h8sx_split_movmd): Remove.
(h8300_swap_into_er6, h8300_swap_out_of_er6): Declare.
* config/h8300/h8300.c (h8300_reg_class_from_letter): Tweak 'd'
handling to improve register allocation for -fno-omit-frame-pointer.
(h8sx_split_movmd): Delete, moving er6 handling into...
(h8300_swap_into_er6, h8300_swap_out_of_er6): ...these new functions.
* config/h8300/h8300.md (UNSPEC_STPCPY): New unspec constant.
(movmd): Add calls to copy_rtx.
(movmd_internal): In the second alternative, allow the initial and
final destination registers to be different .  Update the splitter
accordingly.  Call h8300_swap_into_er6 and h8300_swap_out_of_er6
instead of h8sx_split_movmd.
(stpcpy, movsd): New expanders.
(movsd_internal): New define_insn.
2003-06-13  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300-protos.h (h8300_reg_class_from_letter): Declare.
(h8sx_emit_movmd, h8sx_split_movmd): Declare.
* config/h8300/h8300.h (reg_class): Add COUNTER_REGS, SOURCE_REGS
and DESTINATION_REGS.
(REG_CLASS_NAMES, REG_CLASS_CONTENTS): Update accordingly.
(REGNO_REG_CLASS): Map er4, er5 and er6 to the new classes.
(REG_CLASS_FROM_LETTER): Use h8300_reg_class_from_letter.
(h8300_move_ratio): Declare.
(MOVE_RATIO): Use it.
* config/h8300/h8300.c (h8300_move_ratio): New variable.
(h8300_init_once): Initialize it.
(h8300_reg_class_from_letter): New function.
(print_operand): Add an 'm' prefix for printing ".b", ".w" or ".l".
(h8sx_emit_movmd, h8sx_split_movmd): New functions.
* config/h8300/h8300.md (UNSPEC_MOVMD): New unspec constant.
(COUNTER_REG, SOURCE_REG, DESTINATION_REG): New register constants.
(movstrsi, movmd): New expanders.
(movmd_internal): New insn.
2003-06-06  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.h (EXTRA_MEMORY_CONSTRAINT): Define.
2003-06-04  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/elf.h (LINK_SPEC): Use -m h8300sxnelf for -msx -mn.
* config/h8300/h8300.c (asm_file_start): Use .h8300sxn likewise.
2003-06-03  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.c (nibble_operand): Fix warning.
* config/h8300/h8300.md (movstricthi): Set adjust_length to no.
(movsi_h8sx): Likewise here and the normal h8sx movhi pattern.
(movsf_h8300h): Disable for TARGET_H8300SX.
2003-06-03  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.h (PREDICATE_CODES): Add h8300_ldm_parallel,
h8300_stm_parallel and h8300_return_parallel.
* config/h8300/h8300.c (h8300_push_pop, h8300_stack_offset_p,
h8300_ldm_stm_regno, h8300_ldm_stm_parallel, h8300_ldm_parallel,
h8300_stm_parallel, h8300_return_parallel): New functions.
(h8300_expand_prologue): Don't enforce ldm/stm register alignment
if TARGET_H8300SX.  Use h8300_push_pop.
(h8300_expand_epilogue): Likewise.  Try to merge the return insn
and final pop when generating h8sx code.  Always emit some form
of return insn.
* config/h8300/h8300.md: Don't enforce register alignment in
stm peepholes if TARGET_H8300SX.
(ldm_h8300s, stm_h8300s, return_h8sx): New patterns.
(ldm_h8300s_[234], stm_h8300_[234]): Disable.
(epilogue): Expect h8300_expand_epilogue to emit a return insn.
2003-06-03  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/t-h8300 (MULTILIB_OPTIONS): Add a -msx multilib.
(MULTILIB_DIRNAMES): Add a directory for it.
(MULTILIB_MATCHES): Delete.
2003-05-28  Richard Sandiford  <rsandifo@redhat.com>
* final.c (walk_alter_subreg): Handle addresses with subregs
inside a ZERO_EXTEND or AND.
* config/h8300/h8300-protos.h (h8300_get_index): Declare.
* config/h8300/h8300.h (INDEX_REG_CLASS): Set to GENERAL_REGS
if TARGET_H8300SX.
(GO_IF_LEGITIMATE_ADDRESS): Use h8300_get_index.
* config/h8300/h8300.c (print_operand_address): Handle @(dd,RnL.b),
@(dd,Rn.w) and @(dd,ERn.L).
(h8300_displacement_size): Take the whole address as argument.
(h8300_classify_operand, h8300_short_move_mem_p): Adjust accordingly.
2003-05-28  Richard Sandiford  <rsandifo@redhat.com>
* config/mips/mips-protos.h (h8300_operands_match_p): Declare.
(h8sx_mergeable_memrefs_p): Declare.
* config/h8300/h8300.h (HAVE_POST_DECREMENT): Define to TARGET_H8300SX.
(HAVE_PRE_INCREMENT): Likewise.
(GO_IF_LEGITIMATE_ADDRESS): Accept pre/post increment/decrement
addresses for TARGET_H8300SX,
* config/h8300/h8300.c (print_operand_address): Deal with PRE_INC
and POST_DEC.
(movb_length_table, movl_length_table): New tables.
(movw_length_table): Define to movb_length_table.
(h8300_displacement_size): New, split out from...
(h8300_classify_address): ...here.  Handle pre/post inc/dec.
(h8300_short_immediate_length): Allow H8OP_MEM_COMPLEX operands.
(h8300_insn_length_from_table): Add cases for movb, movw and movl.
(h8sx_mergeable_memrefs_p, h8300_operands_match_p): New functions.
(output_plussi): Use add.l #xx:3,Rn and sub.l #xx:3,Rn for h8sx.
(compute_plussi_length, compute_plussi_cc): Update accordingly.
(h8sx_unary_shift_operator): Get the mode from the operator.
(binary_shift_operator): Likewise.
* config/h8300/h8300.md: If a peephole2 applies gen_lowpart to
a memory reference, check whether the reference is offsettable.
(length_table): Add movb, movw and movl.
(movqi): Add new h8sx pattern.  Don't force one operand to be a
register when generating h8sx code.
(movhi, movsi, movsf): Likewise.
(movstrictqi): Use the length_table attribute.
(movstricthi): Likewise.  Add h8sx alternative for mov.w #xx:3,Rn.
(addqi3): Split into a define_expand and define_insn.  Don't accept
memory operands in the expander.  Use h8300_operands_match_p to
check for matching operands in the define_insn.
(subqi3, negqi2, one_cmplqi2): Likewise.
(add[hs]i3): Don't accept memory operands in the expander.  Likewise
in any patterns that are unused in h8sx code.  In the h8sx patterns,
use h8300_operands_match_p to check whether operands match.
(sub[hs]i3, and[hi]3, ior[hs]i3, xor[hs]i3, neg[hsi]3,
one_cmpl[hs]i3): Likewise.
(andqi3, iorqi3, xorqi3): Likewise.  Don't call fix_bit_operand
in the expander.
2003-05-23  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300-protos.h (expand_a_shift): Return a bool.
(h8300_insn_length_from_table): Add a second parameter.
(output_h8sx_shift): Declare.
* config/h8300/h8300.h (OK_FOR_W, OK_FOR_Y): New macros.
(EXTRA_CONSTRAINT): Replace with...
(EXTRA_CONSTRAINT_STR): ...this.  Use OK_FOR_W and OK_FOR_Y.
(CONSTRAINT_LEN): Define, returning 2 for 'W' and 'Y'.
(PREDICATE_CODES): Add entries for h8sx_unary_shift_operator
and h8sx_binary_shift_operator.
* config/h8300/h8300.c (two_insn_adds_subs_operand): Return false
for TARGET_H8300SX.
(bit_operand): Replace use of EXTRA_CONSTRAINT with OK_FOR_U.
(bit_memory_operand, fix_bit_operand): Likewise.
(h8300_length_table_for_insn): Remove.
(h8300_classify_operand): Fix check for 16-bit operands in 32-bit
instructions.
(h8300_short_immediate_length, h8300_binary_length): New functions.
(h8300_insn_length_from_table): Add an opcodes parameter.  Rework.
(output_plussi): Use sub to add negative constants.
(compute_plussi_length): Adjust accordingly.
(h8sx_single_shift_type): New enum.
(h8sx_single_shift, h8sx_unary_shift_operator,
h8sx_binary_shift_operator, output_h8sx_shift): New functions.
(expand_a_shift, expand_a_rotate): Emit nothing if the shift is a
single h8sx instruction.  Return false in this case.
* config/h8300/h8300.md (length_table): Add short_immediate.
(length): Pass the operand array to h8300_insn_length_from_table.
(adjust_length): Assume "no" for insns with a length_table attribute.
(*cmphi_h8300hs, cmpsi): Add alternatives for #xx:3.
(*addhi3_h8300hs): Don't use for h8sx.
(*addhi3_h8sx): New pattern, with alternatives for add.w #xx:3
and sub.w #xx:3.
(ashl[qhs]i3, lshr[qhs]i3, ashr[qhs]i3, rotl[qhs]i3): Change operand
1's predicate to nonimmediate_operand.  Only skip default expansion
if expand_a_shift or expand_a_rotate returns true.  Add new patterns
for single h8sx shift instructions.
2003-05-22  Alexandre Oliva  <aoliva@redhat.com>
* config/h8300/h8300.c (nibble_operand): Split out of...
(reg_or_nibble_operand): ... this.
* config/h8300/h8300.h (PREDICATE_CODES): Added nibble_operand.
* config/h8300/h8300.md: (mulqihi3, mulhisi3, umulqihi3,
umulhisi3): Introduce expand, and introduce separate insns for
sign- or zero-extended REG and already-extended CONST_INT.
2003-05-20  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.c (h8300_unary_length): Fix miscounting.
* config/h8300/h8300.md (subqi3): Generalize for h8sx.
(subhi3): Likewise.  Don't accept immediates for operand 1.
Remove the early clobber from second alternative of the h8300s pattern.
(subsi3): Generalize for h8sx.  Force operand 2 into a register
on plain h8300 targets.
(subsi3_h8300): Use h8300_dst_operand for consistency with expander.
(subsi3_h8300h): Generalize for h8sx.
(one_cmplqi2, one_cmplhi2, one_cmplsi2): Likewise.
2003-05-19  Alexandre Oliva  <aoliva@redhat.com>
* config/h8300/h8300.c (reg_or_nibble_operand): New.
* config/h8300/h8300.h (PREDICATE_CODES): Adjust.
(TARGET_H8300SXMUL): New.
(CONST_OK_FOR_P): New.
(CONST_OK_FOR_LETTER_P): Adjust.
* config/h8300/h8300.md (mulqihi3, mulhisi3, umulqihi3,
umulhisi3): Accept 4-bit immediate on H8SX.
(mulhi3, mulsi3, smulsi3_highpart, umulsi3_highpart): New.
(udivsi3, divhi3, udivsi3, divsi3): New.
2003-05-19  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300-protos.h (h8300_insn_length_from_table): Declare.
* config/h8300/h8300.h (OK_FOR_Q): New macro.
(EXTRA_CONSTRAINT): Use it to check the 'Q' constraint.
(PREDICATE_CODES): Add h8300_src_operand and h8300_dst_operand.
Add ADDRESSOF to the bit_operand entry.
* config/h8300/h8300.c (h8300_dst_operand): New predicate.
(h8300_src_operand): Likewise.
(bit_operand): Check nonimmediate_operand rather than general_operand.
Accept any nonimmediate_operand in h8sx code.
(h8300_and_costs): Initialize operands[1].
(h8300_rtx_costs) <AND>: Return false if the operands aren't valid.
(h8300_operand_class): New enum.
(h8300_length_table): New typedef.
(addb_length_table, addw_length_table, addl_length_table,
logicl_length_table): New tables.
(logicb_length_table, logicw_length_table): New macros.
(h8300_classify_operand, h8300_length_from_table,
h8300_length_table_for_insn, h8300_unary_length,
h8300_insn_length_from_table): New functions.
(output_plussi): Only use adds and subs for register destinations.
Disable redundant clause.
(compute_plussi_cc): Likewise.
(compute_plussi_length): Likewise.  Use h8300_length_from_table
to work out the length of an insn.
(output_logical_op): Only use narrower immediate instructions
if the destination is a register.
(compute_logical_op_cc): Likewise.
(compute_logical_op_length): Likewise.  Use h8300_length_from_table.
(h8300_adjust_insn_length): Tighten check for reg<->mem moves.
* config/h8300/h8300.md (length_table): New attribute.
(length): When an instruction has a length_table attribute, use
h8300_insn_length_from_table to calculate its default length.
(cmpqi): Use h8300_dst_operand for the first operand and
h8300_src_operand for the second.
(cmphi, *cmphi_h8300hs, cmpsi, negqi2, neghi2, neghi2_h8300h, negsi2,
negsi2_h8300h, addqi3, addhi3, *addhi3_h8300, *addhi3_h8300hs, addsi3,
addsi_h8300, addsi_h8300h, andhi3, andsi3, iorhi3,
iorsi3, xorhi3, xorsi3): Likewise.
(andqi3): Use h8300_src_operand for operand 2.  Adjust the condition
so that it allows any combination of operands for TARGET_H8300SX.
(iorqi3, xorqi3): Likewise.
(cmpqi): Use the length_table attribute.
(*cmphi_h8300hs, cmpsi, addqi, *addhi3_h8300hs, andqi3, iorqi3,
xorqi3, negqi2, neghi2_h8300h, negsi2_h8300h): Likewise.
(cmpqi): Add 'Q' constraint.
(*cmphi_h8300hs, cmpsi, addqi, *addhi3_h8300hs, addsi_h8300h, andqi3,
iorqi3, xorqi3, negqi2, neghi2_h8300h, negsi2_h8300h): Likewise.
2003-05-14  Richard Sandiford  <rsandifo@redhat.com>
* config/h8300/h8300.h (MASK_H8300SX): New macro.
(TARGET_H8300S): True for both -ms and -msx.
(TARGET_H8300SX): New macro.
(TARGET_SWITCHES): Add entries for -msx and -mno-sx.
* config/h8300/h8300.c (asm_file_start): Write .h8300sx for -msx.
* config/h8300/elf.h (LINK_SPEC): Use -m h8300sxelf for -msx.
* config/h8300/t-h8300 (MULTILIB_MATCHES): Use -ms multilibs for -msx.
[Temporary change.]
2003-02-28  Alexandre Oliva  <aoliva@redhat.com>
* config/h8300/h8300.h (SIZE_TYPE, PTRDIFF_TYPE): Use short with
16-bit pointers and 32-bit ints.
* config/h8300/h8300.h (LEGITIMATE_CONSTANT_P): Accept
CONST_DOUBLE with mode no wider than SImode.
* config/h8300/h8300.md (extendqisi2_h8300): Add constraints for
output operand.
2003-02-27  Alexandre Oliva  <aoliva@redhat.com>
* config/h8300/h8300.c (general_operand_src): Match CONSTANT_P_RTX
or SUBREG thereof.
* config/h8300/h8300.h (PREDICATE_CODES): Adjust.
2003-02-22  Alexandre Oliva  <aoliva@redhat.com>
* config/h8300/h8300.c (dosize): Truncate sign * size to Pmode.

From-SVN: r84257
parent 5c121a1b
...@@ -2976,6 +2976,72 @@ expand_builtin_bcopy (tree arglist) ...@@ -2976,6 +2976,72 @@ expand_builtin_bcopy (tree arglist)
return expand_builtin_memmove (newarglist, const0_rtx, VOIDmode); return expand_builtin_memmove (newarglist, const0_rtx, VOIDmode);
} }
#ifndef HAVE_movstr
# define HAVE_movstr 0
# define CODE_FOR_movstr CODE_FOR_nothing
#endif
/* Expand into a movstr instruction, if one is available. Return 0 if
we failed, the caller should emit a normal call, otherwise try to
get the result in TARGET, if convenient. If ENDP is 0 return the
destination pointer, if ENDP is 1 return the end pointer ala
mempcpy, and if ENDP is 2 return the end pointer minus one ala
stpcpy. */
static rtx
expand_movstr (tree dest, tree src, rtx target, int endp)
{
rtx end;
rtx dest_mem;
rtx src_mem;
rtx insn;
const struct insn_data * data;
if (!HAVE_movstr)
return 0;
dest_mem = get_memory_rtx (dest);
src_mem = get_memory_rtx (src);
if (!endp)
{
target = force_reg (Pmode, XEXP (dest_mem, 0));
dest_mem = replace_equiv_address (dest_mem, target);
end = gen_reg_rtx (Pmode);
}
else
{
if (target == 0 || target == const0_rtx)
{
end = gen_reg_rtx (Pmode);
if (target == 0)
target = end;
}
else
end = target;
}
data = insn_data + CODE_FOR_movstr;
if (data->operand[0].mode != VOIDmode)
end = gen_lowpart (data->operand[0].mode, end);
insn = data->genfun (end, dest_mem, src_mem);
if (insn == 0)
abort ();
emit_insn (insn);
/* movstr is supposed to set end to the address of the NUL
terminator. If the caller requested a mempcpy-like return value,
adjust it. */
if (endp == 1 && target != const0_rtx)
emit_move_insn (target, plus_constant (gen_lowpart (GET_MODE (target),
end), 1));
return target;
}
/* Expand expression EXP, which is a call to the strcpy builtin. Return 0 /* Expand expression EXP, which is a call to the strcpy builtin. Return 0
if we failed the caller should emit a normal call, otherwise try to get if we failed the caller should emit a normal call, otherwise try to get
the result in TARGET, if convenient (and in mode MODE if that's the result in TARGET, if convenient (and in mode MODE if that's
...@@ -2996,12 +3062,14 @@ expand_builtin_strcpy (tree arglist, rtx target, enum machine_mode mode) ...@@ -2996,12 +3062,14 @@ expand_builtin_strcpy (tree arglist, rtx target, enum machine_mode mode)
if (operand_equal_p (src, dst, 0)) if (operand_equal_p (src, dst, 0))
return expand_expr (dst, target, mode, EXPAND_NORMAL); return expand_expr (dst, target, mode, EXPAND_NORMAL);
fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0;
len = c_strlen (src, 1); len = c_strlen (src, 1);
if (len == 0 || TREE_SIDE_EFFECTS (len)) if (len == 0 || TREE_SIDE_EFFECTS (len))
return expand_movstr (TREE_VALUE (arglist),
TREE_VALUE (TREE_CHAIN (arglist)),
target, /*endp=*/0);
fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0; return 0;
len = size_binop (PLUS_EXPR, len, ssize_int (1)); len = size_binop (PLUS_EXPR, len, ssize_int (1));
...@@ -3020,22 +3088,17 @@ expand_builtin_strcpy (tree arglist, rtx target, enum machine_mode mode) ...@@ -3020,22 +3088,17 @@ expand_builtin_strcpy (tree arglist, rtx target, enum machine_mode mode)
static rtx static rtx
expand_builtin_stpcpy (tree arglist, rtx target, enum machine_mode mode) expand_builtin_stpcpy (tree arglist, rtx target, enum machine_mode mode)
{ {
/* If return value is ignored, transform stpcpy into strcpy. */
if (target == const0_rtx)
return expand_builtin_strcpy (arglist, target, mode);
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0; return 0;
else else
{ {
tree dst, src, len; tree dst, src, len;
tree narglist;
/* If return value is ignored, transform stpcpy into strcpy. */ rtx ret;
if (target == const0_rtx)
{
tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
if (!fn)
return 0;
return expand_expr (build_function_call_expr (fn, arglist),
target, mode, EXPAND_NORMAL);
}
/* Ensure we get an actual string whose length can be evaluated at /* Ensure we get an actual string whose length can be evaluated at
compile-time, not an expression containing a string. This is compile-time, not an expression containing a string. This is
...@@ -3043,14 +3106,49 @@ expand_builtin_stpcpy (tree arglist, rtx target, enum machine_mode mode) ...@@ -3043,14 +3106,49 @@ expand_builtin_stpcpy (tree arglist, rtx target, enum machine_mode mode)
when used to produce the return value. */ when used to produce the return value. */
src = TREE_VALUE (TREE_CHAIN (arglist)); src = TREE_VALUE (TREE_CHAIN (arglist));
if (! c_getstr (src) || ! (len = c_strlen (src, 0))) if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
return 0; return expand_movstr (TREE_VALUE (arglist),
TREE_VALUE (TREE_CHAIN (arglist)),
target, /*endp=*/2);
dst = TREE_VALUE (arglist); dst = TREE_VALUE (arglist);
len = fold (size_binop (PLUS_EXPR, len, ssize_int (1))); len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
arglist = build_tree_list (NULL_TREE, len); narglist = build_tree_list (NULL_TREE, len);
arglist = tree_cons (NULL_TREE, src, arglist); narglist = tree_cons (NULL_TREE, src, narglist);
arglist = tree_cons (NULL_TREE, dst, arglist); narglist = tree_cons (NULL_TREE, dst, narglist);
return expand_builtin_mempcpy (arglist, target, mode, /*endp=*/2); ret = expand_builtin_mempcpy (narglist, target, mode, /*endp=*/2);
if (ret)
return ret;
if (TREE_CODE (len) == INTEGER_CST)
{
rtx len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
if (GET_CODE (len_rtx) == CONST_INT)
{
ret = expand_builtin_strcpy (arglist, target, mode);
if (ret)
{
if (! target)
target = gen_reg_rtx (mode);
if (GET_MODE (target) != GET_MODE (ret))
ret = gen_lowpart (GET_MODE (target), ret);
ret = emit_move_insn (target,
plus_constant (ret,
INTVAL (len_rtx)));
if (! ret)
abort ();
return target;
}
}
}
return expand_movstr (TREE_VALUE (arglist),
TREE_VALUE (TREE_CHAIN (arglist)),
target, /*endp=*/2);
} }
} }
......
...@@ -52,6 +52,13 @@ Boston, MA 02111-1307, USA. */ ...@@ -52,6 +52,13 @@ Boston, MA 02111-1307, USA. */
.h8300s .h8300s
#endif #endif
#endif #endif
#ifdef __H8300SX__
#ifdef __NORMAL_MODE__
.h8300sxn
#else
.h8300sx
#endif
#endif
.section .init .section .init
.global __init .global __init
......
...@@ -44,6 +44,13 @@ Boston, MA 02111-1307, USA. */ ...@@ -44,6 +44,13 @@ Boston, MA 02111-1307, USA. */
.h8300s .h8300s
#endif #endif
#endif #endif
#ifdef __H8300SX__
#ifdef __NORMAL_MODE__
.h8300sxn
#else
.h8300sx
#endif
#endif
.section .init .section .init
rts rts
......
...@@ -40,6 +40,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -40,6 +40,6 @@ Boston, MA 02111-1307, USA. */
#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) #define JUMP_TABLES_IN_TEXT_SECTION (flag_pic)
#undef LINK_SPEC #undef LINK_SPEC
#define LINK_SPEC "%{mh:%{mn:-m h8300hnelf}} %{mh:%{!mn:-m h8300helf}} %{ms:%{mn:-m h8300snelf}} %{ms:%{!mn:-m h8300self}}" #define LINK_SPEC "%{mh:%{mn:-m h8300hnelf}} %{mh:%{!mn:-m h8300helf}} %{ms:%{mn:-m h8300snelf}} %{ms:%{!mn:-m h8300self}} %{msx:%{mn:-m h8300sxnelf;:-m h8300sxelf}}"
#endif /* h8300/elf.h */ #endif /* h8300/elf.h */
#!/bin/sh
# Generate mova.md, a file containing patterns that can be implemented
# using the h8sx mova instruction.
echo ";; -*- buffer-read-only: t -*-"
echo ";; Generated automatically from genmova.sh"
# Loop over modes for the source operand (the index). Only 8-bit and
# 16-bit indices are allowed.
for s in QI HI; do
# Set $src to the operand syntax for this size of index.
case $s in
QI) src=%X1.b;;
HI) src=%T1.w;;
esac
# A match_operand for the source.
operand="(match_operand:$s 1 \"h8300_dst_operand\" \"0,rQ\")"
# Loop over the destination register's mode. The QI and HI versions use
# the same instructions as the SI ones, they just ignore the upper bits
# of the result.
for d in QI HI SI; do
# If the destination is larger than the source, include a
# zero_extend/plus pattern. We could also match zero extensions
# of memory without the plus, but it's not any smaller or faster
# than separate insns.
case $d:$s in
SI:QI | SI:HI | HI:QI)
cat <<EOF
(define_insn ""
[(set (match_operand:$d 0 "register_operand" "=r,r")
(plus:$d (zero_extend:$d $operand)
(match_operand:$d 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/b.l @(%o2,$src),%S0"
[(set_attr "length_table" "mova")
(set_attr "cc" "none")])
EOF
;;
esac
# Loop over the shift amount.
for shift in 1 2; do
case $shift in
1) opsize=w mult=2;;
2) opsize=l mult=4;;
esac
# Calculate the mask of bits that will be nonzero after the source
# has been extended and shifted.
case $s:$shift in
QI:1) mask=510;;
QI:2) mask=1020;;
HI:1) mask=131070;;
HI:2) mask=262140;;
esac
# There doesn't seem to be a well-established canonical form for
# some of the patterns we need. Emit both shift and multiplication
# patterns.
for form in mult ashift; do
case $form in
mult) amount=$mult;;
ashift) amount=$shift;;
esac
case $d:$s in
# If the source and destination are the same size, we can treat
# mova as a sort of multiply-add instruction.
QI:QI | HI:HI)
cat <<EOF
(define_insn ""
[(set (match_operand:$d 0 "register_operand" "=r,r")
(plus:$d ($form:$d $operand
(const_int $amount))
(match_operand:$d 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/$opsize.l @(%o2,$src),%S0"
[(set_attr "length_table" "mova")
(set_attr "cc" "none")])
EOF
;;
# Handle the cases where the source is smaller than the
# destination. Sometimes combine will keep the extension,
# sometimes it will use an AND.
SI:QI | SI:HI | HI:QI)
# Emit the forms that use zero_extend.
cat <<EOF
(define_insn ""
[(set (match_operand:$d 0 "register_operand" "=r,r")
($form:$d (zero_extend:$d $operand)
(const_int $amount)))]
"TARGET_H8300SX"
"mova/$opsize.l @(0,$src),%S0"
[(set_attr "length_table" "mova_zero")
(set_attr "cc" "none")])
(define_insn ""
[(set (match_operand:$d 0 "register_operand" "=r,r")
(plus:$d ($form:$d (zero_extend:$d $operand)
(const_int $amount))
(match_operand:$d 2 "immediate_operand" "i,i")))]
"TARGET_H8300SX"
"mova/$opsize.l @(%o2,$src),%S0"
[(set_attr "length_table" "mova")
(set_attr "cc" "none")])
EOF
# Now emit the forms that use AND. When the index is a register,
# these forms are effectively $d-mode operations: the index will
# be a $d-mode REG or SUBREG. When the index is a memory
# location, we will have a paradoxical subreg such as:
#
# (and:SI (mult:SI (subreg:SI (mem:QI ...) 0)
# (const_int 4))
# (const_int 1020))
#
# Match the two case separately: a $d-mode register_operand
# or a $d-mode subreg of an $s-mode memory_operand. Match the
# memory form first since register_operand accepts mem subregs
# before reload.
memory="(match_operand:$s 1 \"memory_operand\" \"m\")"
memory="(subreg:$d $memory 0)"
register="(match_operand:$d 1 \"register_operand\" \"0\")"
for paradoxical in "$memory" "$register"; do
cat <<EOF
(define_insn ""
[(set (match_operand:$d 0 "register_operand" "=r")
(and:$d ($form:$d $paradoxical
(const_int $amount))
(const_int $mask)))]
"TARGET_H8300SX"
"mova/$opsize.l @(0,$src),%S0"
[(set_attr "length_table" "mova_zero")
(set_attr "cc" "none")])
(define_insn ""
[(set (match_operand:$d 0 "register_operand" "=r")
(plus:$d (and:$d ($form:$d $paradoxical
(const_int $amount))
(const_int $mask))
(match_operand:$d 2 "immediate_operand" "i")))]
"TARGET_H8300SX"
"mova/$opsize.l @(%o2,$src),%S0"
[(set_attr "length_table" "mova")
(set_attr "cc" "none")])
EOF
done
;;
esac
done
done
done
done
...@@ -46,7 +46,7 @@ extern unsigned int compute_logical_op_length (enum machine_mode, ...@@ -46,7 +46,7 @@ extern unsigned int compute_logical_op_length (enum machine_mode,
rtx *); rtx *);
extern int compute_logical_op_cc (enum machine_mode, rtx *); extern int compute_logical_op_cc (enum machine_mode, rtx *);
extern void h8300_expand_branch (enum rtx_code, rtx); extern void h8300_expand_branch (enum rtx_code, rtx);
extern void expand_a_shift (enum machine_mode, int, rtx[]); extern bool expand_a_shift (enum machine_mode, int, rtx[]);
extern int h8300_shift_needs_scratch_p (int, enum machine_mode); extern int h8300_shift_needs_scratch_p (int, enum machine_mode);
extern int expand_a_rotate (rtx[]); extern int expand_a_rotate (rtx[]);
extern int fix_bit_operand (rtx *, enum rtx_code); extern int fix_bit_operand (rtx *, enum rtx_code);
...@@ -83,7 +83,7 @@ extern int same_cmp_preceding_p (rtx); ...@@ -83,7 +83,7 @@ extern int same_cmp_preceding_p (rtx);
extern int same_cmp_following_p (rtx); extern int same_cmp_following_p (rtx);
extern int h8300_legitimate_constant_p (rtx); extern int h8300_legitimate_constant_p (rtx);
extern int h8300_legitimate_address_p (rtx, int); extern int h8300_legitimate_address_p (enum machine_mode, rtx, int);
/* Used in builtins.c */ /* Used in builtins.c */
extern rtx h8300_return_addr_rtx (int, rtx); extern rtx h8300_return_addr_rtx (int, rtx);
...@@ -111,5 +111,14 @@ extern int h8300_hard_regno_mode_ok (int, enum machine_mode); ...@@ -111,5 +111,14 @@ extern int h8300_hard_regno_mode_ok (int, enum machine_mode);
struct cpp_reader; struct cpp_reader;
extern void h8300_pr_interrupt (struct cpp_reader *); extern void h8300_pr_interrupt (struct cpp_reader *);
extern void h8300_pr_saveall (struct cpp_reader *); extern void h8300_pr_saveall (struct cpp_reader *);
extern enum reg_class h8300_reg_class_from_letter (int);
extern rtx h8300_get_index (rtx, enum machine_mode mode, int *);
extern unsigned int h8300_insn_length_from_table (rtx, rtx *);
extern const char * output_h8sx_shift (rtx *, int, int);
extern bool h8300_operands_match_p (rtx *);
extern bool h8sx_mergeable_memrefs_p (rtx, rtx);
extern bool h8sx_emit_movmd (rtx, rtx, rtx, HOST_WIDE_INT);
extern void h8300_swap_into_er6 (rtx);
extern void h8300_swap_out_of_er6 (rtx);
#endif /* ! GCC_H8300_PROTOS_H */ #endif /* ! GCC_H8300_PROTOS_H */
...@@ -72,7 +72,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -72,7 +72,7 @@ Boston, MA 02111-1307, USA. */
#define S2P r6 #define S2P r6
#endif #endif
#if defined (__H8300H__) || defined (__H8300S__) #if defined (__H8300H__) || defined (__H8300S__) || defined (__H8300SX__)
#define PUSHP push.l #define PUSHP push.l
#define POPP pop.l #define POPP pop.l
...@@ -105,6 +105,13 @@ Boston, MA 02111-1307, USA. */ ...@@ -105,6 +105,13 @@ Boston, MA 02111-1307, USA. */
.h8300s .h8300s
#endif #endif
#endif #endif
#ifdef __H8300SX__
#ifdef __NORMAL_MODE__
.h8300sxn
#else
.h8300sx
#endif
#endif
#ifdef L_cmpsi2 #ifdef L_cmpsi2
#ifdef __H8300__ #ifdef __H8300__
......
...@@ -27,9 +27,17 @@ fp-bit.c: $(srcdir)/config/fp-bit.c ...@@ -27,9 +27,17 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#endif' >> fp-bit.c echo '#endif' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c cat $(srcdir)/config/fp-bit.c >> fp-bit.c
MULTILIB_OPTIONS = mh/ms mn mint32 MULTILIB_OPTIONS = mh/ms/msx mn mint32
MULTILIB_DIRNAMES = h8300h h8300s normal int32 MULTILIB_DIRNAMES = h8300h h8300s h8sx normal int32
MULTILIB_EXCEPTIONS = mint32 mn mn/mint32 MULTILIB_EXCEPTIONS = mint32 mn mn/mint32
LIBGCC = stmp-multilib LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib INSTALL_LIBGCC = install-multilib
s-config s-conditions s-flags s-codes s-constants s-emit s-recog \
s-opinit s-extract s-peep s-attr s-attrtab s-output: \
$(srcdir)/config/h8300/mova.md
$(srcdir)/config/h8300/mova.md: $(srcdir)/config/h8300/genmova.sh
$(SHELL) $(srcdir)/config/h8300/genmova.sh \
> $(srcdir)/config/h8300/mova.md
...@@ -2778,8 +2778,9 @@ The @samp{cmp@var{m}} patterns should be used instead. ...@@ -2778,8 +2778,9 @@ The @samp{cmp@var{m}} patterns should be used instead.
@cindex @code{movmem@var{m}} instruction pattern @cindex @code{movmem@var{m}} instruction pattern
@item @samp{movmem@var{m}} @item @samp{movmem@var{m}}
Block move instruction. The addresses of the destination and source Block move instruction. The destination and source blocks of memory
strings are the first two operands, and both are in mode @code{Pmode}. are the first two operands, and both are @code{mem:BLK}s with an
address in mode @code{Pmode}.
The number of bytes to move is the third operand, in mode @var{m}. The number of bytes to move is the third operand, in mode @var{m}.
Usually, you specify @code{word_mode} for @var{m}. However, if you can Usually, you specify @code{word_mode} for @var{m}. However, if you can
...@@ -2803,12 +2804,21 @@ individually moved data units in the block. ...@@ -2803,12 +2804,21 @@ individually moved data units in the block.
These patterns need not give special consideration to the possibility These patterns need not give special consideration to the possibility
that the source and destination strings might overlap. that the source and destination strings might overlap.
@cindex @code{movstr} instruction pattern
@item @samp{movstr}
String copy instruction, with @code{stpcpy} semantics. Operand 0 is
an output operand in mode @code{Pmode}. The addresses of the
destination and source strings are operands 1 and 2, and both are
@code{mem:BLK}s with addresses in mode @code{Pmode}. The execution of
the expansion of this pattern should store in operand 0 the address in
which the @code{NUL} terminator was stored in the destination string.
@cindex @code{clrmem@var{m}} instruction pattern @cindex @code{clrmem@var{m}} instruction pattern
@item @samp{clrmem@var{m}} @item @samp{clrmem@var{m}}
Block clear instruction. The addresses of the destination string is the Block clear instruction. The destination string is the first operand,
first operand, in mode @code{Pmode}. The number of bytes to clear is given as a @code{mem:BLK} whose address is in mode @code{Pmode}. The
the second operand, in mode @var{m}. See @samp{movmem@var{m}} for number of bytes to clear is the second operand, in mode @var{m}. See
a discussion of the choice of mode. @samp{movmem@var{m}} for a discussion of the choice of mode.
The third operand is the known alignment of the destination, in the form The third operand is the known alignment of the destination, in the form
of a @code{const_int} rtx. Thus, if the compiler knows that the of a @code{const_int} rtx. Thus, if the compiler knows that the
......
...@@ -2660,11 +2660,13 @@ walk_alter_subreg (rtx *xp) ...@@ -2660,11 +2660,13 @@ walk_alter_subreg (rtx *xp)
{ {
case PLUS: case PLUS:
case MULT: case MULT:
case AND:
XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0)); XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1)); XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1));
break; break;
case MEM: case MEM:
case ZERO_EXTEND:
XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0)); XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
break; break;
......
...@@ -5525,6 +5525,11 @@ write_eligible_delay (const char *kind) ...@@ -5525,6 +5525,11 @@ write_eligible_delay (const char *kind)
printf (" if (slot >= %d)\n", max_slots); printf (" if (slot >= %d)\n", max_slots);
printf (" abort ();\n"); printf (" abort ();\n");
printf ("\n"); printf ("\n");
/* Allow dbr_schedule to pass labels, etc. This can happen if try_split
converts a compound instruction into a loop. */
printf (" if (!INSN_P (candidate_insn))\n");
printf (" return 0;\n");
printf ("\n");
/* If more than one delay type, find out which type the delay insn is. */ /* If more than one delay type, find out which type the delay insn is. */
......
...@@ -4544,6 +4544,7 @@ get_narrower (tree op, int *unsignedp_ptr) ...@@ -4544,6 +4544,7 @@ get_narrower (tree op, int *unsignedp_ptr)
int uns = 0; int uns = 0;
int first = 1; int first = 1;
tree win = op; tree win = op;
bool integral_p = INTEGRAL_TYPE_P (TREE_TYPE (op));
while (TREE_CODE (op) == NOP_EXPR) while (TREE_CODE (op) == NOP_EXPR)
{ {
...@@ -4580,6 +4581,10 @@ get_narrower (tree op, int *unsignedp_ptr) ...@@ -4580,6 +4581,10 @@ get_narrower (tree op, int *unsignedp_ptr)
uns = TYPE_UNSIGNED (TREE_TYPE (op)); uns = TYPE_UNSIGNED (TREE_TYPE (op));
first = 0; first = 0;
op = TREE_OPERAND (op, 0); op = TREE_OPERAND (op, 0);
/* Keep trying to narrow, but don't assign op to win if it
would turn an integral type into something else. */
if (INTEGRAL_TYPE_P (TREE_TYPE (op)) != integral_p)
continue;
} }
win = op; win = op;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment