- if (target == 0)
- {
- if (DECL_RTL_SET_P (slot))
- {
- target = DECL_RTL (slot);
- /* If we have already expanded the slot, so don't do
- it again. (mrs) */
- if (TREE_OPERAND (exp, 1) == NULL_TREE)
- return target;
- }
- else
- {
- target = assign_temp (type, 2, 0, 1);
- /* All temp slots at this level must not conflict. */
- preserve_temp_slots (target);
- SET_DECL_RTL (slot, target);
- if (TREE_ADDRESSABLE (slot))
- put_var_into_stack (slot);
-
- /* Since SLOT is not known to the called function
- to belong to its stack frame, we must build an explicit
- cleanup. This case occurs when we must build up a reference
- to pass the reference as an argument. In this case,
- it is very likely that such a reference need not be
- built here. */
-
- if (TREE_OPERAND (exp, 2) == 0)
- TREE_OPERAND (exp, 2) = maybe_build_cleanup (slot);
- cleanups = TREE_OPERAND (exp, 2);
- }
- }
- else
- {
- /* This case does occur, when expanding a parameter which
- needs to be constructed on the stack. The target
- is the actual stack address that we want to initialize.
- The function we call will perform the cleanup in this case. */
-
- /* If we have already assigned it space, use that space,
- not target that we were passed in, as our target
- parameter is only a hint. */
- if (DECL_RTL_SET_P (slot))
- {
- target = DECL_RTL (slot);
- /* If we have already expanded the slot, so don't do
- it again. (mrs) */
- if (TREE_OPERAND (exp, 1) == NULL_TREE)
- return target;
- }
- else
- {
- SET_DECL_RTL (slot, target);
- /* If we must have an addressable slot, then make sure that
- the RTL that we just stored in slot is OK. */
- if (TREE_ADDRESSABLE (slot))
- put_var_into_stack (slot);
- }
- }
-
- exp1 = TREE_OPERAND (exp, 3) = TREE_OPERAND (exp, 1);
- /* Mark it as expanded. */
- TREE_OPERAND (exp, 1) = NULL_TREE;
-
- store_expr (exp1, target, 0);
-
- expand_decl_cleanup (NULL_TREE, cleanups);
-
- return target;
- }
-
- case INIT_EXPR:
- {
- tree lhs = TREE_OPERAND (exp, 0);
- tree rhs = TREE_OPERAND (exp, 1);
-
- temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
- return temp;
- }
-
- case MODIFY_EXPR:
- {
- /* If lhs is complex, expand calls in rhs before computing it.
- That's so we don't compute a pointer and save it over a
- call. If lhs is simple, compute it first so we can give it
- as a target if the rhs is just a call. This avoids an
- extra temp and copy and that prevents a partial-subsumption
- which makes bad code. Actually we could treat
- component_ref's of vars like vars. */
-
- tree lhs = TREE_OPERAND (exp, 0);
- tree rhs = TREE_OPERAND (exp, 1);
-
- temp = 0;
-
- /* Check for |= or &= of a bitfield of size one into another bitfield
- of size 1. In this case, (unless we need the result of the
- assignment) we can do this more efficiently with a
- test followed by an assignment, if necessary.
-
- ??? At this point, we can't get a BIT_FIELD_REF here. But if
- things change so we do, this code should be enhanced to
- support it. */
- if (ignore
- && TREE_CODE (lhs) == COMPONENT_REF
- && (TREE_CODE (rhs) == BIT_IOR_EXPR
- || TREE_CODE (rhs) == BIT_AND_EXPR)
- && TREE_OPERAND (rhs, 0) == lhs
- && TREE_CODE (TREE_OPERAND (rhs, 1)) == COMPONENT_REF
- && integer_onep (DECL_SIZE (TREE_OPERAND (lhs, 1)))
- && integer_onep (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))))
- {
- rtx label = gen_label_rtx ();
-
- do_jump (TREE_OPERAND (rhs, 1),
- TREE_CODE (rhs) == BIT_IOR_EXPR ? label : 0,
- TREE_CODE (rhs) == BIT_AND_EXPR ? label : 0);
- expand_assignment (lhs, convert (TREE_TYPE (rhs),
- (TREE_CODE (rhs) == BIT_IOR_EXPR
- ? integer_one_node
- : integer_zero_node)),
- 0, 0);
- do_pending_stack_adjust ();
- emit_label (label);
- return const0_rtx;
- }
-
- temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
-
- return temp;
- }
-
- case RETURN_EXPR:
- if (!TREE_OPERAND (exp, 0))
- expand_null_return ();
- else
- expand_return (TREE_OPERAND (exp, 0));
- return const0_rtx;
-
- case PREINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- return expand_increment (exp, 0, ignore);
-
- case POSTINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- /* Faster to treat as pre-increment if result is not used. */
- return expand_increment (exp, ! ignore, ignore);
-
- case ADDR_EXPR:
- /* Are we taking the address of a nested function? */
- if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL
- && decl_function_context (TREE_OPERAND (exp, 0)) != 0
- && ! DECL_NO_STATIC_CHAIN (TREE_OPERAND (exp, 0))
- && ! TREE_STATIC (exp))
- {
- op0 = trampoline_address (TREE_OPERAND (exp, 0));
- op0 = force_operand (op0, target);
- }
- /* If we are taking the address of something erroneous, just
- return a zero. */
- else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
- return const0_rtx;
- /* If we are taking the address of a constant and are at the
- top level, we have to use output_constant_def since we can't
- call force_const_mem at top level. */
- else if (cfun == 0
- && (TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
- || (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0)))
- == 'c')))
- op0 = XEXP (output_constant_def (TREE_OPERAND (exp, 0), 0), 0);
- else
- {
- /* We make sure to pass const0_rtx down if we came in with
- ignore set, to avoid doing the cleanups twice for something. */
- op0 = expand_expr (TREE_OPERAND (exp, 0),
- ignore ? const0_rtx : NULL_RTX, VOIDmode,
- (modifier == EXPAND_INITIALIZER
- ? modifier : EXPAND_CONST_ADDRESS));
-
- /* If we are going to ignore the result, OP0 will have been set
- to const0_rtx, so just return it. Don't get confused and
- think we are taking the address of the constant. */
- if (ignore)
- return op0;
-
- /* Pass 1 for MODIFY, so that protect_from_queue doesn't get
- clever and returns a REG when given a MEM. */
- op0 = protect_from_queue (op0, 1);
-
- /* We would like the object in memory. If it is a constant, we can
- have it be statically allocated into memory. For a non-constant,
- we need to allocate some memory and store the value into it. */
-
- if (CONSTANT_P (op0))
- op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
- op0);
- else if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
- || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF
- || GET_CODE (op0) == PARALLEL)
- {
- /* If the operand is a SAVE_EXPR, we can deal with this by
- forcing the SAVE_EXPR into memory. */
- if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
- {
- put_var_into_stack (TREE_OPERAND (exp, 0));
- op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
- }
- else
- {
- /* If this object is in a register, it can't be BLKmode. */
- tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
- rtx memloc = assign_temp (inner_type, 1, 1, 1);
-
- if (GET_CODE (op0) == PARALLEL)
- /* Handle calls that pass values in multiple
- non-contiguous locations. The Irix 6 ABI has examples
- of this. */
- emit_group_store (memloc, op0,
- int_size_in_bytes (inner_type));
- else
- emit_move_insn (memloc, op0);
-
- op0 = memloc;
- }
- }
-
- if (GET_CODE (op0) != MEM)
- abort ();
-
- mark_temp_addr_taken (op0);
- if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
- {
- op0 = XEXP (op0, 0);
-#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE (op0) == Pmode && GET_MODE (op0) != mode
- && mode == ptr_mode)
- op0 = convert_memory_address (ptr_mode, op0);
-#endif
- return op0;
- }
-
- /* If OP0 is not aligned as least as much as the type requires, we
- need to make a temporary, copy OP0 to it, and take the address of
- the temporary. We want to use the alignment of the type, not of
- the operand. Note that this is incorrect for FUNCTION_TYPE, but
- the test for BLKmode means that can't happen. The test for
- BLKmode is because we never make mis-aligned MEMs with
- non-BLKmode.
-
- We don't need to do this at all if the machine doesn't have
- strict alignment. */
- if (STRICT_ALIGNMENT && GET_MODE (op0) == BLKmode
- && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
- > MEM_ALIGN (op0))
- && MEM_ALIGN (op0) < BIGGEST_ALIGNMENT)
- {
- tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
- rtx new
- = assign_stack_temp_for_type
- (TYPE_MODE (inner_type),
- MEM_SIZE (op0) ? INTVAL (MEM_SIZE (op0))
- : int_size_in_bytes (inner_type),
- 1, build_qualified_type (inner_type,
- (TYPE_QUALS (inner_type)
- | TYPE_QUAL_CONST)));
-
- if (TYPE_ALIGN_OK (inner_type))
- abort ();
-
- emit_block_move (new, op0, expr_size (TREE_OPERAND (exp, 0)));
- op0 = new;
- }
-
- op0 = force_operand (XEXP (op0, 0), target);
- }
-
- if (flag_force_addr
- && GET_CODE (op0) != REG
- && modifier != EXPAND_CONST_ADDRESS
- && modifier != EXPAND_INITIALIZER
- && modifier != EXPAND_SUM)
- op0 = force_reg (Pmode, op0);
-
- if (GET_CODE (op0) == REG
- && ! REG_USERVAR_P (op0))
- mark_reg_pointer (op0, TYPE_ALIGN (TREE_TYPE (type)));
-
-#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE (op0) == Pmode && GET_MODE (op0) != mode
- && mode == ptr_mode)
- op0 = convert_memory_address (ptr_mode, op0);
-#endif
-
- return op0;
-
- case ENTRY_VALUE_EXPR:
- abort ();
-
- /* COMPLEX type for Extended Pascal & Fortran */
- case COMPLEX_EXPR:
- {
- enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
- rtx insns;
-
- /* Get the rtx code of the operands. */
- op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
- op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
-
- if (! target)
- target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
-
- start_sequence ();
-
- /* Move the real (op0) and imaginary (op1) parts to their location. */
- emit_move_insn (gen_realpart (mode, target), op0);
- emit_move_insn (gen_imagpart (mode, target), op1);
-
- insns = get_insns ();
- end_sequence ();
-
- /* Complex construction should appear as a single unit. */
- /* If TARGET is a CONCAT, we got insns like RD = RS, ID = IS,
- each with a separate pseudo as destination.
- It's not correct for flow to treat them as a unit. */
- if (GET_CODE (target) != CONCAT)
- emit_no_conflict_block (insns, target, op0, op1, NULL_RTX);
- else
- emit_insns (insns);
-
- return target;
- }
-
- case REALPART_EXPR:
- op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
- return gen_realpart (mode, op0);
-
- case IMAGPART_EXPR:
- op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
- return gen_imagpart (mode, op0);
-
- case CONJ_EXPR:
- {
- enum machine_mode partmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
- rtx imag_t;
- rtx insns;
-
- op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
-
- if (! target)
- target = gen_reg_rtx (mode);
-
- start_sequence ();
-
- /* Store the realpart and the negated imagpart to target. */
- emit_move_insn (gen_realpart (partmode, target),
- gen_realpart (partmode, op0));
-
- imag_t = gen_imagpart (partmode, target);
- temp = expand_unop (partmode,
- ! unsignedp && flag_trapv
- && (GET_MODE_CLASS(partmode) == MODE_INT)
- ? negv_optab : neg_optab,
- gen_imagpart (partmode, op0), imag_t, 0);
- if (temp != imag_t)
- emit_move_insn (imag_t, temp);
-
- insns = get_insns ();
- end_sequence ();
-
- /* Conjugate should appear as a single unit
- If TARGET is a CONCAT, we got insns like RD = RS, ID = - IS,
- each with a separate pseudo as destination.
- It's not correct for flow to treat them as a unit. */
- if (GET_CODE (target) != CONCAT)
- emit_no_conflict_block (insns, target, op0, NULL_RTX, NULL_RTX);
- else
- emit_insns (insns);
-
- return target;
- }
-
- case TRY_CATCH_EXPR:
- {
- tree handler = TREE_OPERAND (exp, 1);
-
- expand_eh_region_start ();
-
- op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
-
- expand_eh_region_end_cleanup (handler);
-
- return op0;
- }
-
- case TRY_FINALLY_EXPR:
- {
- tree try_block = TREE_OPERAND (exp, 0);
- tree finally_block = TREE_OPERAND (exp, 1);
- rtx finally_label = gen_label_rtx ();
- rtx done_label = gen_label_rtx ();
- rtx return_link = gen_reg_rtx (Pmode);
- tree cleanup = build (GOTO_SUBROUTINE_EXPR, void_type_node,
- (tree) finally_label, (tree) return_link);
- TREE_SIDE_EFFECTS (cleanup) = 1;
-
- /* Start a new binding layer that will keep track of all cleanup
- actions to be performed. */
- expand_start_bindings (2);
-
- target_temp_slot_level = temp_slot_level;
-
- expand_decl_cleanup (NULL_TREE, cleanup);
- op0 = expand_expr (try_block, target, tmode, modifier);
-
- preserve_temp_slots (op0);
- expand_end_bindings (NULL_TREE, 0, 0);
- emit_jump (done_label);
- emit_label (finally_label);
- expand_expr (finally_block, const0_rtx, VOIDmode, 0);
- emit_indirect_jump (return_link);
- emit_label (done_label);
- return op0;
- }
-
- case GOTO_SUBROUTINE_EXPR:
- {
- rtx subr = (rtx) TREE_OPERAND (exp, 0);
- rtx return_link = *(rtx *) &TREE_OPERAND (exp, 1);
- rtx return_address = gen_label_rtx ();
- emit_move_insn (return_link,
- gen_rtx_LABEL_REF (Pmode, return_address));
- emit_jump (subr);
- emit_label (return_address);
- return const0_rtx;
- }
-
- case VA_ARG_EXPR:
- return expand_builtin_va_arg (TREE_OPERAND (exp, 0), type);
-
- case EXC_PTR_EXPR:
- return get_exception_pointer (cfun);
-
- case FDESC_EXPR:
- /* Function descriptors are not valid except for as
- initialization constants, and should not be expanded. */
- abort ();
-
- default:
- return (*lang_expand_expr) (exp, original_target, tmode, modifier);
- }
-
- /* Here to do an ordinary binary operator, generating an instruction
- from the optab already placed in `this_optab'. */
- binop:
- if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
- subtarget = 0;
- op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
- binop2:
- temp = expand_binop (mode, this_optab, op0, op1, target,
- unsignedp, OPTAB_LIB_WIDEN);
- if (temp == 0)
- abort ();
- return temp;
-}
-\f
-/* Subroutine of above: returns 1 if OFFSET corresponds to an offset that
- when applied to the address of EXP produces an address known to be
- aligned more than BIGGEST_ALIGNMENT. */
-
-static int
-is_aligning_offset (offset, exp)
- tree offset;
- tree exp;
-{
- /* Strip off any conversions and WITH_RECORD_EXPR nodes. */
- while (TREE_CODE (offset) == NON_LVALUE_EXPR
- || TREE_CODE (offset) == NOP_EXPR
- || TREE_CODE (offset) == CONVERT_EXPR
- || TREE_CODE (offset) == WITH_RECORD_EXPR)
- offset = TREE_OPERAND (offset, 0);
-
- /* We must now have a BIT_AND_EXPR with a constant that is one less than
- power of 2 and which is larger than BIGGEST_ALIGNMENT. */
- if (TREE_CODE (offset) != BIT_AND_EXPR
- || !host_integerp (TREE_OPERAND (offset, 1), 1)
- || compare_tree_int (TREE_OPERAND (offset, 1), BIGGEST_ALIGNMENT) <= 0
- || !exact_log2 (tree_low_cst (TREE_OPERAND (offset, 1), 1) + 1) < 0)
- return 0;
-
- /* Look at the first operand of BIT_AND_EXPR and strip any conversion.
- It must be NEGATE_EXPR. Then strip any more conversions. */
- offset = TREE_OPERAND (offset, 0);
- while (TREE_CODE (offset) == NON_LVALUE_EXPR
- || TREE_CODE (offset) == NOP_EXPR
- || TREE_CODE (offset) == CONVERT_EXPR)
- offset = TREE_OPERAND (offset, 0);
-
- if (TREE_CODE (offset) != NEGATE_EXPR)
- return 0;
-
- offset = TREE_OPERAND (offset, 0);
- while (TREE_CODE (offset) == NON_LVALUE_EXPR
- || TREE_CODE (offset) == NOP_EXPR
- || TREE_CODE (offset) == CONVERT_EXPR)
- offset = TREE_OPERAND (offset, 0);
-
- /* This must now be the address either of EXP or of a PLACEHOLDER_EXPR
- whose type is the same as EXP. */
- return (TREE_CODE (offset) == ADDR_EXPR
- && (TREE_OPERAND (offset, 0) == exp
- || (TREE_CODE (TREE_OPERAND (offset, 0)) == PLACEHOLDER_EXPR
- && (TREE_TYPE (TREE_OPERAND (offset, 0))
- == TREE_TYPE (exp)))));
-}
-\f
-/* Return the tree node if a ARG corresponds to a string constant or zero
- if it doesn't. If we return non-zero, set *PTR_OFFSET to the offset
- in bytes within the string that ARG is accessing. The type of the
- offset will be `sizetype'. */
-
-tree
-string_constant (arg, ptr_offset)
- tree arg;
- tree *ptr_offset;
-{
- STRIP_NOPS (arg);
-
- if (TREE_CODE (arg) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)
- {
- *ptr_offset = size_zero_node;
- return TREE_OPERAND (arg, 0);
- }
- else if (TREE_CODE (arg) == PLUS_EXPR)
- {
- tree arg0 = TREE_OPERAND (arg, 0);
- tree arg1 = TREE_OPERAND (arg, 1);
-
- STRIP_NOPS (arg0);
- STRIP_NOPS (arg1);
-
- if (TREE_CODE (arg0) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (arg0, 0)) == STRING_CST)
- {
- *ptr_offset = convert (sizetype, arg1);
- return TREE_OPERAND (arg0, 0);
- }
- else if (TREE_CODE (arg1) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (arg1, 0)) == STRING_CST)
- {
- *ptr_offset = convert (sizetype, arg0);
- return TREE_OPERAND (arg1, 0);
- }
- }
-
- return 0;
-}
-\f
-/* Expand code for a post- or pre- increment or decrement
- and return the RTX for the result.
- POST is 1 for postinc/decrements and 0 for preinc/decrements. */
-
-static rtx
-expand_increment (exp, post, ignore)
- tree exp;
- int post, ignore;
-{
- rtx op0, op1;
- rtx temp, value;
- tree incremented = TREE_OPERAND (exp, 0);
- optab this_optab = add_optab;
- int icode;
- enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
- int op0_is_copy = 0;
- int single_insn = 0;
- /* 1 means we can't store into OP0 directly,
- because it is a subreg narrower than a word,
- and we don't dare clobber the rest of the word. */
- int bad_subreg = 0;
-
- /* Stabilize any component ref that might need to be
- evaluated more than once below. */
- if (!post
- || TREE_CODE (incremented) == BIT_FIELD_REF
- || (TREE_CODE (incremented) == COMPONENT_REF
- && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF
- || DECL_BIT_FIELD (TREE_OPERAND (incremented, 1)))))
- incremented = stabilize_reference (incremented);
- /* Nested *INCREMENT_EXPRs can happen in C++. We must force innermost
- ones into save exprs so that they don't accidentally get evaluated
- more than once by the code below. */
- if (TREE_CODE (incremented) == PREINCREMENT_EXPR
- || TREE_CODE (incremented) == PREDECREMENT_EXPR)
- incremented = save_expr (incremented);
-
- /* Compute the operands as RTX.
- Note whether OP0 is the actual lvalue or a copy of it:
- I believe it is a copy iff it is a register or subreg
- and insns were generated in computing it. */
-
- temp = get_last_insn ();
- op0 = expand_expr (incremented, NULL_RTX, VOIDmode, 0);
-
- /* If OP0 is a SUBREG made for a promoted variable, we cannot increment
- in place but instead must do sign- or zero-extension during assignment,
- so we copy it into a new register and let the code below use it as
- a copy.
-
- Note that we can safely modify this SUBREG since it is know not to be
- shared (it was made by the expand_expr call above). */
-
- if (GET_CODE (op0) == SUBREG && SUBREG_PROMOTED_VAR_P (op0))
- {
- if (post)
- SUBREG_REG (op0) = copy_to_reg (SUBREG_REG (op0));
- else
- bad_subreg = 1;
- }
- else if (GET_CODE (op0) == SUBREG
- && GET_MODE_BITSIZE (GET_MODE (op0)) < BITS_PER_WORD)
- {
- /* We cannot increment this SUBREG in place. If we are
- post-incrementing, get a copy of the old value. Otherwise,
- just mark that we cannot increment in place. */
- if (post)
- op0 = copy_to_reg (op0);
- else
- bad_subreg = 1;
- }
-
- op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)
- && temp != get_last_insn ());
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
-
- /* Decide whether incrementing or decrementing. */
- if (TREE_CODE (exp) == POSTDECREMENT_EXPR
- || TREE_CODE (exp) == PREDECREMENT_EXPR)
- this_optab = sub_optab;
-
- /* Convert decrement by a constant into a negative increment. */
- if (this_optab == sub_optab
- && GET_CODE (op1) == CONST_INT)
- {
- op1 = GEN_INT (-INTVAL (op1));
- this_optab = add_optab;
- }
-
- if (TYPE_TRAP_SIGNED (TREE_TYPE (exp)))
- this_optab = this_optab == add_optab ? addv_optab : subv_optab;
-
- /* For a preincrement, see if we can do this with a single instruction. */
- if (!post)
- {
- icode = (int) this_optab->handlers[(int) mode].insn_code;
- if (icode != (int) CODE_FOR_nothing
- /* Make sure that OP0 is valid for operands 0 and 1
- of the insn we want to queue. */
- && (*insn_data[icode].operand[0].predicate) (op0, mode)
- && (*insn_data[icode].operand[1].predicate) (op0, mode)
- && (*insn_data[icode].operand[2].predicate) (op1, mode))
- single_insn = 1;
- }
-
- /* If OP0 is not the actual lvalue, but rather a copy in a register,
- then we cannot just increment OP0. We must therefore contrive to
- increment the original value. Then, for postincrement, we can return
- OP0 since it is a copy of the old value. For preincrement, expand here
- unless we can do it with a single insn.
-
- Likewise if storing directly into OP0 would clobber high bits
- we need to preserve (bad_subreg). */
- if (op0_is_copy || (!post && !single_insn) || bad_subreg)
- {
- /* This is the easiest way to increment the value wherever it is.
- Problems with multiple evaluation of INCREMENTED are prevented
- because either (1) it is a component_ref or preincrement,
- in which case it was stabilized above, or (2) it is an array_ref
- with constant index in an array in a register, which is
- safe to reevaluate. */
- tree newexp = build (((TREE_CODE (exp) == POSTDECREMENT_EXPR
- || TREE_CODE (exp) == PREDECREMENT_EXPR)
- ? MINUS_EXPR : PLUS_EXPR),
- TREE_TYPE (exp),
- incremented,
- TREE_OPERAND (exp, 1));
-
- while (TREE_CODE (incremented) == NOP_EXPR
- || TREE_CODE (incremented) == CONVERT_EXPR)
- {
- newexp = convert (TREE_TYPE (incremented), newexp);
- incremented = TREE_OPERAND (incremented, 0);
- }
-
- temp = expand_assignment (incremented, newexp, ! post && ! ignore , 0);
- return post ? op0 : temp;
- }
-
- if (post)
- {
- /* We have a true reference to the value in OP0.
- If there is an insn to add or subtract in this mode, queue it.
- Queueing the increment insn avoids the register shuffling
- that often results if we must increment now and first save
- the old value for subsequent use. */
-
-#if 0 /* Turned off to avoid making extra insn for indexed memref. */
- op0 = stabilize (op0);
-#endif
-
- icode = (int) this_optab->handlers[(int) mode].insn_code;
- if (icode != (int) CODE_FOR_nothing
- /* Make sure that OP0 is valid for operands 0 and 1
- of the insn we want to queue. */
- && (*insn_data[icode].operand[0].predicate) (op0, mode)
- && (*insn_data[icode].operand[1].predicate) (op0, mode))
- {
- if (! (*insn_data[icode].operand[2].predicate) (op1, mode))
- op1 = force_reg (mode, op1);
-
- return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1));
- }
- if (icode != (int) CODE_FOR_nothing && GET_CODE (op0) == MEM)
- {
- rtx addr = (general_operand (XEXP (op0, 0), mode)
- ? force_reg (Pmode, XEXP (op0, 0))
- : copy_to_reg (XEXP (op0, 0)));
- rtx temp, result;
-
- op0 = replace_equiv_address (op0, addr);
- temp = force_reg (GET_MODE (op0), op0);
- if (! (*insn_data[icode].operand[2].predicate) (op1, mode))
- op1 = force_reg (mode, op1);
-
- /* The increment queue is LIFO, thus we have to `queue'
- the instructions in reverse order. */
- enqueue_insn (op0, gen_move_insn (op0, temp));
- result = enqueue_insn (temp, GEN_FCN (icode) (temp, temp, op1));
- return result;
- }
- }
-
- /* Preincrement, or we can't increment with one simple insn. */
- if (post)
- /* Save a copy of the value before inc or dec, to return it later. */
- temp = value = copy_to_reg (op0);
- else
- /* Arrange to return the incremented value. */
- /* Copy the rtx because expand_binop will protect from the queue,
- and the results of that would be invalid for us to return
- if our caller does emit_queue before using our result. */
- temp = copy_rtx (value = op0);
-
- /* Increment however we can. */
- op1 = expand_binop (mode, this_optab, value, op1, op0,
- TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
-
- /* Make sure the value is stored into OP0. */
- if (op1 != op0)
- emit_move_insn (op0, op1);
-
- return temp;
-}
-\f
-/* At the start of a function, record that we have no previously-pushed
- arguments waiting to be popped. */
-
-void
-init_pending_stack_adjust ()
-{
- pending_stack_adjust = 0;
-}
-
-/* When exiting from function, if safe, clear out any pending stack adjust
- so the adjustment won't get done.
-
- Note, if the current function calls alloca, then it must have a
- frame pointer regardless of the value of flag_omit_frame_pointer. */
-
-void
-clear_pending_stack_adjust ()
-{
-#ifdef EXIT_IGNORE_STACK
- if (optimize > 0
- && (! flag_omit_frame_pointer || current_function_calls_alloca)
- && EXIT_IGNORE_STACK
- && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)
- && ! flag_inline_functions)
- {
- stack_pointer_delta -= pending_stack_adjust,
- pending_stack_adjust = 0;
- }
-#endif
-}
-
-/* Pop any previously-pushed arguments that have not been popped yet. */
-
-void
-do_pending_stack_adjust ()
-{
- if (inhibit_defer_pop == 0)
- {
- if (pending_stack_adjust != 0)
- adjust_stack (GEN_INT (pending_stack_adjust));
- pending_stack_adjust = 0;
- }
-}
-\f
-/* Expand conditional expressions. */
-
-/* Generate code to evaluate EXP and jump to LABEL if the value is zero.
- LABEL is an rtx of code CODE_LABEL, in this function and all the
- functions here. */
-
-void
-jumpifnot (exp, label)
- tree exp;
- rtx label;
-{
- do_jump (exp, label, NULL_RTX);
-}
-
-/* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */
-
-void
-jumpif (exp, label)
- tree exp;
- rtx label;
-{
- do_jump (exp, NULL_RTX, label);
-}
-
-/* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
- the result is zero, or IF_TRUE_LABEL if the result is one.
- Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero,
- meaning fall through in that case.
-
- do_jump always does any pending stack adjust except when it does not
- actually perform a jump. An example where there is no jump
- is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null.
-
- This function is responsible for optimizing cases such as
- &&, || and comparison operators in EXP. */
-
-void
-do_jump (exp, if_false_label, if_true_label)
- tree exp;
- rtx if_false_label, if_true_label;
-{
- enum tree_code code = TREE_CODE (exp);
- /* Some cases need to create a label to jump to
- in order to properly fall through.
- These cases set DROP_THROUGH_LABEL nonzero. */
- rtx drop_through_label = 0;
- rtx temp;
- int i;
- tree type;
- enum machine_mode mode;
-
-#ifdef MAX_INTEGER_COMPUTATION_MODE
- check_max_integer_computation_mode (exp);
-#endif
-
- emit_queue ();
-
- switch (code)
- {
- case ERROR_MARK:
- break;
-
- case INTEGER_CST:
- temp = integer_zerop (exp) ? if_false_label : if_true_label;
- if (temp)
- emit_jump (temp);
- break;
-
-#if 0
- /* This is not true with #pragma weak */
- case ADDR_EXPR:
- /* The address of something can never be zero. */
- if (if_true_label)
- emit_jump (if_true_label);
- break;
-#endif
-
- case NOP_EXPR:
- if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
- || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
- || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF
- || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_RANGE_REF)
- goto normal;
- case CONVERT_EXPR:
- /* If we are narrowing the operand, we have to do the compare in the
- narrower mode. */
- if ((TYPE_PRECISION (TREE_TYPE (exp))
- < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))))
- goto normal;
- case NON_LVALUE_EXPR:
- case REFERENCE_EXPR:
- case ABS_EXPR:
- case NEGATE_EXPR:
- case LROTATE_EXPR:
- case RROTATE_EXPR:
- /* These cannot change zero->non-zero or vice versa. */
- do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
- break;
-
- case WITH_RECORD_EXPR:
- /* Put the object on the placeholder list, recurse through our first
- operand, and pop the list. */
- placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
- placeholder_list);
- do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
- placeholder_list = TREE_CHAIN (placeholder_list);
- break;
-
-#if 0
- /* This is never less insns than evaluating the PLUS_EXPR followed by
- a test and can be longer if the test is eliminated. */
- case PLUS_EXPR:
- /* Reduce to minus. */
- exp = build (MINUS_EXPR, TREE_TYPE (exp),
- TREE_OPERAND (exp, 0),
- fold (build1 (NEGATE_EXPR, TREE_TYPE (TREE_OPERAND (exp, 1)),
- TREE_OPERAND (exp, 1))));
- /* Process as MINUS. */
-#endif
-
- case MINUS_EXPR:
- /* Non-zero iff operands of minus differ. */
- do_compare_and_jump (build (NE_EXPR, TREE_TYPE (exp),
- TREE_OPERAND (exp, 0),
- TREE_OPERAND (exp, 1)),
- NE, NE, if_false_label, if_true_label);
- break;
-
- case BIT_AND_EXPR:
- /* If we are AND'ing with a small constant, do this comparison in the
- smallest type that fits. If the machine doesn't have comparisons
- that small, it will be converted back to the wider comparison.
- This helps if we are testing the sign bit of a narrower object.
- combine can't do this for us because it can't know whether a
- ZERO_EXTRACT or a compare in a smaller mode exists, but we do. */
-
- if (! SLOW_BYTE_ACCESS
- && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
- && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
- && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
- && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
- && (type = type_for_mode (mode, 1)) != 0
- && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
- && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
- != CODE_FOR_nothing))
- {
- do_jump (convert (type, exp), if_false_label, if_true_label);
- break;
- }
- goto normal;
-
- case TRUTH_NOT_EXPR:
- do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
- break;
-
- case TRUTH_ANDIF_EXPR:
- if (if_false_label == 0)
- if_false_label = drop_through_label = gen_label_rtx ();
- do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX);
- start_cleanup_deferral ();
- do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
- end_cleanup_deferral ();
- break;
-
- case TRUTH_ORIF_EXPR:
- if (if_true_label == 0)
- if_true_label = drop_through_label = gen_label_rtx ();
- do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label);
- start_cleanup_deferral ();
- do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
- end_cleanup_deferral ();
- break;
-
- case COMPOUND_EXPR:
- push_temp_slots ();
- expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
- preserve_temp_slots (NULL_RTX);
- free_temp_slots ();
- pop_temp_slots ();
- emit_queue ();
- do_pending_stack_adjust ();
- do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
- break;
-
- case COMPONENT_REF:
- case BIT_FIELD_REF:
- case ARRAY_REF:
- case ARRAY_RANGE_REF:
- {
- HOST_WIDE_INT bitsize, bitpos;
- int unsignedp;
- enum machine_mode mode;
- tree type;
- tree offset;
- int volatilep = 0;
-
- /* Get description of this reference. We don't actually care
- about the underlying object here. */
- get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep);
-
- type = type_for_size (bitsize, unsignedp);
- if (! SLOW_BYTE_ACCESS
- && type != 0 && bitsize >= 0
- && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
- && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
- != CODE_FOR_nothing))
- {
- do_jump (convert (type, exp), if_false_label, if_true_label);
- break;
- }
- goto normal;
- }
-
- case COND_EXPR:
- /* Do (a ? 1 : 0) and (a ? 0 : 1) as special cases. */
- if (integer_onep (TREE_OPERAND (exp, 1))
- && integer_zerop (TREE_OPERAND (exp, 2)))
- do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
-
- else if (integer_zerop (TREE_OPERAND (exp, 1))
- && integer_onep (TREE_OPERAND (exp, 2)))
- do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
-
- else
- {
- rtx label1 = gen_label_rtx ();
- drop_through_label = gen_label_rtx ();
-
- do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX);
-
- start_cleanup_deferral ();
- /* Now the THEN-expression. */
- do_jump (TREE_OPERAND (exp, 1),
- if_false_label ? if_false_label : drop_through_label,
- if_true_label ? if_true_label : drop_through_label);
- /* In case the do_jump just above never jumps. */
- do_pending_stack_adjust ();
- emit_label (label1);
-
- /* Now the ELSE-expression. */
- do_jump (TREE_OPERAND (exp, 2),
- if_false_label ? if_false_label : drop_through_label,
- if_true_label ? if_true_label : drop_through_label);
- end_cleanup_deferral ();
- }
- break;
-
- case EQ_EXPR:
- {
- tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-
- if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_FLOAT
- || GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_INT)
- {
- tree exp0 = save_expr (TREE_OPERAND (exp, 0));
- tree exp1 = save_expr (TREE_OPERAND (exp, 1));
- do_jump
- (fold
- (build (TRUTH_ANDIF_EXPR, TREE_TYPE (exp),
- fold (build (EQ_EXPR, TREE_TYPE (exp),
- fold (build1 (REALPART_EXPR,
- TREE_TYPE (inner_type),
- exp0)),
- fold (build1 (REALPART_EXPR,
- TREE_TYPE (inner_type),
- exp1)))),
- fold (build (EQ_EXPR, TREE_TYPE (exp),
- fold (build1 (IMAGPART_EXPR,
- TREE_TYPE (inner_type),
- exp0)),
- fold (build1 (IMAGPART_EXPR,
- TREE_TYPE (inner_type),
- exp1)))))),
- if_false_label, if_true_label);
- }
-
- else if (integer_zerop (TREE_OPERAND (exp, 1)))
- do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
-
- else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
- && !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
- do_jump_by_parts_equality (exp, if_false_label, if_true_label);
- else
- do_compare_and_jump (exp, EQ, EQ, if_false_label, if_true_label);
- break;
- }
-
- case NE_EXPR:
- {
- tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-
- if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_FLOAT
- || GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_INT)
- {
- tree exp0 = save_expr (TREE_OPERAND (exp, 0));
- tree exp1 = save_expr (TREE_OPERAND (exp, 1));
- do_jump
- (fold
- (build (TRUTH_ORIF_EXPR, TREE_TYPE (exp),
- fold (build (NE_EXPR, TREE_TYPE (exp),
- fold (build1 (REALPART_EXPR,
- TREE_TYPE (inner_type),
- exp0)),
- fold (build1 (REALPART_EXPR,
- TREE_TYPE (inner_type),
- exp1)))),
- fold (build (NE_EXPR, TREE_TYPE (exp),
- fold (build1 (IMAGPART_EXPR,
- TREE_TYPE (inner_type),
- exp0)),
- fold (build1 (IMAGPART_EXPR,
- TREE_TYPE (inner_type),
- exp1)))))),
- if_false_label, if_true_label);
- }
-
- else if (integer_zerop (TREE_OPERAND (exp, 1)))
- do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
-
- else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
- && !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
- do_jump_by_parts_equality (exp, if_true_label, if_false_label);
- else
- do_compare_and_jump (exp, NE, NE, if_false_label, if_true_label);
- break;
- }
-
- case LT_EXPR:
- mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
- if (GET_MODE_CLASS (mode) == MODE_INT
- && ! can_compare_p (LT, mode, ccp_jump))
- do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label);
- else
- do_compare_and_jump (exp, LT, LTU, if_false_label, if_true_label);
- break;
-
- case LE_EXPR:
- mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
- if (GET_MODE_CLASS (mode) == MODE_INT
- && ! can_compare_p (LE, mode, ccp_jump))
- do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label);
- else
- do_compare_and_jump (exp, LE, LEU, if_false_label, if_true_label);
- break;
-
- case GT_EXPR:
- mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
- if (GET_MODE_CLASS (mode) == MODE_INT
- && ! can_compare_p (GT, mode, ccp_jump))
- do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label);
- else
- do_compare_and_jump (exp, GT, GTU, if_false_label, if_true_label);
- break;
-
- case GE_EXPR:
- mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
- if (GET_MODE_CLASS (mode) == MODE_INT
- && ! can_compare_p (GE, mode, ccp_jump))
- do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label);
- else
- do_compare_and_jump (exp, GE, GEU, if_false_label, if_true_label);
- break;
-
- case UNORDERED_EXPR:
- case ORDERED_EXPR:
- {
- enum rtx_code cmp, rcmp;
- int do_rev;
-
- if (code == UNORDERED_EXPR)
- cmp = UNORDERED, rcmp = ORDERED;
- else
- cmp = ORDERED, rcmp = UNORDERED;
- mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-
- do_rev = 0;
- if (! can_compare_p (cmp, mode, ccp_jump)
- && (can_compare_p (rcmp, mode, ccp_jump)
- /* If the target doesn't provide either UNORDERED or ORDERED
- comparisons, canonicalize on UNORDERED for the library. */
- || rcmp == UNORDERED))
- do_rev = 1;
-
- if (! do_rev)
- do_compare_and_jump (exp, cmp, cmp, if_false_label, if_true_label);
- else
- do_compare_and_jump (exp, rcmp, rcmp, if_true_label, if_false_label);
- }
- break;
-
- {
- enum rtx_code rcode1;
- enum tree_code tcode2;
-
- case UNLT_EXPR:
- rcode1 = UNLT;
- tcode2 = LT_EXPR;
- goto unordered_bcc;
- case UNLE_EXPR:
- rcode1 = UNLE;
- tcode2 = LE_EXPR;
- goto unordered_bcc;
- case UNGT_EXPR:
- rcode1 = UNGT;
- tcode2 = GT_EXPR;
- goto unordered_bcc;
- case UNGE_EXPR:
- rcode1 = UNGE;
- tcode2 = GE_EXPR;
- goto unordered_bcc;
- case UNEQ_EXPR:
- rcode1 = UNEQ;
- tcode2 = EQ_EXPR;
- goto unordered_bcc;
-
- unordered_bcc:
- mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
- if (can_compare_p (rcode1, mode, ccp_jump))
- do_compare_and_jump (exp, rcode1, rcode1, if_false_label,
- if_true_label);
- else
- {
- tree op0 = save_expr (TREE_OPERAND (exp, 0));
- tree op1 = save_expr (TREE_OPERAND (exp, 1));
- tree cmp0, cmp1;
-
- /* If the target doesn't support combined unordered
- compares, decompose into UNORDERED + comparison. */
- cmp0 = fold (build (UNORDERED_EXPR, TREE_TYPE (exp), op0, op1));
- cmp1 = fold (build (tcode2, TREE_TYPE (exp), op0, op1));
- exp = build (TRUTH_ORIF_EXPR, TREE_TYPE (exp), cmp0, cmp1);
- do_jump (exp, if_false_label, if_true_label);
- }
- }
- break;
-
- /* Special case:
- __builtin_expect (<test>, 0) and
- __builtin_expect (<test>, 1)
-
- We need to do this here, so that <test> is not converted to a SCC
- operation on machines that use condition code registers and COMPARE
- like the PowerPC, and then the jump is done based on whether the SCC
- operation produced a 1 or 0. */
- case CALL_EXPR:
- /* Check for a built-in function. */
- if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
- {
- tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
- tree arglist = TREE_OPERAND (exp, 1);
-
- if (TREE_CODE (fndecl) == FUNCTION_DECL
- && DECL_BUILT_IN (fndecl)
- && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
- && arglist != NULL_TREE
- && TREE_CHAIN (arglist) != NULL_TREE)
- {
- rtx seq = expand_builtin_expect_jump (exp, if_false_label,
- if_true_label);
-
- if (seq != NULL_RTX)
- {
- emit_insn (seq);
- return;
- }
- }
- }
- /* fall through and generate the normal code. */
-
- default:
- normal:
- temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
-#if 0
- /* This is not needed any more and causes poor code since it causes
- comparisons and tests from non-SI objects to have different code
- sequences. */
- /* Copy to register to avoid generating bad insns by cse
- from (set (mem ...) (arithop)) (set (cc0) (mem ...)). */
- if (!cse_not_expected && GET_CODE (temp) == MEM)
- temp = copy_to_reg (temp);
-#endif
- do_pending_stack_adjust ();
- /* Do any postincrements in the expression that was tested. */
- emit_queue ();
-
- if (GET_CODE (temp) == CONST_INT
- || (GET_CODE (temp) == CONST_DOUBLE && GET_MODE (temp) == VOIDmode)
- || GET_CODE (temp) == LABEL_REF)
- {
- rtx target = temp == const0_rtx ? if_false_label : if_true_label;
- if (target)
- emit_jump (target);
- }
- else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
- && ! can_compare_p (NE, GET_MODE (temp), ccp_jump))
- /* Note swapping the labels gives us not-equal. */
- do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label);
- else if (GET_MODE (temp) != VOIDmode)
- do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)),
- NE, TREE_UNSIGNED (TREE_TYPE (exp)),
- GET_MODE (temp), NULL_RTX,
- if_false_label, if_true_label);
- else
- abort ();
- }
-
- if (drop_through_label)
- {
- /* If do_jump produces code that might be jumped around,
- do any stack adjusts from that code, before the place
- where control merges in. */
- do_pending_stack_adjust ();
- emit_label (drop_through_label);
- }
-}
-\f
-/* Given a comparison expression EXP for values too wide to be compared
- with one insn, test the comparison and jump to the appropriate label.
- The code of EXP is ignored; we always test GT if SWAP is 0,
- and LT if SWAP is 1. */
-
-static void
-do_jump_by_parts_greater (exp, swap, if_false_label, if_true_label)
- tree exp;
- int swap;
- rtx if_false_label, if_true_label;
-{
- rtx op0 = expand_expr (TREE_OPERAND (exp, swap), NULL_RTX, VOIDmode, 0);
- rtx op1 = expand_expr (TREE_OPERAND (exp, !swap), NULL_RTX, VOIDmode, 0);
- enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
- int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));