190075Sobrien/* RTL simplification functions for GNU compiler. 290075Sobrien Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3169689Skan 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 4169689Skan Free Software Foundation, Inc. 590075Sobrien 690075SobrienThis file is part of GCC. 790075Sobrien 890075SobrienGCC is free software; you can redistribute it and/or modify it under 990075Sobrienthe terms of the GNU General Public License as published by the Free 1090075SobrienSoftware Foundation; either version 2, or (at your option) any later 1190075Sobrienversion. 1290075Sobrien 1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690075Sobrienfor more details. 1790075Sobrien 1890075SobrienYou should have received a copy of the GNU General Public License 1990075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 2290075Sobrien 2390075Sobrien 2490075Sobrien#include "config.h" 2590075Sobrien#include "system.h" 26132718Skan#include "coretypes.h" 27132718Skan#include "tm.h" 2890075Sobrien#include "rtl.h" 29117395Skan#include "tree.h" 3090075Sobrien#include "tm_p.h" 3190075Sobrien#include "regs.h" 3290075Sobrien#include "hard-reg-set.h" 3390075Sobrien#include "flags.h" 3490075Sobrien#include "real.h" 3590075Sobrien#include "insn-config.h" 3690075Sobrien#include "recog.h" 3790075Sobrien#include "function.h" 3890075Sobrien#include "expr.h" 3990075Sobrien#include "toplev.h" 4090075Sobrien#include "output.h" 4190075Sobrien#include "ggc.h" 42132718Skan#include "target.h" 4390075Sobrien 4490075Sobrien/* Simplification and canonicalization of RTL. */ 4590075Sobrien 4690075Sobrien/* Much code operates on (low, high) pairs; the low value is an 4790075Sobrien unsigned wide int, the high value a signed wide int. We 4890075Sobrien occasionally need to sign extend from low to high as if low were a 4990075Sobrien signed wide int. */ 5090075Sobrien#define HWI_SIGN_EXTEND(low) \ 5190075Sobrien ((((HOST_WIDE_INT) low) < 0) ? ((HOST_WIDE_INT) -1) : ((HOST_WIDE_INT) 0)) 5290075Sobrien 53132718Skanstatic rtx neg_const_int (enum machine_mode, rtx); 54169689Skanstatic bool plus_minus_operand_p (rtx); 55132718Skanstatic int simplify_plus_minus_op_data_cmp (const void *, const void *); 56169689Skanstatic rtx simplify_plus_minus (enum rtx_code, enum machine_mode, rtx, rtx); 57132718Skanstatic rtx simplify_immed_subreg (enum machine_mode, rtx, enum machine_mode, 58132718Skan unsigned int); 59132718Skanstatic rtx simplify_associative_operation (enum rtx_code, enum machine_mode, 60132718Skan rtx, rtx); 61169689Skanstatic rtx simplify_relational_operation_1 (enum rtx_code, enum machine_mode, 62169689Skan enum machine_mode, rtx, rtx); 63169689Skanstatic rtx simplify_unary_operation_1 (enum rtx_code, enum machine_mode, rtx); 64169689Skanstatic rtx simplify_binary_operation_1 (enum rtx_code, enum machine_mode, 65169689Skan rtx, rtx, rtx, rtx); 6690075Sobrien 6790075Sobrien/* Negate a CONST_INT rtx, truncating (because a conversion from a 6890075Sobrien maximally negative number can overflow). */ 6990075Sobrienstatic rtx 70132718Skanneg_const_int (enum machine_mode mode, rtx i) 7190075Sobrien{ 72117395Skan return gen_int_mode (- INTVAL (i), mode); 7390075Sobrien} 7490075Sobrien 75169689Skan/* Test whether expression, X, is an immediate constant that represents 76169689Skan the most significant bit of machine mode MODE. */ 77169689Skan 78169689Skanbool 79169689Skanmode_signbit_p (enum machine_mode mode, rtx x) 80169689Skan{ 81169689Skan unsigned HOST_WIDE_INT val; 82169689Skan unsigned int width; 83169689Skan 84169689Skan if (GET_MODE_CLASS (mode) != MODE_INT) 85169689Skan return false; 86169689Skan 87169689Skan width = GET_MODE_BITSIZE (mode); 88169689Skan if (width == 0) 89169689Skan return false; 90169689Skan 91169689Skan if (width <= HOST_BITS_PER_WIDE_INT 92169689Skan && GET_CODE (x) == CONST_INT) 93169689Skan val = INTVAL (x); 94169689Skan else if (width <= 2 * HOST_BITS_PER_WIDE_INT 95169689Skan && GET_CODE (x) == CONST_DOUBLE 96169689Skan && CONST_DOUBLE_LOW (x) == 0) 97169689Skan { 98169689Skan val = CONST_DOUBLE_HIGH (x); 99169689Skan width -= HOST_BITS_PER_WIDE_INT; 100169689Skan } 101169689Skan else 102169689Skan return false; 103169689Skan 104169689Skan if (width < HOST_BITS_PER_WIDE_INT) 105169689Skan val &= ((unsigned HOST_WIDE_INT) 1 << width) - 1; 106169689Skan return val == ((unsigned HOST_WIDE_INT) 1 << (width - 1)); 107169689Skan} 10890075Sobrien 109117395Skan/* Make a binary operation by properly ordering the operands and 11090075Sobrien seeing if the expression folds. */ 11190075Sobrien 11290075Sobrienrtx 113132718Skansimplify_gen_binary (enum rtx_code code, enum machine_mode mode, rtx op0, 114132718Skan rtx op1) 11590075Sobrien{ 11690075Sobrien rtx tem; 11790075Sobrien 11890075Sobrien /* If this simplifies, do it. */ 11990075Sobrien tem = simplify_binary_operation (code, mode, op0, op1); 12090075Sobrien if (tem) 12190075Sobrien return tem; 12290075Sobrien 123169689Skan /* Put complex operands first and constants second if commutative. */ 124169689Skan if (GET_RTX_CLASS (code) == RTX_COMM_ARITH 125169689Skan && swap_commutative_operands_p (op0, op1)) 126169689Skan tem = op0, op0 = op1, op1 = tem; 12790075Sobrien 12896263Sobrien return gen_rtx_fmt_ee (code, mode, op0, op1); 12990075Sobrien} 13090075Sobrien 13190075Sobrien/* If X is a MEM referencing the constant pool, return the real value. 13290075Sobrien Otherwise return X. */ 13390075Sobrienrtx 134132718Skanavoid_constant_pool_reference (rtx x) 13590075Sobrien{ 136132718Skan rtx c, tmp, addr; 13790075Sobrien enum machine_mode cmode; 138169689Skan HOST_WIDE_INT offset = 0; 13990075Sobrien 140132718Skan switch (GET_CODE (x)) 141132718Skan { 142132718Skan case MEM: 143132718Skan break; 144132718Skan 145132718Skan case FLOAT_EXTEND: 146132718Skan /* Handle float extensions of constant pool references. */ 147132718Skan tmp = XEXP (x, 0); 148132718Skan c = avoid_constant_pool_reference (tmp); 149132718Skan if (c != tmp && GET_CODE (c) == CONST_DOUBLE) 150132718Skan { 151132718Skan REAL_VALUE_TYPE d; 152132718Skan 153132718Skan REAL_VALUE_FROM_CONST_DOUBLE (d, c); 154132718Skan return CONST_DOUBLE_FROM_REAL_VALUE (d, GET_MODE (x)); 155132718Skan } 156132718Skan return x; 157132718Skan 158132718Skan default: 159132718Skan return x; 160132718Skan } 161132718Skan 16290075Sobrien addr = XEXP (x, 0); 16390075Sobrien 164132718Skan /* Call target hook to avoid the effects of -fpic etc.... */ 165169689Skan addr = targetm.delegitimize_address (addr); 166132718Skan 167169689Skan /* Split the address into a base and integer offset. */ 168169689Skan if (GET_CODE (addr) == CONST 169169689Skan && GET_CODE (XEXP (addr, 0)) == PLUS 170169689Skan && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT) 171169689Skan { 172169689Skan offset = INTVAL (XEXP (XEXP (addr, 0), 1)); 173169689Skan addr = XEXP (XEXP (addr, 0), 0); 174169689Skan } 175169689Skan 176117395Skan if (GET_CODE (addr) == LO_SUM) 177117395Skan addr = XEXP (addr, 1); 178117395Skan 179169689Skan /* If this is a constant pool reference, we can turn it into its 180169689Skan constant and hope that simplifications happen. */ 181169689Skan if (GET_CODE (addr) == SYMBOL_REF 182169689Skan && CONSTANT_POOL_ADDRESS_P (addr)) 183169689Skan { 184169689Skan c = get_pool_constant (addr); 185169689Skan cmode = get_pool_mode (addr); 18690075Sobrien 187169689Skan /* If we're accessing the constant in a different mode than it was 188169689Skan originally stored, attempt to fix that up via subreg simplifications. 189169689Skan If that fails we have no choice but to return the original memory. */ 190169689Skan if (offset != 0 || cmode != GET_MODE (x)) 191169689Skan { 192169689Skan rtx tem = simplify_subreg (GET_MODE (x), c, cmode, offset); 193169689Skan if (tem && CONSTANT_P (tem)) 194169689Skan return tem; 195169689Skan } 196169689Skan else 197169689Skan return c; 19890075Sobrien } 19990075Sobrien 200169689Skan return x; 20190075Sobrien} 202169689Skan 203169689Skan/* Return true if X is a MEM referencing the constant pool. */ 204169689Skan 205169689Skanbool 206169689Skanconstant_pool_reference_p (rtx x) 207169689Skan{ 208169689Skan return avoid_constant_pool_reference (x) != x; 209169689Skan} 21090075Sobrien 21190075Sobrien/* Make a unary operation by first seeing if it folds and otherwise making 21290075Sobrien the specified operation. */ 21390075Sobrien 21490075Sobrienrtx 215132718Skansimplify_gen_unary (enum rtx_code code, enum machine_mode mode, rtx op, 216132718Skan enum machine_mode op_mode) 21790075Sobrien{ 21890075Sobrien rtx tem; 21990075Sobrien 22090075Sobrien /* If this simplifies, use it. */ 22190075Sobrien if ((tem = simplify_unary_operation (code, mode, op, op_mode)) != 0) 22290075Sobrien return tem; 22390075Sobrien 22490075Sobrien return gen_rtx_fmt_e (code, mode, op); 22590075Sobrien} 22690075Sobrien 22790075Sobrien/* Likewise for ternary operations. */ 22890075Sobrien 22990075Sobrienrtx 230132718Skansimplify_gen_ternary (enum rtx_code code, enum machine_mode mode, 231132718Skan enum machine_mode op0_mode, rtx op0, rtx op1, rtx op2) 23290075Sobrien{ 23390075Sobrien rtx tem; 23490075Sobrien 23590075Sobrien /* If this simplifies, use it. */ 23690075Sobrien if (0 != (tem = simplify_ternary_operation (code, mode, op0_mode, 23790075Sobrien op0, op1, op2))) 23890075Sobrien return tem; 23990075Sobrien 24090075Sobrien return gen_rtx_fmt_eee (code, mode, op0, op1, op2); 24190075Sobrien} 242161651Skan 24390075Sobrien/* Likewise, for relational operations. 244169689Skan CMP_MODE specifies mode comparison is done in. */ 24590075Sobrien 24690075Sobrienrtx 247132718Skansimplify_gen_relational (enum rtx_code code, enum machine_mode mode, 248132718Skan enum machine_mode cmp_mode, rtx op0, rtx op1) 24990075Sobrien{ 25090075Sobrien rtx tem; 25190075Sobrien 252169689Skan if (0 != (tem = simplify_relational_operation (code, mode, cmp_mode, 253169689Skan op0, op1))) 254169689Skan return tem; 25590075Sobrien 25690075Sobrien return gen_rtx_fmt_ee (code, mode, op0, op1); 25790075Sobrien} 25890075Sobrien 259169689Skan/* Replace all occurrences of OLD_RTX in X with NEW_RTX and try to simplify the 26090075Sobrien resulting RTX. Return a new RTX which is as simplified as possible. */ 26190075Sobrien 26290075Sobrienrtx 263169689Skansimplify_replace_rtx (rtx x, rtx old_rtx, rtx new_rtx) 26490075Sobrien{ 26590075Sobrien enum rtx_code code = GET_CODE (x); 26690075Sobrien enum machine_mode mode = GET_MODE (x); 267132718Skan enum machine_mode op_mode; 268132718Skan rtx op0, op1, op2; 26990075Sobrien 270169689Skan /* If X is OLD_RTX, return NEW_RTX. Otherwise, if this is an expression, try 27190075Sobrien to build a new expression substituting recursively. If we can't do 27290075Sobrien anything, return our input. */ 27390075Sobrien 274169689Skan if (x == old_rtx) 275169689Skan return new_rtx; 27690075Sobrien 27790075Sobrien switch (GET_RTX_CLASS (code)) 27890075Sobrien { 279169689Skan case RTX_UNARY: 280132718Skan op0 = XEXP (x, 0); 281132718Skan op_mode = GET_MODE (op0); 282169689Skan op0 = simplify_replace_rtx (op0, old_rtx, new_rtx); 283132718Skan if (op0 == XEXP (x, 0)) 284132718Skan return x; 285132718Skan return simplify_gen_unary (code, mode, op0, op_mode); 28690075Sobrien 287169689Skan case RTX_BIN_ARITH: 288169689Skan case RTX_COMM_ARITH: 289169689Skan op0 = simplify_replace_rtx (XEXP (x, 0), old_rtx, new_rtx); 290169689Skan op1 = simplify_replace_rtx (XEXP (x, 1), old_rtx, new_rtx); 291132718Skan if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) 292132718Skan return x; 293132718Skan return simplify_gen_binary (code, mode, op0, op1); 294132718Skan 295169689Skan case RTX_COMPARE: 296169689Skan case RTX_COMM_COMPARE: 297132718Skan op0 = XEXP (x, 0); 298132718Skan op1 = XEXP (x, 1); 299132718Skan op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1); 300169689Skan op0 = simplify_replace_rtx (op0, old_rtx, new_rtx); 301169689Skan op1 = simplify_replace_rtx (op1, old_rtx, new_rtx); 302132718Skan if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) 303132718Skan return x; 304132718Skan return simplify_gen_relational (code, mode, op_mode, op0, op1); 30590075Sobrien 306169689Skan case RTX_TERNARY: 307169689Skan case RTX_BITFIELD_OPS: 308132718Skan op0 = XEXP (x, 0); 309132718Skan op_mode = GET_MODE (op0); 310169689Skan op0 = simplify_replace_rtx (op0, old_rtx, new_rtx); 311169689Skan op1 = simplify_replace_rtx (XEXP (x, 1), old_rtx, new_rtx); 312169689Skan op2 = simplify_replace_rtx (XEXP (x, 2), old_rtx, new_rtx); 313132718Skan if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1) && op2 == XEXP (x, 2)) 314132718Skan return x; 315132718Skan if (op_mode == VOIDmode) 316132718Skan op_mode = GET_MODE (op0); 317132718Skan return simplify_gen_ternary (code, mode, op_mode, op0, op1, op2); 31890075Sobrien 319169689Skan case RTX_EXTRA: 32090075Sobrien /* The only case we try to handle is a SUBREG. */ 32190075Sobrien if (code == SUBREG) 32290075Sobrien { 323169689Skan op0 = simplify_replace_rtx (SUBREG_REG (x), old_rtx, new_rtx); 324132718Skan if (op0 == SUBREG_REG (x)) 325132718Skan return x; 326132718Skan op0 = simplify_gen_subreg (GET_MODE (x), op0, 32790075Sobrien GET_MODE (SUBREG_REG (x)), 32890075Sobrien SUBREG_BYTE (x)); 329132718Skan return op0 ? op0 : x; 33090075Sobrien } 331132718Skan break; 33290075Sobrien 333169689Skan case RTX_OBJ: 334117395Skan if (code == MEM) 335132718Skan { 336169689Skan op0 = simplify_replace_rtx (XEXP (x, 0), old_rtx, new_rtx); 337132718Skan if (op0 == XEXP (x, 0)) 338132718Skan return x; 339132718Skan return replace_equiv_address_nv (x, op0); 340132718Skan } 341117395Skan else if (code == LO_SUM) 342117395Skan { 343169689Skan op0 = simplify_replace_rtx (XEXP (x, 0), old_rtx, new_rtx); 344169689Skan op1 = simplify_replace_rtx (XEXP (x, 1), old_rtx, new_rtx); 34590075Sobrien 346117395Skan /* (lo_sum (high x) x) -> x */ 347117395Skan if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1)) 348117395Skan return op1; 34990075Sobrien 350132718Skan if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) 351132718Skan return x; 352117395Skan return gen_rtx_LO_SUM (mode, op0, op1); 353117395Skan } 354117395Skan else if (code == REG) 35590075Sobrien { 356169689Skan if (rtx_equal_p (x, old_rtx)) 357169689Skan return new_rtx; 35890075Sobrien } 359132718Skan break; 36090075Sobrien 361117395Skan default: 362132718Skan break; 36390075Sobrien } 364117395Skan return x; 36590075Sobrien} 366117395Skan 36790075Sobrien/* Try to simplify a unary operation CODE whose output mode is to be 36890075Sobrien MODE with input operand OP whose mode was originally OP_MODE. 36990075Sobrien Return zero if no simplification can be made. */ 37090075Sobrienrtx 371132718Skansimplify_unary_operation (enum rtx_code code, enum machine_mode mode, 372132718Skan rtx op, enum machine_mode op_mode) 37390075Sobrien{ 374169689Skan rtx trueop, tem; 375169689Skan 376169689Skan if (GET_CODE (op) == CONST) 377169689Skan op = XEXP (op, 0); 378169689Skan 379169689Skan trueop = avoid_constant_pool_reference (op); 380169689Skan 381169689Skan tem = simplify_const_unary_operation (code, mode, trueop, op_mode); 382169689Skan if (tem) 383169689Skan return tem; 384169689Skan 385169689Skan return simplify_unary_operation_1 (code, mode, op); 386169689Skan} 387169689Skan 388169689Skan/* Perform some simplifications we can do even if the operands 389169689Skan aren't constant. */ 390169689Skanstatic rtx 391169689Skansimplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) 392169689Skan{ 393169689Skan enum rtx_code reversed; 394169689Skan rtx temp; 395169689Skan 396169689Skan switch (code) 397169689Skan { 398169689Skan case NOT: 399169689Skan /* (not (not X)) == X. */ 400169689Skan if (GET_CODE (op) == NOT) 401169689Skan return XEXP (op, 0); 402169689Skan 403169689Skan /* (not (eq X Y)) == (ne X Y), etc. if BImode or the result of the 404169689Skan comparison is all ones. */ 405169689Skan if (COMPARISON_P (op) 406169689Skan && (mode == BImode || STORE_FLAG_VALUE == -1) 407169689Skan && ((reversed = reversed_comparison_code (op, NULL_RTX)) != UNKNOWN)) 408169689Skan return simplify_gen_relational (reversed, mode, VOIDmode, 409169689Skan XEXP (op, 0), XEXP (op, 1)); 410169689Skan 411169689Skan /* (not (plus X -1)) can become (neg X). */ 412169689Skan if (GET_CODE (op) == PLUS 413169689Skan && XEXP (op, 1) == constm1_rtx) 414169689Skan return simplify_gen_unary (NEG, mode, XEXP (op, 0), mode); 415169689Skan 416169689Skan /* Similarly, (not (neg X)) is (plus X -1). */ 417169689Skan if (GET_CODE (op) == NEG) 418169689Skan return plus_constant (XEXP (op, 0), -1); 419169689Skan 420169689Skan /* (not (xor X C)) for C constant is (xor X D) with D = ~C. */ 421169689Skan if (GET_CODE (op) == XOR 422169689Skan && GET_CODE (XEXP (op, 1)) == CONST_INT 423169689Skan && (temp = simplify_unary_operation (NOT, mode, 424169689Skan XEXP (op, 1), mode)) != 0) 425169689Skan return simplify_gen_binary (XOR, mode, XEXP (op, 0), temp); 426169689Skan 427169689Skan /* (not (plus X C)) for signbit C is (xor X D) with D = ~C. */ 428169689Skan if (GET_CODE (op) == PLUS 429169689Skan && GET_CODE (XEXP (op, 1)) == CONST_INT 430169689Skan && mode_signbit_p (mode, XEXP (op, 1)) 431169689Skan && (temp = simplify_unary_operation (NOT, mode, 432169689Skan XEXP (op, 1), mode)) != 0) 433169689Skan return simplify_gen_binary (XOR, mode, XEXP (op, 0), temp); 434169689Skan 435169689Skan 436169689Skan /* (not (ashift 1 X)) is (rotate ~1 X). We used to do this for 437169689Skan operands other than 1, but that is not valid. We could do a 438169689Skan similar simplification for (not (lshiftrt C X)) where C is 439169689Skan just the sign bit, but this doesn't seem common enough to 440169689Skan bother with. */ 441169689Skan if (GET_CODE (op) == ASHIFT 442169689Skan && XEXP (op, 0) == const1_rtx) 443169689Skan { 444169689Skan temp = simplify_gen_unary (NOT, mode, const1_rtx, mode); 445169689Skan return simplify_gen_binary (ROTATE, mode, temp, XEXP (op, 1)); 446169689Skan } 447169689Skan 448169689Skan /* (not (ashiftrt foo C)) where C is the number of bits in FOO 449169689Skan minus 1 is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1, 450169689Skan so we can perform the above simplification. */ 451169689Skan 452169689Skan if (STORE_FLAG_VALUE == -1 453169689Skan && GET_CODE (op) == ASHIFTRT 454169689Skan && GET_CODE (XEXP (op, 1)) == CONST_INT 455169689Skan && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1) 456169689Skan return simplify_gen_relational (GE, mode, VOIDmode, 457169689Skan XEXP (op, 0), const0_rtx); 458169689Skan 459169689Skan 460169689Skan if (GET_CODE (op) == SUBREG 461169689Skan && subreg_lowpart_p (op) 462169689Skan && (GET_MODE_SIZE (GET_MODE (op)) 463169689Skan < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))) 464169689Skan && GET_CODE (SUBREG_REG (op)) == ASHIFT 465169689Skan && XEXP (SUBREG_REG (op), 0) == const1_rtx) 466169689Skan { 467169689Skan enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op)); 468169689Skan rtx x; 469169689Skan 470169689Skan x = gen_rtx_ROTATE (inner_mode, 471169689Skan simplify_gen_unary (NOT, inner_mode, const1_rtx, 472169689Skan inner_mode), 473169689Skan XEXP (SUBREG_REG (op), 1)); 474169689Skan return rtl_hooks.gen_lowpart_no_emit (mode, x); 475169689Skan } 476169689Skan 477169689Skan /* Apply De Morgan's laws to reduce number of patterns for machines 478169689Skan with negating logical insns (and-not, nand, etc.). If result has 479169689Skan only one NOT, put it first, since that is how the patterns are 480169689Skan coded. */ 481169689Skan 482169689Skan if (GET_CODE (op) == IOR || GET_CODE (op) == AND) 483169689Skan { 484169689Skan rtx in1 = XEXP (op, 0), in2 = XEXP (op, 1); 485169689Skan enum machine_mode op_mode; 486169689Skan 487169689Skan op_mode = GET_MODE (in1); 488169689Skan in1 = simplify_gen_unary (NOT, op_mode, in1, op_mode); 489169689Skan 490169689Skan op_mode = GET_MODE (in2); 491169689Skan if (op_mode == VOIDmode) 492169689Skan op_mode = mode; 493169689Skan in2 = simplify_gen_unary (NOT, op_mode, in2, op_mode); 494169689Skan 495169689Skan if (GET_CODE (in2) == NOT && GET_CODE (in1) != NOT) 496169689Skan { 497169689Skan rtx tem = in2; 498169689Skan in2 = in1; in1 = tem; 499169689Skan } 500169689Skan 501169689Skan return gen_rtx_fmt_ee (GET_CODE (op) == IOR ? AND : IOR, 502169689Skan mode, in1, in2); 503169689Skan } 504169689Skan break; 505169689Skan 506169689Skan case NEG: 507169689Skan /* (neg (neg X)) == X. */ 508169689Skan if (GET_CODE (op) == NEG) 509169689Skan return XEXP (op, 0); 510169689Skan 511169689Skan /* (neg (plus X 1)) can become (not X). */ 512169689Skan if (GET_CODE (op) == PLUS 513169689Skan && XEXP (op, 1) == const1_rtx) 514169689Skan return simplify_gen_unary (NOT, mode, XEXP (op, 0), mode); 515169689Skan 516169689Skan /* Similarly, (neg (not X)) is (plus X 1). */ 517169689Skan if (GET_CODE (op) == NOT) 518169689Skan return plus_constant (XEXP (op, 0), 1); 519169689Skan 520169689Skan /* (neg (minus X Y)) can become (minus Y X). This transformation 521169689Skan isn't safe for modes with signed zeros, since if X and Y are 522169689Skan both +0, (minus Y X) is the same as (minus X Y). If the 523169689Skan rounding mode is towards +infinity (or -infinity) then the two 524169689Skan expressions will be rounded differently. */ 525169689Skan if (GET_CODE (op) == MINUS 526169689Skan && !HONOR_SIGNED_ZEROS (mode) 527169689Skan && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) 528169689Skan return simplify_gen_binary (MINUS, mode, XEXP (op, 1), XEXP (op, 0)); 529169689Skan 530169689Skan if (GET_CODE (op) == PLUS 531169689Skan && !HONOR_SIGNED_ZEROS (mode) 532169689Skan && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) 533169689Skan { 534169689Skan /* (neg (plus A C)) is simplified to (minus -C A). */ 535169689Skan if (GET_CODE (XEXP (op, 1)) == CONST_INT 536169689Skan || GET_CODE (XEXP (op, 1)) == CONST_DOUBLE) 537169689Skan { 538169689Skan temp = simplify_unary_operation (NEG, mode, XEXP (op, 1), mode); 539169689Skan if (temp) 540169689Skan return simplify_gen_binary (MINUS, mode, temp, XEXP (op, 0)); 541169689Skan } 542169689Skan 543169689Skan /* (neg (plus A B)) is canonicalized to (minus (neg A) B). */ 544169689Skan temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode); 545169689Skan return simplify_gen_binary (MINUS, mode, temp, XEXP (op, 1)); 546169689Skan } 547169689Skan 548169689Skan /* (neg (mult A B)) becomes (mult (neg A) B). 549169689Skan This works even for floating-point values. */ 550169689Skan if (GET_CODE (op) == MULT 551169689Skan && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) 552169689Skan { 553169689Skan temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode); 554169689Skan return simplify_gen_binary (MULT, mode, temp, XEXP (op, 1)); 555169689Skan } 556169689Skan 557169689Skan /* NEG commutes with ASHIFT since it is multiplication. Only do 558169689Skan this if we can then eliminate the NEG (e.g., if the operand 559169689Skan is a constant). */ 560169689Skan if (GET_CODE (op) == ASHIFT) 561169689Skan { 562169689Skan temp = simplify_unary_operation (NEG, mode, XEXP (op, 0), mode); 563169689Skan if (temp) 564169689Skan return simplify_gen_binary (ASHIFT, mode, temp, XEXP (op, 1)); 565169689Skan } 566169689Skan 567169689Skan /* (neg (ashiftrt X C)) can be replaced by (lshiftrt X C) when 568169689Skan C is equal to the width of MODE minus 1. */ 569169689Skan if (GET_CODE (op) == ASHIFTRT 570169689Skan && GET_CODE (XEXP (op, 1)) == CONST_INT 571169689Skan && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1) 572169689Skan return simplify_gen_binary (LSHIFTRT, mode, 573169689Skan XEXP (op, 0), XEXP (op, 1)); 574169689Skan 575169689Skan /* (neg (lshiftrt X C)) can be replaced by (ashiftrt X C) when 576169689Skan C is equal to the width of MODE minus 1. */ 577169689Skan if (GET_CODE (op) == LSHIFTRT 578169689Skan && GET_CODE (XEXP (op, 1)) == CONST_INT 579169689Skan && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1) 580169689Skan return simplify_gen_binary (ASHIFTRT, mode, 581169689Skan XEXP (op, 0), XEXP (op, 1)); 582169689Skan 583169689Skan /* (neg (xor A 1)) is (plus A -1) if A is known to be either 0 or 1. */ 584169689Skan if (GET_CODE (op) == XOR 585169689Skan && XEXP (op, 1) == const1_rtx 586169689Skan && nonzero_bits (XEXP (op, 0), mode) == 1) 587169689Skan return plus_constant (XEXP (op, 0), -1); 588169689Skan 589169689Skan /* (neg (lt x 0)) is (ashiftrt X C) if STORE_FLAG_VALUE is 1. */ 590169689Skan /* (neg (lt x 0)) is (lshiftrt X C) if STORE_FLAG_VALUE is -1. */ 591169689Skan if (GET_CODE (op) == LT 592220150Smm && XEXP (op, 1) == const0_rtx 593220150Smm && SCALAR_INT_MODE_P (GET_MODE (XEXP (op, 0)))) 594169689Skan { 595169689Skan enum machine_mode inner = GET_MODE (XEXP (op, 0)); 596169689Skan int isize = GET_MODE_BITSIZE (inner); 597169689Skan if (STORE_FLAG_VALUE == 1) 598169689Skan { 599169689Skan temp = simplify_gen_binary (ASHIFTRT, inner, XEXP (op, 0), 600169689Skan GEN_INT (isize - 1)); 601169689Skan if (mode == inner) 602169689Skan return temp; 603169689Skan if (GET_MODE_BITSIZE (mode) > isize) 604169689Skan return simplify_gen_unary (SIGN_EXTEND, mode, temp, inner); 605169689Skan return simplify_gen_unary (TRUNCATE, mode, temp, inner); 606169689Skan } 607169689Skan else if (STORE_FLAG_VALUE == -1) 608169689Skan { 609169689Skan temp = simplify_gen_binary (LSHIFTRT, inner, XEXP (op, 0), 610169689Skan GEN_INT (isize - 1)); 611169689Skan if (mode == inner) 612169689Skan return temp; 613169689Skan if (GET_MODE_BITSIZE (mode) > isize) 614169689Skan return simplify_gen_unary (ZERO_EXTEND, mode, temp, inner); 615169689Skan return simplify_gen_unary (TRUNCATE, mode, temp, inner); 616169689Skan } 617169689Skan } 618169689Skan break; 619169689Skan 620169689Skan case TRUNCATE: 621169689Skan /* We can't handle truncation to a partial integer mode here 622169689Skan because we don't know the real bitsize of the partial 623169689Skan integer mode. */ 624169689Skan if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) 625169689Skan break; 626169689Skan 627169689Skan /* (truncate:SI ({sign,zero}_extend:DI foo:SI)) == foo:SI. */ 628169689Skan if ((GET_CODE (op) == SIGN_EXTEND 629169689Skan || GET_CODE (op) == ZERO_EXTEND) 630169689Skan && GET_MODE (XEXP (op, 0)) == mode) 631169689Skan return XEXP (op, 0); 632169689Skan 633169689Skan /* (truncate:SI (OP:DI ({sign,zero}_extend:DI foo:SI))) is 634169689Skan (OP:SI foo:SI) if OP is NEG or ABS. */ 635169689Skan if ((GET_CODE (op) == ABS 636169689Skan || GET_CODE (op) == NEG) 637169689Skan && (GET_CODE (XEXP (op, 0)) == SIGN_EXTEND 638169689Skan || GET_CODE (XEXP (op, 0)) == ZERO_EXTEND) 639169689Skan && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode) 640169689Skan return simplify_gen_unary (GET_CODE (op), mode, 641169689Skan XEXP (XEXP (op, 0), 0), mode); 642169689Skan 643169689Skan /* (truncate:A (subreg:B (truncate:C X) 0)) is 644169689Skan (truncate:A X). */ 645169689Skan if (GET_CODE (op) == SUBREG 646169689Skan && GET_CODE (SUBREG_REG (op)) == TRUNCATE 647169689Skan && subreg_lowpart_p (op)) 648169689Skan return simplify_gen_unary (TRUNCATE, mode, XEXP (SUBREG_REG (op), 0), 649169689Skan GET_MODE (XEXP (SUBREG_REG (op), 0))); 650169689Skan 651169689Skan /* If we know that the value is already truncated, we can 652169689Skan replace the TRUNCATE with a SUBREG. Note that this is also 653169689Skan valid if TRULY_NOOP_TRUNCATION is false for the corresponding 654169689Skan modes we just have to apply a different definition for 655169689Skan truncation. But don't do this for an (LSHIFTRT (MULT ...)) 656169689Skan since this will cause problems with the umulXi3_highpart 657169689Skan patterns. */ 658169689Skan if ((TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode), 659169689Skan GET_MODE_BITSIZE (GET_MODE (op))) 660169689Skan ? (num_sign_bit_copies (op, GET_MODE (op)) 661169689Skan > (unsigned int) (GET_MODE_BITSIZE (GET_MODE (op)) 662169689Skan - GET_MODE_BITSIZE (mode))) 663169689Skan : truncated_to_mode (mode, op)) 664169689Skan && ! (GET_CODE (op) == LSHIFTRT 665169689Skan && GET_CODE (XEXP (op, 0)) == MULT)) 666169689Skan return rtl_hooks.gen_lowpart_no_emit (mode, op); 667169689Skan 668169689Skan /* A truncate of a comparison can be replaced with a subreg if 669169689Skan STORE_FLAG_VALUE permits. This is like the previous test, 670169689Skan but it works even if the comparison is done in a mode larger 671169689Skan than HOST_BITS_PER_WIDE_INT. */ 672169689Skan if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 673169689Skan && COMPARISON_P (op) 674169689Skan && ((HOST_WIDE_INT) STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0) 675169689Skan return rtl_hooks.gen_lowpart_no_emit (mode, op); 676169689Skan break; 677169689Skan 678169689Skan case FLOAT_TRUNCATE: 679169689Skan if (DECIMAL_FLOAT_MODE_P (mode)) 680169689Skan break; 681169689Skan 682169689Skan /* (float_truncate:SF (float_extend:DF foo:SF)) = foo:SF. */ 683169689Skan if (GET_CODE (op) == FLOAT_EXTEND 684169689Skan && GET_MODE (XEXP (op, 0)) == mode) 685169689Skan return XEXP (op, 0); 686169689Skan 687169689Skan /* (float_truncate:SF (float_truncate:DF foo:XF)) 688169689Skan = (float_truncate:SF foo:XF). 689169689Skan This may eliminate double rounding, so it is unsafe. 690169689Skan 691169689Skan (float_truncate:SF (float_extend:XF foo:DF)) 692169689Skan = (float_truncate:SF foo:DF). 693169689Skan 694169689Skan (float_truncate:DF (float_extend:XF foo:SF)) 695169689Skan = (float_extend:SF foo:DF). */ 696169689Skan if ((GET_CODE (op) == FLOAT_TRUNCATE 697169689Skan && flag_unsafe_math_optimizations) 698169689Skan || GET_CODE (op) == FLOAT_EXTEND) 699169689Skan return simplify_gen_unary (GET_MODE_SIZE (GET_MODE (XEXP (op, 700169689Skan 0))) 701169689Skan > GET_MODE_SIZE (mode) 702169689Skan ? FLOAT_TRUNCATE : FLOAT_EXTEND, 703169689Skan mode, 704169689Skan XEXP (op, 0), mode); 705169689Skan 706169689Skan /* (float_truncate (float x)) is (float x) */ 707169689Skan if (GET_CODE (op) == FLOAT 708169689Skan && (flag_unsafe_math_optimizations 709169689Skan || ((unsigned)significand_size (GET_MODE (op)) 710169689Skan >= (GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) 711169689Skan - num_sign_bit_copies (XEXP (op, 0), 712169689Skan GET_MODE (XEXP (op, 0))))))) 713169689Skan return simplify_gen_unary (FLOAT, mode, 714169689Skan XEXP (op, 0), 715169689Skan GET_MODE (XEXP (op, 0))); 716169689Skan 717169689Skan /* (float_truncate:SF (OP:DF (float_extend:DF foo:sf))) is 718169689Skan (OP:SF foo:SF) if OP is NEG or ABS. */ 719169689Skan if ((GET_CODE (op) == ABS 720169689Skan || GET_CODE (op) == NEG) 721169689Skan && GET_CODE (XEXP (op, 0)) == FLOAT_EXTEND 722169689Skan && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode) 723169689Skan return simplify_gen_unary (GET_CODE (op), mode, 724169689Skan XEXP (XEXP (op, 0), 0), mode); 725169689Skan 726169689Skan /* (float_truncate:SF (subreg:DF (float_truncate:SF X) 0)) 727169689Skan is (float_truncate:SF x). */ 728169689Skan if (GET_CODE (op) == SUBREG 729169689Skan && subreg_lowpart_p (op) 730169689Skan && GET_CODE (SUBREG_REG (op)) == FLOAT_TRUNCATE) 731169689Skan return SUBREG_REG (op); 732169689Skan break; 733169689Skan 734169689Skan case FLOAT_EXTEND: 735169689Skan if (DECIMAL_FLOAT_MODE_P (mode)) 736169689Skan break; 737169689Skan 738169689Skan /* (float_extend (float_extend x)) is (float_extend x) 739169689Skan 740169689Skan (float_extend (float x)) is (float x) assuming that double 741169689Skan rounding can't happen. 742169689Skan */ 743169689Skan if (GET_CODE (op) == FLOAT_EXTEND 744169689Skan || (GET_CODE (op) == FLOAT 745169689Skan && ((unsigned)significand_size (GET_MODE (op)) 746169689Skan >= (GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) 747169689Skan - num_sign_bit_copies (XEXP (op, 0), 748169689Skan GET_MODE (XEXP (op, 0))))))) 749169689Skan return simplify_gen_unary (GET_CODE (op), mode, 750169689Skan XEXP (op, 0), 751169689Skan GET_MODE (XEXP (op, 0))); 752169689Skan 753169689Skan break; 754169689Skan 755169689Skan case ABS: 756169689Skan /* (abs (neg <foo>)) -> (abs <foo>) */ 757169689Skan if (GET_CODE (op) == NEG) 758169689Skan return simplify_gen_unary (ABS, mode, XEXP (op, 0), 759169689Skan GET_MODE (XEXP (op, 0))); 760169689Skan 761169689Skan /* If the mode of the operand is VOIDmode (i.e. if it is ASM_OPERANDS), 762169689Skan do nothing. */ 763169689Skan if (GET_MODE (op) == VOIDmode) 764169689Skan break; 765169689Skan 766169689Skan /* If operand is something known to be positive, ignore the ABS. */ 767169689Skan if (GET_CODE (op) == FFS || GET_CODE (op) == ABS 768169689Skan || ((GET_MODE_BITSIZE (GET_MODE (op)) 769169689Skan <= HOST_BITS_PER_WIDE_INT) 770169689Skan && ((nonzero_bits (op, GET_MODE (op)) 771169689Skan & ((HOST_WIDE_INT) 1 772169689Skan << (GET_MODE_BITSIZE (GET_MODE (op)) - 1))) 773169689Skan == 0))) 774169689Skan return op; 775169689Skan 776169689Skan /* If operand is known to be only -1 or 0, convert ABS to NEG. */ 777169689Skan if (num_sign_bit_copies (op, mode) == GET_MODE_BITSIZE (mode)) 778169689Skan return gen_rtx_NEG (mode, op); 779169689Skan 780169689Skan break; 781169689Skan 782169689Skan case FFS: 783169689Skan /* (ffs (*_extend <X>)) = (ffs <X>) */ 784169689Skan if (GET_CODE (op) == SIGN_EXTEND 785169689Skan || GET_CODE (op) == ZERO_EXTEND) 786169689Skan return simplify_gen_unary (FFS, mode, XEXP (op, 0), 787169689Skan GET_MODE (XEXP (op, 0))); 788169689Skan break; 789169689Skan 790169689Skan case POPCOUNT: 791169689Skan case PARITY: 792169689Skan /* (pop* (zero_extend <X>)) = (pop* <X>) */ 793169689Skan if (GET_CODE (op) == ZERO_EXTEND) 794169689Skan return simplify_gen_unary (code, mode, XEXP (op, 0), 795169689Skan GET_MODE (XEXP (op, 0))); 796169689Skan break; 797169689Skan 798169689Skan case FLOAT: 799169689Skan /* (float (sign_extend <X>)) = (float <X>). */ 800169689Skan if (GET_CODE (op) == SIGN_EXTEND) 801169689Skan return simplify_gen_unary (FLOAT, mode, XEXP (op, 0), 802169689Skan GET_MODE (XEXP (op, 0))); 803169689Skan break; 804169689Skan 805169689Skan case SIGN_EXTEND: 806169689Skan /* (sign_extend (truncate (minus (label_ref L1) (label_ref L2)))) 807169689Skan becomes just the MINUS if its mode is MODE. This allows 808169689Skan folding switch statements on machines using casesi (such as 809169689Skan the VAX). */ 810169689Skan if (GET_CODE (op) == TRUNCATE 811169689Skan && GET_MODE (XEXP (op, 0)) == mode 812169689Skan && GET_CODE (XEXP (op, 0)) == MINUS 813169689Skan && GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF 814169689Skan && GET_CODE (XEXP (XEXP (op, 0), 1)) == LABEL_REF) 815169689Skan return XEXP (op, 0); 816169689Skan 817169689Skan /* Check for a sign extension of a subreg of a promoted 818169689Skan variable, where the promotion is sign-extended, and the 819169689Skan target mode is the same as the variable's promotion. */ 820169689Skan if (GET_CODE (op) == SUBREG 821169689Skan && SUBREG_PROMOTED_VAR_P (op) 822169689Skan && ! SUBREG_PROMOTED_UNSIGNED_P (op) 823169689Skan && GET_MODE (XEXP (op, 0)) == mode) 824169689Skan return XEXP (op, 0); 825169689Skan 826169689Skan#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend) 827169689Skan if (! POINTERS_EXTEND_UNSIGNED 828169689Skan && mode == Pmode && GET_MODE (op) == ptr_mode 829169689Skan && (CONSTANT_P (op) 830169689Skan || (GET_CODE (op) == SUBREG 831169689Skan && REG_P (SUBREG_REG (op)) 832169689Skan && REG_POINTER (SUBREG_REG (op)) 833169689Skan && GET_MODE (SUBREG_REG (op)) == Pmode))) 834169689Skan return convert_memory_address (Pmode, op); 835169689Skan#endif 836169689Skan break; 837169689Skan 838169689Skan case ZERO_EXTEND: 839169689Skan /* Check for a zero extension of a subreg of a promoted 840169689Skan variable, where the promotion is zero-extended, and the 841169689Skan target mode is the same as the variable's promotion. */ 842169689Skan if (GET_CODE (op) == SUBREG 843169689Skan && SUBREG_PROMOTED_VAR_P (op) 844169689Skan && SUBREG_PROMOTED_UNSIGNED_P (op) > 0 845169689Skan && GET_MODE (XEXP (op, 0)) == mode) 846169689Skan return XEXP (op, 0); 847169689Skan 848169689Skan#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend) 849169689Skan if (POINTERS_EXTEND_UNSIGNED > 0 850169689Skan && mode == Pmode && GET_MODE (op) == ptr_mode 851169689Skan && (CONSTANT_P (op) 852169689Skan || (GET_CODE (op) == SUBREG 853169689Skan && REG_P (SUBREG_REG (op)) 854169689Skan && REG_POINTER (SUBREG_REG (op)) 855169689Skan && GET_MODE (SUBREG_REG (op)) == Pmode))) 856169689Skan return convert_memory_address (Pmode, op); 857169689Skan#endif 858169689Skan break; 859169689Skan 860169689Skan default: 861169689Skan break; 862169689Skan } 863169689Skan 864169689Skan return 0; 865169689Skan} 866169689Skan 867169689Skan/* Try to compute the value of a unary operation CODE whose output mode is to 868169689Skan be MODE with input operand OP whose mode was originally OP_MODE. 869169689Skan Return zero if the value cannot be computed. */ 870169689Skanrtx 871169689Skansimplify_const_unary_operation (enum rtx_code code, enum machine_mode mode, 872169689Skan rtx op, enum machine_mode op_mode) 873169689Skan{ 87490075Sobrien unsigned int width = GET_MODE_BITSIZE (mode); 87590075Sobrien 876117395Skan if (code == VEC_DUPLICATE) 877117395Skan { 878169689Skan gcc_assert (VECTOR_MODE_P (mode)); 879169689Skan if (GET_MODE (op) != VOIDmode) 880169689Skan { 881169689Skan if (!VECTOR_MODE_P (GET_MODE (op))) 882169689Skan gcc_assert (GET_MODE_INNER (mode) == GET_MODE (op)); 883169689Skan else 884169689Skan gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER 885169689Skan (GET_MODE (op))); 886169689Skan } 887169689Skan if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE 888169689Skan || GET_CODE (op) == CONST_VECTOR) 889117395Skan { 890117395Skan int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); 891117395Skan unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); 892117395Skan rtvec v = rtvec_alloc (n_elts); 893117395Skan unsigned int i; 894117395Skan 895169689Skan if (GET_CODE (op) != CONST_VECTOR) 896117395Skan for (i = 0; i < n_elts; i++) 897169689Skan RTVEC_ELT (v, i) = op; 898117395Skan else 899117395Skan { 900169689Skan enum machine_mode inmode = GET_MODE (op); 901117395Skan int in_elt_size = GET_MODE_SIZE (GET_MODE_INNER (inmode)); 902117395Skan unsigned in_n_elts = (GET_MODE_SIZE (inmode) / in_elt_size); 903117395Skan 904169689Skan gcc_assert (in_n_elts < n_elts); 905169689Skan gcc_assert ((n_elts % in_n_elts) == 0); 906117395Skan for (i = 0; i < n_elts; i++) 907169689Skan RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op, i % in_n_elts); 908117395Skan } 909117395Skan return gen_rtx_CONST_VECTOR (mode, v); 910117395Skan } 911117395Skan } 912117395Skan 913169689Skan if (VECTOR_MODE_P (mode) && GET_CODE (op) == CONST_VECTOR) 914132718Skan { 915132718Skan int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); 916132718Skan unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); 917169689Skan enum machine_mode opmode = GET_MODE (op); 918132718Skan int op_elt_size = GET_MODE_SIZE (GET_MODE_INNER (opmode)); 919132718Skan unsigned op_n_elts = (GET_MODE_SIZE (opmode) / op_elt_size); 920132718Skan rtvec v = rtvec_alloc (n_elts); 921132718Skan unsigned int i; 922132718Skan 923169689Skan gcc_assert (op_n_elts == n_elts); 924132718Skan for (i = 0; i < n_elts; i++) 925132718Skan { 926132718Skan rtx x = simplify_unary_operation (code, GET_MODE_INNER (mode), 927169689Skan CONST_VECTOR_ELT (op, i), 928132718Skan GET_MODE_INNER (opmode)); 929132718Skan if (!x) 930132718Skan return 0; 931132718Skan RTVEC_ELT (v, i) = x; 932132718Skan } 933132718Skan return gen_rtx_CONST_VECTOR (mode, v); 934132718Skan } 935132718Skan 93690075Sobrien /* The order of these tests is critical so that, for example, we don't 93790075Sobrien check the wrong mode (input vs. output) for a conversion operation, 93890075Sobrien such as FIX. At some point, this should be simplified. */ 93990075Sobrien 940169689Skan if (code == FLOAT && GET_MODE (op) == VOIDmode 941169689Skan && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT)) 94290075Sobrien { 94390075Sobrien HOST_WIDE_INT hv, lv; 94490075Sobrien REAL_VALUE_TYPE d; 94590075Sobrien 946169689Skan if (GET_CODE (op) == CONST_INT) 947169689Skan lv = INTVAL (op), hv = HWI_SIGN_EXTEND (lv); 94890075Sobrien else 949169689Skan lv = CONST_DOUBLE_LOW (op), hv = CONST_DOUBLE_HIGH (op); 95090075Sobrien 95190075Sobrien REAL_VALUE_FROM_INT (d, lv, hv, mode); 95290075Sobrien d = real_value_truncate (mode, d); 95390075Sobrien return CONST_DOUBLE_FROM_REAL_VALUE (d, mode); 95490075Sobrien } 955169689Skan else if (code == UNSIGNED_FLOAT && GET_MODE (op) == VOIDmode 956169689Skan && (GET_CODE (op) == CONST_DOUBLE 957169689Skan || GET_CODE (op) == CONST_INT)) 95890075Sobrien { 95990075Sobrien HOST_WIDE_INT hv, lv; 96090075Sobrien REAL_VALUE_TYPE d; 96190075Sobrien 962169689Skan if (GET_CODE (op) == CONST_INT) 963169689Skan lv = INTVAL (op), hv = HWI_SIGN_EXTEND (lv); 96490075Sobrien else 965169689Skan lv = CONST_DOUBLE_LOW (op), hv = CONST_DOUBLE_HIGH (op); 96690075Sobrien 96790075Sobrien if (op_mode == VOIDmode) 96890075Sobrien { 96990075Sobrien /* We don't know how to interpret negative-looking numbers in 97090075Sobrien this case, so don't try to fold those. */ 97190075Sobrien if (hv < 0) 97290075Sobrien return 0; 97390075Sobrien } 97490075Sobrien else if (GET_MODE_BITSIZE (op_mode) >= HOST_BITS_PER_WIDE_INT * 2) 97590075Sobrien ; 97690075Sobrien else 97790075Sobrien hv = 0, lv &= GET_MODE_MASK (op_mode); 97890075Sobrien 97990075Sobrien REAL_VALUE_FROM_UNSIGNED_INT (d, lv, hv, mode); 98090075Sobrien d = real_value_truncate (mode, d); 98190075Sobrien return CONST_DOUBLE_FROM_REAL_VALUE (d, mode); 98290075Sobrien } 98390075Sobrien 984169689Skan if (GET_CODE (op) == CONST_INT 98590075Sobrien && width <= HOST_BITS_PER_WIDE_INT && width > 0) 98690075Sobrien { 987169689Skan HOST_WIDE_INT arg0 = INTVAL (op); 98890075Sobrien HOST_WIDE_INT val; 98990075Sobrien 99090075Sobrien switch (code) 99190075Sobrien { 99290075Sobrien case NOT: 99390075Sobrien val = ~ arg0; 99490075Sobrien break; 99590075Sobrien 99690075Sobrien case NEG: 99790075Sobrien val = - arg0; 99890075Sobrien break; 99990075Sobrien 100090075Sobrien case ABS: 100190075Sobrien val = (arg0 >= 0 ? arg0 : - arg0); 100290075Sobrien break; 100390075Sobrien 100490075Sobrien case FFS: 100590075Sobrien /* Don't use ffs here. Instead, get low order bit and then its 100690075Sobrien number. If arg0 is zero, this will return 0, as desired. */ 100790075Sobrien arg0 &= GET_MODE_MASK (mode); 100890075Sobrien val = exact_log2 (arg0 & (- arg0)) + 1; 100990075Sobrien break; 101090075Sobrien 1011132718Skan case CLZ: 1012132718Skan arg0 &= GET_MODE_MASK (mode); 1013132718Skan if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (mode, val)) 1014132718Skan ; 1015132718Skan else 1016132718Skan val = GET_MODE_BITSIZE (mode) - floor_log2 (arg0) - 1; 1017132718Skan break; 1018132718Skan 1019132718Skan case CTZ: 1020132718Skan arg0 &= GET_MODE_MASK (mode); 1021132718Skan if (arg0 == 0) 1022132718Skan { 1023132718Skan /* Even if the value at zero is undefined, we have to come 1024132718Skan up with some replacement. Seems good enough. */ 1025132718Skan if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, val)) 1026132718Skan val = GET_MODE_BITSIZE (mode); 1027132718Skan } 1028132718Skan else 1029132718Skan val = exact_log2 (arg0 & -arg0); 1030132718Skan break; 1031132718Skan 1032132718Skan case POPCOUNT: 1033132718Skan arg0 &= GET_MODE_MASK (mode); 1034132718Skan val = 0; 1035132718Skan while (arg0) 1036132718Skan val++, arg0 &= arg0 - 1; 1037132718Skan break; 1038132718Skan 1039132718Skan case PARITY: 1040132718Skan arg0 &= GET_MODE_MASK (mode); 1041132718Skan val = 0; 1042132718Skan while (arg0) 1043132718Skan val++, arg0 &= arg0 - 1; 1044132718Skan val &= 1; 1045132718Skan break; 1046132718Skan 1047259563Spfg case BSWAP: 1048259563Spfg return 0; 1049259563Spfg 105090075Sobrien case TRUNCATE: 105190075Sobrien val = arg0; 105290075Sobrien break; 105390075Sobrien 105490075Sobrien case ZERO_EXTEND: 105596263Sobrien /* When zero-extending a CONST_INT, we need to know its 105696263Sobrien original mode. */ 1057169689Skan gcc_assert (op_mode != VOIDmode); 105890075Sobrien if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT) 105990075Sobrien { 106090075Sobrien /* If we were really extending the mode, 106190075Sobrien we would have to distinguish between zero-extension 106290075Sobrien and sign-extension. */ 1063169689Skan gcc_assert (width == GET_MODE_BITSIZE (op_mode)); 106490075Sobrien val = arg0; 106590075Sobrien } 106690075Sobrien else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT) 106790075Sobrien val = arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode)); 106890075Sobrien else 106990075Sobrien return 0; 107090075Sobrien break; 107190075Sobrien 107290075Sobrien case SIGN_EXTEND: 107390075Sobrien if (op_mode == VOIDmode) 107490075Sobrien op_mode = mode; 107590075Sobrien if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT) 107690075Sobrien { 107790075Sobrien /* If we were really extending the mode, 107890075Sobrien we would have to distinguish between zero-extension 107990075Sobrien and sign-extension. */ 1080169689Skan gcc_assert (width == GET_MODE_BITSIZE (op_mode)); 108190075Sobrien val = arg0; 108290075Sobrien } 108390075Sobrien else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT) 108490075Sobrien { 108590075Sobrien val 108690075Sobrien = arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode)); 108790075Sobrien if (val 108890075Sobrien & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (op_mode) - 1))) 108990075Sobrien val -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode); 109090075Sobrien } 109190075Sobrien else 109290075Sobrien return 0; 109390075Sobrien break; 109490075Sobrien 109590075Sobrien case SQRT: 109690075Sobrien case FLOAT_EXTEND: 109790075Sobrien case FLOAT_TRUNCATE: 109890075Sobrien case SS_TRUNCATE: 109990075Sobrien case US_TRUNCATE: 1100169689Skan case SS_NEG: 110190075Sobrien return 0; 110290075Sobrien 110390075Sobrien default: 1104169689Skan gcc_unreachable (); 110590075Sobrien } 110690075Sobrien 1107169689Skan return gen_int_mode (val, mode); 110890075Sobrien } 110990075Sobrien 111090075Sobrien /* We can do some operations on integer CONST_DOUBLEs. Also allow 111190075Sobrien for a DImode operation on a CONST_INT. */ 1112169689Skan else if (GET_MODE (op) == VOIDmode 111396263Sobrien && width <= HOST_BITS_PER_WIDE_INT * 2 1114169689Skan && (GET_CODE (op) == CONST_DOUBLE 1115169689Skan || GET_CODE (op) == CONST_INT)) 111690075Sobrien { 111790075Sobrien unsigned HOST_WIDE_INT l1, lv; 111890075Sobrien HOST_WIDE_INT h1, hv; 111990075Sobrien 1120169689Skan if (GET_CODE (op) == CONST_DOUBLE) 1121169689Skan l1 = CONST_DOUBLE_LOW (op), h1 = CONST_DOUBLE_HIGH (op); 112290075Sobrien else 1123169689Skan l1 = INTVAL (op), h1 = HWI_SIGN_EXTEND (l1); 112490075Sobrien 112590075Sobrien switch (code) 112690075Sobrien { 112790075Sobrien case NOT: 112890075Sobrien lv = ~ l1; 112990075Sobrien hv = ~ h1; 113090075Sobrien break; 113190075Sobrien 113290075Sobrien case NEG: 113390075Sobrien neg_double (l1, h1, &lv, &hv); 113490075Sobrien break; 113590075Sobrien 113690075Sobrien case ABS: 113790075Sobrien if (h1 < 0) 113890075Sobrien neg_double (l1, h1, &lv, &hv); 113990075Sobrien else 114090075Sobrien lv = l1, hv = h1; 114190075Sobrien break; 114290075Sobrien 114390075Sobrien case FFS: 114490075Sobrien hv = 0; 114590075Sobrien if (l1 == 0) 1146132718Skan { 1147132718Skan if (h1 == 0) 1148132718Skan lv = 0; 1149132718Skan else 1150132718Skan lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & -h1) + 1; 1151132718Skan } 115290075Sobrien else 1153132718Skan lv = exact_log2 (l1 & -l1) + 1; 115490075Sobrien break; 115590075Sobrien 1156132718Skan case CLZ: 1157132718Skan hv = 0; 1158132718Skan if (h1 != 0) 1159132718Skan lv = GET_MODE_BITSIZE (mode) - floor_log2 (h1) - 1 1160132718Skan - HOST_BITS_PER_WIDE_INT; 1161132718Skan else if (l1 != 0) 1162132718Skan lv = GET_MODE_BITSIZE (mode) - floor_log2 (l1) - 1; 1163132718Skan else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, lv)) 1164132718Skan lv = GET_MODE_BITSIZE (mode); 1165132718Skan break; 1166132718Skan 1167132718Skan case CTZ: 1168132718Skan hv = 0; 1169132718Skan if (l1 != 0) 1170132718Skan lv = exact_log2 (l1 & -l1); 1171132718Skan else if (h1 != 0) 1172132718Skan lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & -h1); 1173132718Skan else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, lv)) 1174132718Skan lv = GET_MODE_BITSIZE (mode); 1175132718Skan break; 1176132718Skan 1177132718Skan case POPCOUNT: 1178132718Skan hv = 0; 1179132718Skan lv = 0; 1180132718Skan while (l1) 1181132718Skan lv++, l1 &= l1 - 1; 1182132718Skan while (h1) 1183132718Skan lv++, h1 &= h1 - 1; 1184132718Skan break; 1185132718Skan 1186132718Skan case PARITY: 1187132718Skan hv = 0; 1188132718Skan lv = 0; 1189132718Skan while (l1) 1190132718Skan lv++, l1 &= l1 - 1; 1191132718Skan while (h1) 1192132718Skan lv++, h1 &= h1 - 1; 1193132718Skan lv &= 1; 1194132718Skan break; 1195132718Skan 119690075Sobrien case TRUNCATE: 119790075Sobrien /* This is just a change-of-mode, so do nothing. */ 119890075Sobrien lv = l1, hv = h1; 119990075Sobrien break; 120090075Sobrien 120190075Sobrien case ZERO_EXTEND: 1202169689Skan gcc_assert (op_mode != VOIDmode); 120396263Sobrien 120496263Sobrien if (GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT) 120590075Sobrien return 0; 120690075Sobrien 120790075Sobrien hv = 0; 120890075Sobrien lv = l1 & GET_MODE_MASK (op_mode); 120990075Sobrien break; 121090075Sobrien 121190075Sobrien case SIGN_EXTEND: 121290075Sobrien if (op_mode == VOIDmode 121390075Sobrien || GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT) 121490075Sobrien return 0; 121590075Sobrien else 121690075Sobrien { 121790075Sobrien lv = l1 & GET_MODE_MASK (op_mode); 121890075Sobrien if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT 121990075Sobrien && (lv & ((HOST_WIDE_INT) 1 122090075Sobrien << (GET_MODE_BITSIZE (op_mode) - 1))) != 0) 122190075Sobrien lv -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode); 122290075Sobrien 122390075Sobrien hv = HWI_SIGN_EXTEND (lv); 122490075Sobrien } 122590075Sobrien break; 122690075Sobrien 122790075Sobrien case SQRT: 122890075Sobrien return 0; 122990075Sobrien 123090075Sobrien default: 123190075Sobrien return 0; 123290075Sobrien } 123390075Sobrien 123490075Sobrien return immed_double_const (lv, hv, mode); 123590075Sobrien } 123690075Sobrien 1237169689Skan else if (GET_CODE (op) == CONST_DOUBLE 1238169689Skan && SCALAR_FLOAT_MODE_P (mode)) 123990075Sobrien { 1240132718Skan REAL_VALUE_TYPE d, t; 1241169689Skan REAL_VALUE_FROM_CONST_DOUBLE (d, op); 124290075Sobrien 1243117395Skan switch (code) 1244117395Skan { 1245117395Skan case SQRT: 1246132718Skan if (HONOR_SNANS (mode) && real_isnan (&d)) 1247132718Skan return 0; 1248132718Skan real_sqrt (&t, mode, &d); 1249132718Skan d = t; 1250132718Skan break; 1251117395Skan case ABS: 1252117395Skan d = REAL_VALUE_ABS (d); 1253117395Skan break; 1254117395Skan case NEG: 1255117395Skan d = REAL_VALUE_NEGATE (d); 1256117395Skan break; 1257117395Skan case FLOAT_TRUNCATE: 1258117395Skan d = real_value_truncate (mode, d); 1259117395Skan break; 1260117395Skan case FLOAT_EXTEND: 1261117395Skan /* All this does is change the mode. */ 1262117395Skan break; 1263117395Skan case FIX: 1264117395Skan real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL); 1265117395Skan break; 1266146895Skan case NOT: 1267146895Skan { 1268146895Skan long tmp[4]; 1269146895Skan int i; 1270117395Skan 1271169689Skan real_to_target (tmp, &d, GET_MODE (op)); 1272146895Skan for (i = 0; i < 4; i++) 1273146895Skan tmp[i] = ~tmp[i]; 1274146895Skan real_from_target (&d, tmp, mode); 1275146895Skan break; 1276146895Skan } 1277117395Skan default: 1278169689Skan gcc_unreachable (); 1279117395Skan } 1280117395Skan return CONST_DOUBLE_FROM_REAL_VALUE (d, mode); 128190075Sobrien } 128290075Sobrien 1283169689Skan else if (GET_CODE (op) == CONST_DOUBLE 1284169689Skan && SCALAR_FLOAT_MODE_P (GET_MODE (op)) 128590075Sobrien && GET_MODE_CLASS (mode) == MODE_INT 1286132718Skan && width <= 2*HOST_BITS_PER_WIDE_INT && width > 0) 128790075Sobrien { 1288132718Skan /* Although the overflow semantics of RTL's FIX and UNSIGNED_FIX 1289132718Skan operators are intentionally left unspecified (to ease implementation 1290132718Skan by target backends), for consistency, this routine implements the 1291132718Skan same semantics for constant folding as used by the middle-end. */ 1292132718Skan 1293169689Skan /* This was formerly used only for non-IEEE float. 1294169689Skan eggert@twinsun.com says it is safe for IEEE also. */ 1295132718Skan HOST_WIDE_INT xh, xl, th, tl; 1296132718Skan REAL_VALUE_TYPE x, t; 1297169689Skan REAL_VALUE_FROM_CONST_DOUBLE (x, op); 1298117395Skan switch (code) 1299117395Skan { 1300132718Skan case FIX: 1301132718Skan if (REAL_VALUE_ISNAN (x)) 1302132718Skan return const0_rtx; 1303132718Skan 1304132718Skan /* Test against the signed upper bound. */ 1305132718Skan if (width > HOST_BITS_PER_WIDE_INT) 1306132718Skan { 1307132718Skan th = ((unsigned HOST_WIDE_INT) 1 1308132718Skan << (width - HOST_BITS_PER_WIDE_INT - 1)) - 1; 1309132718Skan tl = -1; 1310132718Skan } 1311132718Skan else 1312132718Skan { 1313132718Skan th = 0; 1314132718Skan tl = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1; 1315132718Skan } 1316132718Skan real_from_integer (&t, VOIDmode, tl, th, 0); 1317132718Skan if (REAL_VALUES_LESS (t, x)) 1318132718Skan { 1319132718Skan xh = th; 1320132718Skan xl = tl; 1321132718Skan break; 1322132718Skan } 1323132718Skan 1324132718Skan /* Test against the signed lower bound. */ 1325132718Skan if (width > HOST_BITS_PER_WIDE_INT) 1326132718Skan { 1327132718Skan th = (HOST_WIDE_INT) -1 << (width - HOST_BITS_PER_WIDE_INT - 1); 1328132718Skan tl = 0; 1329132718Skan } 1330132718Skan else 1331132718Skan { 1332132718Skan th = -1; 1333132718Skan tl = (HOST_WIDE_INT) -1 << (width - 1); 1334132718Skan } 1335132718Skan real_from_integer (&t, VOIDmode, tl, th, 0); 1336132718Skan if (REAL_VALUES_LESS (x, t)) 1337132718Skan { 1338132718Skan xh = th; 1339132718Skan xl = tl; 1340132718Skan break; 1341132718Skan } 1342132718Skan REAL_VALUE_TO_INT (&xl, &xh, x); 1343132718Skan break; 1344132718Skan 1345132718Skan case UNSIGNED_FIX: 1346132718Skan if (REAL_VALUE_ISNAN (x) || REAL_VALUE_NEGATIVE (x)) 1347132718Skan return const0_rtx; 1348132718Skan 1349132718Skan /* Test against the unsigned upper bound. */ 1350132718Skan if (width == 2*HOST_BITS_PER_WIDE_INT) 1351132718Skan { 1352132718Skan th = -1; 1353132718Skan tl = -1; 1354132718Skan } 1355132718Skan else if (width >= HOST_BITS_PER_WIDE_INT) 1356132718Skan { 1357132718Skan th = ((unsigned HOST_WIDE_INT) 1 1358132718Skan << (width - HOST_BITS_PER_WIDE_INT)) - 1; 1359132718Skan tl = -1; 1360132718Skan } 1361132718Skan else 1362132718Skan { 1363132718Skan th = 0; 1364132718Skan tl = ((unsigned HOST_WIDE_INT) 1 << width) - 1; 1365132718Skan } 1366132718Skan real_from_integer (&t, VOIDmode, tl, th, 1); 1367132718Skan if (REAL_VALUES_LESS (t, x)) 1368132718Skan { 1369132718Skan xh = th; 1370132718Skan xl = tl; 1371132718Skan break; 1372132718Skan } 1373132718Skan 1374132718Skan REAL_VALUE_TO_INT (&xl, &xh, x); 1375132718Skan break; 1376132718Skan 1377117395Skan default: 1378169689Skan gcc_unreachable (); 1379117395Skan } 1380132718Skan return immed_double_const (xl, xh, mode); 1381117395Skan } 138290075Sobrien 1383169689Skan return NULL_RTX; 1384169689Skan} 1385169689Skan 1386169689Skan/* Subroutine of simplify_binary_operation to simplify a commutative, 1387169689Skan associative binary operation CODE with result mode MODE, operating 1388169689Skan on OP0 and OP1. CODE is currently one of PLUS, MULT, AND, IOR, XOR, 1389169689Skan SMIN, SMAX, UMIN or UMAX. Return zero if no simplification or 1390169689Skan canonicalization is possible. */ 1391169689Skan 1392169689Skanstatic rtx 1393169689Skansimplify_associative_operation (enum rtx_code code, enum machine_mode mode, 1394169689Skan rtx op0, rtx op1) 1395169689Skan{ 1396169689Skan rtx tem; 1397169689Skan 1398169689Skan /* Linearize the operator to the left. */ 1399169689Skan if (GET_CODE (op1) == code) 140090075Sobrien { 1401169689Skan /* "(a op b) op (c op d)" becomes "((a op b) op c) op d)". */ 1402169689Skan if (GET_CODE (op0) == code) 1403169689Skan { 1404169689Skan tem = simplify_gen_binary (code, mode, op0, XEXP (op1, 0)); 1405169689Skan return simplify_gen_binary (code, mode, tem, XEXP (op1, 1)); 1406169689Skan } 1407132718Skan 1408169689Skan /* "a op (b op c)" becomes "(b op c) op a". */ 1409169689Skan if (! swap_commutative_operands_p (op1, op0)) 1410169689Skan return simplify_gen_binary (code, mode, op1, op0); 1411169689Skan 1412169689Skan tem = op0; 1413169689Skan op0 = op1; 1414169689Skan op1 = tem; 1415169689Skan } 1416169689Skan 1417169689Skan if (GET_CODE (op0) == code) 1418169689Skan { 1419169689Skan /* Canonicalize "(x op c) op y" as "(x op y) op c". */ 1420169689Skan if (swap_commutative_operands_p (XEXP (op0, 1), op1)) 142190075Sobrien { 1422169689Skan tem = simplify_gen_binary (code, mode, XEXP (op0, 0), op1); 1423169689Skan return simplify_gen_binary (code, mode, tem, XEXP (op0, 1)); 1424169689Skan } 142590075Sobrien 1426169689Skan /* Attempt to simplify "(a op b) op c" as "a op (b op c)". */ 1427169689Skan tem = swap_commutative_operands_p (XEXP (op0, 1), op1) 1428169689Skan ? simplify_binary_operation (code, mode, op1, XEXP (op0, 1)) 1429169689Skan : simplify_binary_operation (code, mode, XEXP (op0, 1), op1); 1430169689Skan if (tem != 0) 1431169689Skan return simplify_gen_binary (code, mode, XEXP (op0, 0), tem); 1432132718Skan 1433169689Skan /* Attempt to simplify "(a op b) op c" as "(a op c) op b". */ 1434169689Skan tem = swap_commutative_operands_p (XEXP (op0, 0), op1) 1435169689Skan ? simplify_binary_operation (code, mode, op1, XEXP (op0, 0)) 1436169689Skan : simplify_binary_operation (code, mode, XEXP (op0, 0), op1); 1437169689Skan if (tem != 0) 1438169689Skan return simplify_gen_binary (code, mode, tem, XEXP (op0, 1)); 1439169689Skan } 1440132718Skan 1441169689Skan return 0; 1442169689Skan} 1443132718Skan 1444132718Skan 1445169689Skan/* Simplify a binary operation CODE with result mode MODE, operating on OP0 1446169689Skan and OP1. Return 0 if no simplification is possible. 1447132718Skan 1448169689Skan Don't use this for relational operations such as EQ or LT. 1449169689Skan Use simplify_relational_operation instead. */ 1450169689Skanrtx 1451169689Skansimplify_binary_operation (enum rtx_code code, enum machine_mode mode, 1452169689Skan rtx op0, rtx op1) 1453169689Skan{ 1454169689Skan rtx trueop0, trueop1; 1455169689Skan rtx tem; 1456169689Skan 1457169689Skan /* Relational operations don't work here. We must know the mode 1458169689Skan of the operands in order to do the comparison correctly. 1459169689Skan Assuming a full word can give incorrect results. 1460169689Skan Consider comparing 128 with -128 in QImode. */ 1461169689Skan gcc_assert (GET_RTX_CLASS (code) != RTX_COMPARE); 1462169689Skan gcc_assert (GET_RTX_CLASS (code) != RTX_COMM_COMPARE); 1463169689Skan 1464169689Skan /* Make sure the constant is second. */ 1465169689Skan if (GET_RTX_CLASS (code) == RTX_COMM_ARITH 1466169689Skan && swap_commutative_operands_p (op0, op1)) 1467169689Skan { 1468169689Skan tem = op0, op0 = op1, op1 = tem; 1469169689Skan } 1470169689Skan 1471169689Skan trueop0 = avoid_constant_pool_reference (op0); 1472169689Skan trueop1 = avoid_constant_pool_reference (op1); 1473169689Skan 1474169689Skan tem = simplify_const_binary_operation (code, mode, trueop0, trueop1); 1475169689Skan if (tem) 1476169689Skan return tem; 1477169689Skan return simplify_binary_operation_1 (code, mode, op0, op1, trueop0, trueop1); 1478169689Skan} 1479169689Skan 1480169689Skan/* Subroutine of simplify_binary_operation. Simplify a binary operation 1481169689Skan CODE with result mode MODE, operating on OP0 and OP1. If OP0 and/or 1482169689Skan OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the 1483169689Skan actual constants. */ 1484169689Skan 1485169689Skanstatic rtx 1486169689Skansimplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, 1487169689Skan rtx op0, rtx op1, rtx trueop0, rtx trueop1) 1488169689Skan{ 1489169689Skan rtx tem, reversed, opleft, opright; 1490169689Skan HOST_WIDE_INT val; 1491169689Skan unsigned int width = GET_MODE_BITSIZE (mode); 1492169689Skan 1493169689Skan /* Even if we can't compute a constant result, 1494169689Skan there are some cases worth simplifying. */ 1495169689Skan 1496169689Skan switch (code) 1497169689Skan { 1498169689Skan case PLUS: 1499169689Skan /* Maybe simplify x + 0 to x. The two expressions are equivalent 1500169689Skan when x is NaN, infinite, or finite and nonzero. They aren't 1501169689Skan when x is -0 and the rounding mode is not towards -infinity, 1502169689Skan since (-0) + 0 is then 0. */ 1503169689Skan if (!HONOR_SIGNED_ZEROS (mode) && trueop1 == CONST0_RTX (mode)) 1504169689Skan return op0; 1505169689Skan 1506169689Skan /* ((-a) + b) -> (b - a) and similarly for (a + (-b)). These 1507169689Skan transformations are safe even for IEEE. */ 1508169689Skan if (GET_CODE (op0) == NEG) 1509169689Skan return simplify_gen_binary (MINUS, mode, op1, XEXP (op0, 0)); 1510169689Skan else if (GET_CODE (op1) == NEG) 1511169689Skan return simplify_gen_binary (MINUS, mode, op0, XEXP (op1, 0)); 1512169689Skan 1513169689Skan /* (~a) + 1 -> -a */ 1514169689Skan if (INTEGRAL_MODE_P (mode) 1515169689Skan && GET_CODE (op0) == NOT 1516169689Skan && trueop1 == const1_rtx) 1517169689Skan return simplify_gen_unary (NEG, mode, XEXP (op0, 0), mode); 1518169689Skan 1519169689Skan /* Handle both-operands-constant cases. We can only add 1520169689Skan CONST_INTs to constants since the sum of relocatable symbols 1521169689Skan can't be handled by most assemblers. Don't add CONST_INT 1522169689Skan to CONST_INT since overflow won't be computed properly if wider 1523169689Skan than HOST_BITS_PER_WIDE_INT. */ 1524169689Skan 1525169689Skan if (CONSTANT_P (op0) && GET_MODE (op0) != VOIDmode 1526169689Skan && GET_CODE (op1) == CONST_INT) 1527169689Skan return plus_constant (op0, INTVAL (op1)); 1528169689Skan else if (CONSTANT_P (op1) && GET_MODE (op1) != VOIDmode 1529169689Skan && GET_CODE (op0) == CONST_INT) 1530169689Skan return plus_constant (op1, INTVAL (op0)); 1531169689Skan 1532169689Skan /* See if this is something like X * C - X or vice versa or 1533169689Skan if the multiplication is written as a shift. If so, we can 1534169689Skan distribute and make a new multiply, shift, or maybe just 1535169689Skan have X (if C is 2 in the example above). But don't make 1536169689Skan something more expensive than we had before. */ 1537169689Skan 1538169689Skan if (SCALAR_INT_MODE_P (mode)) 1539169689Skan { 1540169689Skan HOST_WIDE_INT coeff0h = 0, coeff1h = 0; 1541169689Skan unsigned HOST_WIDE_INT coeff0l = 1, coeff1l = 1; 1542169689Skan rtx lhs = op0, rhs = op1; 1543169689Skan 1544169689Skan if (GET_CODE (lhs) == NEG) 1545132718Skan { 1546169689Skan coeff0l = -1; 1547169689Skan coeff0h = -1; 1548169689Skan lhs = XEXP (lhs, 0); 1549132718Skan } 1550169689Skan else if (GET_CODE (lhs) == MULT 1551169689Skan && GET_CODE (XEXP (lhs, 1)) == CONST_INT) 1552169689Skan { 1553169689Skan coeff0l = INTVAL (XEXP (lhs, 1)); 1554169689Skan coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0; 1555169689Skan lhs = XEXP (lhs, 0); 1556169689Skan } 1557169689Skan else if (GET_CODE (lhs) == ASHIFT 1558169689Skan && GET_CODE (XEXP (lhs, 1)) == CONST_INT 1559169689Skan && INTVAL (XEXP (lhs, 1)) >= 0 1560169689Skan && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT) 1561169689Skan { 1562169689Skan coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); 1563169689Skan coeff0h = 0; 1564169689Skan lhs = XEXP (lhs, 0); 1565169689Skan } 1566132718Skan 1567169689Skan if (GET_CODE (rhs) == NEG) 1568169689Skan { 1569169689Skan coeff1l = -1; 1570169689Skan coeff1h = -1; 1571169689Skan rhs = XEXP (rhs, 0); 1572169689Skan } 1573169689Skan else if (GET_CODE (rhs) == MULT 1574169689Skan && GET_CODE (XEXP (rhs, 1)) == CONST_INT) 1575169689Skan { 1576169689Skan coeff1l = INTVAL (XEXP (rhs, 1)); 1577169689Skan coeff1h = INTVAL (XEXP (rhs, 1)) < 0 ? -1 : 0; 1578169689Skan rhs = XEXP (rhs, 0); 1579169689Skan } 1580169689Skan else if (GET_CODE (rhs) == ASHIFT 1581169689Skan && GET_CODE (XEXP (rhs, 1)) == CONST_INT 1582169689Skan && INTVAL (XEXP (rhs, 1)) >= 0 1583169689Skan && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT) 1584169689Skan { 1585169689Skan coeff1l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1)); 1586169689Skan coeff1h = 0; 1587169689Skan rhs = XEXP (rhs, 0); 1588169689Skan } 1589132718Skan 1590169689Skan if (rtx_equal_p (lhs, rhs)) 1591169689Skan { 1592169689Skan rtx orig = gen_rtx_PLUS (mode, op0, op1); 1593169689Skan rtx coeff; 1594169689Skan unsigned HOST_WIDE_INT l; 1595169689Skan HOST_WIDE_INT h; 1596132718Skan 1597169689Skan add_double (coeff0l, coeff0h, coeff1l, coeff1h, &l, &h); 1598169689Skan coeff = immed_double_const (l, h, mode); 1599132718Skan 1600169689Skan tem = simplify_gen_binary (MULT, mode, lhs, coeff); 1601169689Skan return rtx_cost (tem, SET) <= rtx_cost (orig, SET) 1602169689Skan ? tem : 0; 1603169689Skan } 1604169689Skan } 160590075Sobrien 1606169689Skan /* (plus (xor X C1) C2) is (xor X (C1^C2)) if C2 is signbit. */ 1607169689Skan if ((GET_CODE (op1) == CONST_INT 1608169689Skan || GET_CODE (op1) == CONST_DOUBLE) 1609169689Skan && GET_CODE (op0) == XOR 1610169689Skan && (GET_CODE (XEXP (op0, 1)) == CONST_INT 1611169689Skan || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE) 1612169689Skan && mode_signbit_p (mode, op1)) 1613169689Skan return simplify_gen_binary (XOR, mode, XEXP (op0, 0), 1614169689Skan simplify_gen_binary (XOR, mode, op1, 1615169689Skan XEXP (op0, 1))); 1616132718Skan 1617169689Skan /* Canonicalize (plus (mult (neg B) C) A) to (minus A (mult B C)). */ 1618169689Skan if (GET_CODE (op0) == MULT 1619169689Skan && GET_CODE (XEXP (op0, 0)) == NEG) 1620169689Skan { 1621169689Skan rtx in1, in2; 1622132718Skan 1623169689Skan in1 = XEXP (XEXP (op0, 0), 0); 1624169689Skan in2 = XEXP (op0, 1); 1625169689Skan return simplify_gen_binary (MINUS, mode, op1, 1626169689Skan simplify_gen_binary (MULT, mode, 1627169689Skan in1, in2)); 1628169689Skan } 1629132718Skan 1630169689Skan /* (plus (comparison A B) C) can become (neg (rev-comp A B)) if 1631169689Skan C is 1 and STORE_FLAG_VALUE is -1 or if C is -1 and STORE_FLAG_VALUE 1632169689Skan is 1. */ 1633169689Skan if (COMPARISON_P (op0) 1634169689Skan && ((STORE_FLAG_VALUE == -1 && trueop1 == const1_rtx) 1635169689Skan || (STORE_FLAG_VALUE == 1 && trueop1 == constm1_rtx)) 1636169689Skan && (reversed = reversed_comparison (op0, mode))) 1637169689Skan return 1638169689Skan simplify_gen_unary (NEG, mode, reversed, mode); 1639132718Skan 1640169689Skan /* If one of the operands is a PLUS or a MINUS, see if we can 1641169689Skan simplify this by the associative law. 1642169689Skan Don't use the associative law for floating point. 1643169689Skan The inaccuracy makes it nonassociative, 1644169689Skan and subtle programs can break if operations are associated. */ 1645169689Skan 1646169689Skan if (INTEGRAL_MODE_P (mode) 1647169689Skan && (plus_minus_operand_p (op0) 1648169689Skan || plus_minus_operand_p (op1)) 1649169689Skan && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) 1650169689Skan return tem; 1651169689Skan 1652169689Skan /* Reassociate floating point addition only when the user 1653169689Skan specifies unsafe math optimizations. */ 1654169689Skan if (FLOAT_MODE_P (mode) 1655169689Skan && flag_unsafe_math_optimizations) 1656169689Skan { 1657169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 1658169689Skan if (tem) 1659169689Skan return tem; 1660169689Skan } 1661169689Skan break; 1662169689Skan 1663169689Skan case COMPARE: 1664169689Skan#ifdef HAVE_cc0 1665169689Skan /* Convert (compare FOO (const_int 0)) to FOO unless we aren't 1666169689Skan using cc0, in which case we want to leave it as a COMPARE 1667169689Skan so we can distinguish it from a register-register-copy. 1668169689Skan 1669169689Skan In IEEE floating point, x-0 is not the same as x. */ 1670169689Skan 1671169689Skan if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT 1672169689Skan || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations) 1673169689Skan && trueop1 == CONST0_RTX (mode)) 1674169689Skan return op0; 1675169689Skan#endif 1676169689Skan 1677169689Skan /* Convert (compare (gt (flags) 0) (lt (flags) 0)) to (flags). */ 1678169689Skan if (((GET_CODE (op0) == GT && GET_CODE (op1) == LT) 1679169689Skan || (GET_CODE (op0) == GTU && GET_CODE (op1) == LTU)) 1680169689Skan && XEXP (op0, 1) == const0_rtx && XEXP (op1, 1) == const0_rtx) 1681169689Skan { 1682169689Skan rtx xop00 = XEXP (op0, 0); 1683169689Skan rtx xop10 = XEXP (op1, 0); 1684169689Skan 1685169689Skan#ifdef HAVE_cc0 1686169689Skan if (GET_CODE (xop00) == CC0 && GET_CODE (xop10) == CC0) 1687169689Skan#else 1688169689Skan if (REG_P (xop00) && REG_P (xop10) 1689169689Skan && GET_MODE (xop00) == GET_MODE (xop10) 1690169689Skan && REGNO (xop00) == REGNO (xop10) 1691169689Skan && GET_MODE_CLASS (GET_MODE (xop00)) == MODE_CC 1692169689Skan && GET_MODE_CLASS (GET_MODE (xop10)) == MODE_CC) 1693169689Skan#endif 1694169689Skan return xop00; 1695169689Skan } 1696169689Skan break; 1697169689Skan 1698169689Skan case MINUS: 1699169689Skan /* We can't assume x-x is 0 even with non-IEEE floating point, 1700169689Skan but since it is zero except in very strange circumstances, we 1701169689Skan will treat it as zero with -funsafe-math-optimizations. */ 1702169689Skan if (rtx_equal_p (trueop0, trueop1) 1703169689Skan && ! side_effects_p (op0) 1704169689Skan && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)) 1705169689Skan return CONST0_RTX (mode); 1706169689Skan 1707169689Skan /* Change subtraction from zero into negation. (0 - x) is the 1708169689Skan same as -x when x is NaN, infinite, or finite and nonzero. 1709169689Skan But if the mode has signed zeros, and does not round towards 1710169689Skan -infinity, then 0 - 0 is 0, not -0. */ 1711169689Skan if (!HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode)) 1712169689Skan return simplify_gen_unary (NEG, mode, op1, mode); 1713169689Skan 1714169689Skan /* (-1 - a) is ~a. */ 1715169689Skan if (trueop0 == constm1_rtx) 1716169689Skan return simplify_gen_unary (NOT, mode, op1, mode); 1717169689Skan 1718169689Skan /* Subtracting 0 has no effect unless the mode has signed zeros 1719169689Skan and supports rounding towards -infinity. In such a case, 1720169689Skan 0 - 0 is -0. */ 1721169689Skan if (!(HONOR_SIGNED_ZEROS (mode) 1722169689Skan && HONOR_SIGN_DEPENDENT_ROUNDING (mode)) 1723169689Skan && trueop1 == CONST0_RTX (mode)) 1724169689Skan return op0; 1725169689Skan 1726169689Skan /* See if this is something like X * C - X or vice versa or 1727169689Skan if the multiplication is written as a shift. If so, we can 1728169689Skan distribute and make a new multiply, shift, or maybe just 1729169689Skan have X (if C is 2 in the example above). But don't make 1730169689Skan something more expensive than we had before. */ 1731169689Skan 1732169689Skan if (SCALAR_INT_MODE_P (mode)) 1733169689Skan { 1734169689Skan HOST_WIDE_INT coeff0h = 0, negcoeff1h = -1; 1735169689Skan unsigned HOST_WIDE_INT coeff0l = 1, negcoeff1l = -1; 1736169689Skan rtx lhs = op0, rhs = op1; 1737169689Skan 1738169689Skan if (GET_CODE (lhs) == NEG) 1739132718Skan { 1740169689Skan coeff0l = -1; 1741169689Skan coeff0h = -1; 1742169689Skan lhs = XEXP (lhs, 0); 1743169689Skan } 1744169689Skan else if (GET_CODE (lhs) == MULT 1745169689Skan && GET_CODE (XEXP (lhs, 1)) == CONST_INT) 1746169689Skan { 1747169689Skan coeff0l = INTVAL (XEXP (lhs, 1)); 1748169689Skan coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0; 1749169689Skan lhs = XEXP (lhs, 0); 1750169689Skan } 1751169689Skan else if (GET_CODE (lhs) == ASHIFT 1752169689Skan && GET_CODE (XEXP (lhs, 1)) == CONST_INT 1753169689Skan && INTVAL (XEXP (lhs, 1)) >= 0 1754169689Skan && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT) 1755169689Skan { 1756169689Skan coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); 1757169689Skan coeff0h = 0; 1758169689Skan lhs = XEXP (lhs, 0); 1759169689Skan } 1760169689Skan 1761169689Skan if (GET_CODE (rhs) == NEG) 1762169689Skan { 1763169689Skan negcoeff1l = 1; 1764169689Skan negcoeff1h = 0; 1765169689Skan rhs = XEXP (rhs, 0); 1766169689Skan } 1767169689Skan else if (GET_CODE (rhs) == MULT 1768169689Skan && GET_CODE (XEXP (rhs, 1)) == CONST_INT) 1769169689Skan { 1770169689Skan negcoeff1l = -INTVAL (XEXP (rhs, 1)); 1771169689Skan negcoeff1h = INTVAL (XEXP (rhs, 1)) <= 0 ? 0 : -1; 1772169689Skan rhs = XEXP (rhs, 0); 1773169689Skan } 1774169689Skan else if (GET_CODE (rhs) == ASHIFT 1775169689Skan && GET_CODE (XEXP (rhs, 1)) == CONST_INT 1776169689Skan && INTVAL (XEXP (rhs, 1)) >= 0 1777169689Skan && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT) 1778169689Skan { 1779169689Skan negcoeff1l = -(((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1))); 1780169689Skan negcoeff1h = -1; 1781169689Skan rhs = XEXP (rhs, 0); 1782169689Skan } 1783169689Skan 1784169689Skan if (rtx_equal_p (lhs, rhs)) 1785169689Skan { 1786169689Skan rtx orig = gen_rtx_MINUS (mode, op0, op1); 1787169689Skan rtx coeff; 1788169689Skan unsigned HOST_WIDE_INT l; 1789169689Skan HOST_WIDE_INT h; 1790169689Skan 1791169689Skan add_double (coeff0l, coeff0h, negcoeff1l, negcoeff1h, &l, &h); 1792169689Skan coeff = immed_double_const (l, h, mode); 1793169689Skan 1794169689Skan tem = simplify_gen_binary (MULT, mode, lhs, coeff); 1795169689Skan return rtx_cost (tem, SET) <= rtx_cost (orig, SET) 1796169689Skan ? tem : 0; 1797169689Skan } 1798169689Skan } 1799169689Skan 1800169689Skan /* (a - (-b)) -> (a + b). True even for IEEE. */ 1801169689Skan if (GET_CODE (op1) == NEG) 1802169689Skan return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0)); 1803169689Skan 1804169689Skan /* (-x - c) may be simplified as (-c - x). */ 1805169689Skan if (GET_CODE (op0) == NEG 1806169689Skan && (GET_CODE (op1) == CONST_INT 1807169689Skan || GET_CODE (op1) == CONST_DOUBLE)) 1808169689Skan { 1809169689Skan tem = simplify_unary_operation (NEG, mode, op1, mode); 1810169689Skan if (tem) 1811169689Skan return simplify_gen_binary (MINUS, mode, tem, XEXP (op0, 0)); 1812169689Skan } 1813169689Skan 1814169689Skan /* Don't let a relocatable value get a negative coeff. */ 1815169689Skan if (GET_CODE (op1) == CONST_INT && GET_MODE (op0) != VOIDmode) 1816169689Skan return simplify_gen_binary (PLUS, mode, 1817169689Skan op0, 1818169689Skan neg_const_int (mode, op1)); 1819169689Skan 1820169689Skan /* (x - (x & y)) -> (x & ~y) */ 1821169689Skan if (GET_CODE (op1) == AND) 1822169689Skan { 1823169689Skan if (rtx_equal_p (op0, XEXP (op1, 0))) 1824169689Skan { 1825169689Skan tem = simplify_gen_unary (NOT, mode, XEXP (op1, 1), 1826169689Skan GET_MODE (XEXP (op1, 1))); 1827169689Skan return simplify_gen_binary (AND, mode, op0, tem); 1828169689Skan } 1829169689Skan if (rtx_equal_p (op0, XEXP (op1, 1))) 1830169689Skan { 1831169689Skan tem = simplify_gen_unary (NOT, mode, XEXP (op1, 0), 1832169689Skan GET_MODE (XEXP (op1, 0))); 1833169689Skan return simplify_gen_binary (AND, mode, op0, tem); 1834169689Skan } 1835169689Skan } 1836169689Skan 1837169689Skan /* If STORE_FLAG_VALUE is 1, (minus 1 (comparison foo bar)) can be done 1838169689Skan by reversing the comparison code if valid. */ 1839169689Skan if (STORE_FLAG_VALUE == 1 1840169689Skan && trueop0 == const1_rtx 1841169689Skan && COMPARISON_P (op1) 1842169689Skan && (reversed = reversed_comparison (op1, mode))) 1843169689Skan return reversed; 1844169689Skan 1845169689Skan /* Canonicalize (minus A (mult (neg B) C)) to (plus (mult B C) A). */ 1846169689Skan if (GET_CODE (op1) == MULT 1847169689Skan && GET_CODE (XEXP (op1, 0)) == NEG) 1848169689Skan { 1849169689Skan rtx in1, in2; 1850169689Skan 1851169689Skan in1 = XEXP (XEXP (op1, 0), 0); 1852169689Skan in2 = XEXP (op1, 1); 1853169689Skan return simplify_gen_binary (PLUS, mode, 1854169689Skan simplify_gen_binary (MULT, mode, 1855169689Skan in1, in2), 1856169689Skan op0); 1857169689Skan } 1858169689Skan 1859169689Skan /* Canonicalize (minus (neg A) (mult B C)) to 1860169689Skan (minus (mult (neg B) C) A). */ 1861169689Skan if (GET_CODE (op1) == MULT 1862169689Skan && GET_CODE (op0) == NEG) 1863169689Skan { 1864169689Skan rtx in1, in2; 1865169689Skan 1866169689Skan in1 = simplify_gen_unary (NEG, mode, XEXP (op1, 0), mode); 1867169689Skan in2 = XEXP (op1, 1); 1868169689Skan return simplify_gen_binary (MINUS, mode, 1869169689Skan simplify_gen_binary (MULT, mode, 1870169689Skan in1, in2), 1871169689Skan XEXP (op0, 0)); 1872169689Skan } 1873169689Skan 1874169689Skan /* If one of the operands is a PLUS or a MINUS, see if we can 1875169689Skan simplify this by the associative law. This will, for example, 1876169689Skan canonicalize (minus A (plus B C)) to (minus (minus A B) C). 1877169689Skan Don't use the associative law for floating point. 1878169689Skan The inaccuracy makes it nonassociative, 1879169689Skan and subtle programs can break if operations are associated. */ 1880169689Skan 1881169689Skan if (INTEGRAL_MODE_P (mode) 1882169689Skan && (plus_minus_operand_p (op0) 1883169689Skan || plus_minus_operand_p (op1)) 1884169689Skan && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) 1885169689Skan return tem; 1886169689Skan break; 1887169689Skan 1888169689Skan case MULT: 1889169689Skan if (trueop1 == constm1_rtx) 1890169689Skan return simplify_gen_unary (NEG, mode, op0, mode); 1891169689Skan 1892169689Skan /* Maybe simplify x * 0 to 0. The reduction is not valid if 1893169689Skan x is NaN, since x * 0 is then also NaN. Nor is it valid 1894169689Skan when the mode has signed zeros, since multiplying a negative 1895169689Skan number by 0 will give -0, not 0. */ 1896169689Skan if (!HONOR_NANS (mode) 1897169689Skan && !HONOR_SIGNED_ZEROS (mode) 1898169689Skan && trueop1 == CONST0_RTX (mode) 1899169689Skan && ! side_effects_p (op0)) 1900169689Skan return op1; 1901169689Skan 1902169689Skan /* In IEEE floating point, x*1 is not equivalent to x for 1903169689Skan signalling NaNs. */ 1904169689Skan if (!HONOR_SNANS (mode) 1905169689Skan && trueop1 == CONST1_RTX (mode)) 1906169689Skan return op0; 1907169689Skan 1908169689Skan /* Convert multiply by constant power of two into shift unless 1909169689Skan we are still generating RTL. This test is a kludge. */ 1910169689Skan if (GET_CODE (trueop1) == CONST_INT 1911169689Skan && (val = exact_log2 (INTVAL (trueop1))) >= 0 1912169689Skan /* If the mode is larger than the host word size, and the 1913169689Skan uppermost bit is set, then this isn't a power of two due 1914169689Skan to implicit sign extension. */ 1915169689Skan && (width <= HOST_BITS_PER_WIDE_INT 1916169689Skan || val != HOST_BITS_PER_WIDE_INT - 1)) 1917169689Skan return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val)); 1918169689Skan 1919169689Skan /* Likewise for multipliers wider than a word. */ 1920169689Skan if (GET_CODE (trueop1) == CONST_DOUBLE 1921169689Skan && (GET_MODE (trueop1) == VOIDmode 1922169689Skan || GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_INT) 1923169689Skan && GET_MODE (op0) == mode 1924169689Skan && CONST_DOUBLE_LOW (trueop1) == 0 1925169689Skan && (val = exact_log2 (CONST_DOUBLE_HIGH (trueop1))) >= 0) 1926169689Skan return simplify_gen_binary (ASHIFT, mode, op0, 1927169689Skan GEN_INT (val + HOST_BITS_PER_WIDE_INT)); 1928169689Skan 1929169689Skan /* x*2 is x+x and x*(-1) is -x */ 1930169689Skan if (GET_CODE (trueop1) == CONST_DOUBLE 1931169689Skan && SCALAR_FLOAT_MODE_P (GET_MODE (trueop1)) 1932169689Skan && GET_MODE (op0) == mode) 1933169689Skan { 1934169689Skan REAL_VALUE_TYPE d; 1935169689Skan REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1); 1936169689Skan 1937169689Skan if (REAL_VALUES_EQUAL (d, dconst2)) 1938169689Skan return simplify_gen_binary (PLUS, mode, op0, copy_rtx (op0)); 1939169689Skan 1940169689Skan if (!HONOR_SNANS (mode) 1941169689Skan && REAL_VALUES_EQUAL (d, dconstm1)) 1942169689Skan return simplify_gen_unary (NEG, mode, op0, mode); 1943169689Skan } 1944169689Skan 1945169689Skan /* Optimize -x * -x as x * x. */ 1946169689Skan if (FLOAT_MODE_P (mode) 1947169689Skan && GET_CODE (op0) == NEG 1948169689Skan && GET_CODE (op1) == NEG 1949169689Skan && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)) 1950169689Skan && !side_effects_p (XEXP (op0, 0))) 1951169689Skan return simplify_gen_binary (MULT, mode, XEXP (op0, 0), XEXP (op1, 0)); 1952169689Skan 1953169689Skan /* Likewise, optimize abs(x) * abs(x) as x * x. */ 1954169689Skan if (SCALAR_FLOAT_MODE_P (mode) 1955169689Skan && GET_CODE (op0) == ABS 1956169689Skan && GET_CODE (op1) == ABS 1957169689Skan && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)) 1958169689Skan && !side_effects_p (XEXP (op0, 0))) 1959169689Skan return simplify_gen_binary (MULT, mode, XEXP (op0, 0), XEXP (op1, 0)); 1960169689Skan 1961169689Skan /* Reassociate multiplication, but for floating point MULTs 1962169689Skan only when the user specifies unsafe math optimizations. */ 1963169689Skan if (! FLOAT_MODE_P (mode) 1964169689Skan || flag_unsafe_math_optimizations) 1965169689Skan { 1966169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 1967169689Skan if (tem) 1968169689Skan return tem; 1969169689Skan } 1970169689Skan break; 1971169689Skan 1972169689Skan case IOR: 1973169689Skan if (trueop1 == const0_rtx) 1974169689Skan return op0; 1975169689Skan if (GET_CODE (trueop1) == CONST_INT 1976169689Skan && ((INTVAL (trueop1) & GET_MODE_MASK (mode)) 1977169689Skan == GET_MODE_MASK (mode))) 1978169689Skan return op1; 1979169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) 1980169689Skan return op0; 1981169689Skan /* A | (~A) -> -1 */ 1982169689Skan if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1)) 1983169689Skan || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0))) 1984169689Skan && ! side_effects_p (op0) 1985169689Skan && SCALAR_INT_MODE_P (mode)) 1986169689Skan return constm1_rtx; 1987169689Skan 1988169689Skan /* (ior A C) is C if all bits of A that might be nonzero are on in C. */ 1989169689Skan if (GET_CODE (op1) == CONST_INT 1990169689Skan && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 1991169689Skan && (nonzero_bits (op0, mode) & ~INTVAL (op1)) == 0) 1992169689Skan return op1; 1993169689Skan 1994169689Skan /* Convert (A & B) | A to A. */ 1995169689Skan if (GET_CODE (op0) == AND 1996169689Skan && (rtx_equal_p (XEXP (op0, 0), op1) 1997169689Skan || rtx_equal_p (XEXP (op0, 1), op1)) 1998169689Skan && ! side_effects_p (XEXP (op0, 0)) 1999169689Skan && ! side_effects_p (XEXP (op0, 1))) 2000169689Skan return op1; 2001169689Skan 2002169689Skan /* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the 2003169689Skan mode size to (rotate A CX). */ 2004169689Skan 2005169689Skan if (GET_CODE (op1) == ASHIFT 2006169689Skan || GET_CODE (op1) == SUBREG) 2007169689Skan { 2008169689Skan opleft = op1; 2009169689Skan opright = op0; 2010169689Skan } 2011169689Skan else 2012169689Skan { 2013169689Skan opright = op1; 2014169689Skan opleft = op0; 2015169689Skan } 2016169689Skan 2017169689Skan if (GET_CODE (opleft) == ASHIFT && GET_CODE (opright) == LSHIFTRT 2018169689Skan && rtx_equal_p (XEXP (opleft, 0), XEXP (opright, 0)) 2019169689Skan && GET_CODE (XEXP (opleft, 1)) == CONST_INT 2020169689Skan && GET_CODE (XEXP (opright, 1)) == CONST_INT 2021169689Skan && (INTVAL (XEXP (opleft, 1)) + INTVAL (XEXP (opright, 1)) 2022169689Skan == GET_MODE_BITSIZE (mode))) 2023169689Skan return gen_rtx_ROTATE (mode, XEXP (opright, 0), XEXP (opleft, 1)); 2024169689Skan 2025169689Skan /* Same, but for ashift that has been "simplified" to a wider mode 2026169689Skan by simplify_shift_const. */ 2027169689Skan 2028169689Skan if (GET_CODE (opleft) == SUBREG 2029169689Skan && GET_CODE (SUBREG_REG (opleft)) == ASHIFT 2030169689Skan && GET_CODE (opright) == LSHIFTRT 2031169689Skan && GET_CODE (XEXP (opright, 0)) == SUBREG 2032169689Skan && GET_MODE (opleft) == GET_MODE (XEXP (opright, 0)) 2033169689Skan && SUBREG_BYTE (opleft) == SUBREG_BYTE (XEXP (opright, 0)) 2034169689Skan && (GET_MODE_SIZE (GET_MODE (opleft)) 2035169689Skan < GET_MODE_SIZE (GET_MODE (SUBREG_REG (opleft)))) 2036169689Skan && rtx_equal_p (XEXP (SUBREG_REG (opleft), 0), 2037169689Skan SUBREG_REG (XEXP (opright, 0))) 2038169689Skan && GET_CODE (XEXP (SUBREG_REG (opleft), 1)) == CONST_INT 2039169689Skan && GET_CODE (XEXP (opright, 1)) == CONST_INT 2040169689Skan && (INTVAL (XEXP (SUBREG_REG (opleft), 1)) + INTVAL (XEXP (opright, 1)) 2041169689Skan == GET_MODE_BITSIZE (mode))) 2042169689Skan return gen_rtx_ROTATE (mode, XEXP (opright, 0), 2043169689Skan XEXP (SUBREG_REG (opleft), 1)); 2044169689Skan 2045169689Skan /* If we have (ior (and (X C1) C2)), simplify this by making 2046169689Skan C1 as small as possible if C1 actually changes. */ 2047169689Skan if (GET_CODE (op1) == CONST_INT 2048169689Skan && (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2049169689Skan || INTVAL (op1) > 0) 2050169689Skan && GET_CODE (op0) == AND 2051169689Skan && GET_CODE (XEXP (op0, 1)) == CONST_INT 2052169689Skan && GET_CODE (op1) == CONST_INT 2053169689Skan && (INTVAL (XEXP (op0, 1)) & INTVAL (op1)) != 0) 2054169689Skan return simplify_gen_binary (IOR, mode, 2055169689Skan simplify_gen_binary 2056169689Skan (AND, mode, XEXP (op0, 0), 2057169689Skan GEN_INT (INTVAL (XEXP (op0, 1)) 2058169689Skan & ~INTVAL (op1))), 2059169689Skan op1); 2060169689Skan 2061169689Skan /* If OP0 is (ashiftrt (plus ...) C), it might actually be 2062169689Skan a (sign_extend (plus ...)). Then check if OP1 is a CONST_INT and 2063169689Skan the PLUS does not affect any of the bits in OP1: then we can do 2064169689Skan the IOR as a PLUS and we can associate. This is valid if OP1 2065169689Skan can be safely shifted left C bits. */ 2066169689Skan if (GET_CODE (trueop1) == CONST_INT && GET_CODE (op0) == ASHIFTRT 2067169689Skan && GET_CODE (XEXP (op0, 0)) == PLUS 2068169689Skan && GET_CODE (XEXP (XEXP (op0, 0), 1)) == CONST_INT 2069169689Skan && GET_CODE (XEXP (op0, 1)) == CONST_INT 2070169689Skan && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_WIDE_INT) 2071169689Skan { 2072169689Skan int count = INTVAL (XEXP (op0, 1)); 2073169689Skan HOST_WIDE_INT mask = INTVAL (trueop1) << count; 2074169689Skan 2075169689Skan if (mask >> count == INTVAL (trueop1) 2076169689Skan && (mask & nonzero_bits (XEXP (op0, 0), mode)) == 0) 2077169689Skan return simplify_gen_binary (ASHIFTRT, mode, 2078169689Skan plus_constant (XEXP (op0, 0), mask), 2079169689Skan XEXP (op0, 1)); 2080169689Skan } 2081169689Skan 2082169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2083169689Skan if (tem) 2084169689Skan return tem; 2085169689Skan break; 2086169689Skan 2087169689Skan case XOR: 2088169689Skan if (trueop1 == const0_rtx) 2089169689Skan return op0; 2090169689Skan if (GET_CODE (trueop1) == CONST_INT 2091169689Skan && ((INTVAL (trueop1) & GET_MODE_MASK (mode)) 2092169689Skan == GET_MODE_MASK (mode))) 2093169689Skan return simplify_gen_unary (NOT, mode, op0, mode); 2094169689Skan if (rtx_equal_p (trueop0, trueop1) 2095169689Skan && ! side_effects_p (op0) 2096169689Skan && GET_MODE_CLASS (mode) != MODE_CC) 2097169689Skan return CONST0_RTX (mode); 2098169689Skan 2099169689Skan /* Canonicalize XOR of the most significant bit to PLUS. */ 2100169689Skan if ((GET_CODE (op1) == CONST_INT 2101169689Skan || GET_CODE (op1) == CONST_DOUBLE) 2102169689Skan && mode_signbit_p (mode, op1)) 2103169689Skan return simplify_gen_binary (PLUS, mode, op0, op1); 2104169689Skan /* (xor (plus X C1) C2) is (xor X (C1^C2)) if C1 is signbit. */ 2105169689Skan if ((GET_CODE (op1) == CONST_INT 2106169689Skan || GET_CODE (op1) == CONST_DOUBLE) 2107169689Skan && GET_CODE (op0) == PLUS 2108169689Skan && (GET_CODE (XEXP (op0, 1)) == CONST_INT 2109169689Skan || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE) 2110169689Skan && mode_signbit_p (mode, XEXP (op0, 1))) 2111169689Skan return simplify_gen_binary (XOR, mode, XEXP (op0, 0), 2112169689Skan simplify_gen_binary (XOR, mode, op1, 2113169689Skan XEXP (op0, 1))); 2114169689Skan 2115169689Skan /* If we are XORing two things that have no bits in common, 2116169689Skan convert them into an IOR. This helps to detect rotation encoded 2117169689Skan using those methods and possibly other simplifications. */ 2118169689Skan 2119169689Skan if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2120169689Skan && (nonzero_bits (op0, mode) 2121169689Skan & nonzero_bits (op1, mode)) == 0) 2122169689Skan return (simplify_gen_binary (IOR, mode, op0, op1)); 2123169689Skan 2124169689Skan /* Convert (XOR (NOT x) (NOT y)) to (XOR x y). 2125169689Skan Also convert (XOR (NOT x) y) to (NOT (XOR x y)), similarly for 2126169689Skan (NOT y). */ 2127169689Skan { 2128169689Skan int num_negated = 0; 2129169689Skan 2130169689Skan if (GET_CODE (op0) == NOT) 2131169689Skan num_negated++, op0 = XEXP (op0, 0); 2132169689Skan if (GET_CODE (op1) == NOT) 2133169689Skan num_negated++, op1 = XEXP (op1, 0); 2134169689Skan 2135169689Skan if (num_negated == 2) 2136169689Skan return simplify_gen_binary (XOR, mode, op0, op1); 2137169689Skan else if (num_negated == 1) 2138169689Skan return simplify_gen_unary (NOT, mode, 2139169689Skan simplify_gen_binary (XOR, mode, op0, op1), 2140169689Skan mode); 2141169689Skan } 2142169689Skan 2143169689Skan /* Convert (xor (and A B) B) to (and (not A) B). The latter may 2144169689Skan correspond to a machine insn or result in further simplifications 2145169689Skan if B is a constant. */ 2146169689Skan 2147169689Skan if (GET_CODE (op0) == AND 2148169689Skan && rtx_equal_p (XEXP (op0, 1), op1) 2149169689Skan && ! side_effects_p (op1)) 2150169689Skan return simplify_gen_binary (AND, mode, 2151169689Skan simplify_gen_unary (NOT, mode, 2152169689Skan XEXP (op0, 0), mode), 2153169689Skan op1); 2154169689Skan 2155169689Skan else if (GET_CODE (op0) == AND 2156169689Skan && rtx_equal_p (XEXP (op0, 0), op1) 2157169689Skan && ! side_effects_p (op1)) 2158169689Skan return simplify_gen_binary (AND, mode, 2159169689Skan simplify_gen_unary (NOT, mode, 2160169689Skan XEXP (op0, 1), mode), 2161169689Skan op1); 2162169689Skan 2163169689Skan /* (xor (comparison foo bar) (const_int 1)) can become the reversed 2164169689Skan comparison if STORE_FLAG_VALUE is 1. */ 2165169689Skan if (STORE_FLAG_VALUE == 1 2166169689Skan && trueop1 == const1_rtx 2167169689Skan && COMPARISON_P (op0) 2168169689Skan && (reversed = reversed_comparison (op0, mode))) 2169169689Skan return reversed; 2170169689Skan 2171169689Skan /* (lshiftrt foo C) where C is the number of bits in FOO minus 1 2172169689Skan is (lt foo (const_int 0)), so we can perform the above 2173169689Skan simplification if STORE_FLAG_VALUE is 1. */ 2174169689Skan 2175169689Skan if (STORE_FLAG_VALUE == 1 2176169689Skan && trueop1 == const1_rtx 2177169689Skan && GET_CODE (op0) == LSHIFTRT 2178169689Skan && GET_CODE (XEXP (op0, 1)) == CONST_INT 2179169689Skan && INTVAL (XEXP (op0, 1)) == GET_MODE_BITSIZE (mode) - 1) 2180169689Skan return gen_rtx_GE (mode, XEXP (op0, 0), const0_rtx); 2181169689Skan 2182169689Skan /* (xor (comparison foo bar) (const_int sign-bit)) 2183169689Skan when STORE_FLAG_VALUE is the sign bit. */ 2184169689Skan if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2185169689Skan && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode)) 2186169689Skan == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)) 2187169689Skan && trueop1 == const_true_rtx 2188169689Skan && COMPARISON_P (op0) 2189169689Skan && (reversed = reversed_comparison (op0, mode))) 2190169689Skan return reversed; 2191169689Skan 2192169689Skan break; 2193169689Skan 2194169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2195169689Skan if (tem) 2196169689Skan return tem; 2197169689Skan break; 2198169689Skan 2199169689Skan case AND: 2200169689Skan if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0)) 2201169689Skan return trueop1; 2202169689Skan /* If we are turning off bits already known off in OP0, we need 2203169689Skan not do an AND. */ 2204169689Skan if (GET_CODE (trueop1) == CONST_INT 2205169689Skan && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2206169689Skan && (nonzero_bits (trueop0, mode) & ~INTVAL (trueop1)) == 0) 2207169689Skan return op0; 2208169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0) 2209169689Skan && GET_MODE_CLASS (mode) != MODE_CC) 2210169689Skan return op0; 2211169689Skan /* A & (~A) -> 0 */ 2212169689Skan if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1)) 2213169689Skan || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0))) 2214169689Skan && ! side_effects_p (op0) 2215169689Skan && GET_MODE_CLASS (mode) != MODE_CC) 2216169689Skan return CONST0_RTX (mode); 2217169689Skan 2218169689Skan /* Transform (and (extend X) C) into (zero_extend (and X C)) if 2219169689Skan there are no nonzero bits of C outside of X's mode. */ 2220169689Skan if ((GET_CODE (op0) == SIGN_EXTEND 2221169689Skan || GET_CODE (op0) == ZERO_EXTEND) 2222169689Skan && GET_CODE (trueop1) == CONST_INT 2223169689Skan && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2224169689Skan && (~GET_MODE_MASK (GET_MODE (XEXP (op0, 0))) 2225169689Skan & INTVAL (trueop1)) == 0) 2226169689Skan { 2227169689Skan enum machine_mode imode = GET_MODE (XEXP (op0, 0)); 2228169689Skan tem = simplify_gen_binary (AND, imode, XEXP (op0, 0), 2229169689Skan gen_int_mode (INTVAL (trueop1), 2230169689Skan imode)); 2231169689Skan return simplify_gen_unary (ZERO_EXTEND, mode, tem, imode); 2232169689Skan } 2233169689Skan 2234169689Skan /* Convert (A ^ B) & A to A & (~B) since the latter is often a single 2235169689Skan insn (and may simplify more). */ 2236169689Skan if (GET_CODE (op0) == XOR 2237169689Skan && rtx_equal_p (XEXP (op0, 0), op1) 2238169689Skan && ! side_effects_p (op1)) 2239169689Skan return simplify_gen_binary (AND, mode, 2240169689Skan simplify_gen_unary (NOT, mode, 2241169689Skan XEXP (op0, 1), mode), 2242169689Skan op1); 2243169689Skan 2244169689Skan if (GET_CODE (op0) == XOR 2245169689Skan && rtx_equal_p (XEXP (op0, 1), op1) 2246169689Skan && ! side_effects_p (op1)) 2247169689Skan return simplify_gen_binary (AND, mode, 2248169689Skan simplify_gen_unary (NOT, mode, 2249169689Skan XEXP (op0, 0), mode), 2250169689Skan op1); 2251169689Skan 2252169689Skan /* Similarly for (~(A ^ B)) & A. */ 2253169689Skan if (GET_CODE (op0) == NOT 2254169689Skan && GET_CODE (XEXP (op0, 0)) == XOR 2255169689Skan && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1) 2256169689Skan && ! side_effects_p (op1)) 2257169689Skan return simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 1), op1); 2258169689Skan 2259169689Skan if (GET_CODE (op0) == NOT 2260169689Skan && GET_CODE (XEXP (op0, 0)) == XOR 2261169689Skan && rtx_equal_p (XEXP (XEXP (op0, 0), 1), op1) 2262169689Skan && ! side_effects_p (op1)) 2263169689Skan return simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 0), op1); 2264169689Skan 2265169689Skan /* Convert (A | B) & A to A. */ 2266169689Skan if (GET_CODE (op0) == IOR 2267169689Skan && (rtx_equal_p (XEXP (op0, 0), op1) 2268169689Skan || rtx_equal_p (XEXP (op0, 1), op1)) 2269169689Skan && ! side_effects_p (XEXP (op0, 0)) 2270169689Skan && ! side_effects_p (XEXP (op0, 1))) 2271169689Skan return op1; 2272169689Skan 2273169689Skan /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M, 2274169689Skan ((A & N) + B) & M -> (A + B) & M 2275169689Skan Similarly if (N & M) == 0, 2276169689Skan ((A | N) + B) & M -> (A + B) & M 2277169689Skan and for - instead of + and/or ^ instead of |. */ 2278169689Skan if (GET_CODE (trueop1) == CONST_INT 2279169689Skan && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2280169689Skan && ~INTVAL (trueop1) 2281169689Skan && (INTVAL (trueop1) & (INTVAL (trueop1) + 1)) == 0 2282169689Skan && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS)) 2283169689Skan { 2284169689Skan rtx pmop[2]; 2285169689Skan int which; 2286169689Skan 2287169689Skan pmop[0] = XEXP (op0, 0); 2288169689Skan pmop[1] = XEXP (op0, 1); 2289169689Skan 2290169689Skan for (which = 0; which < 2; which++) 2291169689Skan { 2292169689Skan tem = pmop[which]; 2293169689Skan switch (GET_CODE (tem)) 2294132718Skan { 2295169689Skan case AND: 2296169689Skan if (GET_CODE (XEXP (tem, 1)) == CONST_INT 2297169689Skan && (INTVAL (XEXP (tem, 1)) & INTVAL (trueop1)) 2298169689Skan == INTVAL (trueop1)) 2299169689Skan pmop[which] = XEXP (tem, 0); 2300169689Skan break; 2301169689Skan case IOR: 2302169689Skan case XOR: 2303169689Skan if (GET_CODE (XEXP (tem, 1)) == CONST_INT 2304169689Skan && (INTVAL (XEXP (tem, 1)) & INTVAL (trueop1)) == 0) 2305169689Skan pmop[which] = XEXP (tem, 0); 2306169689Skan break; 2307169689Skan default: 2308169689Skan break; 2309132718Skan } 2310132718Skan } 2311132718Skan 2312169689Skan if (pmop[0] != XEXP (op0, 0) || pmop[1] != XEXP (op0, 1)) 2313132718Skan { 2314169689Skan tem = simplify_gen_binary (GET_CODE (op0), mode, 2315169689Skan pmop[0], pmop[1]); 2316169689Skan return simplify_gen_binary (code, mode, tem, op1); 2317132718Skan } 2318169689Skan } 2319169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2320169689Skan if (tem) 2321169689Skan return tem; 2322169689Skan break; 2323132718Skan 2324169689Skan case UDIV: 2325169689Skan /* 0/x is 0 (or x&0 if x has side-effects). */ 2326169689Skan if (trueop0 == CONST0_RTX (mode)) 2327169689Skan { 2328169689Skan if (side_effects_p (op1)) 2329169689Skan return simplify_gen_binary (AND, mode, op1, trueop0); 2330169689Skan return trueop0; 2331169689Skan } 2332169689Skan /* x/1 is x. */ 2333169689Skan if (trueop1 == CONST1_RTX (mode)) 2334169689Skan return rtl_hooks.gen_lowpart_no_emit (mode, op0); 2335169689Skan /* Convert divide by power of two into shift. */ 2336169689Skan if (GET_CODE (trueop1) == CONST_INT 2337169689Skan && (val = exact_log2 (INTVAL (trueop1))) > 0) 2338169689Skan return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (val)); 2339169689Skan break; 2340169689Skan 2341169689Skan case DIV: 2342169689Skan /* Handle floating point and integers separately. */ 2343169689Skan if (SCALAR_FLOAT_MODE_P (mode)) 2344169689Skan { 2345169689Skan /* Maybe change 0.0 / x to 0.0. This transformation isn't 2346169689Skan safe for modes with NaNs, since 0.0 / 0.0 will then be 2347169689Skan NaN rather than 0.0. Nor is it safe for modes with signed 2348169689Skan zeros, since dividing 0 by a negative number gives -0.0 */ 2349169689Skan if (trueop0 == CONST0_RTX (mode) 2350169689Skan && !HONOR_NANS (mode) 2351169689Skan && !HONOR_SIGNED_ZEROS (mode) 2352169689Skan && ! side_effects_p (op1)) 2353169689Skan return op0; 2354169689Skan /* x/1.0 is x. */ 2355169689Skan if (trueop1 == CONST1_RTX (mode) 2356169689Skan && !HONOR_SNANS (mode)) 2357169689Skan return op0; 2358169689Skan 2359169689Skan if (GET_CODE (trueop1) == CONST_DOUBLE 2360169689Skan && trueop1 != CONST0_RTX (mode)) 2361132718Skan { 2362169689Skan REAL_VALUE_TYPE d; 2363169689Skan REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1); 2364169689Skan 2365169689Skan /* x/-1.0 is -x. */ 2366169689Skan if (REAL_VALUES_EQUAL (d, dconstm1) 2367169689Skan && !HONOR_SNANS (mode)) 2368169689Skan return simplify_gen_unary (NEG, mode, op0, mode); 2369169689Skan 2370169689Skan /* Change FP division by a constant into multiplication. 2371169689Skan Only do this with -funsafe-math-optimizations. */ 2372169689Skan if (flag_unsafe_math_optimizations 2373169689Skan && !REAL_VALUES_EQUAL (d, dconst0)) 2374169689Skan { 2375169689Skan REAL_ARITHMETIC (d, RDIV_EXPR, dconst1, d); 2376169689Skan tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode); 2377169689Skan return simplify_gen_binary (MULT, mode, op0, tem); 2378169689Skan } 2379132718Skan } 2380169689Skan } 2381169689Skan else 2382169689Skan { 2383169689Skan /* 0/x is 0 (or x&0 if x has side-effects). */ 2384169689Skan if (trueop0 == CONST0_RTX (mode)) 2385169689Skan { 2386169689Skan if (side_effects_p (op1)) 2387169689Skan return simplify_gen_binary (AND, mode, op1, trueop0); 2388169689Skan return trueop0; 2389169689Skan } 2390169689Skan /* x/1 is x. */ 2391169689Skan if (trueop1 == CONST1_RTX (mode)) 2392169689Skan return rtl_hooks.gen_lowpart_no_emit (mode, op0); 2393169689Skan /* x/-1 is -x. */ 2394169689Skan if (trueop1 == constm1_rtx) 2395169689Skan { 2396169689Skan rtx x = rtl_hooks.gen_lowpart_no_emit (mode, op0); 2397169689Skan return simplify_gen_unary (NEG, mode, x, mode); 2398169689Skan } 2399169689Skan } 2400169689Skan break; 2401132718Skan 2402169689Skan case UMOD: 2403169689Skan /* 0%x is 0 (or x&0 if x has side-effects). */ 2404169689Skan if (trueop0 == CONST0_RTX (mode)) 2405169689Skan { 2406169689Skan if (side_effects_p (op1)) 2407169689Skan return simplify_gen_binary (AND, mode, op1, trueop0); 2408169689Skan return trueop0; 2409169689Skan } 2410169689Skan /* x%1 is 0 (of x&0 if x has side-effects). */ 2411169689Skan if (trueop1 == CONST1_RTX (mode)) 2412169689Skan { 2413169689Skan if (side_effects_p (op0)) 2414169689Skan return simplify_gen_binary (AND, mode, op0, CONST0_RTX (mode)); 2415169689Skan return CONST0_RTX (mode); 2416169689Skan } 2417169689Skan /* Implement modulus by power of two as AND. */ 2418169689Skan if (GET_CODE (trueop1) == CONST_INT 2419169689Skan && exact_log2 (INTVAL (trueop1)) > 0) 2420169689Skan return simplify_gen_binary (AND, mode, op0, 2421169689Skan GEN_INT (INTVAL (op1) - 1)); 2422169689Skan break; 242390075Sobrien 2424169689Skan case MOD: 2425169689Skan /* 0%x is 0 (or x&0 if x has side-effects). */ 2426169689Skan if (trueop0 == CONST0_RTX (mode)) 2427169689Skan { 2428169689Skan if (side_effects_p (op1)) 2429169689Skan return simplify_gen_binary (AND, mode, op1, trueop0); 2430169689Skan return trueop0; 2431169689Skan } 2432169689Skan /* x%1 and x%-1 is 0 (or x&0 if x has side-effects). */ 2433169689Skan if (trueop1 == CONST1_RTX (mode) || trueop1 == constm1_rtx) 2434169689Skan { 2435169689Skan if (side_effects_p (op0)) 2436169689Skan return simplify_gen_binary (AND, mode, op0, CONST0_RTX (mode)); 2437169689Skan return CONST0_RTX (mode); 2438169689Skan } 2439169689Skan break; 244090075Sobrien 2441169689Skan case ROTATERT: 2442169689Skan case ROTATE: 2443169689Skan case ASHIFTRT: 2444169689Skan if (trueop1 == CONST0_RTX (mode)) 2445169689Skan return op0; 2446169689Skan if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) 2447169689Skan return op0; 2448169689Skan /* Rotating ~0 always results in ~0. */ 2449169689Skan if (GET_CODE (trueop0) == CONST_INT && width <= HOST_BITS_PER_WIDE_INT 2450169689Skan && (unsigned HOST_WIDE_INT) INTVAL (trueop0) == GET_MODE_MASK (mode) 2451169689Skan && ! side_effects_p (op1)) 2452169689Skan return op0; 2453169689Skan break; 2454132718Skan 2455169689Skan case ASHIFT: 2456169689Skan case SS_ASHIFT: 2457169689Skan if (trueop1 == CONST0_RTX (mode)) 2458169689Skan return op0; 2459169689Skan if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) 2460169689Skan return op0; 2461169689Skan break; 246290075Sobrien 2463169689Skan case LSHIFTRT: 2464169689Skan if (trueop1 == CONST0_RTX (mode)) 2465169689Skan return op0; 2466169689Skan if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) 2467169689Skan return op0; 2468169689Skan /* Optimize (lshiftrt (clz X) C) as (eq X 0). */ 2469169689Skan if (GET_CODE (op0) == CLZ 2470169689Skan && GET_CODE (trueop1) == CONST_INT 2471169689Skan && STORE_FLAG_VALUE == 1 2472169689Skan && INTVAL (trueop1) < (HOST_WIDE_INT)width) 2473169689Skan { 2474169689Skan enum machine_mode imode = GET_MODE (XEXP (op0, 0)); 2475169689Skan unsigned HOST_WIDE_INT zero_val = 0; 2476132718Skan 2477169689Skan if (CLZ_DEFINED_VALUE_AT_ZERO (imode, zero_val) 2478169689Skan && zero_val == GET_MODE_BITSIZE (imode) 2479169689Skan && INTVAL (trueop1) == exact_log2 (zero_val)) 2480169689Skan return simplify_gen_relational (EQ, mode, imode, 2481169689Skan XEXP (op0, 0), const0_rtx); 2482169689Skan } 2483169689Skan break; 2484117395Skan 2485169689Skan case SMIN: 2486169689Skan if (width <= HOST_BITS_PER_WIDE_INT 2487169689Skan && GET_CODE (trueop1) == CONST_INT 2488169689Skan && INTVAL (trueop1) == (HOST_WIDE_INT) 1 << (width -1) 2489169689Skan && ! side_effects_p (op0)) 2490169689Skan return op1; 2491169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) 2492169689Skan return op0; 2493169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2494169689Skan if (tem) 2495169689Skan return tem; 2496169689Skan break; 2497169689Skan 2498169689Skan case SMAX: 2499169689Skan if (width <= HOST_BITS_PER_WIDE_INT 2500169689Skan && GET_CODE (trueop1) == CONST_INT 2501169689Skan && ((unsigned HOST_WIDE_INT) INTVAL (trueop1) 2502169689Skan == (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1) 2503169689Skan && ! side_effects_p (op0)) 2504169689Skan return op1; 2505169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) 2506169689Skan return op0; 2507169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2508169689Skan if (tem) 2509169689Skan return tem; 2510169689Skan break; 2511169689Skan 2512169689Skan case UMIN: 2513169689Skan if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0)) 2514169689Skan return op1; 2515169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) 2516169689Skan return op0; 2517169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2518169689Skan if (tem) 2519169689Skan return tem; 2520169689Skan break; 2521169689Skan 2522169689Skan case UMAX: 2523169689Skan if (trueop1 == constm1_rtx && ! side_effects_p (op0)) 2524169689Skan return op1; 2525169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) 2526169689Skan return op0; 2527169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2528169689Skan if (tem) 2529169689Skan return tem; 2530169689Skan break; 2531169689Skan 2532169689Skan case SS_PLUS: 2533169689Skan case US_PLUS: 2534169689Skan case SS_MINUS: 2535169689Skan case US_MINUS: 2536169689Skan /* ??? There are simplifications that can be done. */ 2537169689Skan return 0; 2538169689Skan 2539169689Skan case VEC_SELECT: 2540169689Skan if (!VECTOR_MODE_P (mode)) 2541169689Skan { 2542169689Skan gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0))); 2543169689Skan gcc_assert (mode == GET_MODE_INNER (GET_MODE (trueop0))); 2544169689Skan gcc_assert (GET_CODE (trueop1) == PARALLEL); 2545169689Skan gcc_assert (XVECLEN (trueop1, 0) == 1); 2546169689Skan gcc_assert (GET_CODE (XVECEXP (trueop1, 0, 0)) == CONST_INT); 2547169689Skan 2548169689Skan if (GET_CODE (trueop0) == CONST_VECTOR) 2549169689Skan return CONST_VECTOR_ELT (trueop0, INTVAL (XVECEXP 2550169689Skan (trueop1, 0, 0))); 255190075Sobrien } 2552169689Skan else 2553169689Skan { 2554169689Skan gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0))); 2555169689Skan gcc_assert (GET_MODE_INNER (mode) 2556169689Skan == GET_MODE_INNER (GET_MODE (trueop0))); 2557169689Skan gcc_assert (GET_CODE (trueop1) == PARALLEL); 255890075Sobrien 2559169689Skan if (GET_CODE (trueop0) == CONST_VECTOR) 2560169689Skan { 2561169689Skan int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); 2562169689Skan unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); 2563169689Skan rtvec v = rtvec_alloc (n_elts); 2564169689Skan unsigned int i; 2565169689Skan 2566169689Skan gcc_assert (XVECLEN (trueop1, 0) == (int) n_elts); 2567169689Skan for (i = 0; i < n_elts; i++) 2568169689Skan { 2569169689Skan rtx x = XVECEXP (trueop1, 0, i); 2570169689Skan 2571169689Skan gcc_assert (GET_CODE (x) == CONST_INT); 2572169689Skan RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, 2573169689Skan INTVAL (x)); 2574169689Skan } 2575169689Skan 2576169689Skan return gen_rtx_CONST_VECTOR (mode, v); 2577169689Skan } 2578169689Skan } 2579169689Skan 2580169689Skan if (XVECLEN (trueop1, 0) == 1 2581169689Skan && GET_CODE (XVECEXP (trueop1, 0, 0)) == CONST_INT 2582169689Skan && GET_CODE (trueop0) == VEC_CONCAT) 2583169689Skan { 2584169689Skan rtx vec = trueop0; 2585169689Skan int offset = INTVAL (XVECEXP (trueop1, 0, 0)) * GET_MODE_SIZE (mode); 2586169689Skan 2587169689Skan /* Try to find the element in the VEC_CONCAT. */ 2588169689Skan while (GET_MODE (vec) != mode 2589169689Skan && GET_CODE (vec) == VEC_CONCAT) 2590169689Skan { 2591169689Skan HOST_WIDE_INT vec_size = GET_MODE_SIZE (GET_MODE (XEXP (vec, 0))); 2592169689Skan if (offset < vec_size) 2593169689Skan vec = XEXP (vec, 0); 2594169689Skan else 2595169689Skan { 2596169689Skan offset -= vec_size; 2597169689Skan vec = XEXP (vec, 1); 2598169689Skan } 2599169689Skan vec = avoid_constant_pool_reference (vec); 2600169689Skan } 2601169689Skan 2602169689Skan if (GET_MODE (vec) == mode) 2603169689Skan return vec; 2604169689Skan } 2605169689Skan 260690075Sobrien return 0; 2607169689Skan case VEC_CONCAT: 2608169689Skan { 2609169689Skan enum machine_mode op0_mode = (GET_MODE (trueop0) != VOIDmode 2610169689Skan ? GET_MODE (trueop0) 2611169689Skan : GET_MODE_INNER (mode)); 2612169689Skan enum machine_mode op1_mode = (GET_MODE (trueop1) != VOIDmode 2613169689Skan ? GET_MODE (trueop1) 2614169689Skan : GET_MODE_INNER (mode)); 2615132718Skan 2616169689Skan gcc_assert (VECTOR_MODE_P (mode)); 2617169689Skan gcc_assert (GET_MODE_SIZE (op0_mode) + GET_MODE_SIZE (op1_mode) 2618169689Skan == GET_MODE_SIZE (mode)); 2619132718Skan 2620169689Skan if (VECTOR_MODE_P (op0_mode)) 2621169689Skan gcc_assert (GET_MODE_INNER (mode) 2622169689Skan == GET_MODE_INNER (op0_mode)); 2623169689Skan else 2624169689Skan gcc_assert (GET_MODE_INNER (mode) == op0_mode); 2625132718Skan 2626169689Skan if (VECTOR_MODE_P (op1_mode)) 2627169689Skan gcc_assert (GET_MODE_INNER (mode) 2628169689Skan == GET_MODE_INNER (op1_mode)); 2629169689Skan else 2630169689Skan gcc_assert (GET_MODE_INNER (mode) == op1_mode); 2631132718Skan 2632169689Skan if ((GET_CODE (trueop0) == CONST_VECTOR 2633169689Skan || GET_CODE (trueop0) == CONST_INT 2634169689Skan || GET_CODE (trueop0) == CONST_DOUBLE) 2635169689Skan && (GET_CODE (trueop1) == CONST_VECTOR 2636169689Skan || GET_CODE (trueop1) == CONST_INT 2637169689Skan || GET_CODE (trueop1) == CONST_DOUBLE)) 2638169689Skan { 2639169689Skan int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); 2640169689Skan unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); 2641169689Skan rtvec v = rtvec_alloc (n_elts); 2642169689Skan unsigned int i; 2643169689Skan unsigned in_n_elts = 1; 2644132718Skan 2645169689Skan if (VECTOR_MODE_P (op0_mode)) 2646169689Skan in_n_elts = (GET_MODE_SIZE (op0_mode) / elt_size); 2647169689Skan for (i = 0; i < n_elts; i++) 2648169689Skan { 2649169689Skan if (i < in_n_elts) 2650169689Skan { 2651169689Skan if (!VECTOR_MODE_P (op0_mode)) 2652169689Skan RTVEC_ELT (v, i) = trueop0; 2653169689Skan else 2654169689Skan RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, i); 2655169689Skan } 2656169689Skan else 2657169689Skan { 2658169689Skan if (!VECTOR_MODE_P (op1_mode)) 2659169689Skan RTVEC_ELT (v, i) = trueop1; 2660169689Skan else 2661169689Skan RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop1, 2662169689Skan i - in_n_elts); 2663169689Skan } 2664169689Skan } 2665169689Skan 2666169689Skan return gen_rtx_CONST_VECTOR (mode, v); 2667169689Skan } 2668169689Skan } 2669169689Skan return 0; 2670169689Skan 2671169689Skan default: 2672169689Skan gcc_unreachable (); 2673132718Skan } 2674132718Skan 2675132718Skan return 0; 2676132718Skan} 2677132718Skan 267890075Sobrienrtx 2679169689Skansimplify_const_binary_operation (enum rtx_code code, enum machine_mode mode, 2680169689Skan rtx op0, rtx op1) 268190075Sobrien{ 268290075Sobrien HOST_WIDE_INT arg0, arg1, arg0s, arg1s; 268390075Sobrien HOST_WIDE_INT val; 268490075Sobrien unsigned int width = GET_MODE_BITSIZE (mode); 268590075Sobrien 2686132718Skan if (VECTOR_MODE_P (mode) 2687146895Skan && code != VEC_CONCAT 2688169689Skan && GET_CODE (op0) == CONST_VECTOR 2689169689Skan && GET_CODE (op1) == CONST_VECTOR) 2690132718Skan { 2691169689Skan unsigned n_elts = GET_MODE_NUNITS (mode); 2692169689Skan enum machine_mode op0mode = GET_MODE (op0); 2693169689Skan unsigned op0_n_elts = GET_MODE_NUNITS (op0mode); 2694169689Skan enum machine_mode op1mode = GET_MODE (op1); 2695169689Skan unsigned op1_n_elts = GET_MODE_NUNITS (op1mode); 2696132718Skan rtvec v = rtvec_alloc (n_elts); 2697132718Skan unsigned int i; 2698132718Skan 2699169689Skan gcc_assert (op0_n_elts == n_elts); 2700169689Skan gcc_assert (op1_n_elts == n_elts); 2701132718Skan for (i = 0; i < n_elts; i++) 2702132718Skan { 2703132718Skan rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode), 2704169689Skan CONST_VECTOR_ELT (op0, i), 2705169689Skan CONST_VECTOR_ELT (op1, i)); 2706132718Skan if (!x) 2707132718Skan return 0; 2708132718Skan RTVEC_ELT (v, i) = x; 2709132718Skan } 2710132718Skan 2711132718Skan return gen_rtx_CONST_VECTOR (mode, v); 2712132718Skan } 2713132718Skan 2714169689Skan if (VECTOR_MODE_P (mode) 2715169689Skan && code == VEC_CONCAT 2716169689Skan && CONSTANT_P (op0) && CONSTANT_P (op1)) 2717169689Skan { 2718169689Skan unsigned n_elts = GET_MODE_NUNITS (mode); 2719169689Skan rtvec v = rtvec_alloc (n_elts); 2720169689Skan 2721169689Skan gcc_assert (n_elts >= 2); 2722169689Skan if (n_elts == 2) 2723169689Skan { 2724169689Skan gcc_assert (GET_CODE (op0) != CONST_VECTOR); 2725169689Skan gcc_assert (GET_CODE (op1) != CONST_VECTOR); 2726169689Skan 2727169689Skan RTVEC_ELT (v, 0) = op0; 2728169689Skan RTVEC_ELT (v, 1) = op1; 2729169689Skan } 2730169689Skan else 2731169689Skan { 2732169689Skan unsigned op0_n_elts = GET_MODE_NUNITS (GET_MODE (op0)); 2733169689Skan unsigned op1_n_elts = GET_MODE_NUNITS (GET_MODE (op1)); 2734169689Skan unsigned i; 2735169689Skan 2736169689Skan gcc_assert (GET_CODE (op0) == CONST_VECTOR); 2737169689Skan gcc_assert (GET_CODE (op1) == CONST_VECTOR); 2738169689Skan gcc_assert (op0_n_elts + op1_n_elts == n_elts); 2739169689Skan 2740169689Skan for (i = 0; i < op0_n_elts; ++i) 2741169689Skan RTVEC_ELT (v, i) = XVECEXP (op0, 0, i); 2742169689Skan for (i = 0; i < op1_n_elts; ++i) 2743169689Skan RTVEC_ELT (v, op0_n_elts+i) = XVECEXP (op1, 0, i); 2744169689Skan } 2745169689Skan 2746169689Skan return gen_rtx_CONST_VECTOR (mode, v); 2747169689Skan } 2748169689Skan 2749169689Skan if (SCALAR_FLOAT_MODE_P (mode) 2750169689Skan && GET_CODE (op0) == CONST_DOUBLE 2751169689Skan && GET_CODE (op1) == CONST_DOUBLE 275290075Sobrien && mode == GET_MODE (op0) && mode == GET_MODE (op1)) 275390075Sobrien { 2754146895Skan if (code == AND 2755146895Skan || code == IOR 2756146895Skan || code == XOR) 2757146895Skan { 2758146895Skan long tmp0[4]; 2759146895Skan long tmp1[4]; 2760146895Skan REAL_VALUE_TYPE r; 2761146895Skan int i; 276290075Sobrien 2763146895Skan real_to_target (tmp0, CONST_DOUBLE_REAL_VALUE (op0), 2764146895Skan GET_MODE (op0)); 2765146895Skan real_to_target (tmp1, CONST_DOUBLE_REAL_VALUE (op1), 2766146895Skan GET_MODE (op1)); 2767146895Skan for (i = 0; i < 4; i++) 2768146895Skan { 2769169689Skan switch (code) 2770169689Skan { 2771169689Skan case AND: 2772146895Skan tmp0[i] &= tmp1[i]; 2773169689Skan break; 2774169689Skan case IOR: 2775146895Skan tmp0[i] |= tmp1[i]; 2776169689Skan break; 2777169689Skan case XOR: 2778146895Skan tmp0[i] ^= tmp1[i]; 2779169689Skan break; 2780169689Skan default: 2781169689Skan gcc_unreachable (); 2782169689Skan } 2783146895Skan } 2784146895Skan real_from_target (&r, tmp0, mode); 2785146895Skan return CONST_DOUBLE_FROM_REAL_VALUE (r, mode); 2786146895Skan } 2787146895Skan else 2788146895Skan { 2789169689Skan REAL_VALUE_TYPE f0, f1, value, result; 2790169689Skan bool inexact; 2791117395Skan 2792169689Skan REAL_VALUE_FROM_CONST_DOUBLE (f0, op0); 2793169689Skan REAL_VALUE_FROM_CONST_DOUBLE (f1, op1); 2794169689Skan real_convert (&f0, mode, &f0); 2795169689Skan real_convert (&f1, mode, &f1); 2796132718Skan 2797146895Skan if (HONOR_SNANS (mode) 2798146895Skan && (REAL_VALUE_ISNAN (f0) || REAL_VALUE_ISNAN (f1))) 2799146895Skan return 0; 2800117395Skan 2801146895Skan if (code == DIV 2802146895Skan && REAL_VALUES_EQUAL (f1, dconst0) 2803146895Skan && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode))) 2804146895Skan return 0; 2805132718Skan 2806146895Skan if (MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) 2807146895Skan && flag_trapping_math 2808146895Skan && REAL_VALUE_ISINF (f0) && REAL_VALUE_ISINF (f1)) 2809132718Skan { 2810146895Skan int s0 = REAL_VALUE_NEGATIVE (f0); 2811146895Skan int s1 = REAL_VALUE_NEGATIVE (f1); 2812146895Skan 2813146895Skan switch (code) 2814146895Skan { 2815146895Skan case PLUS: 2816146895Skan /* Inf + -Inf = NaN plus exception. */ 2817146895Skan if (s0 != s1) 2818146895Skan return 0; 2819146895Skan break; 2820146895Skan case MINUS: 2821146895Skan /* Inf - Inf = NaN plus exception. */ 2822146895Skan if (s0 == s1) 2823146895Skan return 0; 2824146895Skan break; 2825146895Skan case DIV: 2826146895Skan /* Inf / Inf = NaN plus exception. */ 2827146895Skan return 0; 2828146895Skan default: 2829146895Skan break; 2830146895Skan } 2831132718Skan } 2832132718Skan 2833146895Skan if (code == MULT && MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) 2834146895Skan && flag_trapping_math 2835146895Skan && ((REAL_VALUE_ISINF (f0) && REAL_VALUES_EQUAL (f1, dconst0)) 2836146895Skan || (REAL_VALUE_ISINF (f1) 2837146895Skan && REAL_VALUES_EQUAL (f0, dconst0)))) 2838146895Skan /* Inf * 0 = NaN plus exception. */ 2839146895Skan return 0; 2840132718Skan 2841169689Skan inexact = real_arithmetic (&value, rtx_to_tree_code (code), 2842169689Skan &f0, &f1); 2843169689Skan real_convert (&result, mode, &value); 2844117395Skan 2845169689Skan /* Don't constant fold this floating point operation if 2846169689Skan the result has overflowed and flag_trapping_math. */ 2847169689Skan 2848169689Skan if (flag_trapping_math 2849169689Skan && MODE_HAS_INFINITIES (mode) 2850169689Skan && REAL_VALUE_ISINF (result) 2851169689Skan && !REAL_VALUE_ISINF (f0) 2852169689Skan && !REAL_VALUE_ISINF (f1)) 2853169689Skan /* Overflow plus exception. */ 2854169689Skan return 0; 2855169689Skan 2856169689Skan /* Don't constant fold this floating point operation if the 2857169689Skan result may dependent upon the run-time rounding mode and 2858169689Skan flag_rounding_math is set, or if GCC's software emulation 2859169689Skan is unable to accurately represent the result. */ 2860169689Skan 2861169689Skan if ((flag_rounding_math 2862169689Skan || (REAL_MODE_FORMAT_COMPOSITE_P (mode) 2863169689Skan && !flag_unsafe_math_optimizations)) 2864169689Skan && (inexact || !real_identical (&result, &value))) 2865169689Skan return NULL_RTX; 2866169689Skan 2867169689Skan return CONST_DOUBLE_FROM_REAL_VALUE (result, mode); 2868146895Skan } 286990075Sobrien } 287090075Sobrien 287190075Sobrien /* We can fold some multi-word operations. */ 287290075Sobrien if (GET_MODE_CLASS (mode) == MODE_INT 287390075Sobrien && width == HOST_BITS_PER_WIDE_INT * 2 2874169689Skan && (GET_CODE (op0) == CONST_DOUBLE || GET_CODE (op0) == CONST_INT) 2875169689Skan && (GET_CODE (op1) == CONST_DOUBLE || GET_CODE (op1) == CONST_INT)) 287690075Sobrien { 2877169689Skan unsigned HOST_WIDE_INT l1, l2, lv, lt; 2878169689Skan HOST_WIDE_INT h1, h2, hv, ht; 287990075Sobrien 2880169689Skan if (GET_CODE (op0) == CONST_DOUBLE) 2881169689Skan l1 = CONST_DOUBLE_LOW (op0), h1 = CONST_DOUBLE_HIGH (op0); 288290075Sobrien else 2883169689Skan l1 = INTVAL (op0), h1 = HWI_SIGN_EXTEND (l1); 288490075Sobrien 2885169689Skan if (GET_CODE (op1) == CONST_DOUBLE) 2886169689Skan l2 = CONST_DOUBLE_LOW (op1), h2 = CONST_DOUBLE_HIGH (op1); 288790075Sobrien else 2888169689Skan l2 = INTVAL (op1), h2 = HWI_SIGN_EXTEND (l2); 288990075Sobrien 289090075Sobrien switch (code) 289190075Sobrien { 289290075Sobrien case MINUS: 289390075Sobrien /* A - B == A + (-B). */ 289490075Sobrien neg_double (l2, h2, &lv, &hv); 289590075Sobrien l2 = lv, h2 = hv; 289690075Sobrien 2897132718Skan /* Fall through.... */ 289890075Sobrien 289990075Sobrien case PLUS: 290090075Sobrien add_double (l1, h1, l2, h2, &lv, &hv); 290190075Sobrien break; 290290075Sobrien 290390075Sobrien case MULT: 290490075Sobrien mul_double (l1, h1, l2, h2, &lv, &hv); 290590075Sobrien break; 290690075Sobrien 2907169689Skan case DIV: 2908169689Skan if (div_and_round_double (TRUNC_DIV_EXPR, 0, l1, h1, l2, h2, 2909169689Skan &lv, &hv, <, &ht)) 2910169689Skan return 0; 2911169689Skan break; 291290075Sobrien 2913169689Skan case MOD: 2914169689Skan if (div_and_round_double (TRUNC_DIV_EXPR, 0, l1, h1, l2, h2, 2915169689Skan <, &ht, &lv, &hv)) 2916169689Skan return 0; 2917169689Skan break; 2918169689Skan 2919169689Skan case UDIV: 2920169689Skan if (div_and_round_double (TRUNC_DIV_EXPR, 1, l1, h1, l2, h2, 2921169689Skan &lv, &hv, <, &ht)) 2922169689Skan return 0; 2923169689Skan break; 2924169689Skan 2925169689Skan case UMOD: 2926169689Skan if (div_and_round_double (TRUNC_DIV_EXPR, 1, l1, h1, l2, h2, 2927169689Skan <, &ht, &lv, &hv)) 2928169689Skan return 0; 2929169689Skan break; 2930169689Skan 293190075Sobrien case AND: 293290075Sobrien lv = l1 & l2, hv = h1 & h2; 293390075Sobrien break; 293490075Sobrien 293590075Sobrien case IOR: 293690075Sobrien lv = l1 | l2, hv = h1 | h2; 293790075Sobrien break; 293890075Sobrien 293990075Sobrien case XOR: 294090075Sobrien lv = l1 ^ l2, hv = h1 ^ h2; 294190075Sobrien break; 294290075Sobrien 294390075Sobrien case SMIN: 294490075Sobrien if (h1 < h2 294590075Sobrien || (h1 == h2 294690075Sobrien && ((unsigned HOST_WIDE_INT) l1 294790075Sobrien < (unsigned HOST_WIDE_INT) l2))) 294890075Sobrien lv = l1, hv = h1; 294990075Sobrien else 295090075Sobrien lv = l2, hv = h2; 295190075Sobrien break; 295290075Sobrien 295390075Sobrien case SMAX: 295490075Sobrien if (h1 > h2 295590075Sobrien || (h1 == h2 295690075Sobrien && ((unsigned HOST_WIDE_INT) l1 295790075Sobrien > (unsigned HOST_WIDE_INT) l2))) 295890075Sobrien lv = l1, hv = h1; 295990075Sobrien else 296090075Sobrien lv = l2, hv = h2; 296190075Sobrien break; 296290075Sobrien 296390075Sobrien case UMIN: 296490075Sobrien if ((unsigned HOST_WIDE_INT) h1 < (unsigned HOST_WIDE_INT) h2 296590075Sobrien || (h1 == h2 296690075Sobrien && ((unsigned HOST_WIDE_INT) l1 296790075Sobrien < (unsigned HOST_WIDE_INT) l2))) 296890075Sobrien lv = l1, hv = h1; 296990075Sobrien else 297090075Sobrien lv = l2, hv = h2; 297190075Sobrien break; 297290075Sobrien 297390075Sobrien case UMAX: 297490075Sobrien if ((unsigned HOST_WIDE_INT) h1 > (unsigned HOST_WIDE_INT) h2 297590075Sobrien || (h1 == h2 297690075Sobrien && ((unsigned HOST_WIDE_INT) l1 297790075Sobrien > (unsigned HOST_WIDE_INT) l2))) 297890075Sobrien lv = l1, hv = h1; 297990075Sobrien else 298090075Sobrien lv = l2, hv = h2; 298190075Sobrien break; 298290075Sobrien 298390075Sobrien case LSHIFTRT: case ASHIFTRT: 298490075Sobrien case ASHIFT: 298590075Sobrien case ROTATE: case ROTATERT: 298690075Sobrien if (SHIFT_COUNT_TRUNCATED) 298790075Sobrien l2 &= (GET_MODE_BITSIZE (mode) - 1), h2 = 0; 298890075Sobrien 298990075Sobrien if (h2 != 0 || l2 >= GET_MODE_BITSIZE (mode)) 299090075Sobrien return 0; 299190075Sobrien 299290075Sobrien if (code == LSHIFTRT || code == ASHIFTRT) 299390075Sobrien rshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv, 299490075Sobrien code == ASHIFTRT); 299590075Sobrien else if (code == ASHIFT) 299690075Sobrien lshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv, 1); 299790075Sobrien else if (code == ROTATE) 299890075Sobrien lrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv); 299990075Sobrien else /* code == ROTATERT */ 300090075Sobrien rrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv); 300190075Sobrien break; 300290075Sobrien 300390075Sobrien default: 300490075Sobrien return 0; 300590075Sobrien } 300690075Sobrien 300790075Sobrien return immed_double_const (lv, hv, mode); 300890075Sobrien } 300990075Sobrien 3010169689Skan if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT 3011169689Skan && width <= HOST_BITS_PER_WIDE_INT && width != 0) 301290075Sobrien { 3013169689Skan /* Get the integer argument values in two forms: 3014169689Skan zero-extended in ARG0, ARG1 and sign-extended in ARG0S, ARG1S. */ 301590075Sobrien 3016169689Skan arg0 = INTVAL (op0); 3017169689Skan arg1 = INTVAL (op1); 3018169689Skan 3019169689Skan if (width < HOST_BITS_PER_WIDE_INT) 3020169689Skan { 3021169689Skan arg0 &= ((HOST_WIDE_INT) 1 << width) - 1; 3022169689Skan arg1 &= ((HOST_WIDE_INT) 1 << width) - 1; 3023169689Skan 3024169689Skan arg0s = arg0; 3025169689Skan if (arg0s & ((HOST_WIDE_INT) 1 << (width - 1))) 3026169689Skan arg0s |= ((HOST_WIDE_INT) (-1) << width); 3027169689Skan 3028169689Skan arg1s = arg1; 3029169689Skan if (arg1s & ((HOST_WIDE_INT) 1 << (width - 1))) 3030169689Skan arg1s |= ((HOST_WIDE_INT) (-1) << width); 3031169689Skan } 3032169689Skan else 3033169689Skan { 3034169689Skan arg0s = arg0; 3035169689Skan arg1s = arg1; 3036169689Skan } 3037169689Skan 3038169689Skan /* Compute the value of the arithmetic. */ 3039169689Skan 304090075Sobrien switch (code) 304190075Sobrien { 304290075Sobrien case PLUS: 3043169689Skan val = arg0s + arg1s; 304490075Sobrien break; 3045169689Skan 304690075Sobrien case MINUS: 3047169689Skan val = arg0s - arg1s; 304890075Sobrien break; 3049169689Skan 305090075Sobrien case MULT: 3051169689Skan val = arg0s * arg1s; 305290075Sobrien break; 3053169689Skan 3054169689Skan case DIV: 3055169689Skan if (arg1s == 0 3056169689Skan || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) 3057169689Skan && arg1s == -1)) 3058169689Skan return 0; 3059169689Skan val = arg0s / arg1s; 306090075Sobrien break; 3061169689Skan 3062169689Skan case MOD: 3063169689Skan if (arg1s == 0 3064169689Skan || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) 3065169689Skan && arg1s == -1)) 3066169689Skan return 0; 3067169689Skan val = arg0s % arg1s; 306890075Sobrien break; 3069169689Skan 307090075Sobrien case UDIV: 3071169689Skan if (arg1 == 0 3072169689Skan || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) 3073169689Skan && arg1s == -1)) 3074169689Skan return 0; 3075169689Skan val = (unsigned HOST_WIDE_INT) arg0 / arg1; 307690075Sobrien break; 3077169689Skan 307890075Sobrien case UMOD: 3079169689Skan if (arg1 == 0 3080169689Skan || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) 3081169689Skan && arg1s == -1)) 3082169689Skan return 0; 3083169689Skan val = (unsigned HOST_WIDE_INT) arg0 % arg1; 308490075Sobrien break; 3085169689Skan 3086169689Skan case AND: 3087169689Skan val = arg0 & arg1; 3088169689Skan break; 3089169689Skan 3090169689Skan case IOR: 3091169689Skan val = arg0 | arg1; 3092169689Skan break; 3093169689Skan 3094169689Skan case XOR: 3095169689Skan val = arg0 ^ arg1; 3096169689Skan break; 3097169689Skan 3098169689Skan case LSHIFTRT: 3099169689Skan case ASHIFT: 3100169689Skan case ASHIFTRT: 3101169689Skan /* Truncate the shift if SHIFT_COUNT_TRUNCATED, otherwise make sure 3102169689Skan the value is in range. We can't return any old value for 3103169689Skan out-of-range arguments because either the middle-end (via 3104169689Skan shift_truncation_mask) or the back-end might be relying on 3105169689Skan target-specific knowledge. Nor can we rely on 3106169689Skan shift_truncation_mask, since the shift might not be part of an 3107169689Skan ashlM3, lshrM3 or ashrM3 instruction. */ 3108169689Skan if (SHIFT_COUNT_TRUNCATED) 3109169689Skan arg1 = (unsigned HOST_WIDE_INT) arg1 % width; 3110169689Skan else if (arg1 < 0 || arg1 >= GET_MODE_BITSIZE (mode)) 3111169689Skan return 0; 3112169689Skan 3113169689Skan val = (code == ASHIFT 3114169689Skan ? ((unsigned HOST_WIDE_INT) arg0) << arg1 3115169689Skan : ((unsigned HOST_WIDE_INT) arg0) >> arg1); 3116169689Skan 3117169689Skan /* Sign-extend the result for arithmetic right shifts. */ 3118169689Skan if (code == ASHIFTRT && arg0s < 0 && arg1 > 0) 3119169689Skan val |= ((HOST_WIDE_INT) -1) << (width - arg1); 3120169689Skan break; 3121169689Skan 312290075Sobrien case ROTATERT: 3123169689Skan if (arg1 < 0) 3124169689Skan return 0; 3125169689Skan 3126169689Skan arg1 %= width; 3127169689Skan val = ((((unsigned HOST_WIDE_INT) arg0) << (width - arg1)) 3128169689Skan | (((unsigned HOST_WIDE_INT) arg0) >> arg1)); 3129169689Skan break; 3130169689Skan 313190075Sobrien case ROTATE: 3132169689Skan if (arg1 < 0) 3133169689Skan return 0; 3134169689Skan 3135169689Skan arg1 %= width; 3136169689Skan val = ((((unsigned HOST_WIDE_INT) arg0) << arg1) 3137169689Skan | (((unsigned HOST_WIDE_INT) arg0) >> (width - arg1))); 313890075Sobrien break; 3139169689Skan 3140169689Skan case COMPARE: 3141169689Skan /* Do nothing here. */ 3142169689Skan return 0; 3143169689Skan 314490075Sobrien case SMIN: 3145169689Skan val = arg0s <= arg1s ? arg0s : arg1s; 314690075Sobrien break; 3147169689Skan 3148169689Skan case UMIN: 3149169689Skan val = ((unsigned HOST_WIDE_INT) arg0 3150169689Skan <= (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1); 3151169689Skan break; 3152169689Skan 315390075Sobrien case SMAX: 3154169689Skan val = arg0s > arg1s ? arg0s : arg1s; 315590075Sobrien break; 3156169689Skan 315790075Sobrien case UMAX: 3158169689Skan val = ((unsigned HOST_WIDE_INT) arg0 3159169689Skan > (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1); 316090075Sobrien break; 3161169689Skan 316290075Sobrien case SS_PLUS: 316390075Sobrien case US_PLUS: 316490075Sobrien case SS_MINUS: 316590075Sobrien case US_MINUS: 3166169689Skan case SS_ASHIFT: 316790075Sobrien /* ??? There are simplifications that can be done. */ 316890075Sobrien return 0; 3169169689Skan 317090075Sobrien default: 3171169689Skan gcc_unreachable (); 317290075Sobrien } 3173117395Skan 3174169689Skan return gen_int_mode (val, mode); 317590075Sobrien } 317690075Sobrien 3177169689Skan return NULL_RTX; 3178169689Skan} 317990075Sobrien 318090075Sobrien 318190075Sobrien 318290075Sobrien/* Simplify a PLUS or MINUS, at least one of whose operands may be another 318390075Sobrien PLUS or MINUS. 318490075Sobrien 318590075Sobrien Rather than test for specific case, we do this by a brute-force method 318690075Sobrien and do all possible simplifications until no more changes occur. Then 3187169689Skan we rebuild the operation. */ 318890075Sobrien 318990075Sobrienstruct simplify_plus_minus_op_data 319090075Sobrien{ 319190075Sobrien rtx op; 3192169689Skan short neg; 319390075Sobrien}; 319490075Sobrien 319590075Sobrienstatic int 3196132718Skansimplify_plus_minus_op_data_cmp (const void *p1, const void *p2) 319790075Sobrien{ 319890075Sobrien const struct simplify_plus_minus_op_data *d1 = p1; 319990075Sobrien const struct simplify_plus_minus_op_data *d2 = p2; 3200169689Skan int result; 320190075Sobrien 3202169689Skan result = (commutative_operand_precedence (d2->op) 3203169689Skan - commutative_operand_precedence (d1->op)); 3204169689Skan if (result) 3205169689Skan return result; 3206169689Skan 3207169689Skan /* Group together equal REGs to do more simplification. */ 3208169689Skan if (REG_P (d1->op) && REG_P (d2->op)) 3209169689Skan return REGNO (d1->op) - REGNO (d2->op); 3210169689Skan else 3211169689Skan return 0; 321290075Sobrien} 321390075Sobrien 321490075Sobrienstatic rtx 3215132718Skansimplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0, 3216169689Skan rtx op1) 321790075Sobrien{ 321890075Sobrien struct simplify_plus_minus_op_data ops[8]; 321990075Sobrien rtx result, tem; 3220169689Skan int n_ops = 2, input_ops = 2; 3221169689Skan int changed, n_constants = 0, canonicalized = 0; 322290075Sobrien int i, j; 322390075Sobrien 3224132718Skan memset (ops, 0, sizeof ops); 3225117395Skan 322690075Sobrien /* Set up the two operands and then expand them until nothing has been 322790075Sobrien changed. If we run out of room in our array, give up; this should 322890075Sobrien almost never happen. */ 322990075Sobrien 323090075Sobrien ops[0].op = op0; 323190075Sobrien ops[0].neg = 0; 323290075Sobrien ops[1].op = op1; 323390075Sobrien ops[1].neg = (code == MINUS); 323490075Sobrien 323590075Sobrien do 323690075Sobrien { 323790075Sobrien changed = 0; 323890075Sobrien 323990075Sobrien for (i = 0; i < n_ops; i++) 324090075Sobrien { 324190075Sobrien rtx this_op = ops[i].op; 324290075Sobrien int this_neg = ops[i].neg; 324390075Sobrien enum rtx_code this_code = GET_CODE (this_op); 324490075Sobrien 324590075Sobrien switch (this_code) 324690075Sobrien { 324790075Sobrien case PLUS: 324890075Sobrien case MINUS: 324990075Sobrien if (n_ops == 7) 325096263Sobrien return NULL_RTX; 325190075Sobrien 325290075Sobrien ops[n_ops].op = XEXP (this_op, 1); 325390075Sobrien ops[n_ops].neg = (this_code == MINUS) ^ this_neg; 325490075Sobrien n_ops++; 325590075Sobrien 325690075Sobrien ops[i].op = XEXP (this_op, 0); 325790075Sobrien input_ops++; 325890075Sobrien changed = 1; 3259169689Skan canonicalized |= this_neg; 326090075Sobrien break; 326190075Sobrien 326290075Sobrien case NEG: 326390075Sobrien ops[i].op = XEXP (this_op, 0); 326490075Sobrien ops[i].neg = ! this_neg; 326590075Sobrien changed = 1; 3266169689Skan canonicalized = 1; 326790075Sobrien break; 326890075Sobrien 326990075Sobrien case CONST: 327096263Sobrien if (n_ops < 7 327196263Sobrien && GET_CODE (XEXP (this_op, 0)) == PLUS 327296263Sobrien && CONSTANT_P (XEXP (XEXP (this_op, 0), 0)) 327396263Sobrien && CONSTANT_P (XEXP (XEXP (this_op, 0), 1))) 327496263Sobrien { 327596263Sobrien ops[i].op = XEXP (XEXP (this_op, 0), 0); 327696263Sobrien ops[n_ops].op = XEXP (XEXP (this_op, 0), 1); 327796263Sobrien ops[n_ops].neg = this_neg; 327896263Sobrien n_ops++; 327996263Sobrien changed = 1; 3280169689Skan canonicalized = 1; 328196263Sobrien } 328290075Sobrien break; 328390075Sobrien 328490075Sobrien case NOT: 328590075Sobrien /* ~a -> (-a - 1) */ 328690075Sobrien if (n_ops != 7) 328790075Sobrien { 328890075Sobrien ops[n_ops].op = constm1_rtx; 328990075Sobrien ops[n_ops++].neg = this_neg; 329090075Sobrien ops[i].op = XEXP (this_op, 0); 329190075Sobrien ops[i].neg = !this_neg; 329290075Sobrien changed = 1; 3293169689Skan canonicalized = 1; 329490075Sobrien } 329590075Sobrien break; 329690075Sobrien 329790075Sobrien case CONST_INT: 3298169689Skan n_constants++; 329990075Sobrien if (this_neg) 330090075Sobrien { 330190075Sobrien ops[i].op = neg_const_int (mode, this_op); 330290075Sobrien ops[i].neg = 0; 330390075Sobrien changed = 1; 3304169689Skan canonicalized = 1; 330590075Sobrien } 330690075Sobrien break; 330790075Sobrien 330890075Sobrien default: 330990075Sobrien break; 331090075Sobrien } 331190075Sobrien } 331290075Sobrien } 331390075Sobrien while (changed); 331490075Sobrien 3315169689Skan if (n_constants > 1) 3316169689Skan canonicalized = 1; 331790075Sobrien 3318169689Skan gcc_assert (n_ops >= 2); 331996263Sobrien 3320169689Skan /* If we only have two operands, we can avoid the loops. */ 3321169689Skan if (n_ops == 2) 3322169689Skan { 3323169689Skan enum rtx_code code = ops[0].neg || ops[1].neg ? MINUS : PLUS; 3324169689Skan rtx lhs, rhs; 332590075Sobrien 3326169689Skan /* Get the two operands. Be careful with the order, especially for 3327169689Skan the cases where code == MINUS. */ 3328169689Skan if (ops[0].neg && ops[1].neg) 3329169689Skan { 3330169689Skan lhs = gen_rtx_NEG (mode, ops[0].op); 3331169689Skan rhs = ops[1].op; 3332169689Skan } 3333169689Skan else if (ops[0].neg) 3334169689Skan { 3335169689Skan lhs = ops[1].op; 3336169689Skan rhs = ops[0].op; 3337169689Skan } 3338169689Skan else 3339169689Skan { 3340169689Skan lhs = ops[0].op; 3341169689Skan rhs = ops[1].op; 3342169689Skan } 3343169689Skan 3344169689Skan return simplify_const_binary_operation (code, mode, lhs, rhs); 3345169689Skan } 3346169689Skan 3347169689Skan /* Now simplify each pair of operands until nothing changes. */ 334890075Sobrien do 334990075Sobrien { 3350169689Skan /* Insertion sort is good enough for an eight-element array. */ 3351169689Skan for (i = 1; i < n_ops; i++) 3352169689Skan { 3353169689Skan struct simplify_plus_minus_op_data save; 3354169689Skan j = i - 1; 3355169689Skan if (simplify_plus_minus_op_data_cmp (&ops[j], &ops[i]) < 0) 3356169689Skan continue; 335790075Sobrien 3358169689Skan canonicalized = 1; 3359169689Skan save = ops[i]; 3360169689Skan do 3361169689Skan ops[j + 1] = ops[j]; 3362169689Skan while (j-- && simplify_plus_minus_op_data_cmp (&ops[j], &save) > 0); 3363169689Skan ops[j + 1] = save; 3364169689Skan } 3365169689Skan 3366169689Skan /* This is only useful the first time through. */ 3367169689Skan if (!canonicalized) 3368169689Skan return NULL_RTX; 3369169689Skan 3370169689Skan changed = 0; 3371169689Skan for (i = n_ops - 1; i > 0; i--) 3372169689Skan for (j = i - 1; j >= 0; j--) 337390075Sobrien { 3374169689Skan rtx lhs = ops[j].op, rhs = ops[i].op; 3375169689Skan int lneg = ops[j].neg, rneg = ops[i].neg; 337690075Sobrien 3377169689Skan if (lhs != 0 && rhs != 0) 337890075Sobrien { 337990075Sobrien enum rtx_code ncode = PLUS; 338090075Sobrien 338190075Sobrien if (lneg != rneg) 338290075Sobrien { 338390075Sobrien ncode = MINUS; 338490075Sobrien if (lneg) 338590075Sobrien tem = lhs, lhs = rhs, rhs = tem; 338690075Sobrien } 338790075Sobrien else if (swap_commutative_operands_p (lhs, rhs)) 338890075Sobrien tem = lhs, lhs = rhs, rhs = tem; 338990075Sobrien 3390169689Skan if ((GET_CODE (lhs) == CONST || GET_CODE (lhs) == CONST_INT) 3391169689Skan && (GET_CODE (rhs) == CONST || GET_CODE (rhs) == CONST_INT)) 3392169689Skan { 3393169689Skan rtx tem_lhs, tem_rhs; 339490075Sobrien 3395169689Skan tem_lhs = GET_CODE (lhs) == CONST ? XEXP (lhs, 0) : lhs; 3396169689Skan tem_rhs = GET_CODE (rhs) == CONST ? XEXP (rhs, 0) : rhs; 3397169689Skan tem = simplify_binary_operation (ncode, mode, tem_lhs, tem_rhs); 3398169689Skan 3399169689Skan if (tem && !CONSTANT_P (tem)) 3400169689Skan tem = gen_rtx_CONST (GET_MODE (tem), tem); 3401169689Skan } 3402169689Skan else 3403169689Skan tem = simplify_binary_operation (ncode, mode, lhs, rhs); 3404169689Skan 3405117395Skan /* Reject "simplifications" that just wrap the two 340690075Sobrien arguments in a CONST. Failure to do so can result 340790075Sobrien in infinite recursion with simplify_binary_operation 340890075Sobrien when it calls us to simplify CONST operations. */ 340990075Sobrien if (tem 341090075Sobrien && ! (GET_CODE (tem) == CONST 341190075Sobrien && GET_CODE (XEXP (tem, 0)) == ncode 341290075Sobrien && XEXP (XEXP (tem, 0), 0) == lhs 3413169689Skan && XEXP (XEXP (tem, 0), 1) == rhs)) 341490075Sobrien { 341590075Sobrien lneg &= rneg; 341690075Sobrien if (GET_CODE (tem) == NEG) 341790075Sobrien tem = XEXP (tem, 0), lneg = !lneg; 341890075Sobrien if (GET_CODE (tem) == CONST_INT && lneg) 341990075Sobrien tem = neg_const_int (mode, tem), lneg = 0; 342090075Sobrien 342190075Sobrien ops[i].op = tem; 342290075Sobrien ops[i].neg = lneg; 342390075Sobrien ops[j].op = NULL_RTX; 342490075Sobrien changed = 1; 342590075Sobrien } 342690075Sobrien } 342790075Sobrien } 342890075Sobrien 3429169689Skan /* Pack all the operands to the lower-numbered entries. */ 3430169689Skan for (i = 0, j = 0; j < n_ops; j++) 3431169689Skan if (ops[j].op) 3432169689Skan { 3433169689Skan ops[i] = ops[j]; 3434169689Skan i++; 3435169689Skan } 3436169689Skan n_ops = i; 343790075Sobrien } 343890075Sobrien while (changed); 343990075Sobrien 3440132718Skan /* Create (minus -C X) instead of (neg (const (plus X C))). */ 3441132718Skan if (n_ops == 2 3442132718Skan && GET_CODE (ops[1].op) == CONST_INT 3443132718Skan && CONSTANT_P (ops[0].op) 3444132718Skan && ops[0].neg) 3445132718Skan return gen_rtx_fmt_ee (MINUS, mode, ops[1].op, ops[0].op); 3446132718Skan 344790075Sobrien /* We suppressed creation of trivial CONST expressions in the 344890075Sobrien combination loop to avoid recursion. Create one manually now. 344990075Sobrien The combination loop should have ensured that there is exactly 345090075Sobrien one CONST_INT, and the sort will have ensured that it is last 345190075Sobrien in the array and that any other constant will be next-to-last. */ 345290075Sobrien 345390075Sobrien if (n_ops > 1 345490075Sobrien && GET_CODE (ops[n_ops - 1].op) == CONST_INT 345590075Sobrien && CONSTANT_P (ops[n_ops - 2].op)) 345690075Sobrien { 345790075Sobrien rtx value = ops[n_ops - 1].op; 345890075Sobrien if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg) 345990075Sobrien value = neg_const_int (mode, value); 346090075Sobrien ops[n_ops - 2].op = plus_constant (ops[n_ops - 2].op, INTVAL (value)); 346190075Sobrien n_ops--; 346290075Sobrien } 346390075Sobrien 3464132718Skan /* Put a non-negated operand first, if possible. */ 346590075Sobrien 346690075Sobrien for (i = 0; i < n_ops && ops[i].neg; i++) 346790075Sobrien continue; 346890075Sobrien if (i == n_ops) 3469132718Skan ops[0].op = gen_rtx_NEG (mode, ops[0].op); 347090075Sobrien else if (i != 0) 347190075Sobrien { 347290075Sobrien tem = ops[0].op; 347390075Sobrien ops[0] = ops[i]; 347490075Sobrien ops[i].op = tem; 347590075Sobrien ops[i].neg = 1; 347690075Sobrien } 347790075Sobrien 347890075Sobrien /* Now make the result by performing the requested operations. */ 347990075Sobrien result = ops[0].op; 348090075Sobrien for (i = 1; i < n_ops; i++) 348190075Sobrien result = gen_rtx_fmt_ee (ops[i].neg ? MINUS : PLUS, 348290075Sobrien mode, result, ops[i].op); 348390075Sobrien 3484132718Skan return result; 348590075Sobrien} 348690075Sobrien 3487169689Skan/* Check whether an operand is suitable for calling simplify_plus_minus. */ 3488169689Skanstatic bool 3489169689Skanplus_minus_operand_p (rtx x) 3490169689Skan{ 3491169689Skan return GET_CODE (x) == PLUS 3492169689Skan || GET_CODE (x) == MINUS 3493169689Skan || (GET_CODE (x) == CONST 3494169689Skan && GET_CODE (XEXP (x, 0)) == PLUS 3495169689Skan && CONSTANT_P (XEXP (XEXP (x, 0), 0)) 3496169689Skan && CONSTANT_P (XEXP (XEXP (x, 0), 1))); 3497169689Skan} 3498169689Skan 349990075Sobrien/* Like simplify_binary_operation except used for relational operators. 3500169689Skan MODE is the mode of the result. If MODE is VOIDmode, both operands must 3501169689Skan not also be VOIDmode. 350290075Sobrien 3503169689Skan CMP_MODE specifies in which mode the comparison is done in, so it is 3504169689Skan the mode of the operands. If CMP_MODE is VOIDmode, it is taken from 3505169689Skan the operands or, if both are VOIDmode, the operands are compared in 3506169689Skan "infinite precision". */ 350790075Sobrienrtx 3508132718Skansimplify_relational_operation (enum rtx_code code, enum machine_mode mode, 3509169689Skan enum machine_mode cmp_mode, rtx op0, rtx op1) 351090075Sobrien{ 3511169689Skan rtx tem, trueop0, trueop1; 3512169689Skan 3513169689Skan if (cmp_mode == VOIDmode) 3514169689Skan cmp_mode = GET_MODE (op0); 3515169689Skan if (cmp_mode == VOIDmode) 3516169689Skan cmp_mode = GET_MODE (op1); 3517169689Skan 3518169689Skan tem = simplify_const_relational_operation (code, cmp_mode, op0, op1); 3519169689Skan if (tem) 3520169689Skan { 3521169689Skan if (SCALAR_FLOAT_MODE_P (mode)) 3522169689Skan { 3523169689Skan if (tem == const0_rtx) 3524169689Skan return CONST0_RTX (mode); 3525169689Skan#ifdef FLOAT_STORE_FLAG_VALUE 3526169689Skan { 3527169689Skan REAL_VALUE_TYPE val; 3528169689Skan val = FLOAT_STORE_FLAG_VALUE (mode); 3529169689Skan return CONST_DOUBLE_FROM_REAL_VALUE (val, mode); 3530169689Skan } 3531169689Skan#else 3532169689Skan return NULL_RTX; 3533169689Skan#endif 3534169689Skan } 3535169689Skan if (VECTOR_MODE_P (mode)) 3536169689Skan { 3537169689Skan if (tem == const0_rtx) 3538169689Skan return CONST0_RTX (mode); 3539169689Skan#ifdef VECTOR_STORE_FLAG_VALUE 3540169689Skan { 3541169689Skan int i, units; 3542169689Skan rtvec v; 3543169689Skan 3544169689Skan rtx val = VECTOR_STORE_FLAG_VALUE (mode); 3545169689Skan if (val == NULL_RTX) 3546169689Skan return NULL_RTX; 3547169689Skan if (val == const1_rtx) 3548169689Skan return CONST1_RTX (mode); 3549169689Skan 3550169689Skan units = GET_MODE_NUNITS (mode); 3551169689Skan v = rtvec_alloc (units); 3552169689Skan for (i = 0; i < units; i++) 3553169689Skan RTVEC_ELT (v, i) = val; 3554169689Skan return gen_rtx_raw_CONST_VECTOR (mode, v); 3555169689Skan } 3556169689Skan#else 3557169689Skan return NULL_RTX; 3558169689Skan#endif 3559169689Skan } 3560169689Skan 3561169689Skan return tem; 3562169689Skan } 3563169689Skan 3564169689Skan /* For the following tests, ensure const0_rtx is op1. */ 3565169689Skan if (swap_commutative_operands_p (op0, op1) 3566169689Skan || (op0 == const0_rtx && op1 != const0_rtx)) 3567169689Skan tem = op0, op0 = op1, op1 = tem, code = swap_condition (code); 3568169689Skan 3569169689Skan /* If op0 is a compare, extract the comparison arguments from it. */ 3570169689Skan if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) 3571169689Skan return simplify_relational_operation (code, mode, VOIDmode, 3572169689Skan XEXP (op0, 0), XEXP (op0, 1)); 3573169689Skan 3574169689Skan if (GET_MODE_CLASS (cmp_mode) == MODE_CC 3575169689Skan || CC0_P (op0)) 3576169689Skan return NULL_RTX; 3577169689Skan 3578169689Skan trueop0 = avoid_constant_pool_reference (op0); 3579169689Skan trueop1 = avoid_constant_pool_reference (op1); 3580169689Skan return simplify_relational_operation_1 (code, mode, cmp_mode, 3581169689Skan trueop0, trueop1); 3582169689Skan} 3583169689Skan 3584169689Skan/* This part of simplify_relational_operation is only used when CMP_MODE 3585169689Skan is not in class MODE_CC (i.e. it is a real comparison). 3586169689Skan 3587169689Skan MODE is the mode of the result, while CMP_MODE specifies in which 3588169689Skan mode the comparison is done in, so it is the mode of the operands. */ 3589169689Skan 3590169689Skanstatic rtx 3591169689Skansimplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode, 3592169689Skan enum machine_mode cmp_mode, rtx op0, rtx op1) 3593169689Skan{ 3594169689Skan enum rtx_code op0code = GET_CODE (op0); 3595169689Skan 3596169689Skan if (GET_CODE (op1) == CONST_INT) 3597169689Skan { 3598169689Skan if (INTVAL (op1) == 0 && COMPARISON_P (op0)) 3599169689Skan { 3600169689Skan /* If op0 is a comparison, extract the comparison arguments 3601169689Skan from it. */ 3602169689Skan if (code == NE) 3603169689Skan { 3604169689Skan if (GET_MODE (op0) == mode) 3605169689Skan return simplify_rtx (op0); 3606169689Skan else 3607169689Skan return simplify_gen_relational (GET_CODE (op0), mode, VOIDmode, 3608169689Skan XEXP (op0, 0), XEXP (op0, 1)); 3609169689Skan } 3610169689Skan else if (code == EQ) 3611169689Skan { 3612169689Skan enum rtx_code new_code = reversed_comparison_code (op0, NULL_RTX); 3613169689Skan if (new_code != UNKNOWN) 3614169689Skan return simplify_gen_relational (new_code, mode, VOIDmode, 3615169689Skan XEXP (op0, 0), XEXP (op0, 1)); 3616169689Skan } 3617169689Skan } 3618169689Skan } 3619169689Skan 3620169689Skan /* (eq/ne (plus x cst1) cst2) simplifies to (eq/ne x (cst2 - cst1)) */ 3621169689Skan if ((code == EQ || code == NE) 3622169689Skan && (op0code == PLUS || op0code == MINUS) 3623169689Skan && CONSTANT_P (op1) 3624169689Skan && CONSTANT_P (XEXP (op0, 1)) 3625169689Skan && (INTEGRAL_MODE_P (cmp_mode) || flag_unsafe_math_optimizations)) 3626169689Skan { 3627169689Skan rtx x = XEXP (op0, 0); 3628169689Skan rtx c = XEXP (op0, 1); 3629169689Skan 3630169689Skan c = simplify_gen_binary (op0code == PLUS ? MINUS : PLUS, 3631169689Skan cmp_mode, op1, c); 3632169689Skan return simplify_gen_relational (code, mode, cmp_mode, x, c); 3633169689Skan } 3634169689Skan 3635169689Skan /* (ne:SI (zero_extract:SI FOO (const_int 1) BAR) (const_int 0))) is 3636169689Skan the same as (zero_extract:SI FOO (const_int 1) BAR). */ 3637169689Skan if (code == NE 3638169689Skan && op1 == const0_rtx 3639169689Skan && GET_MODE_CLASS (mode) == MODE_INT 3640169689Skan && cmp_mode != VOIDmode 3641169689Skan /* ??? Work-around BImode bugs in the ia64 backend. */ 3642169689Skan && mode != BImode 3643169689Skan && cmp_mode != BImode 3644169689Skan && nonzero_bits (op0, cmp_mode) == 1 3645169689Skan && STORE_FLAG_VALUE == 1) 3646169689Skan return GET_MODE_SIZE (mode) > GET_MODE_SIZE (cmp_mode) 3647169689Skan ? simplify_gen_unary (ZERO_EXTEND, mode, op0, cmp_mode) 3648169689Skan : lowpart_subreg (mode, op0, cmp_mode); 3649169689Skan 3650169689Skan /* (eq/ne (xor x y) 0) simplifies to (eq/ne x y). */ 3651169689Skan if ((code == EQ || code == NE) 3652169689Skan && op1 == const0_rtx 3653169689Skan && op0code == XOR) 3654169689Skan return simplify_gen_relational (code, mode, cmp_mode, 3655169689Skan XEXP (op0, 0), XEXP (op0, 1)); 3656169689Skan 3657169689Skan /* (eq/ne (xor x y) x) simplifies to (eq/ne y 0). */ 3658169689Skan if ((code == EQ || code == NE) 3659169689Skan && op0code == XOR 3660169689Skan && rtx_equal_p (XEXP (op0, 0), op1) 3661169689Skan && !side_effects_p (XEXP (op0, 0))) 3662169689Skan return simplify_gen_relational (code, mode, cmp_mode, 3663169689Skan XEXP (op0, 1), const0_rtx); 3664169689Skan 3665169689Skan /* Likewise (eq/ne (xor x y) y) simplifies to (eq/ne x 0). */ 3666169689Skan if ((code == EQ || code == NE) 3667169689Skan && op0code == XOR 3668169689Skan && rtx_equal_p (XEXP (op0, 1), op1) 3669169689Skan && !side_effects_p (XEXP (op0, 1))) 3670169689Skan return simplify_gen_relational (code, mode, cmp_mode, 3671169689Skan XEXP (op0, 0), const0_rtx); 3672169689Skan 3673169689Skan /* (eq/ne (xor x C1) C2) simplifies to (eq/ne x (C1^C2)). */ 3674169689Skan if ((code == EQ || code == NE) 3675169689Skan && op0code == XOR 3676169689Skan && (GET_CODE (op1) == CONST_INT 3677169689Skan || GET_CODE (op1) == CONST_DOUBLE) 3678169689Skan && (GET_CODE (XEXP (op0, 1)) == CONST_INT 3679169689Skan || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE)) 3680169689Skan return simplify_gen_relational (code, mode, cmp_mode, XEXP (op0, 0), 3681169689Skan simplify_gen_binary (XOR, cmp_mode, 3682169689Skan XEXP (op0, 1), op1)); 3683169689Skan 3684169689Skan return NULL_RTX; 3685169689Skan} 3686169689Skan 3687169689Skan/* Check if the given comparison (done in the given MODE) is actually a 3688169689Skan tautology or a contradiction. 3689169689Skan If no simplification is possible, this function returns zero. 3690169689Skan Otherwise, it returns either const_true_rtx or const0_rtx. */ 3691169689Skan 3692169689Skanrtx 3693169689Skansimplify_const_relational_operation (enum rtx_code code, 3694169689Skan enum machine_mode mode, 3695169689Skan rtx op0, rtx op1) 3696169689Skan{ 369790075Sobrien int equal, op0lt, op0ltu, op1lt, op1ltu; 369890075Sobrien rtx tem; 369990075Sobrien rtx trueop0; 370090075Sobrien rtx trueop1; 370190075Sobrien 3702169689Skan gcc_assert (mode != VOIDmode 3703169689Skan || (GET_MODE (op0) == VOIDmode 3704169689Skan && GET_MODE (op1) == VOIDmode)); 370590075Sobrien 370690075Sobrien /* If op0 is a compare, extract the comparison arguments from it. */ 370790075Sobrien if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) 3708169689Skan { 3709169689Skan op1 = XEXP (op0, 1); 3710169689Skan op0 = XEXP (op0, 0); 371190075Sobrien 3712169689Skan if (GET_MODE (op0) != VOIDmode) 3713169689Skan mode = GET_MODE (op0); 3714169689Skan else if (GET_MODE (op1) != VOIDmode) 3715169689Skan mode = GET_MODE (op1); 3716169689Skan else 3717169689Skan return 0; 3718169689Skan } 371990075Sobrien 372090075Sobrien /* We can't simplify MODE_CC values since we don't know what the 372190075Sobrien actual comparison is. */ 3722132718Skan if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC || CC0_P (op0)) 372390075Sobrien return 0; 372490075Sobrien 372590075Sobrien /* Make sure the constant is second. */ 3726169689Skan if (swap_commutative_operands_p (op0, op1)) 372790075Sobrien { 372890075Sobrien tem = op0, op0 = op1, op1 = tem; 372990075Sobrien code = swap_condition (code); 373090075Sobrien } 373190075Sobrien 3732169689Skan trueop0 = avoid_constant_pool_reference (op0); 3733169689Skan trueop1 = avoid_constant_pool_reference (op1); 3734169689Skan 373590075Sobrien /* For integer comparisons of A and B maybe we can simplify A - B and can 373690075Sobrien then simplify a comparison of that with zero. If A and B are both either 373790075Sobrien a register or a CONST_INT, this can't help; testing for these cases will 373890075Sobrien prevent infinite recursion here and speed things up. 373990075Sobrien 3740169689Skan We can only do this for EQ and NE comparisons as otherwise we may 3741169689Skan lose or introduce overflow which we cannot disregard as undefined as 3742169689Skan we do not know the signedness of the operation on either the left or 3743169689Skan the right hand side of the comparison. */ 374490075Sobrien 374590075Sobrien if (INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx 3746169689Skan && (code == EQ || code == NE) 3747169689Skan && ! ((REG_P (op0) || GET_CODE (trueop0) == CONST_INT) 3748169689Skan && (REG_P (op1) || GET_CODE (trueop1) == CONST_INT)) 374990075Sobrien && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1)) 3750169689Skan /* We cannot do this if tem is a nonzero address. */ 3751169689Skan && ! nonzero_address_p (tem)) 3752169689Skan return simplify_const_relational_operation (signed_condition (code), 3753169689Skan mode, tem, const0_rtx); 375490075Sobrien 3755169689Skan if (! HONOR_NANS (mode) && code == ORDERED) 375690075Sobrien return const_true_rtx; 375790075Sobrien 3758169689Skan if (! HONOR_NANS (mode) && code == UNORDERED) 375990075Sobrien return const0_rtx; 376090075Sobrien 3761117395Skan /* For modes without NaNs, if the two operands are equal, we know the 3762132718Skan result except if they have side-effects. */ 3763132718Skan if (! HONOR_NANS (GET_MODE (trueop0)) 3764117395Skan && rtx_equal_p (trueop0, trueop1) 3765117395Skan && ! side_effects_p (trueop0)) 376690075Sobrien equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0; 376790075Sobrien 376890075Sobrien /* If the operands are floating-point constants, see if we can fold 376990075Sobrien the result. */ 377090075Sobrien else if (GET_CODE (trueop0) == CONST_DOUBLE 377190075Sobrien && GET_CODE (trueop1) == CONST_DOUBLE 3772169689Skan && SCALAR_FLOAT_MODE_P (GET_MODE (trueop0))) 377390075Sobrien { 3774117395Skan REAL_VALUE_TYPE d0, d1; 377590075Sobrien 3776117395Skan REAL_VALUE_FROM_CONST_DOUBLE (d0, trueop0); 3777117395Skan REAL_VALUE_FROM_CONST_DOUBLE (d1, trueop1); 377890075Sobrien 3779117395Skan /* Comparisons are unordered iff at least one of the values is NaN. */ 3780117395Skan if (REAL_VALUE_ISNAN (d0) || REAL_VALUE_ISNAN (d1)) 378190075Sobrien switch (code) 378290075Sobrien { 378390075Sobrien case UNEQ: 378490075Sobrien case UNLT: 378590075Sobrien case UNGT: 378690075Sobrien case UNLE: 378790075Sobrien case UNGE: 378890075Sobrien case NE: 378990075Sobrien case UNORDERED: 379090075Sobrien return const_true_rtx; 379190075Sobrien case EQ: 379290075Sobrien case LT: 379390075Sobrien case GT: 379490075Sobrien case LE: 379590075Sobrien case GE: 379690075Sobrien case LTGT: 379790075Sobrien case ORDERED: 379890075Sobrien return const0_rtx; 379990075Sobrien default: 380090075Sobrien return 0; 380190075Sobrien } 380290075Sobrien 3803117395Skan equal = REAL_VALUES_EQUAL (d0, d1); 3804117395Skan op0lt = op0ltu = REAL_VALUES_LESS (d0, d1); 3805117395Skan op1lt = op1ltu = REAL_VALUES_LESS (d1, d0); 380690075Sobrien } 380790075Sobrien 380890075Sobrien /* Otherwise, see if the operands are both integers. */ 380990075Sobrien else if ((GET_MODE_CLASS (mode) == MODE_INT || mode == VOIDmode) 381090075Sobrien && (GET_CODE (trueop0) == CONST_DOUBLE 381190075Sobrien || GET_CODE (trueop0) == CONST_INT) 381290075Sobrien && (GET_CODE (trueop1) == CONST_DOUBLE 381390075Sobrien || GET_CODE (trueop1) == CONST_INT)) 381490075Sobrien { 381590075Sobrien int width = GET_MODE_BITSIZE (mode); 381690075Sobrien HOST_WIDE_INT l0s, h0s, l1s, h1s; 381790075Sobrien unsigned HOST_WIDE_INT l0u, h0u, l1u, h1u; 381890075Sobrien 381990075Sobrien /* Get the two words comprising each integer constant. */ 382090075Sobrien if (GET_CODE (trueop0) == CONST_DOUBLE) 382190075Sobrien { 382290075Sobrien l0u = l0s = CONST_DOUBLE_LOW (trueop0); 382390075Sobrien h0u = h0s = CONST_DOUBLE_HIGH (trueop0); 382490075Sobrien } 382590075Sobrien else 382690075Sobrien { 382790075Sobrien l0u = l0s = INTVAL (trueop0); 382890075Sobrien h0u = h0s = HWI_SIGN_EXTEND (l0s); 382990075Sobrien } 3830117395Skan 383190075Sobrien if (GET_CODE (trueop1) == CONST_DOUBLE) 383290075Sobrien { 383390075Sobrien l1u = l1s = CONST_DOUBLE_LOW (trueop1); 383490075Sobrien h1u = h1s = CONST_DOUBLE_HIGH (trueop1); 383590075Sobrien } 383690075Sobrien else 383790075Sobrien { 383890075Sobrien l1u = l1s = INTVAL (trueop1); 383990075Sobrien h1u = h1s = HWI_SIGN_EXTEND (l1s); 384090075Sobrien } 384190075Sobrien 384290075Sobrien /* If WIDTH is nonzero and smaller than HOST_BITS_PER_WIDE_INT, 384390075Sobrien we have to sign or zero-extend the values. */ 384490075Sobrien if (width != 0 && width < HOST_BITS_PER_WIDE_INT) 384590075Sobrien { 384690075Sobrien l0u &= ((HOST_WIDE_INT) 1 << width) - 1; 384790075Sobrien l1u &= ((HOST_WIDE_INT) 1 << width) - 1; 384890075Sobrien 384990075Sobrien if (l0s & ((HOST_WIDE_INT) 1 << (width - 1))) 385090075Sobrien l0s |= ((HOST_WIDE_INT) (-1) << width); 385190075Sobrien 385290075Sobrien if (l1s & ((HOST_WIDE_INT) 1 << (width - 1))) 385390075Sobrien l1s |= ((HOST_WIDE_INT) (-1) << width); 385490075Sobrien } 385590075Sobrien if (width != 0 && width <= HOST_BITS_PER_WIDE_INT) 385690075Sobrien h0u = h1u = 0, h0s = HWI_SIGN_EXTEND (l0s), h1s = HWI_SIGN_EXTEND (l1s); 385790075Sobrien 385890075Sobrien equal = (h0u == h1u && l0u == l1u); 385990075Sobrien op0lt = (h0s < h1s || (h0s == h1s && l0u < l1u)); 386090075Sobrien op1lt = (h1s < h0s || (h1s == h0s && l1u < l0u)); 386190075Sobrien op0ltu = (h0u < h1u || (h0u == h1u && l0u < l1u)); 386290075Sobrien op1ltu = (h1u < h0u || (h1u == h0u && l1u < l0u)); 386390075Sobrien } 386490075Sobrien 386590075Sobrien /* Otherwise, there are some code-specific tests we can make. */ 386690075Sobrien else 386790075Sobrien { 3868169689Skan /* Optimize comparisons with upper and lower bounds. */ 3869169689Skan if (SCALAR_INT_MODE_P (mode) 3870169689Skan && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) 3871169689Skan { 3872169689Skan rtx mmin, mmax; 3873169689Skan int sign; 3874169689Skan 3875169689Skan if (code == GEU 3876169689Skan || code == LEU 3877169689Skan || code == GTU 3878169689Skan || code == LTU) 3879169689Skan sign = 0; 3880169689Skan else 3881169689Skan sign = 1; 3882169689Skan 3883169689Skan get_mode_bounds (mode, sign, mode, &mmin, &mmax); 3884169689Skan 3885169689Skan tem = NULL_RTX; 3886169689Skan switch (code) 3887169689Skan { 3888169689Skan case GEU: 3889169689Skan case GE: 3890169689Skan /* x >= min is always true. */ 3891169689Skan if (rtx_equal_p (trueop1, mmin)) 3892169689Skan tem = const_true_rtx; 3893169689Skan else 3894169689Skan break; 3895169689Skan 3896169689Skan case LEU: 3897169689Skan case LE: 3898169689Skan /* x <= max is always true. */ 3899169689Skan if (rtx_equal_p (trueop1, mmax)) 3900169689Skan tem = const_true_rtx; 3901169689Skan break; 3902169689Skan 3903169689Skan case GTU: 3904169689Skan case GT: 3905169689Skan /* x > max is always false. */ 3906169689Skan if (rtx_equal_p (trueop1, mmax)) 3907169689Skan tem = const0_rtx; 3908169689Skan break; 3909169689Skan 3910169689Skan case LTU: 3911169689Skan case LT: 3912169689Skan /* x < min is always false. */ 3913169689Skan if (rtx_equal_p (trueop1, mmin)) 3914169689Skan tem = const0_rtx; 3915169689Skan break; 3916169689Skan 3917169689Skan default: 3918169689Skan break; 3919169689Skan } 3920169689Skan if (tem == const0_rtx 3921169689Skan || tem == const_true_rtx) 3922169689Skan return tem; 3923169689Skan } 3924169689Skan 392590075Sobrien switch (code) 392690075Sobrien { 392790075Sobrien case EQ: 3928132718Skan if (trueop1 == const0_rtx && nonzero_address_p (op0)) 392990075Sobrien return const0_rtx; 393090075Sobrien break; 393190075Sobrien 393290075Sobrien case NE: 3933132718Skan if (trueop1 == const0_rtx && nonzero_address_p (op0)) 393490075Sobrien return const_true_rtx; 393590075Sobrien break; 393690075Sobrien 3937117395Skan case LT: 3938117395Skan /* Optimize abs(x) < 0.0. */ 3939169689Skan if (trueop1 == CONST0_RTX (mode) 3940169689Skan && !HONOR_SNANS (mode) 3941169689Skan && (!INTEGRAL_MODE_P (mode) 3942169689Skan || (!flag_wrapv && !flag_trapv && flag_strict_overflow))) 3943117395Skan { 3944117395Skan tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0) 3945117395Skan : trueop0; 3946117395Skan if (GET_CODE (tem) == ABS) 3947169689Skan { 3948169689Skan if (INTEGRAL_MODE_P (mode) 3949169689Skan && (issue_strict_overflow_warning 3950169689Skan (WARN_STRICT_OVERFLOW_CONDITIONAL))) 3951169689Skan warning (OPT_Wstrict_overflow, 3952169689Skan ("assuming signed overflow does not occur when " 3953169689Skan "assuming abs (x) < 0 is false")); 3954169689Skan return const0_rtx; 3955169689Skan } 3956117395Skan } 3957117395Skan break; 3958117395Skan 3959117395Skan case GE: 3960117395Skan /* Optimize abs(x) >= 0.0. */ 3961169689Skan if (trueop1 == CONST0_RTX (mode) 3962169689Skan && !HONOR_NANS (mode) 3963169689Skan && (!INTEGRAL_MODE_P (mode) 3964169689Skan || (!flag_wrapv && !flag_trapv && flag_strict_overflow))) 3965117395Skan { 3966117395Skan tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0) 3967117395Skan : trueop0; 3968117395Skan if (GET_CODE (tem) == ABS) 3969169689Skan { 3970169689Skan if (INTEGRAL_MODE_P (mode) 3971169689Skan && (issue_strict_overflow_warning 3972169689Skan (WARN_STRICT_OVERFLOW_CONDITIONAL))) 3973169689Skan warning (OPT_Wstrict_overflow, 3974169689Skan ("assuming signed overflow does not occur when " 3975169689Skan "assuming abs (x) >= 0 is true")); 3976169689Skan return const_true_rtx; 3977169689Skan } 3978117395Skan } 3979117395Skan break; 3980117395Skan 3981132718Skan case UNGE: 3982132718Skan /* Optimize ! (abs(x) < 0.0). */ 3983132718Skan if (trueop1 == CONST0_RTX (mode)) 3984132718Skan { 3985132718Skan tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0) 3986132718Skan : trueop0; 3987132718Skan if (GET_CODE (tem) == ABS) 3988132718Skan return const_true_rtx; 3989132718Skan } 3990132718Skan break; 3991132718Skan 399290075Sobrien default: 399390075Sobrien break; 399490075Sobrien } 399590075Sobrien 399690075Sobrien return 0; 399790075Sobrien } 399890075Sobrien 399990075Sobrien /* If we reach here, EQUAL, OP0LT, OP0LTU, OP1LT, and OP1LTU are set 400090075Sobrien as appropriate. */ 400190075Sobrien switch (code) 400290075Sobrien { 400390075Sobrien case EQ: 400490075Sobrien case UNEQ: 400590075Sobrien return equal ? const_true_rtx : const0_rtx; 400690075Sobrien case NE: 400790075Sobrien case LTGT: 400890075Sobrien return ! equal ? const_true_rtx : const0_rtx; 400990075Sobrien case LT: 401090075Sobrien case UNLT: 401190075Sobrien return op0lt ? const_true_rtx : const0_rtx; 401290075Sobrien case GT: 401390075Sobrien case UNGT: 401490075Sobrien return op1lt ? const_true_rtx : const0_rtx; 401590075Sobrien case LTU: 401690075Sobrien return op0ltu ? const_true_rtx : const0_rtx; 401790075Sobrien case GTU: 401890075Sobrien return op1ltu ? const_true_rtx : const0_rtx; 401990075Sobrien case LE: 402090075Sobrien case UNLE: 402190075Sobrien return equal || op0lt ? const_true_rtx : const0_rtx; 402290075Sobrien case GE: 402390075Sobrien case UNGE: 402490075Sobrien return equal || op1lt ? const_true_rtx : const0_rtx; 402590075Sobrien case LEU: 402690075Sobrien return equal || op0ltu ? const_true_rtx : const0_rtx; 402790075Sobrien case GEU: 402890075Sobrien return equal || op1ltu ? const_true_rtx : const0_rtx; 402990075Sobrien case ORDERED: 403090075Sobrien return const_true_rtx; 403190075Sobrien case UNORDERED: 403290075Sobrien return const0_rtx; 403390075Sobrien default: 4034169689Skan gcc_unreachable (); 403590075Sobrien } 403690075Sobrien} 403790075Sobrien 403890075Sobrien/* Simplify CODE, an operation with result mode MODE and three operands, 403990075Sobrien OP0, OP1, and OP2. OP0_MODE was the mode of OP0 before it became 404090075Sobrien a constant. Return 0 if no simplifications is possible. */ 404190075Sobrien 404290075Sobrienrtx 4043132718Skansimplify_ternary_operation (enum rtx_code code, enum machine_mode mode, 4044132718Skan enum machine_mode op0_mode, rtx op0, rtx op1, 4045132718Skan rtx op2) 404690075Sobrien{ 404790075Sobrien unsigned int width = GET_MODE_BITSIZE (mode); 404890075Sobrien 404990075Sobrien /* VOIDmode means "infinite" precision. */ 405090075Sobrien if (width == 0) 405190075Sobrien width = HOST_BITS_PER_WIDE_INT; 405290075Sobrien 405390075Sobrien switch (code) 405490075Sobrien { 405590075Sobrien case SIGN_EXTRACT: 405690075Sobrien case ZERO_EXTRACT: 405790075Sobrien if (GET_CODE (op0) == CONST_INT 405890075Sobrien && GET_CODE (op1) == CONST_INT 405990075Sobrien && GET_CODE (op2) == CONST_INT 406090075Sobrien && ((unsigned) INTVAL (op1) + (unsigned) INTVAL (op2) <= width) 406190075Sobrien && width <= (unsigned) HOST_BITS_PER_WIDE_INT) 406290075Sobrien { 406390075Sobrien /* Extracting a bit-field from a constant */ 406490075Sobrien HOST_WIDE_INT val = INTVAL (op0); 406590075Sobrien 406690075Sobrien if (BITS_BIG_ENDIAN) 406790075Sobrien val >>= (GET_MODE_BITSIZE (op0_mode) 406890075Sobrien - INTVAL (op2) - INTVAL (op1)); 406990075Sobrien else 407090075Sobrien val >>= INTVAL (op2); 407190075Sobrien 407290075Sobrien if (HOST_BITS_PER_WIDE_INT != INTVAL (op1)) 407390075Sobrien { 407490075Sobrien /* First zero-extend. */ 407590075Sobrien val &= ((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1; 407690075Sobrien /* If desired, propagate sign bit. */ 407790075Sobrien if (code == SIGN_EXTRACT 407890075Sobrien && (val & ((HOST_WIDE_INT) 1 << (INTVAL (op1) - 1)))) 407990075Sobrien val |= ~ (((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1); 408090075Sobrien } 408190075Sobrien 408290075Sobrien /* Clear the bits that don't belong in our mode, 408390075Sobrien unless they and our sign bit are all one. 408490075Sobrien So we get either a reasonable negative value or a reasonable 408590075Sobrien unsigned value for this mode. */ 408690075Sobrien if (width < HOST_BITS_PER_WIDE_INT 408790075Sobrien && ((val & ((HOST_WIDE_INT) (-1) << (width - 1))) 408890075Sobrien != ((HOST_WIDE_INT) (-1) << (width - 1)))) 408990075Sobrien val &= ((HOST_WIDE_INT) 1 << width) - 1; 409090075Sobrien 4091169689Skan return gen_int_mode (val, mode); 409290075Sobrien } 409390075Sobrien break; 409490075Sobrien 409590075Sobrien case IF_THEN_ELSE: 409690075Sobrien if (GET_CODE (op0) == CONST_INT) 409790075Sobrien return op0 != const0_rtx ? op1 : op2; 409890075Sobrien 4099132718Skan /* Convert c ? a : a into "a". */ 4100132718Skan if (rtx_equal_p (op1, op2) && ! side_effects_p (op0)) 410190075Sobrien return op1; 4102132718Skan 4103132718Skan /* Convert a != b ? a : b into "a". */ 4104132718Skan if (GET_CODE (op0) == NE 4105132718Skan && ! side_effects_p (op0) 4106132718Skan && ! HONOR_NANS (mode) 4107132718Skan && ! HONOR_SIGNED_ZEROS (mode) 4108132718Skan && ((rtx_equal_p (XEXP (op0, 0), op1) 4109132718Skan && rtx_equal_p (XEXP (op0, 1), op2)) 4110132718Skan || (rtx_equal_p (XEXP (op0, 0), op2) 4111132718Skan && rtx_equal_p (XEXP (op0, 1), op1)))) 4112132718Skan return op1; 4113132718Skan 4114132718Skan /* Convert a == b ? a : b into "b". */ 4115132718Skan if (GET_CODE (op0) == EQ 4116132718Skan && ! side_effects_p (op0) 4117132718Skan && ! HONOR_NANS (mode) 4118132718Skan && ! HONOR_SIGNED_ZEROS (mode) 4119132718Skan && ((rtx_equal_p (XEXP (op0, 0), op1) 4120132718Skan && rtx_equal_p (XEXP (op0, 1), op2)) 4121132718Skan || (rtx_equal_p (XEXP (op0, 0), op2) 4122132718Skan && rtx_equal_p (XEXP (op0, 1), op1)))) 412390075Sobrien return op2; 4124132718Skan 4125169689Skan if (COMPARISON_P (op0) && ! side_effects_p (op0)) 412690075Sobrien { 412790075Sobrien enum machine_mode cmp_mode = (GET_MODE (XEXP (op0, 0)) == VOIDmode 412890075Sobrien ? GET_MODE (XEXP (op0, 1)) 412990075Sobrien : GET_MODE (XEXP (op0, 0))); 413090075Sobrien rtx temp; 413190075Sobrien 413290075Sobrien /* Look for happy constants in op1 and op2. */ 413390075Sobrien if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT) 413490075Sobrien { 413590075Sobrien HOST_WIDE_INT t = INTVAL (op1); 413690075Sobrien HOST_WIDE_INT f = INTVAL (op2); 4137117395Skan 413890075Sobrien if (t == STORE_FLAG_VALUE && f == 0) 413990075Sobrien code = GET_CODE (op0); 414090075Sobrien else if (t == 0 && f == STORE_FLAG_VALUE) 414190075Sobrien { 414290075Sobrien enum rtx_code tmp; 414390075Sobrien tmp = reversed_comparison_code (op0, NULL_RTX); 414490075Sobrien if (tmp == UNKNOWN) 414590075Sobrien break; 414690075Sobrien code = tmp; 414790075Sobrien } 414890075Sobrien else 414990075Sobrien break; 415090075Sobrien 4151169689Skan return simplify_gen_relational (code, mode, cmp_mode, 4152169689Skan XEXP (op0, 0), XEXP (op0, 1)); 415390075Sobrien } 4154169689Skan 4155169689Skan if (cmp_mode == VOIDmode) 4156169689Skan cmp_mode = op0_mode; 4157169689Skan temp = simplify_relational_operation (GET_CODE (op0), op0_mode, 4158169689Skan cmp_mode, XEXP (op0, 0), 4159169689Skan XEXP (op0, 1)); 4160169689Skan 4161169689Skan /* See if any simplifications were possible. */ 4162169689Skan if (temp) 4163169689Skan { 4164169689Skan if (GET_CODE (temp) == CONST_INT) 4165169689Skan return temp == const0_rtx ? op2 : op1; 4166169689Skan else if (temp) 4167169689Skan return gen_rtx_IF_THEN_ELSE (mode, temp, op1, op2); 4168169689Skan } 416990075Sobrien } 417090075Sobrien break; 4171132718Skan 4172117395Skan case VEC_MERGE: 4173169689Skan gcc_assert (GET_MODE (op0) == mode); 4174169689Skan gcc_assert (GET_MODE (op1) == mode); 4175169689Skan gcc_assert (VECTOR_MODE_P (mode)); 4176117395Skan op2 = avoid_constant_pool_reference (op2); 4177132718Skan if (GET_CODE (op2) == CONST_INT) 4178117395Skan { 4179117395Skan int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); 4180117395Skan unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); 4181132718Skan int mask = (1 << n_elts) - 1; 418290075Sobrien 4183132718Skan if (!(INTVAL (op2) & mask)) 4184132718Skan return op1; 4185132718Skan if ((INTVAL (op2) & mask) == mask) 4186132718Skan return op0; 4187132718Skan 4188132718Skan op0 = avoid_constant_pool_reference (op0); 4189132718Skan op1 = avoid_constant_pool_reference (op1); 4190132718Skan if (GET_CODE (op0) == CONST_VECTOR 4191132718Skan && GET_CODE (op1) == CONST_VECTOR) 4192132718Skan { 4193132718Skan rtvec v = rtvec_alloc (n_elts); 4194132718Skan unsigned int i; 4195132718Skan 4196132718Skan for (i = 0; i < n_elts; i++) 4197132718Skan RTVEC_ELT (v, i) = (INTVAL (op2) & (1 << i) 4198132718Skan ? CONST_VECTOR_ELT (op0, i) 4199132718Skan : CONST_VECTOR_ELT (op1, i)); 4200132718Skan return gen_rtx_CONST_VECTOR (mode, v); 4201132718Skan } 4202117395Skan } 4203117395Skan break; 4204117395Skan 420590075Sobrien default: 4206169689Skan gcc_unreachable (); 420790075Sobrien } 420890075Sobrien 420990075Sobrien return 0; 421090075Sobrien} 421190075Sobrien 4212132718Skan/* Evaluate a SUBREG of a CONST_INT or CONST_DOUBLE or CONST_VECTOR, 4213132718Skan returning another CONST_INT or CONST_DOUBLE or CONST_VECTOR. 4214132718Skan 4215132718Skan Works by unpacking OP into a collection of 8-bit values 4216132718Skan represented as a little-endian array of 'unsigned char', selecting by BYTE, 4217132718Skan and then repacking them again for OUTERMODE. */ 4218132718Skan 4219132718Skanstatic rtx 4220132718Skansimplify_immed_subreg (enum machine_mode outermode, rtx op, 4221132718Skan enum machine_mode innermode, unsigned int byte) 422290075Sobrien{ 4223132718Skan /* We support up to 512-bit values (for V8DFmode). */ 4224132718Skan enum { 4225132718Skan max_bitsize = 512, 4226132718Skan value_bit = 8, 4227132718Skan value_mask = (1 << value_bit) - 1 4228132718Skan }; 4229132718Skan unsigned char value[max_bitsize / value_bit]; 4230132718Skan int value_start; 4231132718Skan int i; 4232132718Skan int elem; 423390075Sobrien 4234132718Skan int num_elem; 4235132718Skan rtx * elems; 4236132718Skan int elem_bitsize; 4237132718Skan rtx result_s; 4238132718Skan rtvec result_v = NULL; 4239132718Skan enum mode_class outer_class; 4240132718Skan enum machine_mode outer_submode; 424190075Sobrien 4242132718Skan /* Some ports misuse CCmode. */ 4243132718Skan if (GET_MODE_CLASS (outermode) == MODE_CC && GET_CODE (op) == CONST_INT) 424490075Sobrien return op; 424590075Sobrien 4246169689Skan /* We have no way to represent a complex constant at the rtl level. */ 4247169689Skan if (COMPLEX_MODE_P (outermode)) 4248169689Skan return NULL_RTX; 4249169689Skan 4250132718Skan /* Unpack the value. */ 4251132718Skan 4252117395Skan if (GET_CODE (op) == CONST_VECTOR) 4253117395Skan { 4254132718Skan num_elem = CONST_VECTOR_NUNITS (op); 4255132718Skan elems = &CONST_VECTOR_ELT (op, 0); 4256132718Skan elem_bitsize = GET_MODE_BITSIZE (GET_MODE_INNER (innermode)); 4257132718Skan } 4258132718Skan else 4259132718Skan { 4260132718Skan num_elem = 1; 4261132718Skan elems = &op; 4262132718Skan elem_bitsize = max_bitsize; 4263132718Skan } 4264169689Skan /* If this asserts, it is too complicated; reducing value_bit may help. */ 4265169689Skan gcc_assert (BITS_PER_UNIT % value_bit == 0); 4266169689Skan /* I don't know how to handle endianness of sub-units. */ 4267169689Skan gcc_assert (elem_bitsize % BITS_PER_UNIT == 0); 4268132718Skan 4269132718Skan for (elem = 0; elem < num_elem; elem++) 4270132718Skan { 4271132718Skan unsigned char * vp; 4272132718Skan rtx el = elems[elem]; 4273132718Skan 4274132718Skan /* Vectors are kept in target memory order. (This is probably 4275132718Skan a mistake.) */ 4276132718Skan { 4277132718Skan unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT; 4278132718Skan unsigned ibyte = (((num_elem - 1 - elem) * elem_bitsize) 4279132718Skan / BITS_PER_UNIT); 4280132718Skan unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; 4281132718Skan unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; 4282132718Skan unsigned bytele = (subword_byte % UNITS_PER_WORD 4283132718Skan + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); 4284132718Skan vp = value + (bytele * BITS_PER_UNIT) / value_bit; 4285132718Skan } 4286132718Skan 4287132718Skan switch (GET_CODE (el)) 4288117395Skan { 4289132718Skan case CONST_INT: 4290132718Skan for (i = 0; 4291132718Skan i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize; 4292132718Skan i += value_bit) 4293132718Skan *vp++ = INTVAL (el) >> i; 4294132718Skan /* CONST_INTs are always logically sign-extended. */ 4295132718Skan for (; i < elem_bitsize; i += value_bit) 4296132718Skan *vp++ = INTVAL (el) < 0 ? -1 : 0; 4297132718Skan break; 4298132718Skan 4299132718Skan case CONST_DOUBLE: 4300132718Skan if (GET_MODE (el) == VOIDmode) 4301132718Skan { 4302132718Skan /* If this triggers, someone should have generated a 4303132718Skan CONST_INT instead. */ 4304169689Skan gcc_assert (elem_bitsize > HOST_BITS_PER_WIDE_INT); 4305117395Skan 4306132718Skan for (i = 0; i < HOST_BITS_PER_WIDE_INT; i += value_bit) 4307132718Skan *vp++ = CONST_DOUBLE_LOW (el) >> i; 4308132718Skan while (i < HOST_BITS_PER_WIDE_INT * 2 && i < elem_bitsize) 4309132718Skan { 4310132718Skan *vp++ 4311132718Skan = CONST_DOUBLE_HIGH (el) >> (i - HOST_BITS_PER_WIDE_INT); 4312132718Skan i += value_bit; 4313132718Skan } 4314132718Skan /* It shouldn't matter what's done here, so fill it with 4315132718Skan zero. */ 4316161651Skan for (; i < elem_bitsize; i += value_bit) 4317132718Skan *vp++ = 0; 4318132718Skan } 4319169689Skan else 4320132718Skan { 4321132718Skan long tmp[max_bitsize / 32]; 4322132718Skan int bitsize = GET_MODE_BITSIZE (GET_MODE (el)); 4323117395Skan 4324169689Skan gcc_assert (SCALAR_FLOAT_MODE_P (GET_MODE (el))); 4325169689Skan gcc_assert (bitsize <= elem_bitsize); 4326169689Skan gcc_assert (bitsize % value_bit == 0); 4327169689Skan 4328132718Skan real_to_target (tmp, CONST_DOUBLE_REAL_VALUE (el), 4329132718Skan GET_MODE (el)); 4330117395Skan 4331132718Skan /* real_to_target produces its result in words affected by 4332132718Skan FLOAT_WORDS_BIG_ENDIAN. However, we ignore this, 4333132718Skan and use WORDS_BIG_ENDIAN instead; see the documentation 4334132718Skan of SUBREG in rtl.texi. */ 4335132718Skan for (i = 0; i < bitsize; i += value_bit) 4336117395Skan { 4337132718Skan int ibase; 4338132718Skan if (WORDS_BIG_ENDIAN) 4339132718Skan ibase = bitsize - 1 - i; 4340132718Skan else 4341132718Skan ibase = i; 4342132718Skan *vp++ = tmp[ibase / 32] >> i % 32; 4343117395Skan } 4344132718Skan 4345132718Skan /* It shouldn't matter what's done here, so fill it with 4346132718Skan zero. */ 4347132718Skan for (; i < elem_bitsize; i += value_bit) 4348132718Skan *vp++ = 0; 4349117395Skan } 4350132718Skan break; 4351132718Skan 4352132718Skan default: 4353169689Skan gcc_unreachable (); 4354117395Skan } 4355117395Skan } 4356117395Skan 4357132718Skan /* Now, pick the right byte to start with. */ 4358132718Skan /* Renumber BYTE so that the least-significant byte is byte 0. A special 4359132718Skan case is paradoxical SUBREGs, which shouldn't be adjusted since they 4360132718Skan will already have offset 0. */ 4361132718Skan if (GET_MODE_SIZE (innermode) >= GET_MODE_SIZE (outermode)) 436290075Sobrien { 4363132718Skan unsigned ibyte = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode) 4364132718Skan - byte); 4365132718Skan unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; 4366132718Skan unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; 4367132718Skan byte = (subword_byte % UNITS_PER_WORD 4368132718Skan + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); 4369132718Skan } 437090075Sobrien 4371132718Skan /* BYTE should still be inside OP. (Note that BYTE is unsigned, 4372132718Skan so if it's become negative it will instead be very large.) */ 4373169689Skan gcc_assert (byte < GET_MODE_SIZE (innermode)); 4374117395Skan 4375132718Skan /* Convert from bytes to chunks of size value_bit. */ 4376132718Skan value_start = byte * (BITS_PER_UNIT / value_bit); 4377117395Skan 4378132718Skan /* Re-pack the value. */ 4379132718Skan 4380132718Skan if (VECTOR_MODE_P (outermode)) 4381132718Skan { 4382132718Skan num_elem = GET_MODE_NUNITS (outermode); 4383132718Skan result_v = rtvec_alloc (num_elem); 4384132718Skan elems = &RTVEC_ELT (result_v, 0); 4385132718Skan outer_submode = GET_MODE_INNER (outermode); 4386132718Skan } 4387132718Skan else 4388132718Skan { 4389132718Skan num_elem = 1; 4390132718Skan elems = &result_s; 4391132718Skan outer_submode = outermode; 4392132718Skan } 439390075Sobrien 4394132718Skan outer_class = GET_MODE_CLASS (outer_submode); 4395132718Skan elem_bitsize = GET_MODE_BITSIZE (outer_submode); 439690075Sobrien 4397169689Skan gcc_assert (elem_bitsize % value_bit == 0); 4398169689Skan gcc_assert (elem_bitsize + value_start * value_bit <= max_bitsize); 4399117395Skan 4400132718Skan for (elem = 0; elem < num_elem; elem++) 4401132718Skan { 4402132718Skan unsigned char *vp; 4403132718Skan 4404132718Skan /* Vectors are stored in target memory order. (This is probably 4405132718Skan a mistake.) */ 4406132718Skan { 4407132718Skan unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT; 4408132718Skan unsigned ibyte = (((num_elem - 1 - elem) * elem_bitsize) 4409132718Skan / BITS_PER_UNIT); 4410132718Skan unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; 4411132718Skan unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; 4412132718Skan unsigned bytele = (subword_byte % UNITS_PER_WORD 4413132718Skan + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); 4414132718Skan vp = value + value_start + (bytele * BITS_PER_UNIT) / value_bit; 4415132718Skan } 4416117395Skan 4417132718Skan switch (outer_class) 441890075Sobrien { 4419132718Skan case MODE_INT: 4420132718Skan case MODE_PARTIAL_INT: 4421132718Skan { 4422132718Skan unsigned HOST_WIDE_INT hi = 0, lo = 0; 442390075Sobrien 4424132718Skan for (i = 0; 4425132718Skan i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize; 4426132718Skan i += value_bit) 4427132718Skan lo |= (HOST_WIDE_INT)(*vp++ & value_mask) << i; 4428132718Skan for (; i < elem_bitsize; i += value_bit) 4429132718Skan hi |= ((HOST_WIDE_INT)(*vp++ & value_mask) 4430132718Skan << (i - HOST_BITS_PER_WIDE_INT)); 4431132718Skan 4432132718Skan /* immed_double_const doesn't call trunc_int_for_mode. I don't 4433132718Skan know why. */ 4434132718Skan if (elem_bitsize <= HOST_BITS_PER_WIDE_INT) 4435132718Skan elems[elem] = gen_int_mode (lo, outer_submode); 4436169689Skan else if (elem_bitsize <= 2 * HOST_BITS_PER_WIDE_INT) 4437169689Skan elems[elem] = immed_double_const (lo, hi, outer_submode); 4438132718Skan else 4439169689Skan return NULL_RTX; 4440132718Skan } 4441132718Skan break; 4442132718Skan 4443132718Skan case MODE_FLOAT: 4444169689Skan case MODE_DECIMAL_FLOAT: 4445132718Skan { 4446132718Skan REAL_VALUE_TYPE r; 4447132718Skan long tmp[max_bitsize / 32]; 4448132718Skan 4449132718Skan /* real_from_target wants its input in words affected by 4450132718Skan FLOAT_WORDS_BIG_ENDIAN. However, we ignore this, 4451132718Skan and use WORDS_BIG_ENDIAN instead; see the documentation 4452132718Skan of SUBREG in rtl.texi. */ 4453132718Skan for (i = 0; i < max_bitsize / 32; i++) 4454132718Skan tmp[i] = 0; 4455132718Skan for (i = 0; i < elem_bitsize; i += value_bit) 4456132718Skan { 4457132718Skan int ibase; 4458132718Skan if (WORDS_BIG_ENDIAN) 4459132718Skan ibase = elem_bitsize - 1 - i; 4460132718Skan else 4461132718Skan ibase = i; 4462132718Skan tmp[ibase / 32] |= (*vp++ & value_mask) << i % 32; 4463132718Skan } 446490075Sobrien 4465132718Skan real_from_target (&r, tmp, outer_submode); 4466132718Skan elems[elem] = CONST_DOUBLE_FROM_REAL_VALUE (r, outer_submode); 4467132718Skan } 4468132718Skan break; 4469132718Skan 4470132718Skan default: 4471169689Skan gcc_unreachable (); 4472132718Skan } 4473132718Skan } 4474132718Skan if (VECTOR_MODE_P (outermode)) 4475132718Skan return gen_rtx_CONST_VECTOR (outermode, result_v); 4476132718Skan else 4477132718Skan return result_s; 4478132718Skan} 447990075Sobrien 4480132718Skan/* Simplify SUBREG:OUTERMODE(OP:INNERMODE, BYTE) 4481132718Skan Return 0 if no simplifications are possible. */ 4482132718Skanrtx 4483132718Skansimplify_subreg (enum machine_mode outermode, rtx op, 4484132718Skan enum machine_mode innermode, unsigned int byte) 4485132718Skan{ 4486132718Skan /* Little bit of sanity checking. */ 4487169689Skan gcc_assert (innermode != VOIDmode); 4488169689Skan gcc_assert (outermode != VOIDmode); 4489169689Skan gcc_assert (innermode != BLKmode); 4490169689Skan gcc_assert (outermode != BLKmode); 449190075Sobrien 4492169689Skan gcc_assert (GET_MODE (op) == innermode 4493169689Skan || GET_MODE (op) == VOIDmode); 449490075Sobrien 4495169689Skan gcc_assert ((byte % GET_MODE_SIZE (outermode)) == 0); 4496169689Skan gcc_assert (byte < GET_MODE_SIZE (innermode)); 449790075Sobrien 4498132718Skan if (outermode == innermode && !byte) 4499132718Skan return op; 450090075Sobrien 4501132718Skan if (GET_CODE (op) == CONST_INT 4502132718Skan || GET_CODE (op) == CONST_DOUBLE 4503132718Skan || GET_CODE (op) == CONST_VECTOR) 4504132718Skan return simplify_immed_subreg (outermode, op, innermode, byte); 450590075Sobrien 450690075Sobrien /* Changing mode twice with SUBREG => just change it once, 450790075Sobrien or not at all if changing back op starting mode. */ 450890075Sobrien if (GET_CODE (op) == SUBREG) 450990075Sobrien { 451090075Sobrien enum machine_mode innermostmode = GET_MODE (SUBREG_REG (op)); 451190075Sobrien int final_offset = byte + SUBREG_BYTE (op); 4512169689Skan rtx newx; 451390075Sobrien 451490075Sobrien if (outermode == innermostmode 451590075Sobrien && byte == 0 && SUBREG_BYTE (op) == 0) 451690075Sobrien return SUBREG_REG (op); 451790075Sobrien 451890075Sobrien /* The SUBREG_BYTE represents offset, as if the value were stored 451990075Sobrien in memory. Irritating exception is paradoxical subreg, where 452090075Sobrien we define SUBREG_BYTE to be 0. On big endian machines, this 452190075Sobrien value should be negative. For a moment, undo this exception. */ 452290075Sobrien if (byte == 0 && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) 452390075Sobrien { 452490075Sobrien int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode)); 452590075Sobrien if (WORDS_BIG_ENDIAN) 452690075Sobrien final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 452790075Sobrien if (BYTES_BIG_ENDIAN) 452890075Sobrien final_offset += difference % UNITS_PER_WORD; 452990075Sobrien } 453090075Sobrien if (SUBREG_BYTE (op) == 0 453190075Sobrien && GET_MODE_SIZE (innermostmode) < GET_MODE_SIZE (innermode)) 453290075Sobrien { 453390075Sobrien int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (innermode)); 453490075Sobrien if (WORDS_BIG_ENDIAN) 453590075Sobrien final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 453690075Sobrien if (BYTES_BIG_ENDIAN) 453790075Sobrien final_offset += difference % UNITS_PER_WORD; 453890075Sobrien } 453990075Sobrien 454090075Sobrien /* See whether resulting subreg will be paradoxical. */ 454190075Sobrien if (GET_MODE_SIZE (innermostmode) > GET_MODE_SIZE (outermode)) 454290075Sobrien { 454390075Sobrien /* In nonparadoxical subregs we can't handle negative offsets. */ 454490075Sobrien if (final_offset < 0) 454590075Sobrien return NULL_RTX; 454690075Sobrien /* Bail out in case resulting subreg would be incorrect. */ 454790075Sobrien if (final_offset % GET_MODE_SIZE (outermode) 454890075Sobrien || (unsigned) final_offset >= GET_MODE_SIZE (innermostmode)) 454990075Sobrien return NULL_RTX; 455090075Sobrien } 455190075Sobrien else 455290075Sobrien { 455390075Sobrien int offset = 0; 455490075Sobrien int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (outermode)); 455590075Sobrien 455690075Sobrien /* In paradoxical subreg, see if we are still looking on lower part. 455790075Sobrien If so, our SUBREG_BYTE will be 0. */ 455890075Sobrien if (WORDS_BIG_ENDIAN) 455990075Sobrien offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 456090075Sobrien if (BYTES_BIG_ENDIAN) 456190075Sobrien offset += difference % UNITS_PER_WORD; 456290075Sobrien if (offset == final_offset) 456390075Sobrien final_offset = 0; 456490075Sobrien else 456590075Sobrien return NULL_RTX; 456690075Sobrien } 456790075Sobrien 4568132718Skan /* Recurse for further possible simplifications. */ 4569169689Skan newx = simplify_subreg (outermode, SUBREG_REG (op), innermostmode, 4570169689Skan final_offset); 4571169689Skan if (newx) 4572169689Skan return newx; 4573169689Skan if (validate_subreg (outermode, innermostmode, 4574169689Skan SUBREG_REG (op), final_offset)) 4575169689Skan return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset); 4576169689Skan return NULL_RTX; 457790075Sobrien } 457890075Sobrien 4579169689Skan /* Merge implicit and explicit truncations. */ 4580169689Skan 4581169689Skan if (GET_CODE (op) == TRUNCATE 4582169689Skan && GET_MODE_SIZE (outermode) < GET_MODE_SIZE (innermode) 4583169689Skan && subreg_lowpart_offset (outermode, innermode) == byte) 4584169689Skan return simplify_gen_unary (TRUNCATE, outermode, XEXP (op, 0), 4585169689Skan GET_MODE (XEXP (op, 0))); 4586169689Skan 458790075Sobrien /* SUBREG of a hard register => just change the register number 458890075Sobrien and/or mode. If the hard register is not valid in that mode, 458990075Sobrien suppress this simplification. If the hard register is the stack, 459090075Sobrien frame, or argument pointer, leave this as a SUBREG. */ 459190075Sobrien 459290075Sobrien if (REG_P (op) 4593117395Skan && REGNO (op) < FIRST_PSEUDO_REGISTER 4594117395Skan#ifdef CANNOT_CHANGE_MODE_CLASS 4595117395Skan && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), innermode, outermode) 459690075Sobrien && GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT 4597117395Skan && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT) 459890075Sobrien#endif 459990075Sobrien && ((reload_completed && !frame_pointer_needed) 460090075Sobrien || (REGNO (op) != FRAME_POINTER_REGNUM 460190075Sobrien#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM 460290075Sobrien && REGNO (op) != HARD_FRAME_POINTER_REGNUM 460390075Sobrien#endif 460490075Sobrien )) 460590075Sobrien#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM 460690075Sobrien && REGNO (op) != ARG_POINTER_REGNUM 460790075Sobrien#endif 4608132718Skan && REGNO (op) != STACK_POINTER_REGNUM 4609132718Skan && subreg_offset_representable_p (REGNO (op), innermode, 4610132718Skan byte, outermode)) 461190075Sobrien { 4612169689Skan unsigned int regno = REGNO (op); 4613169689Skan unsigned int final_regno 4614169689Skan = regno + subreg_regno_offset (regno, innermode, byte, outermode); 461590075Sobrien 461690075Sobrien /* ??? We do allow it if the current REG is not valid for 461790075Sobrien its mode. This is a kludge to work around how float/complex 4618117395Skan arguments are passed on 32-bit SPARC and should be fixed. */ 461990075Sobrien if (HARD_REGNO_MODE_OK (final_regno, outermode) 4620169689Skan || ! HARD_REGNO_MODE_OK (regno, innermode)) 462190075Sobrien { 4622169689Skan rtx x; 4623169689Skan int final_offset = byte; 462490075Sobrien 4625169689Skan /* Adjust offset for paradoxical subregs. */ 4626169689Skan if (byte == 0 4627169689Skan && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) 4628169689Skan { 4629169689Skan int difference = (GET_MODE_SIZE (innermode) 4630169689Skan - GET_MODE_SIZE (outermode)); 4631169689Skan if (WORDS_BIG_ENDIAN) 4632169689Skan final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 4633169689Skan if (BYTES_BIG_ENDIAN) 4634169689Skan final_offset += difference % UNITS_PER_WORD; 4635169689Skan } 4636169689Skan 4637169689Skan x = gen_rtx_REG_offset (op, outermode, final_regno, final_offset); 4638169689Skan 463990075Sobrien /* Propagate original regno. We don't have any way to specify 4640132718Skan the offset inside original regno, so do so only for lowpart. 464190075Sobrien The information is used only by alias analysis that can not 464290075Sobrien grog partial register anyway. */ 464390075Sobrien 464490075Sobrien if (subreg_lowpart_offset (outermode, innermode) == byte) 464590075Sobrien ORIGINAL_REGNO (x) = ORIGINAL_REGNO (op); 464690075Sobrien return x; 464790075Sobrien } 464890075Sobrien } 464990075Sobrien 465090075Sobrien /* If we have a SUBREG of a register that we are replacing and we are 465190075Sobrien replacing it with a MEM, make a new MEM and try replacing the 465290075Sobrien SUBREG with it. Don't do this if the MEM has a mode-dependent address 465390075Sobrien or if we would be widening it. */ 465490075Sobrien 4655169689Skan if (MEM_P (op) 465690075Sobrien && ! mode_dependent_address_p (XEXP (op, 0)) 465790075Sobrien /* Allow splitting of volatile memory references in case we don't 465890075Sobrien have instruction to move the whole thing. */ 465990075Sobrien && (! MEM_VOLATILE_P (op) 466090075Sobrien || ! have_insn_for (SET, innermode)) 466190075Sobrien && GET_MODE_SIZE (outermode) <= GET_MODE_SIZE (GET_MODE (op))) 466290075Sobrien return adjust_address_nv (op, outermode, byte); 466390075Sobrien 466490075Sobrien /* Handle complex values represented as CONCAT 466590075Sobrien of real and imaginary part. */ 466690075Sobrien if (GET_CODE (op) == CONCAT) 466790075Sobrien { 4668169689Skan unsigned int inner_size, final_offset; 4669169689Skan rtx part, res; 467090075Sobrien 4671169689Skan inner_size = GET_MODE_UNIT_SIZE (innermode); 4672169689Skan part = byte < inner_size ? XEXP (op, 0) : XEXP (op, 1); 4673169689Skan final_offset = byte % inner_size; 4674169689Skan if (final_offset + GET_MODE_SIZE (outermode) > inner_size) 4675169689Skan return NULL_RTX; 4676169689Skan 467790075Sobrien res = simplify_subreg (outermode, part, GET_MODE (part), final_offset); 467890075Sobrien if (res) 467990075Sobrien return res; 4680169689Skan if (validate_subreg (outermode, GET_MODE (part), part, final_offset)) 4681169689Skan return gen_rtx_SUBREG (outermode, part, final_offset); 4682169689Skan return NULL_RTX; 468390075Sobrien } 468490075Sobrien 4685169689Skan /* Optimize SUBREG truncations of zero and sign extended values. */ 4686169689Skan if ((GET_CODE (op) == ZERO_EXTEND 4687169689Skan || GET_CODE (op) == SIGN_EXTEND) 4688169689Skan && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode)) 4689169689Skan { 4690169689Skan unsigned int bitpos = subreg_lsb_1 (outermode, innermode, byte); 4691169689Skan 4692169689Skan /* If we're requesting the lowpart of a zero or sign extension, 4693169689Skan there are three possibilities. If the outermode is the same 4694169689Skan as the origmode, we can omit both the extension and the subreg. 4695169689Skan If the outermode is not larger than the origmode, we can apply 4696169689Skan the truncation without the extension. Finally, if the outermode 4697169689Skan is larger than the origmode, but both are integer modes, we 4698169689Skan can just extend to the appropriate mode. */ 4699169689Skan if (bitpos == 0) 4700169689Skan { 4701169689Skan enum machine_mode origmode = GET_MODE (XEXP (op, 0)); 4702169689Skan if (outermode == origmode) 4703169689Skan return XEXP (op, 0); 4704169689Skan if (GET_MODE_BITSIZE (outermode) <= GET_MODE_BITSIZE (origmode)) 4705169689Skan return simplify_gen_subreg (outermode, XEXP (op, 0), origmode, 4706169689Skan subreg_lowpart_offset (outermode, 4707169689Skan origmode)); 4708169689Skan if (SCALAR_INT_MODE_P (outermode)) 4709169689Skan return simplify_gen_unary (GET_CODE (op), outermode, 4710169689Skan XEXP (op, 0), origmode); 4711169689Skan } 4712169689Skan 4713169689Skan /* A SUBREG resulting from a zero extension may fold to zero if 4714169689Skan it extracts higher bits that the ZERO_EXTEND's source bits. */ 4715169689Skan if (GET_CODE (op) == ZERO_EXTEND 4716169689Skan && bitpos >= GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0)))) 4717169689Skan return CONST0_RTX (outermode); 4718169689Skan } 4719169689Skan 4720169689Skan /* Simplify (subreg:QI (lshiftrt:SI (sign_extend:SI (x:QI)) C), 0) into 4721169689Skan to (ashiftrt:QI (x:QI) C), where C is a suitable small constant and 4722169689Skan the outer subreg is effectively a truncation to the original mode. */ 4723169689Skan if ((GET_CODE (op) == LSHIFTRT 4724169689Skan || GET_CODE (op) == ASHIFTRT) 4725169689Skan && SCALAR_INT_MODE_P (outermode) 4726169689Skan /* Ensure that OUTERMODE is at least twice as wide as the INNERMODE 4727169689Skan to avoid the possibility that an outer LSHIFTRT shifts by more 4728169689Skan than the sign extension's sign_bit_copies and introduces zeros 4729169689Skan into the high bits of the result. */ 4730169689Skan && (2 * GET_MODE_BITSIZE (outermode)) <= GET_MODE_BITSIZE (innermode) 4731169689Skan && GET_CODE (XEXP (op, 1)) == CONST_INT 4732169689Skan && GET_CODE (XEXP (op, 0)) == SIGN_EXTEND 4733169689Skan && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode 4734169689Skan && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode) 4735169689Skan && subreg_lsb_1 (outermode, innermode, byte) == 0) 4736169689Skan return simplify_gen_binary (ASHIFTRT, outermode, 4737169689Skan XEXP (XEXP (op, 0), 0), XEXP (op, 1)); 4738169689Skan 4739169689Skan /* Likewise (subreg:QI (lshiftrt:SI (zero_extend:SI (x:QI)) C), 0) into 4740169689Skan to (lshiftrt:QI (x:QI) C), where C is a suitable small constant and 4741169689Skan the outer subreg is effectively a truncation to the original mode. */ 4742169689Skan if ((GET_CODE (op) == LSHIFTRT 4743169689Skan || GET_CODE (op) == ASHIFTRT) 4744169689Skan && SCALAR_INT_MODE_P (outermode) 4745169689Skan && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode) 4746169689Skan && GET_CODE (XEXP (op, 1)) == CONST_INT 4747169689Skan && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND 4748169689Skan && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode 4749169689Skan && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode) 4750169689Skan && subreg_lsb_1 (outermode, innermode, byte) == 0) 4751169689Skan return simplify_gen_binary (LSHIFTRT, outermode, 4752169689Skan XEXP (XEXP (op, 0), 0), XEXP (op, 1)); 4753169689Skan 4754169689Skan /* Likewise (subreg:QI (ashift:SI (zero_extend:SI (x:QI)) C), 0) into 4755169689Skan to (ashift:QI (x:QI) C), where C is a suitable small constant and 4756169689Skan the outer subreg is effectively a truncation to the original mode. */ 4757169689Skan if (GET_CODE (op) == ASHIFT 4758169689Skan && SCALAR_INT_MODE_P (outermode) 4759169689Skan && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode) 4760169689Skan && GET_CODE (XEXP (op, 1)) == CONST_INT 4761169689Skan && (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND 4762169689Skan || GET_CODE (XEXP (op, 0)) == SIGN_EXTEND) 4763169689Skan && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode 4764169689Skan && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode) 4765169689Skan && subreg_lsb_1 (outermode, innermode, byte) == 0) 4766169689Skan return simplify_gen_binary (ASHIFT, outermode, 4767169689Skan XEXP (XEXP (op, 0), 0), XEXP (op, 1)); 4768169689Skan 476990075Sobrien return NULL_RTX; 477090075Sobrien} 4771132718Skan 477290075Sobrien/* Make a SUBREG operation or equivalent if it folds. */ 477390075Sobrien 477490075Sobrienrtx 4775132718Skansimplify_gen_subreg (enum machine_mode outermode, rtx op, 4776132718Skan enum machine_mode innermode, unsigned int byte) 477790075Sobrien{ 4778169689Skan rtx newx; 477990075Sobrien 4780169689Skan newx = simplify_subreg (outermode, op, innermode, byte); 4781169689Skan if (newx) 4782169689Skan return newx; 478390075Sobrien 4784169689Skan if (GET_CODE (op) == SUBREG 4785169689Skan || GET_CODE (op) == CONCAT 4786169689Skan || GET_MODE (op) == VOIDmode) 478790075Sobrien return NULL_RTX; 478890075Sobrien 4789169689Skan if (validate_subreg (outermode, innermode, op, byte)) 4790169689Skan return gen_rtx_SUBREG (outermode, op, byte); 479190075Sobrien 4792169689Skan return NULL_RTX; 4793169689Skan} 479490075Sobrien 479590075Sobrien/* Simplify X, an rtx expression. 479690075Sobrien 479790075Sobrien Return the simplified expression or NULL if no simplifications 479890075Sobrien were possible. 479990075Sobrien 480090075Sobrien This is the preferred entry point into the simplification routines; 480190075Sobrien however, we still allow passes to call the more specific routines. 480290075Sobrien 4803132718Skan Right now GCC has three (yes, three) major bodies of RTL simplification 480490075Sobrien code that need to be unified. 480590075Sobrien 480690075Sobrien 1. fold_rtx in cse.c. This code uses various CSE specific 480790075Sobrien information to aid in RTL simplification. 480890075Sobrien 480990075Sobrien 2. simplify_rtx in combine.c. Similar to fold_rtx, except that 481090075Sobrien it uses combine specific information to aid in RTL 481190075Sobrien simplification. 481290075Sobrien 481390075Sobrien 3. The routines in this file. 481490075Sobrien 481590075Sobrien 481690075Sobrien Long term we want to only have one body of simplification code; to 481790075Sobrien get to that state I recommend the following steps: 481890075Sobrien 481990075Sobrien 1. Pour over fold_rtx & simplify_rtx and move any simplifications 482090075Sobrien which are not pass dependent state into these routines. 482190075Sobrien 482290075Sobrien 2. As code is moved by #1, change fold_rtx & simplify_rtx to 482390075Sobrien use this routine whenever possible. 482490075Sobrien 482590075Sobrien 3. Allow for pass dependent state to be provided to these 482690075Sobrien routines and add simplifications based on the pass dependent 482790075Sobrien state. Remove code from cse.c & combine.c that becomes 482890075Sobrien redundant/dead. 482990075Sobrien 483090075Sobrien It will take time, but ultimately the compiler will be easier to 483190075Sobrien maintain and improve. It's totally silly that when we add a 483290075Sobrien simplification that it needs to be added to 4 places (3 for RTL 483390075Sobrien simplification and 1 for tree simplification. */ 4834117395Skan 483590075Sobrienrtx 4836132718Skansimplify_rtx (rtx x) 483790075Sobrien{ 483890075Sobrien enum rtx_code code = GET_CODE (x); 483990075Sobrien enum machine_mode mode = GET_MODE (x); 484090075Sobrien 484190075Sobrien switch (GET_RTX_CLASS (code)) 484290075Sobrien { 4843169689Skan case RTX_UNARY: 484490075Sobrien return simplify_unary_operation (code, mode, 484590075Sobrien XEXP (x, 0), GET_MODE (XEXP (x, 0))); 4846169689Skan case RTX_COMM_ARITH: 484790075Sobrien if (swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1))) 4848132718Skan return simplify_gen_binary (code, mode, XEXP (x, 1), XEXP (x, 0)); 484990075Sobrien 4850132718Skan /* Fall through.... */ 485190075Sobrien 4852169689Skan case RTX_BIN_ARITH: 485390075Sobrien return simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1)); 485490075Sobrien 4855169689Skan case RTX_TERNARY: 4856169689Skan case RTX_BITFIELD_OPS: 485790075Sobrien return simplify_ternary_operation (code, mode, GET_MODE (XEXP (x, 0)), 485890075Sobrien XEXP (x, 0), XEXP (x, 1), 485990075Sobrien XEXP (x, 2)); 486090075Sobrien 4861169689Skan case RTX_COMPARE: 4862169689Skan case RTX_COMM_COMPARE: 4863169689Skan return simplify_relational_operation (code, mode, 4864169689Skan ((GET_MODE (XEXP (x, 0)) 4865169689Skan != VOIDmode) 4866169689Skan ? GET_MODE (XEXP (x, 0)) 4867169689Skan : GET_MODE (XEXP (x, 1))), 4868169689Skan XEXP (x, 0), 4869169689Skan XEXP (x, 1)); 4870132718Skan 4871169689Skan case RTX_EXTRA: 487290075Sobrien if (code == SUBREG) 4873117395Skan return simplify_gen_subreg (mode, SUBREG_REG (x), 487490075Sobrien GET_MODE (SUBREG_REG (x)), 487590075Sobrien SUBREG_BYTE (x)); 4876132718Skan break; 4877132718Skan 4878169689Skan case RTX_OBJ: 4879132718Skan if (code == LO_SUM) 4880132718Skan { 4881132718Skan /* Convert (lo_sum (high FOO) FOO) to FOO. */ 4882132718Skan if (GET_CODE (XEXP (x, 0)) == HIGH 4883132718Skan && rtx_equal_p (XEXP (XEXP (x, 0), 0), XEXP (x, 1))) 4884132718Skan return XEXP (x, 1); 4885132718Skan } 4886132718Skan break; 4887132718Skan 488890075Sobrien default: 4889132718Skan break; 489090075Sobrien } 4891132718Skan return NULL; 489290075Sobrien} 4893