/* Convert tree expression to rtl instructions, for GNU compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
int i;
tree type;
enum machine_mode mode;
+ rtx drop_through_label = 0;
switch (code)
{
do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
break;
- case MINUS_EXPR:
- /* Nonzero iff operands of minus differ. */
- do_compare_and_jump (build2 (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:
/* fold_single_bit_test() converts (X & (1 << C)) into (X >> C) & 1.
See if the former is preferred for jump tests and restore it
do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
break;
+ case COND_EXPR:
+ {
+ rtx label1 = gen_label_rtx ();
+ if (!if_true_label || !if_false_label)
+ {
+ drop_through_label = gen_label_rtx ();
+ if (!if_true_label)
+ if_true_label = drop_through_label;
+ if (!if_false_label)
+ if_false_label = drop_through_label;
+ }
+
+ do_pending_stack_adjust ();
+ do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX);
+ do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
+ emit_label (label1);
+ do_jump (TREE_OPERAND (exp, 2), if_false_label, if_true_label);
+ break;
+ }
+
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case COMPOUND_EXPR:
- case COND_EXPR:
/* Lowered by gimplify.c. */
gcc_unreachable ();
break;
}
+ case MINUS_EXPR:
+ /* Nonzero iff operands of minus differ. */
+ exp = build2 (NE_EXPR, TREE_TYPE (exp),
+ TREE_OPERAND (exp, 0),
+ TREE_OPERAND (exp, 1));
+ /* FALLTHRU */
case NE_EXPR:
{
tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
tree op0 = save_expr (TREE_OPERAND (exp, 0));
tree op1 = save_expr (TREE_OPERAND (exp, 1));
tree cmp0, cmp1;
- rtx drop_through_label = 0;
/* If the target doesn't support combined unordered
compares, decompose into two comparisons. */
if (if_true_label == 0)
drop_through_label = if_true_label = gen_label_rtx ();
- cmp0 = fold (build2 (tcode1, TREE_TYPE (exp), op0, op1));
- cmp1 = fold (build2 (tcode2, TREE_TYPE (exp), op0, op1));
+ cmp0 = fold_build2 (tcode1, TREE_TYPE (exp), op0, op1);
+ cmp1 = fold_build2 (tcode2, TREE_TYPE (exp), op0, op1);
do_jump (cmp0, 0, if_true_label);
do_jump (cmp1, if_false_label, if_true_label);
-
- if (drop_through_label)
- {
- do_pending_stack_adjust ();
- emit_label (drop_through_label);
- }
}
}
break;
+ case TRUTH_AND_EXPR:
+ /* High branch cost, expand as the bitwise AND of the conditions.
+ Do the same if the RHS has side effects, because we're effectively
+ turning a TRUTH_AND_EXPR into a TRUTH_ANDIF_EXPR. */
+ if (BRANCH_COST >= 4 || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
+ goto normal;
+
+ if (if_false_label == NULL_RTX)
+ {
+ drop_through_label = gen_label_rtx ();
+ do_jump (TREE_OPERAND (exp, 0), drop_through_label, NULL_RTX);
+ do_jump (TREE_OPERAND (exp, 1), NULL_RTX, if_true_label);
+ }
+ else
+ {
+ do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX);
+ do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
+ }
+ break;
+
+ case TRUTH_OR_EXPR:
+ /* High branch cost, expand as the bitwise OR of the conditions.
+ Do the same if the RHS has side effects, because we're effectively
+ turning a TRUTH_OR_EXPR into a TRUTH_ORIF_EXPR. */
+ if (BRANCH_COST >= 4 || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
+ goto normal;
+
+ if (if_true_label == NULL_RTX)
+ {
+ drop_through_label = gen_label_rtx ();
+ do_jump (TREE_OPERAND (exp, 0), NULL_RTX, drop_through_label);
+ do_jump (TREE_OPERAND (exp, 1), if_false_label, NULL_RTX);
+ }
+ else
+ {
+ do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label);
+ do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
+ }
+ break;
+
/* Special case:
__builtin_expect (<test>, 0) and
__builtin_expect (<test>, 1)
tree arglist = TREE_OPERAND (exp, 1);
if (fndecl
- && DECL_BUILT_IN (fndecl)
+ && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
&& arglist != NULL_TREE
&& TREE_CHAIN (arglist) != NULL_TREE)
}
}
}
+
/* Fall through and generate the normal code. */
-
default:
normal:
temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
if_false_label, if_true_label);
}
}
+
+ if (drop_through_label)
+ {
+ do_pending_stack_adjust ();
+ emit_label (drop_through_label);
+ }
}
\f
/* Given a comparison expression EXP for values too wide to be compared
code = swap_condition (code);
}
- if (flag_force_mem)
- {
- op0 = force_not_mem (op0);
- op1 = force_not_mem (op1);
- }
-
do_pending_stack_adjust ();
code = unsignedp ? unsigned_condition (code) : code;
code = swap_condition (code);
}
- if (flag_force_mem)
- {
- op0 = force_not_mem (op0);
- op1 = force_not_mem (op1);
- }
-
do_pending_stack_adjust ();
code = unsignedp ? unsigned_condition (code) : code;
be reliably compared, then canonicalize them.
Only do this if *both* sides of the comparison are function pointers.
If one side isn't, we want a noncanonicalized comparison. See PR
- middle-end/17564. */
+ middle-end/17564. */
if (HAVE_canonicalize_funcptr_for_compare
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))