1132718Skan/* Convert tree expression to rtl instructions, for GNU compiler. 2132718Skan Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3169689Skan 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 4132718Skan 5132718SkanThis file is part of GCC. 6132718Skan 7132718SkanGCC is free software; you can redistribute it and/or modify it under 8132718Skanthe terms of the GNU General Public License as published by the Free 9132718SkanSoftware Foundation; either version 2, or (at your option) any later 10132718Skanversion. 11132718Skan 12132718SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 13132718SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 14132718SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15132718Skanfor more details. 16132718Skan 17132718SkanYou should have received a copy of the GNU General Public License 18132718Skanalong with GCC; see the file COPYING. If not, write to the Free 19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20169689Skan02110-1301, USA. */ 21132718Skan 22132718Skan#include "config.h" 23132718Skan#include "system.h" 24132718Skan#include "coretypes.h" 25132718Skan#include "tm.h" 26132718Skan#include "rtl.h" 27132718Skan#include "tree.h" 28132718Skan#include "flags.h" 29132718Skan#include "function.h" 30132718Skan#include "insn-config.h" 31132718Skan#include "insn-attr.h" 32132718Skan/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */ 33132718Skan#include "expr.h" 34132718Skan#include "optabs.h" 35132718Skan#include "langhooks.h" 36146895Skan#include "ggc.h" 37132718Skan 38146895Skanstatic bool prefer_and_bit_test (enum machine_mode, int); 39132718Skanstatic void do_jump_by_parts_greater (tree, int, rtx, rtx); 40132718Skanstatic void do_jump_by_parts_equality (tree, rtx, rtx); 41132718Skanstatic void do_compare_and_jump (tree, enum rtx_code, enum rtx_code, rtx, 42132718Skan rtx); 43132718Skan 44132718Skan/* At the start of a function, record that we have no previously-pushed 45132718Skan arguments waiting to be popped. */ 46132718Skan 47132718Skanvoid 48132718Skaninit_pending_stack_adjust (void) 49132718Skan{ 50132718Skan pending_stack_adjust = 0; 51132718Skan} 52132718Skan 53146895Skan/* Discard any pending stack adjustment. This avoid relying on the 54146895Skan RTL optimizers to remove useless adjustments when we know the 55146895Skan stack pointer value is dead. */ 56169689Skanvoid 57169689Skandiscard_pending_stack_adjust (void) 58146895Skan{ 59146895Skan stack_pointer_delta -= pending_stack_adjust; 60146895Skan pending_stack_adjust = 0; 61146895Skan} 62146895Skan 63132718Skan/* When exiting from function, if safe, clear out any pending stack adjust 64132718Skan so the adjustment won't get done. 65132718Skan 66132718Skan Note, if the current function calls alloca, then it must have a 67132718Skan frame pointer regardless of the value of flag_omit_frame_pointer. */ 68132718Skan 69132718Skanvoid 70132718Skanclear_pending_stack_adjust (void) 71132718Skan{ 72132718Skan if (optimize > 0 73132718Skan && (! flag_omit_frame_pointer || current_function_calls_alloca) 74132718Skan && EXIT_IGNORE_STACK 75169689Skan && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)) 76146895Skan discard_pending_stack_adjust (); 77132718Skan} 78132718Skan 79132718Skan/* Pop any previously-pushed arguments that have not been popped yet. */ 80132718Skan 81132718Skanvoid 82132718Skando_pending_stack_adjust (void) 83132718Skan{ 84132718Skan if (inhibit_defer_pop == 0) 85132718Skan { 86132718Skan if (pending_stack_adjust != 0) 87132718Skan adjust_stack (GEN_INT (pending_stack_adjust)); 88132718Skan pending_stack_adjust = 0; 89132718Skan } 90132718Skan} 91132718Skan 92132718Skan/* Expand conditional expressions. */ 93132718Skan 94132718Skan/* Generate code to evaluate EXP and jump to LABEL if the value is zero. 95132718Skan LABEL is an rtx of code CODE_LABEL, in this function and all the 96132718Skan functions here. */ 97132718Skan 98132718Skanvoid 99132718Skanjumpifnot (tree exp, rtx label) 100132718Skan{ 101132718Skan do_jump (exp, label, NULL_RTX); 102132718Skan} 103132718Skan 104132718Skan/* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */ 105132718Skan 106132718Skanvoid 107132718Skanjumpif (tree exp, rtx label) 108132718Skan{ 109132718Skan do_jump (exp, NULL_RTX, label); 110132718Skan} 111132718Skan 112146895Skan/* Used internally by prefer_and_bit_test. */ 113146895Skan 114146895Skanstatic GTY(()) rtx and_reg; 115146895Skanstatic GTY(()) rtx and_test; 116146895Skanstatic GTY(()) rtx shift_test; 117146895Skan 118169689Skan/* Compare the relative costs of "(X & (1 << BITNUM))" and "(X >> BITNUM) & 1", 119146895Skan where X is an arbitrary register of mode MODE. Return true if the former 120146895Skan is preferred. */ 121146895Skan 122146895Skanstatic bool 123146895Skanprefer_and_bit_test (enum machine_mode mode, int bitnum) 124146895Skan{ 125146895Skan if (and_test == 0) 126146895Skan { 127146895Skan /* Set up rtxes for the two variations. Use NULL as a placeholder 128146895Skan for the BITNUM-based constants. */ 129146895Skan and_reg = gen_rtx_REG (mode, FIRST_PSEUDO_REGISTER); 130146895Skan and_test = gen_rtx_AND (mode, and_reg, NULL); 131146895Skan shift_test = gen_rtx_AND (mode, gen_rtx_ASHIFTRT (mode, and_reg, NULL), 132146895Skan const1_rtx); 133146895Skan } 134146895Skan else 135146895Skan { 136146895Skan /* Change the mode of the previously-created rtxes. */ 137146895Skan PUT_MODE (and_reg, mode); 138146895Skan PUT_MODE (and_test, mode); 139146895Skan PUT_MODE (shift_test, mode); 140146895Skan PUT_MODE (XEXP (shift_test, 0), mode); 141146895Skan } 142146895Skan 143146895Skan /* Fill in the integers. */ 144146895Skan XEXP (and_test, 1) = GEN_INT ((unsigned HOST_WIDE_INT) 1 << bitnum); 145146895Skan XEXP (XEXP (shift_test, 0), 1) = GEN_INT (bitnum); 146146895Skan 147146895Skan return (rtx_cost (and_test, IF_THEN_ELSE) 148146895Skan <= rtx_cost (shift_test, IF_THEN_ELSE)); 149146895Skan} 150146895Skan 151132718Skan/* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if 152132718Skan the result is zero, or IF_TRUE_LABEL if the result is one. 153132718Skan Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero, 154132718Skan meaning fall through in that case. 155132718Skan 156132718Skan do_jump always does any pending stack adjust except when it does not 157132718Skan actually perform a jump. An example where there is no jump 158169689Skan is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null. */ 159132718Skan 160132718Skanvoid 161132718Skando_jump (tree exp, rtx if_false_label, rtx if_true_label) 162132718Skan{ 163132718Skan enum tree_code code = TREE_CODE (exp); 164132718Skan rtx temp; 165132718Skan int i; 166132718Skan tree type; 167132718Skan enum machine_mode mode; 168169689Skan rtx drop_through_label = 0; 169132718Skan 170132718Skan switch (code) 171132718Skan { 172132718Skan case ERROR_MARK: 173132718Skan break; 174132718Skan 175132718Skan case INTEGER_CST: 176132718Skan temp = integer_zerop (exp) ? if_false_label : if_true_label; 177132718Skan if (temp) 178132718Skan emit_jump (temp); 179132718Skan break; 180132718Skan 181132718Skan#if 0 182132718Skan /* This is not true with #pragma weak */ 183132718Skan case ADDR_EXPR: 184132718Skan /* The address of something can never be zero. */ 185132718Skan if (if_true_label) 186132718Skan emit_jump (if_true_label); 187132718Skan break; 188132718Skan#endif 189132718Skan 190132718Skan case NOP_EXPR: 191132718Skan if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF 192132718Skan || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF 193132718Skan || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF 194132718Skan || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_RANGE_REF) 195132718Skan goto normal; 196132718Skan case CONVERT_EXPR: 197132718Skan /* If we are narrowing the operand, we have to do the compare in the 198132718Skan narrower mode. */ 199132718Skan if ((TYPE_PRECISION (TREE_TYPE (exp)) 200132718Skan < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))) 201132718Skan goto normal; 202132718Skan case NON_LVALUE_EXPR: 203132718Skan case ABS_EXPR: 204132718Skan case NEGATE_EXPR: 205132718Skan case LROTATE_EXPR: 206132718Skan case RROTATE_EXPR: 207132718Skan /* These cannot change zero->nonzero or vice versa. */ 208132718Skan do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label); 209132718Skan break; 210132718Skan 211132718Skan case BIT_AND_EXPR: 212146895Skan /* fold_single_bit_test() converts (X & (1 << C)) into (X >> C) & 1. 213146895Skan See if the former is preferred for jump tests and restore it 214146895Skan if so. */ 215146895Skan if (integer_onep (TREE_OPERAND (exp, 1))) 216146895Skan { 217146895Skan tree exp0 = TREE_OPERAND (exp, 0); 218146895Skan rtx set_label, clr_label; 219146895Skan 220146895Skan /* Strip narrowing integral type conversions. */ 221146895Skan while ((TREE_CODE (exp0) == NOP_EXPR 222146895Skan || TREE_CODE (exp0) == CONVERT_EXPR 223146895Skan || TREE_CODE (exp0) == NON_LVALUE_EXPR) 224146895Skan && TREE_OPERAND (exp0, 0) != error_mark_node 225146895Skan && TYPE_PRECISION (TREE_TYPE (exp0)) 226146895Skan <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp0, 0)))) 227146895Skan exp0 = TREE_OPERAND (exp0, 0); 228146895Skan 229146895Skan /* "exp0 ^ 1" inverts the sense of the single bit test. */ 230146895Skan if (TREE_CODE (exp0) == BIT_XOR_EXPR 231146895Skan && integer_onep (TREE_OPERAND (exp0, 1))) 232146895Skan { 233146895Skan exp0 = TREE_OPERAND (exp0, 0); 234146895Skan clr_label = if_true_label; 235146895Skan set_label = if_false_label; 236146895Skan } 237146895Skan else 238146895Skan { 239146895Skan clr_label = if_false_label; 240146895Skan set_label = if_true_label; 241146895Skan } 242146895Skan 243146895Skan if (TREE_CODE (exp0) == RSHIFT_EXPR) 244146895Skan { 245146895Skan tree arg = TREE_OPERAND (exp0, 0); 246146895Skan tree shift = TREE_OPERAND (exp0, 1); 247146895Skan tree argtype = TREE_TYPE (arg); 248146895Skan if (TREE_CODE (shift) == INTEGER_CST 249146895Skan && compare_tree_int (shift, 0) >= 0 250146895Skan && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0 251146895Skan && prefer_and_bit_test (TYPE_MODE (argtype), 252146895Skan TREE_INT_CST_LOW (shift))) 253146895Skan { 254146895Skan HOST_WIDE_INT mask = (HOST_WIDE_INT) 1 255146895Skan << TREE_INT_CST_LOW (shift); 256169689Skan do_jump (build2 (BIT_AND_EXPR, argtype, arg, 257169689Skan build_int_cst_type (argtype, mask)), 258146895Skan clr_label, set_label); 259146895Skan break; 260146895Skan } 261146895Skan } 262146895Skan } 263146895Skan 264132718Skan /* If we are AND'ing with a small constant, do this comparison in the 265132718Skan smallest type that fits. If the machine doesn't have comparisons 266132718Skan that small, it will be converted back to the wider comparison. 267132718Skan This helps if we are testing the sign bit of a narrower object. 268132718Skan combine can't do this for us because it can't know whether a 269132718Skan ZERO_EXTRACT or a compare in a smaller mode exists, but we do. */ 270132718Skan 271132718Skan if (! SLOW_BYTE_ACCESS 272132718Skan && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST 273132718Skan && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT 274132718Skan && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0 275132718Skan && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode 276169689Skan && (type = lang_hooks.types.type_for_mode (mode, 1)) != 0 277132718Skan && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp)) 278132718Skan && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code 279132718Skan != CODE_FOR_nothing)) 280132718Skan { 281169689Skan do_jump (fold_convert (type, exp), if_false_label, if_true_label); 282132718Skan break; 283132718Skan } 284132718Skan goto normal; 285132718Skan 286132718Skan case TRUTH_NOT_EXPR: 287132718Skan do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label); 288132718Skan break; 289132718Skan 290169689Skan case COND_EXPR: 291169689Skan { 292169689Skan rtx label1 = gen_label_rtx (); 293169689Skan if (!if_true_label || !if_false_label) 294169689Skan { 295169689Skan drop_through_label = gen_label_rtx (); 296169689Skan if (!if_true_label) 297169689Skan if_true_label = drop_through_label; 298169689Skan if (!if_false_label) 299169689Skan if_false_label = drop_through_label; 300169689Skan } 301169689Skan 302169689Skan do_pending_stack_adjust (); 303169689Skan do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX); 304169689Skan do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); 305169689Skan emit_label (label1); 306169689Skan do_jump (TREE_OPERAND (exp, 2), if_false_label, if_true_label); 307169689Skan break; 308169689Skan } 309169689Skan 310132718Skan case TRUTH_ANDIF_EXPR: 311132718Skan case TRUTH_ORIF_EXPR: 312132718Skan case COMPOUND_EXPR: 313169689Skan /* Lowered by gimplify.c. */ 314169689Skan gcc_unreachable (); 315132718Skan 316132718Skan case COMPONENT_REF: 317132718Skan case BIT_FIELD_REF: 318132718Skan case ARRAY_REF: 319132718Skan case ARRAY_RANGE_REF: 320132718Skan { 321132718Skan HOST_WIDE_INT bitsize, bitpos; 322132718Skan int unsignedp; 323132718Skan enum machine_mode mode; 324132718Skan tree type; 325132718Skan tree offset; 326132718Skan int volatilep = 0; 327132718Skan 328132718Skan /* Get description of this reference. We don't actually care 329132718Skan about the underlying object here. */ 330132718Skan get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode, 331169689Skan &unsignedp, &volatilep, false); 332132718Skan 333169689Skan type = lang_hooks.types.type_for_size (bitsize, unsignedp); 334132718Skan if (! SLOW_BYTE_ACCESS 335132718Skan && type != 0 && bitsize >= 0 336132718Skan && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp)) 337132718Skan && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code 338169689Skan != CODE_FOR_nothing)) 339132718Skan { 340169689Skan do_jump (fold_convert (type, exp), if_false_label, if_true_label); 341132718Skan break; 342132718Skan } 343132718Skan goto normal; 344132718Skan } 345132718Skan 346132718Skan case EQ_EXPR: 347132718Skan { 348132718Skan tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); 349132718Skan 350169689Skan gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type)) 351169689Skan != MODE_COMPLEX_FLOAT); 352169689Skan gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type)) 353169689Skan != MODE_COMPLEX_INT); 354169689Skan 355169689Skan if (integer_zerop (TREE_OPERAND (exp, 1))) 356132718Skan do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label); 357132718Skan else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT 358132718Skan && !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump)) 359132718Skan do_jump_by_parts_equality (exp, if_false_label, if_true_label); 360132718Skan else 361132718Skan do_compare_and_jump (exp, EQ, EQ, if_false_label, if_true_label); 362132718Skan break; 363132718Skan } 364132718Skan 365169689Skan case MINUS_EXPR: 366169689Skan /* Nonzero iff operands of minus differ. */ 367169689Skan exp = build2 (NE_EXPR, TREE_TYPE (exp), 368169689Skan TREE_OPERAND (exp, 0), 369169689Skan TREE_OPERAND (exp, 1)); 370169689Skan /* FALLTHRU */ 371132718Skan case NE_EXPR: 372132718Skan { 373132718Skan tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); 374132718Skan 375169689Skan gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type)) 376169689Skan != MODE_COMPLEX_FLOAT); 377169689Skan gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type)) 378169689Skan != MODE_COMPLEX_INT); 379169689Skan 380169689Skan if (integer_zerop (TREE_OPERAND (exp, 1))) 381132718Skan do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label); 382132718Skan else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT 383132718Skan && !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump)) 384132718Skan do_jump_by_parts_equality (exp, if_true_label, if_false_label); 385132718Skan else 386132718Skan do_compare_and_jump (exp, NE, NE, if_false_label, if_true_label); 387132718Skan break; 388132718Skan } 389132718Skan 390132718Skan case LT_EXPR: 391132718Skan mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); 392132718Skan if (GET_MODE_CLASS (mode) == MODE_INT 393132718Skan && ! can_compare_p (LT, mode, ccp_jump)) 394132718Skan do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label); 395132718Skan else 396132718Skan do_compare_and_jump (exp, LT, LTU, if_false_label, if_true_label); 397132718Skan break; 398132718Skan 399132718Skan case LE_EXPR: 400132718Skan mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); 401132718Skan if (GET_MODE_CLASS (mode) == MODE_INT 402132718Skan && ! can_compare_p (LE, mode, ccp_jump)) 403132718Skan do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label); 404132718Skan else 405132718Skan do_compare_and_jump (exp, LE, LEU, if_false_label, if_true_label); 406132718Skan break; 407132718Skan 408132718Skan case GT_EXPR: 409132718Skan mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); 410132718Skan if (GET_MODE_CLASS (mode) == MODE_INT 411132718Skan && ! can_compare_p (GT, mode, ccp_jump)) 412132718Skan do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label); 413132718Skan else 414132718Skan do_compare_and_jump (exp, GT, GTU, if_false_label, if_true_label); 415132718Skan break; 416132718Skan 417132718Skan case GE_EXPR: 418132718Skan mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); 419132718Skan if (GET_MODE_CLASS (mode) == MODE_INT 420132718Skan && ! can_compare_p (GE, mode, ccp_jump)) 421132718Skan do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label); 422132718Skan else 423132718Skan do_compare_and_jump (exp, GE, GEU, if_false_label, if_true_label); 424132718Skan break; 425132718Skan 426132718Skan case UNORDERED_EXPR: 427132718Skan case ORDERED_EXPR: 428132718Skan { 429132718Skan enum rtx_code cmp, rcmp; 430132718Skan int do_rev; 431132718Skan 432132718Skan if (code == UNORDERED_EXPR) 433132718Skan cmp = UNORDERED, rcmp = ORDERED; 434132718Skan else 435132718Skan cmp = ORDERED, rcmp = UNORDERED; 436132718Skan mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); 437132718Skan 438132718Skan do_rev = 0; 439132718Skan if (! can_compare_p (cmp, mode, ccp_jump) 440132718Skan && (can_compare_p (rcmp, mode, ccp_jump) 441132718Skan /* If the target doesn't provide either UNORDERED or ORDERED 442132718Skan comparisons, canonicalize on UNORDERED for the library. */ 443132718Skan || rcmp == UNORDERED)) 444132718Skan do_rev = 1; 445132718Skan 446132718Skan if (! do_rev) 447132718Skan do_compare_and_jump (exp, cmp, cmp, if_false_label, if_true_label); 448132718Skan else 449132718Skan do_compare_and_jump (exp, rcmp, rcmp, if_true_label, if_false_label); 450132718Skan } 451132718Skan break; 452132718Skan 453132718Skan { 454132718Skan enum rtx_code rcode1; 455169689Skan enum tree_code tcode1, tcode2; 456132718Skan 457132718Skan case UNLT_EXPR: 458132718Skan rcode1 = UNLT; 459169689Skan tcode1 = UNORDERED_EXPR; 460132718Skan tcode2 = LT_EXPR; 461132718Skan goto unordered_bcc; 462132718Skan case UNLE_EXPR: 463132718Skan rcode1 = UNLE; 464169689Skan tcode1 = UNORDERED_EXPR; 465132718Skan tcode2 = LE_EXPR; 466132718Skan goto unordered_bcc; 467132718Skan case UNGT_EXPR: 468132718Skan rcode1 = UNGT; 469169689Skan tcode1 = UNORDERED_EXPR; 470132718Skan tcode2 = GT_EXPR; 471132718Skan goto unordered_bcc; 472132718Skan case UNGE_EXPR: 473132718Skan rcode1 = UNGE; 474169689Skan tcode1 = UNORDERED_EXPR; 475132718Skan tcode2 = GE_EXPR; 476132718Skan goto unordered_bcc; 477132718Skan case UNEQ_EXPR: 478132718Skan rcode1 = UNEQ; 479169689Skan tcode1 = UNORDERED_EXPR; 480132718Skan tcode2 = EQ_EXPR; 481132718Skan goto unordered_bcc; 482169689Skan case LTGT_EXPR: 483169689Skan /* It is ok for LTGT_EXPR to trap when the result is unordered, 484169689Skan so expand to (a < b) || (a > b). */ 485169689Skan rcode1 = LTGT; 486169689Skan tcode1 = LT_EXPR; 487169689Skan tcode2 = GT_EXPR; 488169689Skan goto unordered_bcc; 489132718Skan 490132718Skan unordered_bcc: 491132718Skan mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); 492132718Skan if (can_compare_p (rcode1, mode, ccp_jump)) 493132718Skan do_compare_and_jump (exp, rcode1, rcode1, if_false_label, 494132718Skan if_true_label); 495132718Skan else 496132718Skan { 497132718Skan tree op0 = save_expr (TREE_OPERAND (exp, 0)); 498132718Skan tree op1 = save_expr (TREE_OPERAND (exp, 1)); 499132718Skan tree cmp0, cmp1; 500132718Skan 501132718Skan /* If the target doesn't support combined unordered 502169689Skan compares, decompose into two comparisons. */ 503169689Skan if (if_true_label == 0) 504169689Skan drop_through_label = if_true_label = gen_label_rtx (); 505169689Skan 506169689Skan cmp0 = fold_build2 (tcode1, TREE_TYPE (exp), op0, op1); 507169689Skan cmp1 = fold_build2 (tcode2, TREE_TYPE (exp), op0, op1); 508169689Skan do_jump (cmp0, 0, if_true_label); 509169689Skan do_jump (cmp1, if_false_label, if_true_label); 510132718Skan } 511132718Skan } 512132718Skan break; 513132718Skan 514169689Skan case TRUTH_AND_EXPR: 515169689Skan /* High branch cost, expand as the bitwise AND of the conditions. 516169689Skan Do the same if the RHS has side effects, because we're effectively 517169689Skan turning a TRUTH_AND_EXPR into a TRUTH_ANDIF_EXPR. */ 518169689Skan if (BRANCH_COST >= 4 || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1))) 519169689Skan goto normal; 520169689Skan 521169689Skan if (if_false_label == NULL_RTX) 522169689Skan { 523169689Skan drop_through_label = gen_label_rtx (); 524169689Skan do_jump (TREE_OPERAND (exp, 0), drop_through_label, NULL_RTX); 525169689Skan do_jump (TREE_OPERAND (exp, 1), NULL_RTX, if_true_label); 526169689Skan } 527169689Skan else 528169689Skan { 529169689Skan do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX); 530169689Skan do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); 531169689Skan } 532169689Skan break; 533169689Skan 534169689Skan case TRUTH_OR_EXPR: 535169689Skan /* High branch cost, expand as the bitwise OR of the conditions. 536169689Skan Do the same if the RHS has side effects, because we're effectively 537169689Skan turning a TRUTH_OR_EXPR into a TRUTH_ORIF_EXPR. */ 538169689Skan if (BRANCH_COST >= 4 || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1))) 539169689Skan goto normal; 540169689Skan 541169689Skan if (if_true_label == NULL_RTX) 542169689Skan { 543169689Skan drop_through_label = gen_label_rtx (); 544169689Skan do_jump (TREE_OPERAND (exp, 0), NULL_RTX, drop_through_label); 545169689Skan do_jump (TREE_OPERAND (exp, 1), if_false_label, NULL_RTX); 546169689Skan } 547169689Skan else 548169689Skan { 549169689Skan do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label); 550169689Skan do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); 551169689Skan } 552169689Skan break; 553169689Skan 554132718Skan /* Special case: 555132718Skan __builtin_expect (<test>, 0) and 556132718Skan __builtin_expect (<test>, 1) 557132718Skan 558132718Skan We need to do this here, so that <test> is not converted to a SCC 559132718Skan operation on machines that use condition code registers and COMPARE 560132718Skan like the PowerPC, and then the jump is done based on whether the SCC 561132718Skan operation produced a 1 or 0. */ 562132718Skan case CALL_EXPR: 563132718Skan /* Check for a built-in function. */ 564132718Skan { 565132718Skan tree fndecl = get_callee_fndecl (exp); 566132718Skan tree arglist = TREE_OPERAND (exp, 1); 567132718Skan 568132718Skan if (fndecl 569169689Skan && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 570132718Skan && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT 571132718Skan && arglist != NULL_TREE 572132718Skan && TREE_CHAIN (arglist) != NULL_TREE) 573132718Skan { 574132718Skan rtx seq = expand_builtin_expect_jump (exp, if_false_label, 575132718Skan if_true_label); 576132718Skan 577132718Skan if (seq != NULL_RTX) 578132718Skan { 579132718Skan emit_insn (seq); 580132718Skan return; 581132718Skan } 582132718Skan } 583132718Skan } 584169689Skan 585132718Skan /* Fall through and generate the normal code. */ 586132718Skan default: 587132718Skan normal: 588169689Skan temp = expand_normal (exp); 589132718Skan do_pending_stack_adjust (); 590169689Skan /* The RTL optimizers prefer comparisons against pseudos. */ 591169689Skan if (GET_CODE (temp) == SUBREG) 592132718Skan { 593169689Skan /* Compare promoted variables in their promoted mode. */ 594169689Skan if (SUBREG_PROMOTED_VAR_P (temp) 595169689Skan && REG_P (XEXP (temp, 0))) 596169689Skan temp = XEXP (temp, 0); 597169689Skan else 598169689Skan temp = copy_to_reg (temp); 599132718Skan } 600169689Skan do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)), 601169689Skan NE, TYPE_UNSIGNED (TREE_TYPE (exp)), 602169689Skan GET_MODE (temp), NULL_RTX, 603169689Skan if_false_label, if_true_label); 604132718Skan } 605132718Skan 606132718Skan if (drop_through_label) 607132718Skan { 608132718Skan do_pending_stack_adjust (); 609132718Skan emit_label (drop_through_label); 610132718Skan } 611132718Skan} 612132718Skan 613132718Skan/* Compare OP0 with OP1, word at a time, in mode MODE. 614132718Skan UNSIGNEDP says to do unsigned comparison. 615132718Skan Jump to IF_TRUE_LABEL if OP0 is greater, IF_FALSE_LABEL otherwise. */ 616132718Skan 617169689Skanstatic void 618132718Skando_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0, 619132718Skan rtx op1, rtx if_false_label, rtx if_true_label) 620132718Skan{ 621132718Skan int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); 622132718Skan rtx drop_through_label = 0; 623132718Skan int i; 624132718Skan 625132718Skan if (! if_true_label || ! if_false_label) 626132718Skan drop_through_label = gen_label_rtx (); 627132718Skan if (! if_true_label) 628132718Skan if_true_label = drop_through_label; 629132718Skan if (! if_false_label) 630132718Skan if_false_label = drop_through_label; 631132718Skan 632132718Skan /* Compare a word at a time, high order first. */ 633132718Skan for (i = 0; i < nwords; i++) 634132718Skan { 635132718Skan rtx op0_word, op1_word; 636132718Skan 637132718Skan if (WORDS_BIG_ENDIAN) 638132718Skan { 639132718Skan op0_word = operand_subword_force (op0, i, mode); 640132718Skan op1_word = operand_subword_force (op1, i, mode); 641132718Skan } 642132718Skan else 643132718Skan { 644132718Skan op0_word = operand_subword_force (op0, nwords - 1 - i, mode); 645132718Skan op1_word = operand_subword_force (op1, nwords - 1 - i, mode); 646132718Skan } 647132718Skan 648132718Skan /* All but high-order word must be compared as unsigned. */ 649132718Skan do_compare_rtx_and_jump (op0_word, op1_word, GT, 650132718Skan (unsignedp || i > 0), word_mode, NULL_RTX, 651132718Skan NULL_RTX, if_true_label); 652132718Skan 653132718Skan /* Consider lower words only if these are equal. */ 654132718Skan do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode, 655132718Skan NULL_RTX, NULL_RTX, if_false_label); 656132718Skan } 657132718Skan 658132718Skan if (if_false_label) 659132718Skan emit_jump (if_false_label); 660132718Skan if (drop_through_label) 661132718Skan emit_label (drop_through_label); 662132718Skan} 663132718Skan 664169689Skan/* Given a comparison expression EXP for values too wide to be compared 665169689Skan with one insn, test the comparison and jump to the appropriate label. 666169689Skan The code of EXP is ignored; we always test GT if SWAP is 0, 667169689Skan and LT if SWAP is 1. */ 668132718Skan 669132718Skanstatic void 670169689Skando_jump_by_parts_greater (tree exp, int swap, rtx if_false_label, 671169689Skan rtx if_true_label) 672132718Skan{ 673169689Skan rtx op0 = expand_normal (TREE_OPERAND (exp, swap)); 674169689Skan rtx op1 = expand_normal (TREE_OPERAND (exp, !swap)); 675132718Skan enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); 676169689Skan int unsignedp = TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))); 677132718Skan 678169689Skan do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label, 679169689Skan if_true_label); 680132718Skan} 681132718Skan 682169689Skan/* Jump according to whether OP0 is 0. We assume that OP0 has an integer 683169689Skan mode, MODE, that is too wide for the available compare insns. Either 684169689Skan Either (but not both) of IF_TRUE_LABEL and IF_FALSE_LABEL may be NULL_RTX 685169689Skan to indicate drop through. */ 686132718Skan 687169689Skanstatic void 688169689Skando_jump_by_parts_zero_rtx (enum machine_mode mode, rtx op0, 689169689Skan rtx if_false_label, rtx if_true_label) 690132718Skan{ 691169689Skan int nwords = GET_MODE_SIZE (mode) / UNITS_PER_WORD; 692132718Skan rtx part; 693132718Skan int i; 694132718Skan rtx drop_through_label = 0; 695132718Skan 696132718Skan /* The fastest way of doing this comparison on almost any machine is to 697132718Skan "or" all the words and compare the result. If all have to be loaded 698132718Skan from memory and this is a very wide item, it's possible this may 699132718Skan be slower, but that's highly unlikely. */ 700132718Skan 701132718Skan part = gen_reg_rtx (word_mode); 702132718Skan emit_move_insn (part, operand_subword_force (op0, 0, GET_MODE (op0))); 703132718Skan for (i = 1; i < nwords && part != 0; i++) 704132718Skan part = expand_binop (word_mode, ior_optab, part, 705132718Skan operand_subword_force (op0, i, GET_MODE (op0)), 706132718Skan part, 1, OPTAB_WIDEN); 707132718Skan 708132718Skan if (part != 0) 709132718Skan { 710132718Skan do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, word_mode, 711132718Skan NULL_RTX, if_false_label, if_true_label); 712132718Skan 713132718Skan return; 714132718Skan } 715132718Skan 716132718Skan /* If we couldn't do the "or" simply, do this with a series of compares. */ 717132718Skan if (! if_false_label) 718132718Skan drop_through_label = if_false_label = gen_label_rtx (); 719132718Skan 720132718Skan for (i = 0; i < nwords; i++) 721132718Skan do_compare_rtx_and_jump (operand_subword_force (op0, i, GET_MODE (op0)), 722132718Skan const0_rtx, EQ, 1, word_mode, NULL_RTX, 723132718Skan if_false_label, NULL_RTX); 724132718Skan 725132718Skan if (if_true_label) 726132718Skan emit_jump (if_true_label); 727132718Skan 728132718Skan if (drop_through_label) 729132718Skan emit_label (drop_through_label); 730132718Skan} 731169689Skan 732169689Skan/* Test for the equality of two RTX expressions OP0 and OP1 in mode MODE, 733169689Skan where MODE is an integer mode too wide to be compared with one insn. 734169689Skan Either (but not both) of IF_TRUE_LABEL and IF_FALSE_LABEL may be NULL_RTX 735169689Skan to indicate drop through. */ 736169689Skan 737169689Skanstatic void 738169689Skando_jump_by_parts_equality_rtx (enum machine_mode mode, rtx op0, rtx op1, 739169689Skan rtx if_false_label, rtx if_true_label) 740169689Skan{ 741169689Skan int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); 742169689Skan rtx drop_through_label = 0; 743169689Skan int i; 744169689Skan 745169689Skan if (op1 == const0_rtx) 746169689Skan { 747169689Skan do_jump_by_parts_zero_rtx (mode, op0, if_false_label, if_true_label); 748169689Skan return; 749169689Skan } 750169689Skan else if (op0 == const0_rtx) 751169689Skan { 752169689Skan do_jump_by_parts_zero_rtx (mode, op1, if_false_label, if_true_label); 753169689Skan return; 754169689Skan } 755169689Skan 756169689Skan if (! if_false_label) 757169689Skan drop_through_label = if_false_label = gen_label_rtx (); 758169689Skan 759169689Skan for (i = 0; i < nwords; i++) 760169689Skan do_compare_rtx_and_jump (operand_subword_force (op0, i, mode), 761169689Skan operand_subword_force (op1, i, mode), 762169689Skan EQ, 0, word_mode, NULL_RTX, 763169689Skan if_false_label, NULL_RTX); 764169689Skan 765169689Skan if (if_true_label) 766169689Skan emit_jump (if_true_label); 767169689Skan if (drop_through_label) 768169689Skan emit_label (drop_through_label); 769169689Skan} 770169689Skan 771169689Skan/* Given an EQ_EXPR expression EXP for values too wide to be compared 772169689Skan with one insn, test the comparison and jump to the appropriate label. */ 773169689Skan 774169689Skanstatic void 775169689Skando_jump_by_parts_equality (tree exp, rtx if_false_label, rtx if_true_label) 776169689Skan{ 777169689Skan rtx op0 = expand_normal (TREE_OPERAND (exp, 0)); 778169689Skan rtx op1 = expand_normal (TREE_OPERAND (exp, 1)); 779169689Skan enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); 780169689Skan do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label, 781169689Skan if_true_label); 782169689Skan} 783132718Skan 784132718Skan/* Generate code for a comparison of OP0 and OP1 with rtx code CODE. 785169689Skan MODE is the machine mode of the comparison, not of the result. 786169689Skan (including code to compute the values to be compared) and set CC0 787169689Skan according to the result. The decision as to signed or unsigned 788169689Skan comparison must be made by the caller. 789132718Skan 790132718Skan We force a stack adjustment unless there are currently 791132718Skan things pushed on the stack that aren't yet used. 792132718Skan 793132718Skan If MODE is BLKmode, SIZE is an RTX giving the size of the objects being 794132718Skan compared. */ 795132718Skan 796132718Skanrtx 797132718Skancompare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp, 798132718Skan enum machine_mode mode, rtx size) 799132718Skan{ 800132718Skan rtx tem; 801132718Skan 802132718Skan /* If one operand is constant, make it the second one. Only do this 803132718Skan if the other operand is not constant as well. */ 804132718Skan 805132718Skan if (swap_commutative_operands_p (op0, op1)) 806132718Skan { 807132718Skan tem = op0; 808132718Skan op0 = op1; 809132718Skan op1 = tem; 810132718Skan code = swap_condition (code); 811132718Skan } 812132718Skan 813132718Skan do_pending_stack_adjust (); 814132718Skan 815169689Skan code = unsignedp ? unsigned_condition (code) : code; 816169689Skan tem = simplify_relational_operation (code, VOIDmode, mode, op0, op1); 817169689Skan if (tem) 818169689Skan { 819169689Skan if (CONSTANT_P (tem)) 820169689Skan return tem; 821132718Skan 822169689Skan if (COMPARISON_P (tem)) 823169689Skan { 824169689Skan code = GET_CODE (tem); 825169689Skan op0 = XEXP (tem, 0); 826169689Skan op1 = XEXP (tem, 1); 827169689Skan mode = GET_MODE (op0); 828169689Skan unsignedp = (code == GTU || code == LTU 829169689Skan || code == GEU || code == LEU); 830169689Skan } 831132718Skan } 832132718Skan 833132718Skan emit_cmp_insn (op0, op1, code, size, mode, unsignedp); 834132718Skan 835132718Skan#if HAVE_cc0 836132718Skan return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx); 837132718Skan#else 838132718Skan return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); 839132718Skan#endif 840132718Skan} 841132718Skan 842132718Skan/* Like do_compare_and_jump but expects the values to compare as two rtx's. 843132718Skan The decision as to signed or unsigned comparison must be made by the caller. 844132718Skan 845132718Skan If MODE is BLKmode, SIZE is an RTX giving the size of the objects being 846132718Skan compared. */ 847132718Skan 848132718Skanvoid 849132718Skando_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, 850132718Skan enum machine_mode mode, rtx size, rtx if_false_label, 851132718Skan rtx if_true_label) 852132718Skan{ 853132718Skan rtx tem; 854132718Skan int dummy_true_label = 0; 855132718Skan 856132718Skan /* Reverse the comparison if that is safe and we want to jump if it is 857132718Skan false. */ 858132718Skan if (! if_true_label && ! FLOAT_MODE_P (mode)) 859132718Skan { 860132718Skan if_true_label = if_false_label; 861132718Skan if_false_label = 0; 862132718Skan code = reverse_condition (code); 863132718Skan } 864132718Skan 865132718Skan /* If one operand is constant, make it the second one. Only do this 866132718Skan if the other operand is not constant as well. */ 867132718Skan 868132718Skan if (swap_commutative_operands_p (op0, op1)) 869132718Skan { 870132718Skan tem = op0; 871132718Skan op0 = op1; 872132718Skan op1 = tem; 873132718Skan code = swap_condition (code); 874132718Skan } 875132718Skan 876132718Skan do_pending_stack_adjust (); 877132718Skan 878169689Skan code = unsignedp ? unsigned_condition (code) : code; 879169689Skan if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode, 880169689Skan op0, op1))) 881132718Skan { 882169689Skan if (CONSTANT_P (tem)) 883169689Skan { 884169689Skan rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode)) 885169689Skan ? if_false_label : if_true_label; 886169689Skan if (label) 887169689Skan emit_jump (label); 888169689Skan return; 889169689Skan } 890169689Skan 891169689Skan code = GET_CODE (tem); 892169689Skan mode = GET_MODE (tem); 893169689Skan op0 = XEXP (tem, 0); 894169689Skan op1 = XEXP (tem, 1); 895169689Skan unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU); 896132718Skan } 897132718Skan 898132718Skan 899132718Skan if (! if_true_label) 900132718Skan { 901132718Skan dummy_true_label = 1; 902132718Skan if_true_label = gen_label_rtx (); 903132718Skan } 904132718Skan 905169689Skan if (GET_MODE_CLASS (mode) == MODE_INT 906169689Skan && ! can_compare_p (code, mode, ccp_jump)) 907169689Skan { 908169689Skan switch (code) 909169689Skan { 910169689Skan case LTU: 911169689Skan do_jump_by_parts_greater_rtx (mode, 1, op1, op0, 912169689Skan if_false_label, if_true_label); 913169689Skan break; 914132718Skan 915169689Skan case LEU: 916169689Skan do_jump_by_parts_greater_rtx (mode, 1, op0, op1, 917169689Skan if_true_label, if_false_label); 918169689Skan break; 919169689Skan 920169689Skan case GTU: 921169689Skan do_jump_by_parts_greater_rtx (mode, 1, op0, op1, 922169689Skan if_false_label, if_true_label); 923169689Skan break; 924169689Skan 925169689Skan case GEU: 926169689Skan do_jump_by_parts_greater_rtx (mode, 1, op1, op0, 927169689Skan if_true_label, if_false_label); 928169689Skan break; 929169689Skan 930169689Skan case LT: 931169689Skan do_jump_by_parts_greater_rtx (mode, 0, op1, op0, 932169689Skan if_false_label, if_true_label); 933169689Skan break; 934169689Skan 935169689Skan case LE: 936169689Skan do_jump_by_parts_greater_rtx (mode, 0, op0, op1, 937169689Skan if_true_label, if_false_label); 938169689Skan break; 939169689Skan 940169689Skan case GT: 941169689Skan do_jump_by_parts_greater_rtx (mode, 0, op0, op1, 942169689Skan if_false_label, if_true_label); 943169689Skan break; 944169689Skan 945169689Skan case GE: 946169689Skan do_jump_by_parts_greater_rtx (mode, 0, op1, op0, 947169689Skan if_true_label, if_false_label); 948169689Skan break; 949169689Skan 950169689Skan case EQ: 951169689Skan do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label, 952169689Skan if_true_label); 953169689Skan break; 954169689Skan 955169689Skan case NE: 956169689Skan do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label, 957169689Skan if_false_label); 958169689Skan break; 959169689Skan 960169689Skan default: 961169689Skan gcc_unreachable (); 962169689Skan } 963169689Skan } 964169689Skan else 965169689Skan emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp, 966169689Skan if_true_label); 967169689Skan 968132718Skan if (if_false_label) 969132718Skan emit_jump (if_false_label); 970132718Skan if (dummy_true_label) 971132718Skan emit_label (if_true_label); 972132718Skan} 973132718Skan 974132718Skan/* Generate code for a comparison expression EXP (including code to compute 975132718Skan the values to be compared) and a conditional jump to IF_FALSE_LABEL and/or 976132718Skan IF_TRUE_LABEL. One of the labels can be NULL_RTX, in which case the 977132718Skan generated code will drop through. 978132718Skan SIGNED_CODE should be the rtx operation for this comparison for 979132718Skan signed data; UNSIGNED_CODE, likewise for use if data is unsigned. 980132718Skan 981132718Skan We force a stack adjustment unless there are currently 982132718Skan things pushed on the stack that aren't yet used. */ 983132718Skan 984132718Skanstatic void 985132718Skando_compare_and_jump (tree exp, enum rtx_code signed_code, 986132718Skan enum rtx_code unsigned_code, rtx if_false_label, 987132718Skan rtx if_true_label) 988132718Skan{ 989132718Skan rtx op0, op1; 990132718Skan tree type; 991132718Skan enum machine_mode mode; 992132718Skan int unsignedp; 993132718Skan enum rtx_code code; 994132718Skan 995132718Skan /* Don't crash if the comparison was erroneous. */ 996169689Skan op0 = expand_normal (TREE_OPERAND (exp, 0)); 997132718Skan if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK) 998132718Skan return; 999132718Skan 1000169689Skan op1 = expand_normal (TREE_OPERAND (exp, 1)); 1001132718Skan if (TREE_CODE (TREE_OPERAND (exp, 1)) == ERROR_MARK) 1002132718Skan return; 1003132718Skan 1004132718Skan type = TREE_TYPE (TREE_OPERAND (exp, 0)); 1005132718Skan mode = TYPE_MODE (type); 1006132718Skan if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST 1007132718Skan && (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST 1008132718Skan || (GET_MODE_BITSIZE (mode) 1009132718Skan > GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1010132718Skan 1))))))) 1011132718Skan { 1012132718Skan /* op0 might have been replaced by promoted constant, in which 1013132718Skan case the type of second argument should be used. */ 1014132718Skan type = TREE_TYPE (TREE_OPERAND (exp, 1)); 1015132718Skan mode = TYPE_MODE (type); 1016132718Skan } 1017169689Skan unsignedp = TYPE_UNSIGNED (type); 1018132718Skan code = unsignedp ? unsigned_code : signed_code; 1019132718Skan 1020132718Skan#ifdef HAVE_canonicalize_funcptr_for_compare 1021132718Skan /* If function pointers need to be "canonicalized" before they can 1022169689Skan be reliably compared, then canonicalize them. 1023169689Skan Only do this if *both* sides of the comparison are function pointers. 1024169689Skan If one side isn't, we want a noncanonicalized comparison. See PR 1025169689Skan middle-end/17564. */ 1026132718Skan if (HAVE_canonicalize_funcptr_for_compare 1027132718Skan && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE 1028169689Skan && TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)))) 1029169689Skan == FUNCTION_TYPE 1030169689Skan && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 1))) == POINTER_TYPE 1031169689Skan && TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1)))) 1032169689Skan == FUNCTION_TYPE) 1033132718Skan { 1034132718Skan rtx new_op0 = gen_reg_rtx (mode); 1035169689Skan rtx new_op1 = gen_reg_rtx (mode); 1036132718Skan 1037132718Skan emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0)); 1038132718Skan op0 = new_op0; 1039132718Skan 1040132718Skan emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1)); 1041132718Skan op1 = new_op1; 1042132718Skan } 1043132718Skan#endif 1044132718Skan 1045132718Skan do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, 1046132718Skan ((mode == BLKmode) 1047132718Skan ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX), 1048132718Skan if_false_label, if_true_label); 1049132718Skan} 1050146895Skan 1051146895Skan#include "gt-dojump.h" 1052