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 104790075Sobrien case TRUNCATE: 104890075Sobrien val = arg0; 104990075Sobrien break; 105090075Sobrien 105190075Sobrien case ZERO_EXTEND: 105296263Sobrien /* When zero-extending a CONST_INT, we need to know its 105396263Sobrien original mode. */ 1054169689Skan gcc_assert (op_mode != VOIDmode); 105590075Sobrien if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT) 105690075Sobrien { 105790075Sobrien /* If we were really extending the mode, 105890075Sobrien we would have to distinguish between zero-extension 105990075Sobrien and sign-extension. */ 1060169689Skan gcc_assert (width == GET_MODE_BITSIZE (op_mode)); 106190075Sobrien val = arg0; 106290075Sobrien } 106390075Sobrien else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT) 106490075Sobrien val = arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode)); 106590075Sobrien else 106690075Sobrien return 0; 106790075Sobrien break; 106890075Sobrien 106990075Sobrien case SIGN_EXTEND: 107090075Sobrien if (op_mode == VOIDmode) 107190075Sobrien op_mode = mode; 107290075Sobrien if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT) 107390075Sobrien { 107490075Sobrien /* If we were really extending the mode, 107590075Sobrien we would have to distinguish between zero-extension 107690075Sobrien and sign-extension. */ 1077169689Skan gcc_assert (width == GET_MODE_BITSIZE (op_mode)); 107890075Sobrien val = arg0; 107990075Sobrien } 108090075Sobrien else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT) 108190075Sobrien { 108290075Sobrien val 108390075Sobrien = arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode)); 108490075Sobrien if (val 108590075Sobrien & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (op_mode) - 1))) 108690075Sobrien val -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode); 108790075Sobrien } 108890075Sobrien else 108990075Sobrien return 0; 109090075Sobrien break; 109190075Sobrien 109290075Sobrien case SQRT: 109390075Sobrien case FLOAT_EXTEND: 109490075Sobrien case FLOAT_TRUNCATE: 109590075Sobrien case SS_TRUNCATE: 109690075Sobrien case US_TRUNCATE: 1097169689Skan case SS_NEG: 109890075Sobrien return 0; 109990075Sobrien 110090075Sobrien default: 1101169689Skan gcc_unreachable (); 110290075Sobrien } 110390075Sobrien 1104169689Skan return gen_int_mode (val, mode); 110590075Sobrien } 110690075Sobrien 110790075Sobrien /* We can do some operations on integer CONST_DOUBLEs. Also allow 110890075Sobrien for a DImode operation on a CONST_INT. */ 1109169689Skan else if (GET_MODE (op) == VOIDmode 111096263Sobrien && width <= HOST_BITS_PER_WIDE_INT * 2 1111169689Skan && (GET_CODE (op) == CONST_DOUBLE 1112169689Skan || GET_CODE (op) == CONST_INT)) 111390075Sobrien { 111490075Sobrien unsigned HOST_WIDE_INT l1, lv; 111590075Sobrien HOST_WIDE_INT h1, hv; 111690075Sobrien 1117169689Skan if (GET_CODE (op) == CONST_DOUBLE) 1118169689Skan l1 = CONST_DOUBLE_LOW (op), h1 = CONST_DOUBLE_HIGH (op); 111990075Sobrien else 1120169689Skan l1 = INTVAL (op), h1 = HWI_SIGN_EXTEND (l1); 112190075Sobrien 112290075Sobrien switch (code) 112390075Sobrien { 112490075Sobrien case NOT: 112590075Sobrien lv = ~ l1; 112690075Sobrien hv = ~ h1; 112790075Sobrien break; 112890075Sobrien 112990075Sobrien case NEG: 113090075Sobrien neg_double (l1, h1, &lv, &hv); 113190075Sobrien break; 113290075Sobrien 113390075Sobrien case ABS: 113490075Sobrien if (h1 < 0) 113590075Sobrien neg_double (l1, h1, &lv, &hv); 113690075Sobrien else 113790075Sobrien lv = l1, hv = h1; 113890075Sobrien break; 113990075Sobrien 114090075Sobrien case FFS: 114190075Sobrien hv = 0; 114290075Sobrien if (l1 == 0) 1143132718Skan { 1144132718Skan if (h1 == 0) 1145132718Skan lv = 0; 1146132718Skan else 1147132718Skan lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & -h1) + 1; 1148132718Skan } 114990075Sobrien else 1150132718Skan lv = exact_log2 (l1 & -l1) + 1; 115190075Sobrien break; 115290075Sobrien 1153132718Skan case CLZ: 1154132718Skan hv = 0; 1155132718Skan if (h1 != 0) 1156132718Skan lv = GET_MODE_BITSIZE (mode) - floor_log2 (h1) - 1 1157132718Skan - HOST_BITS_PER_WIDE_INT; 1158132718Skan else if (l1 != 0) 1159132718Skan lv = GET_MODE_BITSIZE (mode) - floor_log2 (l1) - 1; 1160132718Skan else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, lv)) 1161132718Skan lv = GET_MODE_BITSIZE (mode); 1162132718Skan break; 1163132718Skan 1164132718Skan case CTZ: 1165132718Skan hv = 0; 1166132718Skan if (l1 != 0) 1167132718Skan lv = exact_log2 (l1 & -l1); 1168132718Skan else if (h1 != 0) 1169132718Skan lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & -h1); 1170132718Skan else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, lv)) 1171132718Skan lv = GET_MODE_BITSIZE (mode); 1172132718Skan break; 1173132718Skan 1174132718Skan case POPCOUNT: 1175132718Skan hv = 0; 1176132718Skan lv = 0; 1177132718Skan while (l1) 1178132718Skan lv++, l1 &= l1 - 1; 1179132718Skan while (h1) 1180132718Skan lv++, h1 &= h1 - 1; 1181132718Skan break; 1182132718Skan 1183132718Skan case PARITY: 1184132718Skan hv = 0; 1185132718Skan lv = 0; 1186132718Skan while (l1) 1187132718Skan lv++, l1 &= l1 - 1; 1188132718Skan while (h1) 1189132718Skan lv++, h1 &= h1 - 1; 1190132718Skan lv &= 1; 1191132718Skan break; 1192132718Skan 119390075Sobrien case TRUNCATE: 119490075Sobrien /* This is just a change-of-mode, so do nothing. */ 119590075Sobrien lv = l1, hv = h1; 119690075Sobrien break; 119790075Sobrien 119890075Sobrien case ZERO_EXTEND: 1199169689Skan gcc_assert (op_mode != VOIDmode); 120096263Sobrien 120196263Sobrien if (GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT) 120290075Sobrien return 0; 120390075Sobrien 120490075Sobrien hv = 0; 120590075Sobrien lv = l1 & GET_MODE_MASK (op_mode); 120690075Sobrien break; 120790075Sobrien 120890075Sobrien case SIGN_EXTEND: 120990075Sobrien if (op_mode == VOIDmode 121090075Sobrien || GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT) 121190075Sobrien return 0; 121290075Sobrien else 121390075Sobrien { 121490075Sobrien lv = l1 & GET_MODE_MASK (op_mode); 121590075Sobrien if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT 121690075Sobrien && (lv & ((HOST_WIDE_INT) 1 121790075Sobrien << (GET_MODE_BITSIZE (op_mode) - 1))) != 0) 121890075Sobrien lv -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode); 121990075Sobrien 122090075Sobrien hv = HWI_SIGN_EXTEND (lv); 122190075Sobrien } 122290075Sobrien break; 122390075Sobrien 122490075Sobrien case SQRT: 122590075Sobrien return 0; 122690075Sobrien 122790075Sobrien default: 122890075Sobrien return 0; 122990075Sobrien } 123090075Sobrien 123190075Sobrien return immed_double_const (lv, hv, mode); 123290075Sobrien } 123390075Sobrien 1234169689Skan else if (GET_CODE (op) == CONST_DOUBLE 1235169689Skan && SCALAR_FLOAT_MODE_P (mode)) 123690075Sobrien { 1237132718Skan REAL_VALUE_TYPE d, t; 1238169689Skan REAL_VALUE_FROM_CONST_DOUBLE (d, op); 123990075Sobrien 1240117395Skan switch (code) 1241117395Skan { 1242117395Skan case SQRT: 1243132718Skan if (HONOR_SNANS (mode) && real_isnan (&d)) 1244132718Skan return 0; 1245132718Skan real_sqrt (&t, mode, &d); 1246132718Skan d = t; 1247132718Skan break; 1248117395Skan case ABS: 1249117395Skan d = REAL_VALUE_ABS (d); 1250117395Skan break; 1251117395Skan case NEG: 1252117395Skan d = REAL_VALUE_NEGATE (d); 1253117395Skan break; 1254117395Skan case FLOAT_TRUNCATE: 1255117395Skan d = real_value_truncate (mode, d); 1256117395Skan break; 1257117395Skan case FLOAT_EXTEND: 1258117395Skan /* All this does is change the mode. */ 1259117395Skan break; 1260117395Skan case FIX: 1261117395Skan real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL); 1262117395Skan break; 1263146895Skan case NOT: 1264146895Skan { 1265146895Skan long tmp[4]; 1266146895Skan int i; 1267117395Skan 1268169689Skan real_to_target (tmp, &d, GET_MODE (op)); 1269146895Skan for (i = 0; i < 4; i++) 1270146895Skan tmp[i] = ~tmp[i]; 1271146895Skan real_from_target (&d, tmp, mode); 1272146895Skan break; 1273146895Skan } 1274117395Skan default: 1275169689Skan gcc_unreachable (); 1276117395Skan } 1277117395Skan return CONST_DOUBLE_FROM_REAL_VALUE (d, mode); 127890075Sobrien } 127990075Sobrien 1280169689Skan else if (GET_CODE (op) == CONST_DOUBLE 1281169689Skan && SCALAR_FLOAT_MODE_P (GET_MODE (op)) 128290075Sobrien && GET_MODE_CLASS (mode) == MODE_INT 1283132718Skan && width <= 2*HOST_BITS_PER_WIDE_INT && width > 0) 128490075Sobrien { 1285132718Skan /* Although the overflow semantics of RTL's FIX and UNSIGNED_FIX 1286132718Skan operators are intentionally left unspecified (to ease implementation 1287132718Skan by target backends), for consistency, this routine implements the 1288132718Skan same semantics for constant folding as used by the middle-end. */ 1289132718Skan 1290169689Skan /* This was formerly used only for non-IEEE float. 1291169689Skan eggert@twinsun.com says it is safe for IEEE also. */ 1292132718Skan HOST_WIDE_INT xh, xl, th, tl; 1293132718Skan REAL_VALUE_TYPE x, t; 1294169689Skan REAL_VALUE_FROM_CONST_DOUBLE (x, op); 1295117395Skan switch (code) 1296117395Skan { 1297132718Skan case FIX: 1298132718Skan if (REAL_VALUE_ISNAN (x)) 1299132718Skan return const0_rtx; 1300132718Skan 1301132718Skan /* Test against the signed upper bound. */ 1302132718Skan if (width > HOST_BITS_PER_WIDE_INT) 1303132718Skan { 1304132718Skan th = ((unsigned HOST_WIDE_INT) 1 1305132718Skan << (width - HOST_BITS_PER_WIDE_INT - 1)) - 1; 1306132718Skan tl = -1; 1307132718Skan } 1308132718Skan else 1309132718Skan { 1310132718Skan th = 0; 1311132718Skan tl = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1; 1312132718Skan } 1313132718Skan real_from_integer (&t, VOIDmode, tl, th, 0); 1314132718Skan if (REAL_VALUES_LESS (t, x)) 1315132718Skan { 1316132718Skan xh = th; 1317132718Skan xl = tl; 1318132718Skan break; 1319132718Skan } 1320132718Skan 1321132718Skan /* Test against the signed lower bound. */ 1322132718Skan if (width > HOST_BITS_PER_WIDE_INT) 1323132718Skan { 1324132718Skan th = (HOST_WIDE_INT) -1 << (width - HOST_BITS_PER_WIDE_INT - 1); 1325132718Skan tl = 0; 1326132718Skan } 1327132718Skan else 1328132718Skan { 1329132718Skan th = -1; 1330132718Skan tl = (HOST_WIDE_INT) -1 << (width - 1); 1331132718Skan } 1332132718Skan real_from_integer (&t, VOIDmode, tl, th, 0); 1333132718Skan if (REAL_VALUES_LESS (x, t)) 1334132718Skan { 1335132718Skan xh = th; 1336132718Skan xl = tl; 1337132718Skan break; 1338132718Skan } 1339132718Skan REAL_VALUE_TO_INT (&xl, &xh, x); 1340132718Skan break; 1341132718Skan 1342132718Skan case UNSIGNED_FIX: 1343132718Skan if (REAL_VALUE_ISNAN (x) || REAL_VALUE_NEGATIVE (x)) 1344132718Skan return const0_rtx; 1345132718Skan 1346132718Skan /* Test against the unsigned upper bound. */ 1347132718Skan if (width == 2*HOST_BITS_PER_WIDE_INT) 1348132718Skan { 1349132718Skan th = -1; 1350132718Skan tl = -1; 1351132718Skan } 1352132718Skan else if (width >= HOST_BITS_PER_WIDE_INT) 1353132718Skan { 1354132718Skan th = ((unsigned HOST_WIDE_INT) 1 1355132718Skan << (width - HOST_BITS_PER_WIDE_INT)) - 1; 1356132718Skan tl = -1; 1357132718Skan } 1358132718Skan else 1359132718Skan { 1360132718Skan th = 0; 1361132718Skan tl = ((unsigned HOST_WIDE_INT) 1 << width) - 1; 1362132718Skan } 1363132718Skan real_from_integer (&t, VOIDmode, tl, th, 1); 1364132718Skan if (REAL_VALUES_LESS (t, x)) 1365132718Skan { 1366132718Skan xh = th; 1367132718Skan xl = tl; 1368132718Skan break; 1369132718Skan } 1370132718Skan 1371132718Skan REAL_VALUE_TO_INT (&xl, &xh, x); 1372132718Skan break; 1373132718Skan 1374117395Skan default: 1375169689Skan gcc_unreachable (); 1376117395Skan } 1377132718Skan return immed_double_const (xl, xh, mode); 1378117395Skan } 137990075Sobrien 1380169689Skan return NULL_RTX; 1381169689Skan} 1382169689Skan 1383169689Skan/* Subroutine of simplify_binary_operation to simplify a commutative, 1384169689Skan associative binary operation CODE with result mode MODE, operating 1385169689Skan on OP0 and OP1. CODE is currently one of PLUS, MULT, AND, IOR, XOR, 1386169689Skan SMIN, SMAX, UMIN or UMAX. Return zero if no simplification or 1387169689Skan canonicalization is possible. */ 1388169689Skan 1389169689Skanstatic rtx 1390169689Skansimplify_associative_operation (enum rtx_code code, enum machine_mode mode, 1391169689Skan rtx op0, rtx op1) 1392169689Skan{ 1393169689Skan rtx tem; 1394169689Skan 1395169689Skan /* Linearize the operator to the left. */ 1396169689Skan if (GET_CODE (op1) == code) 139790075Sobrien { 1398169689Skan /* "(a op b) op (c op d)" becomes "((a op b) op c) op d)". */ 1399169689Skan if (GET_CODE (op0) == code) 1400169689Skan { 1401169689Skan tem = simplify_gen_binary (code, mode, op0, XEXP (op1, 0)); 1402169689Skan return simplify_gen_binary (code, mode, tem, XEXP (op1, 1)); 1403169689Skan } 1404132718Skan 1405169689Skan /* "a op (b op c)" becomes "(b op c) op a". */ 1406169689Skan if (! swap_commutative_operands_p (op1, op0)) 1407169689Skan return simplify_gen_binary (code, mode, op1, op0); 1408169689Skan 1409169689Skan tem = op0; 1410169689Skan op0 = op1; 1411169689Skan op1 = tem; 1412169689Skan } 1413169689Skan 1414169689Skan if (GET_CODE (op0) == code) 1415169689Skan { 1416169689Skan /* Canonicalize "(x op c) op y" as "(x op y) op c". */ 1417169689Skan if (swap_commutative_operands_p (XEXP (op0, 1), op1)) 141890075Sobrien { 1419169689Skan tem = simplify_gen_binary (code, mode, XEXP (op0, 0), op1); 1420169689Skan return simplify_gen_binary (code, mode, tem, XEXP (op0, 1)); 1421169689Skan } 142290075Sobrien 1423169689Skan /* Attempt to simplify "(a op b) op c" as "a op (b op c)". */ 1424169689Skan tem = swap_commutative_operands_p (XEXP (op0, 1), op1) 1425169689Skan ? simplify_binary_operation (code, mode, op1, XEXP (op0, 1)) 1426169689Skan : simplify_binary_operation (code, mode, XEXP (op0, 1), op1); 1427169689Skan if (tem != 0) 1428169689Skan return simplify_gen_binary (code, mode, XEXP (op0, 0), tem); 1429132718Skan 1430169689Skan /* Attempt to simplify "(a op b) op c" as "(a op c) op b". */ 1431169689Skan tem = swap_commutative_operands_p (XEXP (op0, 0), op1) 1432169689Skan ? simplify_binary_operation (code, mode, op1, XEXP (op0, 0)) 1433169689Skan : simplify_binary_operation (code, mode, XEXP (op0, 0), op1); 1434169689Skan if (tem != 0) 1435169689Skan return simplify_gen_binary (code, mode, tem, XEXP (op0, 1)); 1436169689Skan } 1437132718Skan 1438169689Skan return 0; 1439169689Skan} 1440132718Skan 1441132718Skan 1442169689Skan/* Simplify a binary operation CODE with result mode MODE, operating on OP0 1443169689Skan and OP1. Return 0 if no simplification is possible. 1444132718Skan 1445169689Skan Don't use this for relational operations such as EQ or LT. 1446169689Skan Use simplify_relational_operation instead. */ 1447169689Skanrtx 1448169689Skansimplify_binary_operation (enum rtx_code code, enum machine_mode mode, 1449169689Skan rtx op0, rtx op1) 1450169689Skan{ 1451169689Skan rtx trueop0, trueop1; 1452169689Skan rtx tem; 1453169689Skan 1454169689Skan /* Relational operations don't work here. We must know the mode 1455169689Skan of the operands in order to do the comparison correctly. 1456169689Skan Assuming a full word can give incorrect results. 1457169689Skan Consider comparing 128 with -128 in QImode. */ 1458169689Skan gcc_assert (GET_RTX_CLASS (code) != RTX_COMPARE); 1459169689Skan gcc_assert (GET_RTX_CLASS (code) != RTX_COMM_COMPARE); 1460169689Skan 1461169689Skan /* Make sure the constant is second. */ 1462169689Skan if (GET_RTX_CLASS (code) == RTX_COMM_ARITH 1463169689Skan && swap_commutative_operands_p (op0, op1)) 1464169689Skan { 1465169689Skan tem = op0, op0 = op1, op1 = tem; 1466169689Skan } 1467169689Skan 1468169689Skan trueop0 = avoid_constant_pool_reference (op0); 1469169689Skan trueop1 = avoid_constant_pool_reference (op1); 1470169689Skan 1471169689Skan tem = simplify_const_binary_operation (code, mode, trueop0, trueop1); 1472169689Skan if (tem) 1473169689Skan return tem; 1474169689Skan return simplify_binary_operation_1 (code, mode, op0, op1, trueop0, trueop1); 1475169689Skan} 1476169689Skan 1477169689Skan/* Subroutine of simplify_binary_operation. Simplify a binary operation 1478169689Skan CODE with result mode MODE, operating on OP0 and OP1. If OP0 and/or 1479169689Skan OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the 1480169689Skan actual constants. */ 1481169689Skan 1482169689Skanstatic rtx 1483169689Skansimplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, 1484169689Skan rtx op0, rtx op1, rtx trueop0, rtx trueop1) 1485169689Skan{ 1486169689Skan rtx tem, reversed, opleft, opright; 1487169689Skan HOST_WIDE_INT val; 1488169689Skan unsigned int width = GET_MODE_BITSIZE (mode); 1489169689Skan 1490169689Skan /* Even if we can't compute a constant result, 1491169689Skan there are some cases worth simplifying. */ 1492169689Skan 1493169689Skan switch (code) 1494169689Skan { 1495169689Skan case PLUS: 1496169689Skan /* Maybe simplify x + 0 to x. The two expressions are equivalent 1497169689Skan when x is NaN, infinite, or finite and nonzero. They aren't 1498169689Skan when x is -0 and the rounding mode is not towards -infinity, 1499169689Skan since (-0) + 0 is then 0. */ 1500169689Skan if (!HONOR_SIGNED_ZEROS (mode) && trueop1 == CONST0_RTX (mode)) 1501169689Skan return op0; 1502169689Skan 1503169689Skan /* ((-a) + b) -> (b - a) and similarly for (a + (-b)). These 1504169689Skan transformations are safe even for IEEE. */ 1505169689Skan if (GET_CODE (op0) == NEG) 1506169689Skan return simplify_gen_binary (MINUS, mode, op1, XEXP (op0, 0)); 1507169689Skan else if (GET_CODE (op1) == NEG) 1508169689Skan return simplify_gen_binary (MINUS, mode, op0, XEXP (op1, 0)); 1509169689Skan 1510169689Skan /* (~a) + 1 -> -a */ 1511169689Skan if (INTEGRAL_MODE_P (mode) 1512169689Skan && GET_CODE (op0) == NOT 1513169689Skan && trueop1 == const1_rtx) 1514169689Skan return simplify_gen_unary (NEG, mode, XEXP (op0, 0), mode); 1515169689Skan 1516169689Skan /* Handle both-operands-constant cases. We can only add 1517169689Skan CONST_INTs to constants since the sum of relocatable symbols 1518169689Skan can't be handled by most assemblers. Don't add CONST_INT 1519169689Skan to CONST_INT since overflow won't be computed properly if wider 1520169689Skan than HOST_BITS_PER_WIDE_INT. */ 1521169689Skan 1522169689Skan if (CONSTANT_P (op0) && GET_MODE (op0) != VOIDmode 1523169689Skan && GET_CODE (op1) == CONST_INT) 1524169689Skan return plus_constant (op0, INTVAL (op1)); 1525169689Skan else if (CONSTANT_P (op1) && GET_MODE (op1) != VOIDmode 1526169689Skan && GET_CODE (op0) == CONST_INT) 1527169689Skan return plus_constant (op1, INTVAL (op0)); 1528169689Skan 1529169689Skan /* See if this is something like X * C - X or vice versa or 1530169689Skan if the multiplication is written as a shift. If so, we can 1531169689Skan distribute and make a new multiply, shift, or maybe just 1532169689Skan have X (if C is 2 in the example above). But don't make 1533169689Skan something more expensive than we had before. */ 1534169689Skan 1535169689Skan if (SCALAR_INT_MODE_P (mode)) 1536169689Skan { 1537169689Skan HOST_WIDE_INT coeff0h = 0, coeff1h = 0; 1538169689Skan unsigned HOST_WIDE_INT coeff0l = 1, coeff1l = 1; 1539169689Skan rtx lhs = op0, rhs = op1; 1540169689Skan 1541169689Skan if (GET_CODE (lhs) == NEG) 1542132718Skan { 1543169689Skan coeff0l = -1; 1544169689Skan coeff0h = -1; 1545169689Skan lhs = XEXP (lhs, 0); 1546132718Skan } 1547169689Skan else if (GET_CODE (lhs) == MULT 1548169689Skan && GET_CODE (XEXP (lhs, 1)) == CONST_INT) 1549169689Skan { 1550169689Skan coeff0l = INTVAL (XEXP (lhs, 1)); 1551169689Skan coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0; 1552169689Skan lhs = XEXP (lhs, 0); 1553169689Skan } 1554169689Skan else if (GET_CODE (lhs) == ASHIFT 1555169689Skan && GET_CODE (XEXP (lhs, 1)) == CONST_INT 1556169689Skan && INTVAL (XEXP (lhs, 1)) >= 0 1557169689Skan && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT) 1558169689Skan { 1559169689Skan coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); 1560169689Skan coeff0h = 0; 1561169689Skan lhs = XEXP (lhs, 0); 1562169689Skan } 1563132718Skan 1564169689Skan if (GET_CODE (rhs) == NEG) 1565169689Skan { 1566169689Skan coeff1l = -1; 1567169689Skan coeff1h = -1; 1568169689Skan rhs = XEXP (rhs, 0); 1569169689Skan } 1570169689Skan else if (GET_CODE (rhs) == MULT 1571169689Skan && GET_CODE (XEXP (rhs, 1)) == CONST_INT) 1572169689Skan { 1573169689Skan coeff1l = INTVAL (XEXP (rhs, 1)); 1574169689Skan coeff1h = INTVAL (XEXP (rhs, 1)) < 0 ? -1 : 0; 1575169689Skan rhs = XEXP (rhs, 0); 1576169689Skan } 1577169689Skan else if (GET_CODE (rhs) == ASHIFT 1578169689Skan && GET_CODE (XEXP (rhs, 1)) == CONST_INT 1579169689Skan && INTVAL (XEXP (rhs, 1)) >= 0 1580169689Skan && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT) 1581169689Skan { 1582169689Skan coeff1l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1)); 1583169689Skan coeff1h = 0; 1584169689Skan rhs = XEXP (rhs, 0); 1585169689Skan } 1586132718Skan 1587169689Skan if (rtx_equal_p (lhs, rhs)) 1588169689Skan { 1589169689Skan rtx orig = gen_rtx_PLUS (mode, op0, op1); 1590169689Skan rtx coeff; 1591169689Skan unsigned HOST_WIDE_INT l; 1592169689Skan HOST_WIDE_INT h; 1593132718Skan 1594169689Skan add_double (coeff0l, coeff0h, coeff1l, coeff1h, &l, &h); 1595169689Skan coeff = immed_double_const (l, h, mode); 1596132718Skan 1597169689Skan tem = simplify_gen_binary (MULT, mode, lhs, coeff); 1598169689Skan return rtx_cost (tem, SET) <= rtx_cost (orig, SET) 1599169689Skan ? tem : 0; 1600169689Skan } 1601169689Skan } 160290075Sobrien 1603169689Skan /* (plus (xor X C1) C2) is (xor X (C1^C2)) if C2 is signbit. */ 1604169689Skan if ((GET_CODE (op1) == CONST_INT 1605169689Skan || GET_CODE (op1) == CONST_DOUBLE) 1606169689Skan && GET_CODE (op0) == XOR 1607169689Skan && (GET_CODE (XEXP (op0, 1)) == CONST_INT 1608169689Skan || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE) 1609169689Skan && mode_signbit_p (mode, op1)) 1610169689Skan return simplify_gen_binary (XOR, mode, XEXP (op0, 0), 1611169689Skan simplify_gen_binary (XOR, mode, op1, 1612169689Skan XEXP (op0, 1))); 1613132718Skan 1614169689Skan /* Canonicalize (plus (mult (neg B) C) A) to (minus A (mult B C)). */ 1615169689Skan if (GET_CODE (op0) == MULT 1616169689Skan && GET_CODE (XEXP (op0, 0)) == NEG) 1617169689Skan { 1618169689Skan rtx in1, in2; 1619132718Skan 1620169689Skan in1 = XEXP (XEXP (op0, 0), 0); 1621169689Skan in2 = XEXP (op0, 1); 1622169689Skan return simplify_gen_binary (MINUS, mode, op1, 1623169689Skan simplify_gen_binary (MULT, mode, 1624169689Skan in1, in2)); 1625169689Skan } 1626132718Skan 1627169689Skan /* (plus (comparison A B) C) can become (neg (rev-comp A B)) if 1628169689Skan C is 1 and STORE_FLAG_VALUE is -1 or if C is -1 and STORE_FLAG_VALUE 1629169689Skan is 1. */ 1630169689Skan if (COMPARISON_P (op0) 1631169689Skan && ((STORE_FLAG_VALUE == -1 && trueop1 == const1_rtx) 1632169689Skan || (STORE_FLAG_VALUE == 1 && trueop1 == constm1_rtx)) 1633169689Skan && (reversed = reversed_comparison (op0, mode))) 1634169689Skan return 1635169689Skan simplify_gen_unary (NEG, mode, reversed, mode); 1636132718Skan 1637169689Skan /* If one of the operands is a PLUS or a MINUS, see if we can 1638169689Skan simplify this by the associative law. 1639169689Skan Don't use the associative law for floating point. 1640169689Skan The inaccuracy makes it nonassociative, 1641169689Skan and subtle programs can break if operations are associated. */ 1642169689Skan 1643169689Skan if (INTEGRAL_MODE_P (mode) 1644169689Skan && (plus_minus_operand_p (op0) 1645169689Skan || plus_minus_operand_p (op1)) 1646169689Skan && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) 1647169689Skan return tem; 1648169689Skan 1649169689Skan /* Reassociate floating point addition only when the user 1650169689Skan specifies unsafe math optimizations. */ 1651169689Skan if (FLOAT_MODE_P (mode) 1652169689Skan && flag_unsafe_math_optimizations) 1653169689Skan { 1654169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 1655169689Skan if (tem) 1656169689Skan return tem; 1657169689Skan } 1658169689Skan break; 1659169689Skan 1660169689Skan case COMPARE: 1661169689Skan#ifdef HAVE_cc0 1662169689Skan /* Convert (compare FOO (const_int 0)) to FOO unless we aren't 1663169689Skan using cc0, in which case we want to leave it as a COMPARE 1664169689Skan so we can distinguish it from a register-register-copy. 1665169689Skan 1666169689Skan In IEEE floating point, x-0 is not the same as x. */ 1667169689Skan 1668169689Skan if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT 1669169689Skan || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations) 1670169689Skan && trueop1 == CONST0_RTX (mode)) 1671169689Skan return op0; 1672169689Skan#endif 1673169689Skan 1674169689Skan /* Convert (compare (gt (flags) 0) (lt (flags) 0)) to (flags). */ 1675169689Skan if (((GET_CODE (op0) == GT && GET_CODE (op1) == LT) 1676169689Skan || (GET_CODE (op0) == GTU && GET_CODE (op1) == LTU)) 1677169689Skan && XEXP (op0, 1) == const0_rtx && XEXP (op1, 1) == const0_rtx) 1678169689Skan { 1679169689Skan rtx xop00 = XEXP (op0, 0); 1680169689Skan rtx xop10 = XEXP (op1, 0); 1681169689Skan 1682169689Skan#ifdef HAVE_cc0 1683169689Skan if (GET_CODE (xop00) == CC0 && GET_CODE (xop10) == CC0) 1684169689Skan#else 1685169689Skan if (REG_P (xop00) && REG_P (xop10) 1686169689Skan && GET_MODE (xop00) == GET_MODE (xop10) 1687169689Skan && REGNO (xop00) == REGNO (xop10) 1688169689Skan && GET_MODE_CLASS (GET_MODE (xop00)) == MODE_CC 1689169689Skan && GET_MODE_CLASS (GET_MODE (xop10)) == MODE_CC) 1690169689Skan#endif 1691169689Skan return xop00; 1692169689Skan } 1693169689Skan break; 1694169689Skan 1695169689Skan case MINUS: 1696169689Skan /* We can't assume x-x is 0 even with non-IEEE floating point, 1697169689Skan but since it is zero except in very strange circumstances, we 1698169689Skan will treat it as zero with -funsafe-math-optimizations. */ 1699169689Skan if (rtx_equal_p (trueop0, trueop1) 1700169689Skan && ! side_effects_p (op0) 1701169689Skan && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)) 1702169689Skan return CONST0_RTX (mode); 1703169689Skan 1704169689Skan /* Change subtraction from zero into negation. (0 - x) is the 1705169689Skan same as -x when x is NaN, infinite, or finite and nonzero. 1706169689Skan But if the mode has signed zeros, and does not round towards 1707169689Skan -infinity, then 0 - 0 is 0, not -0. */ 1708169689Skan if (!HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode)) 1709169689Skan return simplify_gen_unary (NEG, mode, op1, mode); 1710169689Skan 1711169689Skan /* (-1 - a) is ~a. */ 1712169689Skan if (trueop0 == constm1_rtx) 1713169689Skan return simplify_gen_unary (NOT, mode, op1, mode); 1714169689Skan 1715169689Skan /* Subtracting 0 has no effect unless the mode has signed zeros 1716169689Skan and supports rounding towards -infinity. In such a case, 1717169689Skan 0 - 0 is -0. */ 1718169689Skan if (!(HONOR_SIGNED_ZEROS (mode) 1719169689Skan && HONOR_SIGN_DEPENDENT_ROUNDING (mode)) 1720169689Skan && trueop1 == CONST0_RTX (mode)) 1721169689Skan return op0; 1722169689Skan 1723169689Skan /* See if this is something like X * C - X or vice versa or 1724169689Skan if the multiplication is written as a shift. If so, we can 1725169689Skan distribute and make a new multiply, shift, or maybe just 1726169689Skan have X (if C is 2 in the example above). But don't make 1727169689Skan something more expensive than we had before. */ 1728169689Skan 1729169689Skan if (SCALAR_INT_MODE_P (mode)) 1730169689Skan { 1731169689Skan HOST_WIDE_INT coeff0h = 0, negcoeff1h = -1; 1732169689Skan unsigned HOST_WIDE_INT coeff0l = 1, negcoeff1l = -1; 1733169689Skan rtx lhs = op0, rhs = op1; 1734169689Skan 1735169689Skan if (GET_CODE (lhs) == NEG) 1736132718Skan { 1737169689Skan coeff0l = -1; 1738169689Skan coeff0h = -1; 1739169689Skan lhs = XEXP (lhs, 0); 1740169689Skan } 1741169689Skan else if (GET_CODE (lhs) == MULT 1742169689Skan && GET_CODE (XEXP (lhs, 1)) == CONST_INT) 1743169689Skan { 1744169689Skan coeff0l = INTVAL (XEXP (lhs, 1)); 1745169689Skan coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0; 1746169689Skan lhs = XEXP (lhs, 0); 1747169689Skan } 1748169689Skan else if (GET_CODE (lhs) == ASHIFT 1749169689Skan && GET_CODE (XEXP (lhs, 1)) == CONST_INT 1750169689Skan && INTVAL (XEXP (lhs, 1)) >= 0 1751169689Skan && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT) 1752169689Skan { 1753169689Skan coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); 1754169689Skan coeff0h = 0; 1755169689Skan lhs = XEXP (lhs, 0); 1756169689Skan } 1757169689Skan 1758169689Skan if (GET_CODE (rhs) == NEG) 1759169689Skan { 1760169689Skan negcoeff1l = 1; 1761169689Skan negcoeff1h = 0; 1762169689Skan rhs = XEXP (rhs, 0); 1763169689Skan } 1764169689Skan else if (GET_CODE (rhs) == MULT 1765169689Skan && GET_CODE (XEXP (rhs, 1)) == CONST_INT) 1766169689Skan { 1767169689Skan negcoeff1l = -INTVAL (XEXP (rhs, 1)); 1768169689Skan negcoeff1h = INTVAL (XEXP (rhs, 1)) <= 0 ? 0 : -1; 1769169689Skan rhs = XEXP (rhs, 0); 1770169689Skan } 1771169689Skan else if (GET_CODE (rhs) == ASHIFT 1772169689Skan && GET_CODE (XEXP (rhs, 1)) == CONST_INT 1773169689Skan && INTVAL (XEXP (rhs, 1)) >= 0 1774169689Skan && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT) 1775169689Skan { 1776169689Skan negcoeff1l = -(((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1))); 1777169689Skan negcoeff1h = -1; 1778169689Skan rhs = XEXP (rhs, 0); 1779169689Skan } 1780169689Skan 1781169689Skan if (rtx_equal_p (lhs, rhs)) 1782169689Skan { 1783169689Skan rtx orig = gen_rtx_MINUS (mode, op0, op1); 1784169689Skan rtx coeff; 1785169689Skan unsigned HOST_WIDE_INT l; 1786169689Skan HOST_WIDE_INT h; 1787169689Skan 1788169689Skan add_double (coeff0l, coeff0h, negcoeff1l, negcoeff1h, &l, &h); 1789169689Skan coeff = immed_double_const (l, h, mode); 1790169689Skan 1791169689Skan tem = simplify_gen_binary (MULT, mode, lhs, coeff); 1792169689Skan return rtx_cost (tem, SET) <= rtx_cost (orig, SET) 1793169689Skan ? tem : 0; 1794169689Skan } 1795169689Skan } 1796169689Skan 1797169689Skan /* (a - (-b)) -> (a + b). True even for IEEE. */ 1798169689Skan if (GET_CODE (op1) == NEG) 1799169689Skan return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0)); 1800169689Skan 1801169689Skan /* (-x - c) may be simplified as (-c - x). */ 1802169689Skan if (GET_CODE (op0) == NEG 1803169689Skan && (GET_CODE (op1) == CONST_INT 1804169689Skan || GET_CODE (op1) == CONST_DOUBLE)) 1805169689Skan { 1806169689Skan tem = simplify_unary_operation (NEG, mode, op1, mode); 1807169689Skan if (tem) 1808169689Skan return simplify_gen_binary (MINUS, mode, tem, XEXP (op0, 0)); 1809169689Skan } 1810169689Skan 1811169689Skan /* Don't let a relocatable value get a negative coeff. */ 1812169689Skan if (GET_CODE (op1) == CONST_INT && GET_MODE (op0) != VOIDmode) 1813169689Skan return simplify_gen_binary (PLUS, mode, 1814169689Skan op0, 1815169689Skan neg_const_int (mode, op1)); 1816169689Skan 1817169689Skan /* (x - (x & y)) -> (x & ~y) */ 1818169689Skan if (GET_CODE (op1) == AND) 1819169689Skan { 1820169689Skan if (rtx_equal_p (op0, XEXP (op1, 0))) 1821169689Skan { 1822169689Skan tem = simplify_gen_unary (NOT, mode, XEXP (op1, 1), 1823169689Skan GET_MODE (XEXP (op1, 1))); 1824169689Skan return simplify_gen_binary (AND, mode, op0, tem); 1825169689Skan } 1826169689Skan if (rtx_equal_p (op0, XEXP (op1, 1))) 1827169689Skan { 1828169689Skan tem = simplify_gen_unary (NOT, mode, XEXP (op1, 0), 1829169689Skan GET_MODE (XEXP (op1, 0))); 1830169689Skan return simplify_gen_binary (AND, mode, op0, tem); 1831169689Skan } 1832169689Skan } 1833169689Skan 1834169689Skan /* If STORE_FLAG_VALUE is 1, (minus 1 (comparison foo bar)) can be done 1835169689Skan by reversing the comparison code if valid. */ 1836169689Skan if (STORE_FLAG_VALUE == 1 1837169689Skan && trueop0 == const1_rtx 1838169689Skan && COMPARISON_P (op1) 1839169689Skan && (reversed = reversed_comparison (op1, mode))) 1840169689Skan return reversed; 1841169689Skan 1842169689Skan /* Canonicalize (minus A (mult (neg B) C)) to (plus (mult B C) A). */ 1843169689Skan if (GET_CODE (op1) == MULT 1844169689Skan && GET_CODE (XEXP (op1, 0)) == NEG) 1845169689Skan { 1846169689Skan rtx in1, in2; 1847169689Skan 1848169689Skan in1 = XEXP (XEXP (op1, 0), 0); 1849169689Skan in2 = XEXP (op1, 1); 1850169689Skan return simplify_gen_binary (PLUS, mode, 1851169689Skan simplify_gen_binary (MULT, mode, 1852169689Skan in1, in2), 1853169689Skan op0); 1854169689Skan } 1855169689Skan 1856169689Skan /* Canonicalize (minus (neg A) (mult B C)) to 1857169689Skan (minus (mult (neg B) C) A). */ 1858169689Skan if (GET_CODE (op1) == MULT 1859169689Skan && GET_CODE (op0) == NEG) 1860169689Skan { 1861169689Skan rtx in1, in2; 1862169689Skan 1863169689Skan in1 = simplify_gen_unary (NEG, mode, XEXP (op1, 0), mode); 1864169689Skan in2 = XEXP (op1, 1); 1865169689Skan return simplify_gen_binary (MINUS, mode, 1866169689Skan simplify_gen_binary (MULT, mode, 1867169689Skan in1, in2), 1868169689Skan XEXP (op0, 0)); 1869169689Skan } 1870169689Skan 1871169689Skan /* If one of the operands is a PLUS or a MINUS, see if we can 1872169689Skan simplify this by the associative law. This will, for example, 1873169689Skan canonicalize (minus A (plus B C)) to (minus (minus A B) C). 1874169689Skan Don't use the associative law for floating point. 1875169689Skan The inaccuracy makes it nonassociative, 1876169689Skan and subtle programs can break if operations are associated. */ 1877169689Skan 1878169689Skan if (INTEGRAL_MODE_P (mode) 1879169689Skan && (plus_minus_operand_p (op0) 1880169689Skan || plus_minus_operand_p (op1)) 1881169689Skan && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) 1882169689Skan return tem; 1883169689Skan break; 1884169689Skan 1885169689Skan case MULT: 1886169689Skan if (trueop1 == constm1_rtx) 1887169689Skan return simplify_gen_unary (NEG, mode, op0, mode); 1888169689Skan 1889169689Skan /* Maybe simplify x * 0 to 0. The reduction is not valid if 1890169689Skan x is NaN, since x * 0 is then also NaN. Nor is it valid 1891169689Skan when the mode has signed zeros, since multiplying a negative 1892169689Skan number by 0 will give -0, not 0. */ 1893169689Skan if (!HONOR_NANS (mode) 1894169689Skan && !HONOR_SIGNED_ZEROS (mode) 1895169689Skan && trueop1 == CONST0_RTX (mode) 1896169689Skan && ! side_effects_p (op0)) 1897169689Skan return op1; 1898169689Skan 1899169689Skan /* In IEEE floating point, x*1 is not equivalent to x for 1900169689Skan signalling NaNs. */ 1901169689Skan if (!HONOR_SNANS (mode) 1902169689Skan && trueop1 == CONST1_RTX (mode)) 1903169689Skan return op0; 1904169689Skan 1905169689Skan /* Convert multiply by constant power of two into shift unless 1906169689Skan we are still generating RTL. This test is a kludge. */ 1907169689Skan if (GET_CODE (trueop1) == CONST_INT 1908169689Skan && (val = exact_log2 (INTVAL (trueop1))) >= 0 1909169689Skan /* If the mode is larger than the host word size, and the 1910169689Skan uppermost bit is set, then this isn't a power of two due 1911169689Skan to implicit sign extension. */ 1912169689Skan && (width <= HOST_BITS_PER_WIDE_INT 1913169689Skan || val != HOST_BITS_PER_WIDE_INT - 1)) 1914169689Skan return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val)); 1915169689Skan 1916169689Skan /* Likewise for multipliers wider than a word. */ 1917169689Skan if (GET_CODE (trueop1) == CONST_DOUBLE 1918169689Skan && (GET_MODE (trueop1) == VOIDmode 1919169689Skan || GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_INT) 1920169689Skan && GET_MODE (op0) == mode 1921169689Skan && CONST_DOUBLE_LOW (trueop1) == 0 1922169689Skan && (val = exact_log2 (CONST_DOUBLE_HIGH (trueop1))) >= 0) 1923169689Skan return simplify_gen_binary (ASHIFT, mode, op0, 1924169689Skan GEN_INT (val + HOST_BITS_PER_WIDE_INT)); 1925169689Skan 1926169689Skan /* x*2 is x+x and x*(-1) is -x */ 1927169689Skan if (GET_CODE (trueop1) == CONST_DOUBLE 1928169689Skan && SCALAR_FLOAT_MODE_P (GET_MODE (trueop1)) 1929169689Skan && GET_MODE (op0) == mode) 1930169689Skan { 1931169689Skan REAL_VALUE_TYPE d; 1932169689Skan REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1); 1933169689Skan 1934169689Skan if (REAL_VALUES_EQUAL (d, dconst2)) 1935169689Skan return simplify_gen_binary (PLUS, mode, op0, copy_rtx (op0)); 1936169689Skan 1937169689Skan if (!HONOR_SNANS (mode) 1938169689Skan && REAL_VALUES_EQUAL (d, dconstm1)) 1939169689Skan return simplify_gen_unary (NEG, mode, op0, mode); 1940169689Skan } 1941169689Skan 1942169689Skan /* Optimize -x * -x as x * x. */ 1943169689Skan if (FLOAT_MODE_P (mode) 1944169689Skan && GET_CODE (op0) == NEG 1945169689Skan && GET_CODE (op1) == NEG 1946169689Skan && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)) 1947169689Skan && !side_effects_p (XEXP (op0, 0))) 1948169689Skan return simplify_gen_binary (MULT, mode, XEXP (op0, 0), XEXP (op1, 0)); 1949169689Skan 1950169689Skan /* Likewise, optimize abs(x) * abs(x) as x * x. */ 1951169689Skan if (SCALAR_FLOAT_MODE_P (mode) 1952169689Skan && GET_CODE (op0) == ABS 1953169689Skan && GET_CODE (op1) == ABS 1954169689Skan && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)) 1955169689Skan && !side_effects_p (XEXP (op0, 0))) 1956169689Skan return simplify_gen_binary (MULT, mode, XEXP (op0, 0), XEXP (op1, 0)); 1957169689Skan 1958169689Skan /* Reassociate multiplication, but for floating point MULTs 1959169689Skan only when the user specifies unsafe math optimizations. */ 1960169689Skan if (! FLOAT_MODE_P (mode) 1961169689Skan || flag_unsafe_math_optimizations) 1962169689Skan { 1963169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 1964169689Skan if (tem) 1965169689Skan return tem; 1966169689Skan } 1967169689Skan break; 1968169689Skan 1969169689Skan case IOR: 1970169689Skan if (trueop1 == const0_rtx) 1971169689Skan return op0; 1972169689Skan if (GET_CODE (trueop1) == CONST_INT 1973169689Skan && ((INTVAL (trueop1) & GET_MODE_MASK (mode)) 1974169689Skan == GET_MODE_MASK (mode))) 1975169689Skan return op1; 1976169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) 1977169689Skan return op0; 1978169689Skan /* A | (~A) -> -1 */ 1979169689Skan if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1)) 1980169689Skan || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0))) 1981169689Skan && ! side_effects_p (op0) 1982169689Skan && SCALAR_INT_MODE_P (mode)) 1983169689Skan return constm1_rtx; 1984169689Skan 1985169689Skan /* (ior A C) is C if all bits of A that might be nonzero are on in C. */ 1986169689Skan if (GET_CODE (op1) == CONST_INT 1987169689Skan && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 1988169689Skan && (nonzero_bits (op0, mode) & ~INTVAL (op1)) == 0) 1989169689Skan return op1; 1990169689Skan 1991169689Skan /* Convert (A & B) | A to A. */ 1992169689Skan if (GET_CODE (op0) == AND 1993169689Skan && (rtx_equal_p (XEXP (op0, 0), op1) 1994169689Skan || rtx_equal_p (XEXP (op0, 1), op1)) 1995169689Skan && ! side_effects_p (XEXP (op0, 0)) 1996169689Skan && ! side_effects_p (XEXP (op0, 1))) 1997169689Skan return op1; 1998169689Skan 1999169689Skan /* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the 2000169689Skan mode size to (rotate A CX). */ 2001169689Skan 2002169689Skan if (GET_CODE (op1) == ASHIFT 2003169689Skan || GET_CODE (op1) == SUBREG) 2004169689Skan { 2005169689Skan opleft = op1; 2006169689Skan opright = op0; 2007169689Skan } 2008169689Skan else 2009169689Skan { 2010169689Skan opright = op1; 2011169689Skan opleft = op0; 2012169689Skan } 2013169689Skan 2014169689Skan if (GET_CODE (opleft) == ASHIFT && GET_CODE (opright) == LSHIFTRT 2015169689Skan && rtx_equal_p (XEXP (opleft, 0), XEXP (opright, 0)) 2016169689Skan && GET_CODE (XEXP (opleft, 1)) == CONST_INT 2017169689Skan && GET_CODE (XEXP (opright, 1)) == CONST_INT 2018169689Skan && (INTVAL (XEXP (opleft, 1)) + INTVAL (XEXP (opright, 1)) 2019169689Skan == GET_MODE_BITSIZE (mode))) 2020169689Skan return gen_rtx_ROTATE (mode, XEXP (opright, 0), XEXP (opleft, 1)); 2021169689Skan 2022169689Skan /* Same, but for ashift that has been "simplified" to a wider mode 2023169689Skan by simplify_shift_const. */ 2024169689Skan 2025169689Skan if (GET_CODE (opleft) == SUBREG 2026169689Skan && GET_CODE (SUBREG_REG (opleft)) == ASHIFT 2027169689Skan && GET_CODE (opright) == LSHIFTRT 2028169689Skan && GET_CODE (XEXP (opright, 0)) == SUBREG 2029169689Skan && GET_MODE (opleft) == GET_MODE (XEXP (opright, 0)) 2030169689Skan && SUBREG_BYTE (opleft) == SUBREG_BYTE (XEXP (opright, 0)) 2031169689Skan && (GET_MODE_SIZE (GET_MODE (opleft)) 2032169689Skan < GET_MODE_SIZE (GET_MODE (SUBREG_REG (opleft)))) 2033169689Skan && rtx_equal_p (XEXP (SUBREG_REG (opleft), 0), 2034169689Skan SUBREG_REG (XEXP (opright, 0))) 2035169689Skan && GET_CODE (XEXP (SUBREG_REG (opleft), 1)) == CONST_INT 2036169689Skan && GET_CODE (XEXP (opright, 1)) == CONST_INT 2037169689Skan && (INTVAL (XEXP (SUBREG_REG (opleft), 1)) + INTVAL (XEXP (opright, 1)) 2038169689Skan == GET_MODE_BITSIZE (mode))) 2039169689Skan return gen_rtx_ROTATE (mode, XEXP (opright, 0), 2040169689Skan XEXP (SUBREG_REG (opleft), 1)); 2041169689Skan 2042169689Skan /* If we have (ior (and (X C1) C2)), simplify this by making 2043169689Skan C1 as small as possible if C1 actually changes. */ 2044169689Skan if (GET_CODE (op1) == CONST_INT 2045169689Skan && (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2046169689Skan || INTVAL (op1) > 0) 2047169689Skan && GET_CODE (op0) == AND 2048169689Skan && GET_CODE (XEXP (op0, 1)) == CONST_INT 2049169689Skan && GET_CODE (op1) == CONST_INT 2050169689Skan && (INTVAL (XEXP (op0, 1)) & INTVAL (op1)) != 0) 2051169689Skan return simplify_gen_binary (IOR, mode, 2052169689Skan simplify_gen_binary 2053169689Skan (AND, mode, XEXP (op0, 0), 2054169689Skan GEN_INT (INTVAL (XEXP (op0, 1)) 2055169689Skan & ~INTVAL (op1))), 2056169689Skan op1); 2057169689Skan 2058169689Skan /* If OP0 is (ashiftrt (plus ...) C), it might actually be 2059169689Skan a (sign_extend (plus ...)). Then check if OP1 is a CONST_INT and 2060169689Skan the PLUS does not affect any of the bits in OP1: then we can do 2061169689Skan the IOR as a PLUS and we can associate. This is valid if OP1 2062169689Skan can be safely shifted left C bits. */ 2063169689Skan if (GET_CODE (trueop1) == CONST_INT && GET_CODE (op0) == ASHIFTRT 2064169689Skan && GET_CODE (XEXP (op0, 0)) == PLUS 2065169689Skan && GET_CODE (XEXP (XEXP (op0, 0), 1)) == CONST_INT 2066169689Skan && GET_CODE (XEXP (op0, 1)) == CONST_INT 2067169689Skan && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_WIDE_INT) 2068169689Skan { 2069169689Skan int count = INTVAL (XEXP (op0, 1)); 2070169689Skan HOST_WIDE_INT mask = INTVAL (trueop1) << count; 2071169689Skan 2072169689Skan if (mask >> count == INTVAL (trueop1) 2073169689Skan && (mask & nonzero_bits (XEXP (op0, 0), mode)) == 0) 2074169689Skan return simplify_gen_binary (ASHIFTRT, mode, 2075169689Skan plus_constant (XEXP (op0, 0), mask), 2076169689Skan XEXP (op0, 1)); 2077169689Skan } 2078169689Skan 2079169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2080169689Skan if (tem) 2081169689Skan return tem; 2082169689Skan break; 2083169689Skan 2084169689Skan case XOR: 2085169689Skan if (trueop1 == const0_rtx) 2086169689Skan return op0; 2087169689Skan if (GET_CODE (trueop1) == CONST_INT 2088169689Skan && ((INTVAL (trueop1) & GET_MODE_MASK (mode)) 2089169689Skan == GET_MODE_MASK (mode))) 2090169689Skan return simplify_gen_unary (NOT, mode, op0, mode); 2091169689Skan if (rtx_equal_p (trueop0, trueop1) 2092169689Skan && ! side_effects_p (op0) 2093169689Skan && GET_MODE_CLASS (mode) != MODE_CC) 2094169689Skan return CONST0_RTX (mode); 2095169689Skan 2096169689Skan /* Canonicalize XOR of the most significant bit to PLUS. */ 2097169689Skan if ((GET_CODE (op1) == CONST_INT 2098169689Skan || GET_CODE (op1) == CONST_DOUBLE) 2099169689Skan && mode_signbit_p (mode, op1)) 2100169689Skan return simplify_gen_binary (PLUS, mode, op0, op1); 2101169689Skan /* (xor (plus X C1) C2) is (xor X (C1^C2)) if C1 is signbit. */ 2102169689Skan if ((GET_CODE (op1) == CONST_INT 2103169689Skan || GET_CODE (op1) == CONST_DOUBLE) 2104169689Skan && GET_CODE (op0) == PLUS 2105169689Skan && (GET_CODE (XEXP (op0, 1)) == CONST_INT 2106169689Skan || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE) 2107169689Skan && mode_signbit_p (mode, XEXP (op0, 1))) 2108169689Skan return simplify_gen_binary (XOR, mode, XEXP (op0, 0), 2109169689Skan simplify_gen_binary (XOR, mode, op1, 2110169689Skan XEXP (op0, 1))); 2111169689Skan 2112169689Skan /* If we are XORing two things that have no bits in common, 2113169689Skan convert them into an IOR. This helps to detect rotation encoded 2114169689Skan using those methods and possibly other simplifications. */ 2115169689Skan 2116169689Skan if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2117169689Skan && (nonzero_bits (op0, mode) 2118169689Skan & nonzero_bits (op1, mode)) == 0) 2119169689Skan return (simplify_gen_binary (IOR, mode, op0, op1)); 2120169689Skan 2121169689Skan /* Convert (XOR (NOT x) (NOT y)) to (XOR x y). 2122169689Skan Also convert (XOR (NOT x) y) to (NOT (XOR x y)), similarly for 2123169689Skan (NOT y). */ 2124169689Skan { 2125169689Skan int num_negated = 0; 2126169689Skan 2127169689Skan if (GET_CODE (op0) == NOT) 2128169689Skan num_negated++, op0 = XEXP (op0, 0); 2129169689Skan if (GET_CODE (op1) == NOT) 2130169689Skan num_negated++, op1 = XEXP (op1, 0); 2131169689Skan 2132169689Skan if (num_negated == 2) 2133169689Skan return simplify_gen_binary (XOR, mode, op0, op1); 2134169689Skan else if (num_negated == 1) 2135169689Skan return simplify_gen_unary (NOT, mode, 2136169689Skan simplify_gen_binary (XOR, mode, op0, op1), 2137169689Skan mode); 2138169689Skan } 2139169689Skan 2140169689Skan /* Convert (xor (and A B) B) to (and (not A) B). The latter may 2141169689Skan correspond to a machine insn or result in further simplifications 2142169689Skan if B is a constant. */ 2143169689Skan 2144169689Skan if (GET_CODE (op0) == AND 2145169689Skan && rtx_equal_p (XEXP (op0, 1), op1) 2146169689Skan && ! side_effects_p (op1)) 2147169689Skan return simplify_gen_binary (AND, mode, 2148169689Skan simplify_gen_unary (NOT, mode, 2149169689Skan XEXP (op0, 0), mode), 2150169689Skan op1); 2151169689Skan 2152169689Skan else if (GET_CODE (op0) == AND 2153169689Skan && rtx_equal_p (XEXP (op0, 0), op1) 2154169689Skan && ! side_effects_p (op1)) 2155169689Skan return simplify_gen_binary (AND, mode, 2156169689Skan simplify_gen_unary (NOT, mode, 2157169689Skan XEXP (op0, 1), mode), 2158169689Skan op1); 2159169689Skan 2160169689Skan /* (xor (comparison foo bar) (const_int 1)) can become the reversed 2161169689Skan comparison if STORE_FLAG_VALUE is 1. */ 2162169689Skan if (STORE_FLAG_VALUE == 1 2163169689Skan && trueop1 == const1_rtx 2164169689Skan && COMPARISON_P (op0) 2165169689Skan && (reversed = reversed_comparison (op0, mode))) 2166169689Skan return reversed; 2167169689Skan 2168169689Skan /* (lshiftrt foo C) where C is the number of bits in FOO minus 1 2169169689Skan is (lt foo (const_int 0)), so we can perform the above 2170169689Skan simplification if STORE_FLAG_VALUE is 1. */ 2171169689Skan 2172169689Skan if (STORE_FLAG_VALUE == 1 2173169689Skan && trueop1 == const1_rtx 2174169689Skan && GET_CODE (op0) == LSHIFTRT 2175169689Skan && GET_CODE (XEXP (op0, 1)) == CONST_INT 2176169689Skan && INTVAL (XEXP (op0, 1)) == GET_MODE_BITSIZE (mode) - 1) 2177169689Skan return gen_rtx_GE (mode, XEXP (op0, 0), const0_rtx); 2178169689Skan 2179169689Skan /* (xor (comparison foo bar) (const_int sign-bit)) 2180169689Skan when STORE_FLAG_VALUE is the sign bit. */ 2181169689Skan if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2182169689Skan && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode)) 2183169689Skan == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)) 2184169689Skan && trueop1 == const_true_rtx 2185169689Skan && COMPARISON_P (op0) 2186169689Skan && (reversed = reversed_comparison (op0, mode))) 2187169689Skan return reversed; 2188169689Skan 2189169689Skan break; 2190169689Skan 2191169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2192169689Skan if (tem) 2193169689Skan return tem; 2194169689Skan break; 2195169689Skan 2196169689Skan case AND: 2197169689Skan if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0)) 2198169689Skan return trueop1; 2199169689Skan /* If we are turning off bits already known off in OP0, we need 2200169689Skan not do an AND. */ 2201169689Skan if (GET_CODE (trueop1) == CONST_INT 2202169689Skan && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2203169689Skan && (nonzero_bits (trueop0, mode) & ~INTVAL (trueop1)) == 0) 2204169689Skan return op0; 2205169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0) 2206169689Skan && GET_MODE_CLASS (mode) != MODE_CC) 2207169689Skan return op0; 2208169689Skan /* A & (~A) -> 0 */ 2209169689Skan if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1)) 2210169689Skan || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0))) 2211169689Skan && ! side_effects_p (op0) 2212169689Skan && GET_MODE_CLASS (mode) != MODE_CC) 2213169689Skan return CONST0_RTX (mode); 2214169689Skan 2215169689Skan /* Transform (and (extend X) C) into (zero_extend (and X C)) if 2216169689Skan there are no nonzero bits of C outside of X's mode. */ 2217169689Skan if ((GET_CODE (op0) == SIGN_EXTEND 2218169689Skan || GET_CODE (op0) == ZERO_EXTEND) 2219169689Skan && GET_CODE (trueop1) == CONST_INT 2220169689Skan && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2221169689Skan && (~GET_MODE_MASK (GET_MODE (XEXP (op0, 0))) 2222169689Skan & INTVAL (trueop1)) == 0) 2223169689Skan { 2224169689Skan enum machine_mode imode = GET_MODE (XEXP (op0, 0)); 2225169689Skan tem = simplify_gen_binary (AND, imode, XEXP (op0, 0), 2226169689Skan gen_int_mode (INTVAL (trueop1), 2227169689Skan imode)); 2228169689Skan return simplify_gen_unary (ZERO_EXTEND, mode, tem, imode); 2229169689Skan } 2230169689Skan 2231169689Skan /* Convert (A ^ B) & A to A & (~B) since the latter is often a single 2232169689Skan insn (and may simplify more). */ 2233169689Skan if (GET_CODE (op0) == XOR 2234169689Skan && rtx_equal_p (XEXP (op0, 0), op1) 2235169689Skan && ! side_effects_p (op1)) 2236169689Skan return simplify_gen_binary (AND, mode, 2237169689Skan simplify_gen_unary (NOT, mode, 2238169689Skan XEXP (op0, 1), mode), 2239169689Skan op1); 2240169689Skan 2241169689Skan if (GET_CODE (op0) == XOR 2242169689Skan && rtx_equal_p (XEXP (op0, 1), op1) 2243169689Skan && ! side_effects_p (op1)) 2244169689Skan return simplify_gen_binary (AND, mode, 2245169689Skan simplify_gen_unary (NOT, mode, 2246169689Skan XEXP (op0, 0), mode), 2247169689Skan op1); 2248169689Skan 2249169689Skan /* Similarly for (~(A ^ B)) & A. */ 2250169689Skan if (GET_CODE (op0) == NOT 2251169689Skan && GET_CODE (XEXP (op0, 0)) == XOR 2252169689Skan && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1) 2253169689Skan && ! side_effects_p (op1)) 2254169689Skan return simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 1), op1); 2255169689Skan 2256169689Skan if (GET_CODE (op0) == NOT 2257169689Skan && GET_CODE (XEXP (op0, 0)) == XOR 2258169689Skan && rtx_equal_p (XEXP (XEXP (op0, 0), 1), op1) 2259169689Skan && ! side_effects_p (op1)) 2260169689Skan return simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 0), op1); 2261169689Skan 2262169689Skan /* Convert (A | B) & A to A. */ 2263169689Skan if (GET_CODE (op0) == IOR 2264169689Skan && (rtx_equal_p (XEXP (op0, 0), op1) 2265169689Skan || rtx_equal_p (XEXP (op0, 1), op1)) 2266169689Skan && ! side_effects_p (XEXP (op0, 0)) 2267169689Skan && ! side_effects_p (XEXP (op0, 1))) 2268169689Skan return op1; 2269169689Skan 2270169689Skan /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M, 2271169689Skan ((A & N) + B) & M -> (A + B) & M 2272169689Skan Similarly if (N & M) == 0, 2273169689Skan ((A | N) + B) & M -> (A + B) & M 2274169689Skan and for - instead of + and/or ^ instead of |. */ 2275169689Skan if (GET_CODE (trueop1) == CONST_INT 2276169689Skan && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT 2277169689Skan && ~INTVAL (trueop1) 2278169689Skan && (INTVAL (trueop1) & (INTVAL (trueop1) + 1)) == 0 2279169689Skan && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS)) 2280169689Skan { 2281169689Skan rtx pmop[2]; 2282169689Skan int which; 2283169689Skan 2284169689Skan pmop[0] = XEXP (op0, 0); 2285169689Skan pmop[1] = XEXP (op0, 1); 2286169689Skan 2287169689Skan for (which = 0; which < 2; which++) 2288169689Skan { 2289169689Skan tem = pmop[which]; 2290169689Skan switch (GET_CODE (tem)) 2291132718Skan { 2292169689Skan case AND: 2293169689Skan if (GET_CODE (XEXP (tem, 1)) == CONST_INT 2294169689Skan && (INTVAL (XEXP (tem, 1)) & INTVAL (trueop1)) 2295169689Skan == INTVAL (trueop1)) 2296169689Skan pmop[which] = XEXP (tem, 0); 2297169689Skan break; 2298169689Skan case IOR: 2299169689Skan case XOR: 2300169689Skan if (GET_CODE (XEXP (tem, 1)) == CONST_INT 2301169689Skan && (INTVAL (XEXP (tem, 1)) & INTVAL (trueop1)) == 0) 2302169689Skan pmop[which] = XEXP (tem, 0); 2303169689Skan break; 2304169689Skan default: 2305169689Skan break; 2306132718Skan } 2307132718Skan } 2308132718Skan 2309169689Skan if (pmop[0] != XEXP (op0, 0) || pmop[1] != XEXP (op0, 1)) 2310132718Skan { 2311169689Skan tem = simplify_gen_binary (GET_CODE (op0), mode, 2312169689Skan pmop[0], pmop[1]); 2313169689Skan return simplify_gen_binary (code, mode, tem, op1); 2314132718Skan } 2315169689Skan } 2316169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2317169689Skan if (tem) 2318169689Skan return tem; 2319169689Skan break; 2320132718Skan 2321169689Skan case UDIV: 2322169689Skan /* 0/x is 0 (or x&0 if x has side-effects). */ 2323169689Skan if (trueop0 == CONST0_RTX (mode)) 2324169689Skan { 2325169689Skan if (side_effects_p (op1)) 2326169689Skan return simplify_gen_binary (AND, mode, op1, trueop0); 2327169689Skan return trueop0; 2328169689Skan } 2329169689Skan /* x/1 is x. */ 2330169689Skan if (trueop1 == CONST1_RTX (mode)) 2331169689Skan return rtl_hooks.gen_lowpart_no_emit (mode, op0); 2332169689Skan /* Convert divide by power of two into shift. */ 2333169689Skan if (GET_CODE (trueop1) == CONST_INT 2334169689Skan && (val = exact_log2 (INTVAL (trueop1))) > 0) 2335169689Skan return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (val)); 2336169689Skan break; 2337169689Skan 2338169689Skan case DIV: 2339169689Skan /* Handle floating point and integers separately. */ 2340169689Skan if (SCALAR_FLOAT_MODE_P (mode)) 2341169689Skan { 2342169689Skan /* Maybe change 0.0 / x to 0.0. This transformation isn't 2343169689Skan safe for modes with NaNs, since 0.0 / 0.0 will then be 2344169689Skan NaN rather than 0.0. Nor is it safe for modes with signed 2345169689Skan zeros, since dividing 0 by a negative number gives -0.0 */ 2346169689Skan if (trueop0 == CONST0_RTX (mode) 2347169689Skan && !HONOR_NANS (mode) 2348169689Skan && !HONOR_SIGNED_ZEROS (mode) 2349169689Skan && ! side_effects_p (op1)) 2350169689Skan return op0; 2351169689Skan /* x/1.0 is x. */ 2352169689Skan if (trueop1 == CONST1_RTX (mode) 2353169689Skan && !HONOR_SNANS (mode)) 2354169689Skan return op0; 2355169689Skan 2356169689Skan if (GET_CODE (trueop1) == CONST_DOUBLE 2357169689Skan && trueop1 != CONST0_RTX (mode)) 2358132718Skan { 2359169689Skan REAL_VALUE_TYPE d; 2360169689Skan REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1); 2361169689Skan 2362169689Skan /* x/-1.0 is -x. */ 2363169689Skan if (REAL_VALUES_EQUAL (d, dconstm1) 2364169689Skan && !HONOR_SNANS (mode)) 2365169689Skan return simplify_gen_unary (NEG, mode, op0, mode); 2366169689Skan 2367169689Skan /* Change FP division by a constant into multiplication. 2368169689Skan Only do this with -funsafe-math-optimizations. */ 2369169689Skan if (flag_unsafe_math_optimizations 2370169689Skan && !REAL_VALUES_EQUAL (d, dconst0)) 2371169689Skan { 2372169689Skan REAL_ARITHMETIC (d, RDIV_EXPR, dconst1, d); 2373169689Skan tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode); 2374169689Skan return simplify_gen_binary (MULT, mode, op0, tem); 2375169689Skan } 2376132718Skan } 2377169689Skan } 2378169689Skan else 2379169689Skan { 2380169689Skan /* 0/x is 0 (or x&0 if x has side-effects). */ 2381169689Skan if (trueop0 == CONST0_RTX (mode)) 2382169689Skan { 2383169689Skan if (side_effects_p (op1)) 2384169689Skan return simplify_gen_binary (AND, mode, op1, trueop0); 2385169689Skan return trueop0; 2386169689Skan } 2387169689Skan /* x/1 is x. */ 2388169689Skan if (trueop1 == CONST1_RTX (mode)) 2389169689Skan return rtl_hooks.gen_lowpart_no_emit (mode, op0); 2390169689Skan /* x/-1 is -x. */ 2391169689Skan if (trueop1 == constm1_rtx) 2392169689Skan { 2393169689Skan rtx x = rtl_hooks.gen_lowpart_no_emit (mode, op0); 2394169689Skan return simplify_gen_unary (NEG, mode, x, mode); 2395169689Skan } 2396169689Skan } 2397169689Skan break; 2398132718Skan 2399169689Skan case UMOD: 2400169689Skan /* 0%x is 0 (or x&0 if x has side-effects). */ 2401169689Skan if (trueop0 == CONST0_RTX (mode)) 2402169689Skan { 2403169689Skan if (side_effects_p (op1)) 2404169689Skan return simplify_gen_binary (AND, mode, op1, trueop0); 2405169689Skan return trueop0; 2406169689Skan } 2407169689Skan /* x%1 is 0 (of x&0 if x has side-effects). */ 2408169689Skan if (trueop1 == CONST1_RTX (mode)) 2409169689Skan { 2410169689Skan if (side_effects_p (op0)) 2411169689Skan return simplify_gen_binary (AND, mode, op0, CONST0_RTX (mode)); 2412169689Skan return CONST0_RTX (mode); 2413169689Skan } 2414169689Skan /* Implement modulus by power of two as AND. */ 2415169689Skan if (GET_CODE (trueop1) == CONST_INT 2416169689Skan && exact_log2 (INTVAL (trueop1)) > 0) 2417169689Skan return simplify_gen_binary (AND, mode, op0, 2418169689Skan GEN_INT (INTVAL (op1) - 1)); 2419169689Skan break; 242090075Sobrien 2421169689Skan case MOD: 2422169689Skan /* 0%x is 0 (or x&0 if x has side-effects). */ 2423169689Skan if (trueop0 == CONST0_RTX (mode)) 2424169689Skan { 2425169689Skan if (side_effects_p (op1)) 2426169689Skan return simplify_gen_binary (AND, mode, op1, trueop0); 2427169689Skan return trueop0; 2428169689Skan } 2429169689Skan /* x%1 and x%-1 is 0 (or x&0 if x has side-effects). */ 2430169689Skan if (trueop1 == CONST1_RTX (mode) || trueop1 == constm1_rtx) 2431169689Skan { 2432169689Skan if (side_effects_p (op0)) 2433169689Skan return simplify_gen_binary (AND, mode, op0, CONST0_RTX (mode)); 2434169689Skan return CONST0_RTX (mode); 2435169689Skan } 2436169689Skan break; 243790075Sobrien 2438169689Skan case ROTATERT: 2439169689Skan case ROTATE: 2440169689Skan case ASHIFTRT: 2441169689Skan if (trueop1 == CONST0_RTX (mode)) 2442169689Skan return op0; 2443169689Skan if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) 2444169689Skan return op0; 2445169689Skan /* Rotating ~0 always results in ~0. */ 2446169689Skan if (GET_CODE (trueop0) == CONST_INT && width <= HOST_BITS_PER_WIDE_INT 2447169689Skan && (unsigned HOST_WIDE_INT) INTVAL (trueop0) == GET_MODE_MASK (mode) 2448169689Skan && ! side_effects_p (op1)) 2449169689Skan return op0; 2450169689Skan break; 2451132718Skan 2452169689Skan case ASHIFT: 2453169689Skan case SS_ASHIFT: 2454169689Skan if (trueop1 == CONST0_RTX (mode)) 2455169689Skan return op0; 2456169689Skan if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) 2457169689Skan return op0; 2458169689Skan break; 245990075Sobrien 2460169689Skan case LSHIFTRT: 2461169689Skan if (trueop1 == CONST0_RTX (mode)) 2462169689Skan return op0; 2463169689Skan if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) 2464169689Skan return op0; 2465169689Skan /* Optimize (lshiftrt (clz X) C) as (eq X 0). */ 2466169689Skan if (GET_CODE (op0) == CLZ 2467169689Skan && GET_CODE (trueop1) == CONST_INT 2468169689Skan && STORE_FLAG_VALUE == 1 2469169689Skan && INTVAL (trueop1) < (HOST_WIDE_INT)width) 2470169689Skan { 2471169689Skan enum machine_mode imode = GET_MODE (XEXP (op0, 0)); 2472169689Skan unsigned HOST_WIDE_INT zero_val = 0; 2473132718Skan 2474169689Skan if (CLZ_DEFINED_VALUE_AT_ZERO (imode, zero_val) 2475169689Skan && zero_val == GET_MODE_BITSIZE (imode) 2476169689Skan && INTVAL (trueop1) == exact_log2 (zero_val)) 2477169689Skan return simplify_gen_relational (EQ, mode, imode, 2478169689Skan XEXP (op0, 0), const0_rtx); 2479169689Skan } 2480169689Skan break; 2481117395Skan 2482169689Skan case SMIN: 2483169689Skan if (width <= HOST_BITS_PER_WIDE_INT 2484169689Skan && GET_CODE (trueop1) == CONST_INT 2485169689Skan && INTVAL (trueop1) == (HOST_WIDE_INT) 1 << (width -1) 2486169689Skan && ! side_effects_p (op0)) 2487169689Skan return op1; 2488169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) 2489169689Skan return op0; 2490169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2491169689Skan if (tem) 2492169689Skan return tem; 2493169689Skan break; 2494169689Skan 2495169689Skan case SMAX: 2496169689Skan if (width <= HOST_BITS_PER_WIDE_INT 2497169689Skan && GET_CODE (trueop1) == CONST_INT 2498169689Skan && ((unsigned HOST_WIDE_INT) INTVAL (trueop1) 2499169689Skan == (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1) 2500169689Skan && ! side_effects_p (op0)) 2501169689Skan return op1; 2502169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) 2503169689Skan return op0; 2504169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2505169689Skan if (tem) 2506169689Skan return tem; 2507169689Skan break; 2508169689Skan 2509169689Skan case UMIN: 2510169689Skan if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0)) 2511169689Skan return op1; 2512169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) 2513169689Skan return op0; 2514169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2515169689Skan if (tem) 2516169689Skan return tem; 2517169689Skan break; 2518169689Skan 2519169689Skan case UMAX: 2520169689Skan if (trueop1 == constm1_rtx && ! side_effects_p (op0)) 2521169689Skan return op1; 2522169689Skan if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) 2523169689Skan return op0; 2524169689Skan tem = simplify_associative_operation (code, mode, op0, op1); 2525169689Skan if (tem) 2526169689Skan return tem; 2527169689Skan break; 2528169689Skan 2529169689Skan case SS_PLUS: 2530169689Skan case US_PLUS: 2531169689Skan case SS_MINUS: 2532169689Skan case US_MINUS: 2533169689Skan /* ??? There are simplifications that can be done. */ 2534169689Skan return 0; 2535169689Skan 2536169689Skan case VEC_SELECT: 2537169689Skan if (!VECTOR_MODE_P (mode)) 2538169689Skan { 2539169689Skan gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0))); 2540169689Skan gcc_assert (mode == GET_MODE_INNER (GET_MODE (trueop0))); 2541169689Skan gcc_assert (GET_CODE (trueop1) == PARALLEL); 2542169689Skan gcc_assert (XVECLEN (trueop1, 0) == 1); 2543169689Skan gcc_assert (GET_CODE (XVECEXP (trueop1, 0, 0)) == CONST_INT); 2544169689Skan 2545169689Skan if (GET_CODE (trueop0) == CONST_VECTOR) 2546169689Skan return CONST_VECTOR_ELT (trueop0, INTVAL (XVECEXP 2547169689Skan (trueop1, 0, 0))); 254890075Sobrien } 2549169689Skan else 2550169689Skan { 2551169689Skan gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0))); 2552169689Skan gcc_assert (GET_MODE_INNER (mode) 2553169689Skan == GET_MODE_INNER (GET_MODE (trueop0))); 2554169689Skan gcc_assert (GET_CODE (trueop1) == PARALLEL); 255590075Sobrien 2556169689Skan if (GET_CODE (trueop0) == CONST_VECTOR) 2557169689Skan { 2558169689Skan int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); 2559169689Skan unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); 2560169689Skan rtvec v = rtvec_alloc (n_elts); 2561169689Skan unsigned int i; 2562169689Skan 2563169689Skan gcc_assert (XVECLEN (trueop1, 0) == (int) n_elts); 2564169689Skan for (i = 0; i < n_elts; i++) 2565169689Skan { 2566169689Skan rtx x = XVECEXP (trueop1, 0, i); 2567169689Skan 2568169689Skan gcc_assert (GET_CODE (x) == CONST_INT); 2569169689Skan RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, 2570169689Skan INTVAL (x)); 2571169689Skan } 2572169689Skan 2573169689Skan return gen_rtx_CONST_VECTOR (mode, v); 2574169689Skan } 2575169689Skan } 2576169689Skan 2577169689Skan if (XVECLEN (trueop1, 0) == 1 2578169689Skan && GET_CODE (XVECEXP (trueop1, 0, 0)) == CONST_INT 2579169689Skan && GET_CODE (trueop0) == VEC_CONCAT) 2580169689Skan { 2581169689Skan rtx vec = trueop0; 2582169689Skan int offset = INTVAL (XVECEXP (trueop1, 0, 0)) * GET_MODE_SIZE (mode); 2583169689Skan 2584169689Skan /* Try to find the element in the VEC_CONCAT. */ 2585169689Skan while (GET_MODE (vec) != mode 2586169689Skan && GET_CODE (vec) == VEC_CONCAT) 2587169689Skan { 2588169689Skan HOST_WIDE_INT vec_size = GET_MODE_SIZE (GET_MODE (XEXP (vec, 0))); 2589169689Skan if (offset < vec_size) 2590169689Skan vec = XEXP (vec, 0); 2591169689Skan else 2592169689Skan { 2593169689Skan offset -= vec_size; 2594169689Skan vec = XEXP (vec, 1); 2595169689Skan } 2596169689Skan vec = avoid_constant_pool_reference (vec); 2597169689Skan } 2598169689Skan 2599169689Skan if (GET_MODE (vec) == mode) 2600169689Skan return vec; 2601169689Skan } 2602169689Skan 260390075Sobrien return 0; 2604169689Skan case VEC_CONCAT: 2605169689Skan { 2606169689Skan enum machine_mode op0_mode = (GET_MODE (trueop0) != VOIDmode 2607169689Skan ? GET_MODE (trueop0) 2608169689Skan : GET_MODE_INNER (mode)); 2609169689Skan enum machine_mode op1_mode = (GET_MODE (trueop1) != VOIDmode 2610169689Skan ? GET_MODE (trueop1) 2611169689Skan : GET_MODE_INNER (mode)); 2612132718Skan 2613169689Skan gcc_assert (VECTOR_MODE_P (mode)); 2614169689Skan gcc_assert (GET_MODE_SIZE (op0_mode) + GET_MODE_SIZE (op1_mode) 2615169689Skan == GET_MODE_SIZE (mode)); 2616132718Skan 2617169689Skan if (VECTOR_MODE_P (op0_mode)) 2618169689Skan gcc_assert (GET_MODE_INNER (mode) 2619169689Skan == GET_MODE_INNER (op0_mode)); 2620169689Skan else 2621169689Skan gcc_assert (GET_MODE_INNER (mode) == op0_mode); 2622132718Skan 2623169689Skan if (VECTOR_MODE_P (op1_mode)) 2624169689Skan gcc_assert (GET_MODE_INNER (mode) 2625169689Skan == GET_MODE_INNER (op1_mode)); 2626169689Skan else 2627169689Skan gcc_assert (GET_MODE_INNER (mode) == op1_mode); 2628132718Skan 2629169689Skan if ((GET_CODE (trueop0) == CONST_VECTOR 2630169689Skan || GET_CODE (trueop0) == CONST_INT 2631169689Skan || GET_CODE (trueop0) == CONST_DOUBLE) 2632169689Skan && (GET_CODE (trueop1) == CONST_VECTOR 2633169689Skan || GET_CODE (trueop1) == CONST_INT 2634169689Skan || GET_CODE (trueop1) == CONST_DOUBLE)) 2635169689Skan { 2636169689Skan int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); 2637169689Skan unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); 2638169689Skan rtvec v = rtvec_alloc (n_elts); 2639169689Skan unsigned int i; 2640169689Skan unsigned in_n_elts = 1; 2641132718Skan 2642169689Skan if (VECTOR_MODE_P (op0_mode)) 2643169689Skan in_n_elts = (GET_MODE_SIZE (op0_mode) / elt_size); 2644169689Skan for (i = 0; i < n_elts; i++) 2645169689Skan { 2646169689Skan if (i < in_n_elts) 2647169689Skan { 2648169689Skan if (!VECTOR_MODE_P (op0_mode)) 2649169689Skan RTVEC_ELT (v, i) = trueop0; 2650169689Skan else 2651169689Skan RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, i); 2652169689Skan } 2653169689Skan else 2654169689Skan { 2655169689Skan if (!VECTOR_MODE_P (op1_mode)) 2656169689Skan RTVEC_ELT (v, i) = trueop1; 2657169689Skan else 2658169689Skan RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop1, 2659169689Skan i - in_n_elts); 2660169689Skan } 2661169689Skan } 2662169689Skan 2663169689Skan return gen_rtx_CONST_VECTOR (mode, v); 2664169689Skan } 2665169689Skan } 2666169689Skan return 0; 2667169689Skan 2668169689Skan default: 2669169689Skan gcc_unreachable (); 2670132718Skan } 2671132718Skan 2672132718Skan return 0; 2673132718Skan} 2674132718Skan 267590075Sobrienrtx 2676169689Skansimplify_const_binary_operation (enum rtx_code code, enum machine_mode mode, 2677169689Skan rtx op0, rtx op1) 267890075Sobrien{ 267990075Sobrien HOST_WIDE_INT arg0, arg1, arg0s, arg1s; 268090075Sobrien HOST_WIDE_INT val; 268190075Sobrien unsigned int width = GET_MODE_BITSIZE (mode); 268290075Sobrien 2683132718Skan if (VECTOR_MODE_P (mode) 2684146895Skan && code != VEC_CONCAT 2685169689Skan && GET_CODE (op0) == CONST_VECTOR 2686169689Skan && GET_CODE (op1) == CONST_VECTOR) 2687132718Skan { 2688169689Skan unsigned n_elts = GET_MODE_NUNITS (mode); 2689169689Skan enum machine_mode op0mode = GET_MODE (op0); 2690169689Skan unsigned op0_n_elts = GET_MODE_NUNITS (op0mode); 2691169689Skan enum machine_mode op1mode = GET_MODE (op1); 2692169689Skan unsigned op1_n_elts = GET_MODE_NUNITS (op1mode); 2693132718Skan rtvec v = rtvec_alloc (n_elts); 2694132718Skan unsigned int i; 2695132718Skan 2696169689Skan gcc_assert (op0_n_elts == n_elts); 2697169689Skan gcc_assert (op1_n_elts == n_elts); 2698132718Skan for (i = 0; i < n_elts; i++) 2699132718Skan { 2700132718Skan rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode), 2701169689Skan CONST_VECTOR_ELT (op0, i), 2702169689Skan CONST_VECTOR_ELT (op1, i)); 2703132718Skan if (!x) 2704132718Skan return 0; 2705132718Skan RTVEC_ELT (v, i) = x; 2706132718Skan } 2707132718Skan 2708132718Skan return gen_rtx_CONST_VECTOR (mode, v); 2709132718Skan } 2710132718Skan 2711169689Skan if (VECTOR_MODE_P (mode) 2712169689Skan && code == VEC_CONCAT 2713169689Skan && CONSTANT_P (op0) && CONSTANT_P (op1)) 2714169689Skan { 2715169689Skan unsigned n_elts = GET_MODE_NUNITS (mode); 2716169689Skan rtvec v = rtvec_alloc (n_elts); 2717169689Skan 2718169689Skan gcc_assert (n_elts >= 2); 2719169689Skan if (n_elts == 2) 2720169689Skan { 2721169689Skan gcc_assert (GET_CODE (op0) != CONST_VECTOR); 2722169689Skan gcc_assert (GET_CODE (op1) != CONST_VECTOR); 2723169689Skan 2724169689Skan RTVEC_ELT (v, 0) = op0; 2725169689Skan RTVEC_ELT (v, 1) = op1; 2726169689Skan } 2727169689Skan else 2728169689Skan { 2729169689Skan unsigned op0_n_elts = GET_MODE_NUNITS (GET_MODE (op0)); 2730169689Skan unsigned op1_n_elts = GET_MODE_NUNITS (GET_MODE (op1)); 2731169689Skan unsigned i; 2732169689Skan 2733169689Skan gcc_assert (GET_CODE (op0) == CONST_VECTOR); 2734169689Skan gcc_assert (GET_CODE (op1) == CONST_VECTOR); 2735169689Skan gcc_assert (op0_n_elts + op1_n_elts == n_elts); 2736169689Skan 2737169689Skan for (i = 0; i < op0_n_elts; ++i) 2738169689Skan RTVEC_ELT (v, i) = XVECEXP (op0, 0, i); 2739169689Skan for (i = 0; i < op1_n_elts; ++i) 2740169689Skan RTVEC_ELT (v, op0_n_elts+i) = XVECEXP (op1, 0, i); 2741169689Skan } 2742169689Skan 2743169689Skan return gen_rtx_CONST_VECTOR (mode, v); 2744169689Skan } 2745169689Skan 2746169689Skan if (SCALAR_FLOAT_MODE_P (mode) 2747169689Skan && GET_CODE (op0) == CONST_DOUBLE 2748169689Skan && GET_CODE (op1) == CONST_DOUBLE 274990075Sobrien && mode == GET_MODE (op0) && mode == GET_MODE (op1)) 275090075Sobrien { 2751146895Skan if (code == AND 2752146895Skan || code == IOR 2753146895Skan || code == XOR) 2754146895Skan { 2755146895Skan long tmp0[4]; 2756146895Skan long tmp1[4]; 2757146895Skan REAL_VALUE_TYPE r; 2758146895Skan int i; 275990075Sobrien 2760146895Skan real_to_target (tmp0, CONST_DOUBLE_REAL_VALUE (op0), 2761146895Skan GET_MODE (op0)); 2762146895Skan real_to_target (tmp1, CONST_DOUBLE_REAL_VALUE (op1), 2763146895Skan GET_MODE (op1)); 2764146895Skan for (i = 0; i < 4; i++) 2765146895Skan { 2766169689Skan switch (code) 2767169689Skan { 2768169689Skan case AND: 2769146895Skan tmp0[i] &= tmp1[i]; 2770169689Skan break; 2771169689Skan case IOR: 2772146895Skan tmp0[i] |= tmp1[i]; 2773169689Skan break; 2774169689Skan case XOR: 2775146895Skan tmp0[i] ^= tmp1[i]; 2776169689Skan break; 2777169689Skan default: 2778169689Skan gcc_unreachable (); 2779169689Skan } 2780146895Skan } 2781146895Skan real_from_target (&r, tmp0, mode); 2782146895Skan return CONST_DOUBLE_FROM_REAL_VALUE (r, mode); 2783146895Skan } 2784146895Skan else 2785146895Skan { 2786169689Skan REAL_VALUE_TYPE f0, f1, value, result; 2787169689Skan bool inexact; 2788117395Skan 2789169689Skan REAL_VALUE_FROM_CONST_DOUBLE (f0, op0); 2790169689Skan REAL_VALUE_FROM_CONST_DOUBLE (f1, op1); 2791169689Skan real_convert (&f0, mode, &f0); 2792169689Skan real_convert (&f1, mode, &f1); 2793132718Skan 2794146895Skan if (HONOR_SNANS (mode) 2795146895Skan && (REAL_VALUE_ISNAN (f0) || REAL_VALUE_ISNAN (f1))) 2796146895Skan return 0; 2797117395Skan 2798146895Skan if (code == DIV 2799146895Skan && REAL_VALUES_EQUAL (f1, dconst0) 2800146895Skan && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode))) 2801146895Skan return 0; 2802132718Skan 2803146895Skan if (MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) 2804146895Skan && flag_trapping_math 2805146895Skan && REAL_VALUE_ISINF (f0) && REAL_VALUE_ISINF (f1)) 2806132718Skan { 2807146895Skan int s0 = REAL_VALUE_NEGATIVE (f0); 2808146895Skan int s1 = REAL_VALUE_NEGATIVE (f1); 2809146895Skan 2810146895Skan switch (code) 2811146895Skan { 2812146895Skan case PLUS: 2813146895Skan /* Inf + -Inf = NaN plus exception. */ 2814146895Skan if (s0 != s1) 2815146895Skan return 0; 2816146895Skan break; 2817146895Skan case MINUS: 2818146895Skan /* Inf - Inf = NaN plus exception. */ 2819146895Skan if (s0 == s1) 2820146895Skan return 0; 2821146895Skan break; 2822146895Skan case DIV: 2823146895Skan /* Inf / Inf = NaN plus exception. */ 2824146895Skan return 0; 2825146895Skan default: 2826146895Skan break; 2827146895Skan } 2828132718Skan } 2829132718Skan 2830146895Skan if (code == MULT && MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) 2831146895Skan && flag_trapping_math 2832146895Skan && ((REAL_VALUE_ISINF (f0) && REAL_VALUES_EQUAL (f1, dconst0)) 2833146895Skan || (REAL_VALUE_ISINF (f1) 2834146895Skan && REAL_VALUES_EQUAL (f0, dconst0)))) 2835146895Skan /* Inf * 0 = NaN plus exception. */ 2836146895Skan return 0; 2837132718Skan 2838169689Skan inexact = real_arithmetic (&value, rtx_to_tree_code (code), 2839169689Skan &f0, &f1); 2840169689Skan real_convert (&result, mode, &value); 2841117395Skan 2842169689Skan /* Don't constant fold this floating point operation if 2843169689Skan the result has overflowed and flag_trapping_math. */ 2844169689Skan 2845169689Skan if (flag_trapping_math 2846169689Skan && MODE_HAS_INFINITIES (mode) 2847169689Skan && REAL_VALUE_ISINF (result) 2848169689Skan && !REAL_VALUE_ISINF (f0) 2849169689Skan && !REAL_VALUE_ISINF (f1)) 2850169689Skan /* Overflow plus exception. */ 2851169689Skan return 0; 2852169689Skan 2853169689Skan /* Don't constant fold this floating point operation if the 2854169689Skan result may dependent upon the run-time rounding mode and 2855169689Skan flag_rounding_math is set, or if GCC's software emulation 2856169689Skan is unable to accurately represent the result. */ 2857169689Skan 2858169689Skan if ((flag_rounding_math 2859169689Skan || (REAL_MODE_FORMAT_COMPOSITE_P (mode) 2860169689Skan && !flag_unsafe_math_optimizations)) 2861169689Skan && (inexact || !real_identical (&result, &value))) 2862169689Skan return NULL_RTX; 2863169689Skan 2864169689Skan return CONST_DOUBLE_FROM_REAL_VALUE (result, mode); 2865146895Skan } 286690075Sobrien } 286790075Sobrien 286890075Sobrien /* We can fold some multi-word operations. */ 286990075Sobrien if (GET_MODE_CLASS (mode) == MODE_INT 287090075Sobrien && width == HOST_BITS_PER_WIDE_INT * 2 2871169689Skan && (GET_CODE (op0) == CONST_DOUBLE || GET_CODE (op0) == CONST_INT) 2872169689Skan && (GET_CODE (op1) == CONST_DOUBLE || GET_CODE (op1) == CONST_INT)) 287390075Sobrien { 2874169689Skan unsigned HOST_WIDE_INT l1, l2, lv, lt; 2875169689Skan HOST_WIDE_INT h1, h2, hv, ht; 287690075Sobrien 2877169689Skan if (GET_CODE (op0) == CONST_DOUBLE) 2878169689Skan l1 = CONST_DOUBLE_LOW (op0), h1 = CONST_DOUBLE_HIGH (op0); 287990075Sobrien else 2880169689Skan l1 = INTVAL (op0), h1 = HWI_SIGN_EXTEND (l1); 288190075Sobrien 2882169689Skan if (GET_CODE (op1) == CONST_DOUBLE) 2883169689Skan l2 = CONST_DOUBLE_LOW (op1), h2 = CONST_DOUBLE_HIGH (op1); 288490075Sobrien else 2885169689Skan l2 = INTVAL (op1), h2 = HWI_SIGN_EXTEND (l2); 288690075Sobrien 288790075Sobrien switch (code) 288890075Sobrien { 288990075Sobrien case MINUS: 289090075Sobrien /* A - B == A + (-B). */ 289190075Sobrien neg_double (l2, h2, &lv, &hv); 289290075Sobrien l2 = lv, h2 = hv; 289390075Sobrien 2894132718Skan /* Fall through.... */ 289590075Sobrien 289690075Sobrien case PLUS: 289790075Sobrien add_double (l1, h1, l2, h2, &lv, &hv); 289890075Sobrien break; 289990075Sobrien 290090075Sobrien case MULT: 290190075Sobrien mul_double (l1, h1, l2, h2, &lv, &hv); 290290075Sobrien break; 290390075Sobrien 2904169689Skan case DIV: 2905169689Skan if (div_and_round_double (TRUNC_DIV_EXPR, 0, l1, h1, l2, h2, 2906169689Skan &lv, &hv, <, &ht)) 2907169689Skan return 0; 2908169689Skan break; 290990075Sobrien 2910169689Skan case MOD: 2911169689Skan if (div_and_round_double (TRUNC_DIV_EXPR, 0, l1, h1, l2, h2, 2912169689Skan <, &ht, &lv, &hv)) 2913169689Skan return 0; 2914169689Skan break; 2915169689Skan 2916169689Skan case UDIV: 2917169689Skan if (div_and_round_double (TRUNC_DIV_EXPR, 1, l1, h1, l2, h2, 2918169689Skan &lv, &hv, <, &ht)) 2919169689Skan return 0; 2920169689Skan break; 2921169689Skan 2922169689Skan case UMOD: 2923169689Skan if (div_and_round_double (TRUNC_DIV_EXPR, 1, l1, h1, l2, h2, 2924169689Skan <, &ht, &lv, &hv)) 2925169689Skan return 0; 2926169689Skan break; 2927169689Skan 292890075Sobrien case AND: 292990075Sobrien lv = l1 & l2, hv = h1 & h2; 293090075Sobrien break; 293190075Sobrien 293290075Sobrien case IOR: 293390075Sobrien lv = l1 | l2, hv = h1 | h2; 293490075Sobrien break; 293590075Sobrien 293690075Sobrien case XOR: 293790075Sobrien lv = l1 ^ l2, hv = h1 ^ h2; 293890075Sobrien break; 293990075Sobrien 294090075Sobrien case SMIN: 294190075Sobrien if (h1 < h2 294290075Sobrien || (h1 == h2 294390075Sobrien && ((unsigned HOST_WIDE_INT) l1 294490075Sobrien < (unsigned HOST_WIDE_INT) l2))) 294590075Sobrien lv = l1, hv = h1; 294690075Sobrien else 294790075Sobrien lv = l2, hv = h2; 294890075Sobrien break; 294990075Sobrien 295090075Sobrien case SMAX: 295190075Sobrien if (h1 > h2 295290075Sobrien || (h1 == h2 295390075Sobrien && ((unsigned HOST_WIDE_INT) l1 295490075Sobrien > (unsigned HOST_WIDE_INT) l2))) 295590075Sobrien lv = l1, hv = h1; 295690075Sobrien else 295790075Sobrien lv = l2, hv = h2; 295890075Sobrien break; 295990075Sobrien 296090075Sobrien case UMIN: 296190075Sobrien if ((unsigned HOST_WIDE_INT) h1 < (unsigned HOST_WIDE_INT) h2 296290075Sobrien || (h1 == h2 296390075Sobrien && ((unsigned HOST_WIDE_INT) l1 296490075Sobrien < (unsigned HOST_WIDE_INT) l2))) 296590075Sobrien lv = l1, hv = h1; 296690075Sobrien else 296790075Sobrien lv = l2, hv = h2; 296890075Sobrien break; 296990075Sobrien 297090075Sobrien case UMAX: 297190075Sobrien if ((unsigned HOST_WIDE_INT) h1 > (unsigned HOST_WIDE_INT) h2 297290075Sobrien || (h1 == h2 297390075Sobrien && ((unsigned HOST_WIDE_INT) l1 297490075Sobrien > (unsigned HOST_WIDE_INT) l2))) 297590075Sobrien lv = l1, hv = h1; 297690075Sobrien else 297790075Sobrien lv = l2, hv = h2; 297890075Sobrien break; 297990075Sobrien 298090075Sobrien case LSHIFTRT: case ASHIFTRT: 298190075Sobrien case ASHIFT: 298290075Sobrien case ROTATE: case ROTATERT: 298390075Sobrien if (SHIFT_COUNT_TRUNCATED) 298490075Sobrien l2 &= (GET_MODE_BITSIZE (mode) - 1), h2 = 0; 298590075Sobrien 298690075Sobrien if (h2 != 0 || l2 >= GET_MODE_BITSIZE (mode)) 298790075Sobrien return 0; 298890075Sobrien 298990075Sobrien if (code == LSHIFTRT || code == ASHIFTRT) 299090075Sobrien rshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv, 299190075Sobrien code == ASHIFTRT); 299290075Sobrien else if (code == ASHIFT) 299390075Sobrien lshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv, 1); 299490075Sobrien else if (code == ROTATE) 299590075Sobrien lrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv); 299690075Sobrien else /* code == ROTATERT */ 299790075Sobrien rrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv); 299890075Sobrien break; 299990075Sobrien 300090075Sobrien default: 300190075Sobrien return 0; 300290075Sobrien } 300390075Sobrien 300490075Sobrien return immed_double_const (lv, hv, mode); 300590075Sobrien } 300690075Sobrien 3007169689Skan if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT 3008169689Skan && width <= HOST_BITS_PER_WIDE_INT && width != 0) 300990075Sobrien { 3010169689Skan /* Get the integer argument values in two forms: 3011169689Skan zero-extended in ARG0, ARG1 and sign-extended in ARG0S, ARG1S. */ 301290075Sobrien 3013169689Skan arg0 = INTVAL (op0); 3014169689Skan arg1 = INTVAL (op1); 3015169689Skan 3016169689Skan if (width < HOST_BITS_PER_WIDE_INT) 3017169689Skan { 3018169689Skan arg0 &= ((HOST_WIDE_INT) 1 << width) - 1; 3019169689Skan arg1 &= ((HOST_WIDE_INT) 1 << width) - 1; 3020169689Skan 3021169689Skan arg0s = arg0; 3022169689Skan if (arg0s & ((HOST_WIDE_INT) 1 << (width - 1))) 3023169689Skan arg0s |= ((HOST_WIDE_INT) (-1) << width); 3024169689Skan 3025169689Skan arg1s = arg1; 3026169689Skan if (arg1s & ((HOST_WIDE_INT) 1 << (width - 1))) 3027169689Skan arg1s |= ((HOST_WIDE_INT) (-1) << width); 3028169689Skan } 3029169689Skan else 3030169689Skan { 3031169689Skan arg0s = arg0; 3032169689Skan arg1s = arg1; 3033169689Skan } 3034169689Skan 3035169689Skan /* Compute the value of the arithmetic. */ 3036169689Skan 303790075Sobrien switch (code) 303890075Sobrien { 303990075Sobrien case PLUS: 3040169689Skan val = arg0s + arg1s; 304190075Sobrien break; 3042169689Skan 304390075Sobrien case MINUS: 3044169689Skan val = arg0s - arg1s; 304590075Sobrien break; 3046169689Skan 304790075Sobrien case MULT: 3048169689Skan val = arg0s * arg1s; 304990075Sobrien break; 3050169689Skan 3051169689Skan case DIV: 3052169689Skan if (arg1s == 0 3053169689Skan || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) 3054169689Skan && arg1s == -1)) 3055169689Skan return 0; 3056169689Skan val = arg0s / arg1s; 305790075Sobrien break; 3058169689Skan 3059169689Skan case MOD: 3060169689Skan if (arg1s == 0 3061169689Skan || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) 3062169689Skan && arg1s == -1)) 3063169689Skan return 0; 3064169689Skan val = arg0s % arg1s; 306590075Sobrien break; 3066169689Skan 306790075Sobrien case UDIV: 3068169689Skan if (arg1 == 0 3069169689Skan || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) 3070169689Skan && arg1s == -1)) 3071169689Skan return 0; 3072169689Skan val = (unsigned HOST_WIDE_INT) arg0 / arg1; 307390075Sobrien break; 3074169689Skan 307590075Sobrien case UMOD: 3076169689Skan if (arg1 == 0 3077169689Skan || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) 3078169689Skan && arg1s == -1)) 3079169689Skan return 0; 3080169689Skan val = (unsigned HOST_WIDE_INT) arg0 % arg1; 308190075Sobrien break; 3082169689Skan 3083169689Skan case AND: 3084169689Skan val = arg0 & arg1; 3085169689Skan break; 3086169689Skan 3087169689Skan case IOR: 3088169689Skan val = arg0 | arg1; 3089169689Skan break; 3090169689Skan 3091169689Skan case XOR: 3092169689Skan val = arg0 ^ arg1; 3093169689Skan break; 3094169689Skan 3095169689Skan case LSHIFTRT: 3096169689Skan case ASHIFT: 3097169689Skan case ASHIFTRT: 3098169689Skan /* Truncate the shift if SHIFT_COUNT_TRUNCATED, otherwise make sure 3099169689Skan the value is in range. We can't return any old value for 3100169689Skan out-of-range arguments because either the middle-end (via 3101169689Skan shift_truncation_mask) or the back-end might be relying on 3102169689Skan target-specific knowledge. Nor can we rely on 3103169689Skan shift_truncation_mask, since the shift might not be part of an 3104169689Skan ashlM3, lshrM3 or ashrM3 instruction. */ 3105169689Skan if (SHIFT_COUNT_TRUNCATED) 3106169689Skan arg1 = (unsigned HOST_WIDE_INT) arg1 % width; 3107169689Skan else if (arg1 < 0 || arg1 >= GET_MODE_BITSIZE (mode)) 3108169689Skan return 0; 3109169689Skan 3110169689Skan val = (code == ASHIFT 3111169689Skan ? ((unsigned HOST_WIDE_INT) arg0) << arg1 3112169689Skan : ((unsigned HOST_WIDE_INT) arg0) >> arg1); 3113169689Skan 3114169689Skan /* Sign-extend the result for arithmetic right shifts. */ 3115169689Skan if (code == ASHIFTRT && arg0s < 0 && arg1 > 0) 3116169689Skan val |= ((HOST_WIDE_INT) -1) << (width - arg1); 3117169689Skan break; 3118169689Skan 311990075Sobrien case ROTATERT: 3120169689Skan if (arg1 < 0) 3121169689Skan return 0; 3122169689Skan 3123169689Skan arg1 %= width; 3124169689Skan val = ((((unsigned HOST_WIDE_INT) arg0) << (width - arg1)) 3125169689Skan | (((unsigned HOST_WIDE_INT) arg0) >> arg1)); 3126169689Skan break; 3127169689Skan 312890075Sobrien case ROTATE: 3129169689Skan if (arg1 < 0) 3130169689Skan return 0; 3131169689Skan 3132169689Skan arg1 %= width; 3133169689Skan val = ((((unsigned HOST_WIDE_INT) arg0) << arg1) 3134169689Skan | (((unsigned HOST_WIDE_INT) arg0) >> (width - arg1))); 313590075Sobrien break; 3136169689Skan 3137169689Skan case COMPARE: 3138169689Skan /* Do nothing here. */ 3139169689Skan return 0; 3140169689Skan 314190075Sobrien case SMIN: 3142169689Skan val = arg0s <= arg1s ? arg0s : arg1s; 314390075Sobrien break; 3144169689Skan 3145169689Skan case UMIN: 3146169689Skan val = ((unsigned HOST_WIDE_INT) arg0 3147169689Skan <= (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1); 3148169689Skan break; 3149169689Skan 315090075Sobrien case SMAX: 3151169689Skan val = arg0s > arg1s ? arg0s : arg1s; 315290075Sobrien break; 3153169689Skan 315490075Sobrien case UMAX: 3155169689Skan val = ((unsigned HOST_WIDE_INT) arg0 3156169689Skan > (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1); 315790075Sobrien break; 3158169689Skan 315990075Sobrien case SS_PLUS: 316090075Sobrien case US_PLUS: 316190075Sobrien case SS_MINUS: 316290075Sobrien case US_MINUS: 3163169689Skan case SS_ASHIFT: 316490075Sobrien /* ??? There are simplifications that can be done. */ 316590075Sobrien return 0; 3166169689Skan 316790075Sobrien default: 3168169689Skan gcc_unreachable (); 316990075Sobrien } 3170117395Skan 3171169689Skan return gen_int_mode (val, mode); 317290075Sobrien } 317390075Sobrien 3174169689Skan return NULL_RTX; 3175169689Skan} 317690075Sobrien 317790075Sobrien 317890075Sobrien 317990075Sobrien/* Simplify a PLUS or MINUS, at least one of whose operands may be another 318090075Sobrien PLUS or MINUS. 318190075Sobrien 318290075Sobrien Rather than test for specific case, we do this by a brute-force method 318390075Sobrien and do all possible simplifications until no more changes occur. Then 3184169689Skan we rebuild the operation. */ 318590075Sobrien 318690075Sobrienstruct simplify_plus_minus_op_data 318790075Sobrien{ 318890075Sobrien rtx op; 3189169689Skan short neg; 319090075Sobrien}; 319190075Sobrien 319290075Sobrienstatic int 3193132718Skansimplify_plus_minus_op_data_cmp (const void *p1, const void *p2) 319490075Sobrien{ 319590075Sobrien const struct simplify_plus_minus_op_data *d1 = p1; 319690075Sobrien const struct simplify_plus_minus_op_data *d2 = p2; 3197169689Skan int result; 319890075Sobrien 3199169689Skan result = (commutative_operand_precedence (d2->op) 3200169689Skan - commutative_operand_precedence (d1->op)); 3201169689Skan if (result) 3202169689Skan return result; 3203169689Skan 3204169689Skan /* Group together equal REGs to do more simplification. */ 3205169689Skan if (REG_P (d1->op) && REG_P (d2->op)) 3206169689Skan return REGNO (d1->op) - REGNO (d2->op); 3207169689Skan else 3208169689Skan return 0; 320990075Sobrien} 321090075Sobrien 321190075Sobrienstatic rtx 3212132718Skansimplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0, 3213169689Skan rtx op1) 321490075Sobrien{ 321590075Sobrien struct simplify_plus_minus_op_data ops[8]; 321690075Sobrien rtx result, tem; 3217169689Skan int n_ops = 2, input_ops = 2; 3218169689Skan int changed, n_constants = 0, canonicalized = 0; 321990075Sobrien int i, j; 322090075Sobrien 3221132718Skan memset (ops, 0, sizeof ops); 3222117395Skan 322390075Sobrien /* Set up the two operands and then expand them until nothing has been 322490075Sobrien changed. If we run out of room in our array, give up; this should 322590075Sobrien almost never happen. */ 322690075Sobrien 322790075Sobrien ops[0].op = op0; 322890075Sobrien ops[0].neg = 0; 322990075Sobrien ops[1].op = op1; 323090075Sobrien ops[1].neg = (code == MINUS); 323190075Sobrien 323290075Sobrien do 323390075Sobrien { 323490075Sobrien changed = 0; 323590075Sobrien 323690075Sobrien for (i = 0; i < n_ops; i++) 323790075Sobrien { 323890075Sobrien rtx this_op = ops[i].op; 323990075Sobrien int this_neg = ops[i].neg; 324090075Sobrien enum rtx_code this_code = GET_CODE (this_op); 324190075Sobrien 324290075Sobrien switch (this_code) 324390075Sobrien { 324490075Sobrien case PLUS: 324590075Sobrien case MINUS: 324690075Sobrien if (n_ops == 7) 324796263Sobrien return NULL_RTX; 324890075Sobrien 324990075Sobrien ops[n_ops].op = XEXP (this_op, 1); 325090075Sobrien ops[n_ops].neg = (this_code == MINUS) ^ this_neg; 325190075Sobrien n_ops++; 325290075Sobrien 325390075Sobrien ops[i].op = XEXP (this_op, 0); 325490075Sobrien input_ops++; 325590075Sobrien changed = 1; 3256169689Skan canonicalized |= this_neg; 325790075Sobrien break; 325890075Sobrien 325990075Sobrien case NEG: 326090075Sobrien ops[i].op = XEXP (this_op, 0); 326190075Sobrien ops[i].neg = ! this_neg; 326290075Sobrien changed = 1; 3263169689Skan canonicalized = 1; 326490075Sobrien break; 326590075Sobrien 326690075Sobrien case CONST: 326796263Sobrien if (n_ops < 7 326896263Sobrien && GET_CODE (XEXP (this_op, 0)) == PLUS 326996263Sobrien && CONSTANT_P (XEXP (XEXP (this_op, 0), 0)) 327096263Sobrien && CONSTANT_P (XEXP (XEXP (this_op, 0), 1))) 327196263Sobrien { 327296263Sobrien ops[i].op = XEXP (XEXP (this_op, 0), 0); 327396263Sobrien ops[n_ops].op = XEXP (XEXP (this_op, 0), 1); 327496263Sobrien ops[n_ops].neg = this_neg; 327596263Sobrien n_ops++; 327696263Sobrien changed = 1; 3277169689Skan canonicalized = 1; 327896263Sobrien } 327990075Sobrien break; 328090075Sobrien 328190075Sobrien case NOT: 328290075Sobrien /* ~a -> (-a - 1) */ 328390075Sobrien if (n_ops != 7) 328490075Sobrien { 328590075Sobrien ops[n_ops].op = constm1_rtx; 328690075Sobrien ops[n_ops++].neg = this_neg; 328790075Sobrien ops[i].op = XEXP (this_op, 0); 328890075Sobrien ops[i].neg = !this_neg; 328990075Sobrien changed = 1; 3290169689Skan canonicalized = 1; 329190075Sobrien } 329290075Sobrien break; 329390075Sobrien 329490075Sobrien case CONST_INT: 3295169689Skan n_constants++; 329690075Sobrien if (this_neg) 329790075Sobrien { 329890075Sobrien ops[i].op = neg_const_int (mode, this_op); 329990075Sobrien ops[i].neg = 0; 330090075Sobrien changed = 1; 3301169689Skan canonicalized = 1; 330290075Sobrien } 330390075Sobrien break; 330490075Sobrien 330590075Sobrien default: 330690075Sobrien break; 330790075Sobrien } 330890075Sobrien } 330990075Sobrien } 331090075Sobrien while (changed); 331190075Sobrien 3312169689Skan if (n_constants > 1) 3313169689Skan canonicalized = 1; 331490075Sobrien 3315169689Skan gcc_assert (n_ops >= 2); 331696263Sobrien 3317169689Skan /* If we only have two operands, we can avoid the loops. */ 3318169689Skan if (n_ops == 2) 3319169689Skan { 3320169689Skan enum rtx_code code = ops[0].neg || ops[1].neg ? MINUS : PLUS; 3321169689Skan rtx lhs, rhs; 332290075Sobrien 3323169689Skan /* Get the two operands. Be careful with the order, especially for 3324169689Skan the cases where code == MINUS. */ 3325169689Skan if (ops[0].neg && ops[1].neg) 3326169689Skan { 3327169689Skan lhs = gen_rtx_NEG (mode, ops[0].op); 3328169689Skan rhs = ops[1].op; 3329169689Skan } 3330169689Skan else if (ops[0].neg) 3331169689Skan { 3332169689Skan lhs = ops[1].op; 3333169689Skan rhs = ops[0].op; 3334169689Skan } 3335169689Skan else 3336169689Skan { 3337169689Skan lhs = ops[0].op; 3338169689Skan rhs = ops[1].op; 3339169689Skan } 3340169689Skan 3341169689Skan return simplify_const_binary_operation (code, mode, lhs, rhs); 3342169689Skan } 3343169689Skan 3344169689Skan /* Now simplify each pair of operands until nothing changes. */ 334590075Sobrien do 334690075Sobrien { 3347169689Skan /* Insertion sort is good enough for an eight-element array. */ 3348169689Skan for (i = 1; i < n_ops; i++) 3349169689Skan { 3350169689Skan struct simplify_plus_minus_op_data save; 3351169689Skan j = i - 1; 3352169689Skan if (simplify_plus_minus_op_data_cmp (&ops[j], &ops[i]) < 0) 3353169689Skan continue; 335490075Sobrien 3355169689Skan canonicalized = 1; 3356169689Skan save = ops[i]; 3357169689Skan do 3358169689Skan ops[j + 1] = ops[j]; 3359169689Skan while (j-- && simplify_plus_minus_op_data_cmp (&ops[j], &save) > 0); 3360169689Skan ops[j + 1] = save; 3361169689Skan } 3362169689Skan 3363169689Skan /* This is only useful the first time through. */ 3364169689Skan if (!canonicalized) 3365169689Skan return NULL_RTX; 3366169689Skan 3367169689Skan changed = 0; 3368169689Skan for (i = n_ops - 1; i > 0; i--) 3369169689Skan for (j = i - 1; j >= 0; j--) 337090075Sobrien { 3371169689Skan rtx lhs = ops[j].op, rhs = ops[i].op; 3372169689Skan int lneg = ops[j].neg, rneg = ops[i].neg; 337390075Sobrien 3374169689Skan if (lhs != 0 && rhs != 0) 337590075Sobrien { 337690075Sobrien enum rtx_code ncode = PLUS; 337790075Sobrien 337890075Sobrien if (lneg != rneg) 337990075Sobrien { 338090075Sobrien ncode = MINUS; 338190075Sobrien if (lneg) 338290075Sobrien tem = lhs, lhs = rhs, rhs = tem; 338390075Sobrien } 338490075Sobrien else if (swap_commutative_operands_p (lhs, rhs)) 338590075Sobrien tem = lhs, lhs = rhs, rhs = tem; 338690075Sobrien 3387169689Skan if ((GET_CODE (lhs) == CONST || GET_CODE (lhs) == CONST_INT) 3388169689Skan && (GET_CODE (rhs) == CONST || GET_CODE (rhs) == CONST_INT)) 3389169689Skan { 3390169689Skan rtx tem_lhs, tem_rhs; 339190075Sobrien 3392169689Skan tem_lhs = GET_CODE (lhs) == CONST ? XEXP (lhs, 0) : lhs; 3393169689Skan tem_rhs = GET_CODE (rhs) == CONST ? XEXP (rhs, 0) : rhs; 3394169689Skan tem = simplify_binary_operation (ncode, mode, tem_lhs, tem_rhs); 3395169689Skan 3396169689Skan if (tem && !CONSTANT_P (tem)) 3397169689Skan tem = gen_rtx_CONST (GET_MODE (tem), tem); 3398169689Skan } 3399169689Skan else 3400169689Skan tem = simplify_binary_operation (ncode, mode, lhs, rhs); 3401169689Skan 3402117395Skan /* Reject "simplifications" that just wrap the two 340390075Sobrien arguments in a CONST. Failure to do so can result 340490075Sobrien in infinite recursion with simplify_binary_operation 340590075Sobrien when it calls us to simplify CONST operations. */ 340690075Sobrien if (tem 340790075Sobrien && ! (GET_CODE (tem) == CONST 340890075Sobrien && GET_CODE (XEXP (tem, 0)) == ncode 340990075Sobrien && XEXP (XEXP (tem, 0), 0) == lhs 3410169689Skan && XEXP (XEXP (tem, 0), 1) == rhs)) 341190075Sobrien { 341290075Sobrien lneg &= rneg; 341390075Sobrien if (GET_CODE (tem) == NEG) 341490075Sobrien tem = XEXP (tem, 0), lneg = !lneg; 341590075Sobrien if (GET_CODE (tem) == CONST_INT && lneg) 341690075Sobrien tem = neg_const_int (mode, tem), lneg = 0; 341790075Sobrien 341890075Sobrien ops[i].op = tem; 341990075Sobrien ops[i].neg = lneg; 342090075Sobrien ops[j].op = NULL_RTX; 342190075Sobrien changed = 1; 342290075Sobrien } 342390075Sobrien } 342490075Sobrien } 342590075Sobrien 3426169689Skan /* Pack all the operands to the lower-numbered entries. */ 3427169689Skan for (i = 0, j = 0; j < n_ops; j++) 3428169689Skan if (ops[j].op) 3429169689Skan { 3430169689Skan ops[i] = ops[j]; 3431169689Skan i++; 3432169689Skan } 3433169689Skan n_ops = i; 343490075Sobrien } 343590075Sobrien while (changed); 343690075Sobrien 3437132718Skan /* Create (minus -C X) instead of (neg (const (plus X C))). */ 3438132718Skan if (n_ops == 2 3439132718Skan && GET_CODE (ops[1].op) == CONST_INT 3440132718Skan && CONSTANT_P (ops[0].op) 3441132718Skan && ops[0].neg) 3442132718Skan return gen_rtx_fmt_ee (MINUS, mode, ops[1].op, ops[0].op); 3443132718Skan 344490075Sobrien /* We suppressed creation of trivial CONST expressions in the 344590075Sobrien combination loop to avoid recursion. Create one manually now. 344690075Sobrien The combination loop should have ensured that there is exactly 344790075Sobrien one CONST_INT, and the sort will have ensured that it is last 344890075Sobrien in the array and that any other constant will be next-to-last. */ 344990075Sobrien 345090075Sobrien if (n_ops > 1 345190075Sobrien && GET_CODE (ops[n_ops - 1].op) == CONST_INT 345290075Sobrien && CONSTANT_P (ops[n_ops - 2].op)) 345390075Sobrien { 345490075Sobrien rtx value = ops[n_ops - 1].op; 345590075Sobrien if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg) 345690075Sobrien value = neg_const_int (mode, value); 345790075Sobrien ops[n_ops - 2].op = plus_constant (ops[n_ops - 2].op, INTVAL (value)); 345890075Sobrien n_ops--; 345990075Sobrien } 346090075Sobrien 3461132718Skan /* Put a non-negated operand first, if possible. */ 346290075Sobrien 346390075Sobrien for (i = 0; i < n_ops && ops[i].neg; i++) 346490075Sobrien continue; 346590075Sobrien if (i == n_ops) 3466132718Skan ops[0].op = gen_rtx_NEG (mode, ops[0].op); 346790075Sobrien else if (i != 0) 346890075Sobrien { 346990075Sobrien tem = ops[0].op; 347090075Sobrien ops[0] = ops[i]; 347190075Sobrien ops[i].op = tem; 347290075Sobrien ops[i].neg = 1; 347390075Sobrien } 347490075Sobrien 347590075Sobrien /* Now make the result by performing the requested operations. */ 347690075Sobrien result = ops[0].op; 347790075Sobrien for (i = 1; i < n_ops; i++) 347890075Sobrien result = gen_rtx_fmt_ee (ops[i].neg ? MINUS : PLUS, 347990075Sobrien mode, result, ops[i].op); 348090075Sobrien 3481132718Skan return result; 348290075Sobrien} 348390075Sobrien 3484169689Skan/* Check whether an operand is suitable for calling simplify_plus_minus. */ 3485169689Skanstatic bool 3486169689Skanplus_minus_operand_p (rtx x) 3487169689Skan{ 3488169689Skan return GET_CODE (x) == PLUS 3489169689Skan || GET_CODE (x) == MINUS 3490169689Skan || (GET_CODE (x) == CONST 3491169689Skan && GET_CODE (XEXP (x, 0)) == PLUS 3492169689Skan && CONSTANT_P (XEXP (XEXP (x, 0), 0)) 3493169689Skan && CONSTANT_P (XEXP (XEXP (x, 0), 1))); 3494169689Skan} 3495169689Skan 349690075Sobrien/* Like simplify_binary_operation except used for relational operators. 3497169689Skan MODE is the mode of the result. If MODE is VOIDmode, both operands must 3498169689Skan not also be VOIDmode. 349990075Sobrien 3500169689Skan CMP_MODE specifies in which mode the comparison is done in, so it is 3501169689Skan the mode of the operands. If CMP_MODE is VOIDmode, it is taken from 3502169689Skan the operands or, if both are VOIDmode, the operands are compared in 3503169689Skan "infinite precision". */ 350490075Sobrienrtx 3505132718Skansimplify_relational_operation (enum rtx_code code, enum machine_mode mode, 3506169689Skan enum machine_mode cmp_mode, rtx op0, rtx op1) 350790075Sobrien{ 3508169689Skan rtx tem, trueop0, trueop1; 3509169689Skan 3510169689Skan if (cmp_mode == VOIDmode) 3511169689Skan cmp_mode = GET_MODE (op0); 3512169689Skan if (cmp_mode == VOIDmode) 3513169689Skan cmp_mode = GET_MODE (op1); 3514169689Skan 3515169689Skan tem = simplify_const_relational_operation (code, cmp_mode, op0, op1); 3516169689Skan if (tem) 3517169689Skan { 3518169689Skan if (SCALAR_FLOAT_MODE_P (mode)) 3519169689Skan { 3520169689Skan if (tem == const0_rtx) 3521169689Skan return CONST0_RTX (mode); 3522169689Skan#ifdef FLOAT_STORE_FLAG_VALUE 3523169689Skan { 3524169689Skan REAL_VALUE_TYPE val; 3525169689Skan val = FLOAT_STORE_FLAG_VALUE (mode); 3526169689Skan return CONST_DOUBLE_FROM_REAL_VALUE (val, mode); 3527169689Skan } 3528169689Skan#else 3529169689Skan return NULL_RTX; 3530169689Skan#endif 3531169689Skan } 3532169689Skan if (VECTOR_MODE_P (mode)) 3533169689Skan { 3534169689Skan if (tem == const0_rtx) 3535169689Skan return CONST0_RTX (mode); 3536169689Skan#ifdef VECTOR_STORE_FLAG_VALUE 3537169689Skan { 3538169689Skan int i, units; 3539169689Skan rtvec v; 3540169689Skan 3541169689Skan rtx val = VECTOR_STORE_FLAG_VALUE (mode); 3542169689Skan if (val == NULL_RTX) 3543169689Skan return NULL_RTX; 3544169689Skan if (val == const1_rtx) 3545169689Skan return CONST1_RTX (mode); 3546169689Skan 3547169689Skan units = GET_MODE_NUNITS (mode); 3548169689Skan v = rtvec_alloc (units); 3549169689Skan for (i = 0; i < units; i++) 3550169689Skan RTVEC_ELT (v, i) = val; 3551169689Skan return gen_rtx_raw_CONST_VECTOR (mode, v); 3552169689Skan } 3553169689Skan#else 3554169689Skan return NULL_RTX; 3555169689Skan#endif 3556169689Skan } 3557169689Skan 3558169689Skan return tem; 3559169689Skan } 3560169689Skan 3561169689Skan /* For the following tests, ensure const0_rtx is op1. */ 3562169689Skan if (swap_commutative_operands_p (op0, op1) 3563169689Skan || (op0 == const0_rtx && op1 != const0_rtx)) 3564169689Skan tem = op0, op0 = op1, op1 = tem, code = swap_condition (code); 3565169689Skan 3566169689Skan /* If op0 is a compare, extract the comparison arguments from it. */ 3567169689Skan if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) 3568169689Skan return simplify_relational_operation (code, mode, VOIDmode, 3569169689Skan XEXP (op0, 0), XEXP (op0, 1)); 3570169689Skan 3571169689Skan if (GET_MODE_CLASS (cmp_mode) == MODE_CC 3572169689Skan || CC0_P (op0)) 3573169689Skan return NULL_RTX; 3574169689Skan 3575169689Skan trueop0 = avoid_constant_pool_reference (op0); 3576169689Skan trueop1 = avoid_constant_pool_reference (op1); 3577169689Skan return simplify_relational_operation_1 (code, mode, cmp_mode, 3578169689Skan trueop0, trueop1); 3579169689Skan} 3580169689Skan 3581169689Skan/* This part of simplify_relational_operation is only used when CMP_MODE 3582169689Skan is not in class MODE_CC (i.e. it is a real comparison). 3583169689Skan 3584169689Skan MODE is the mode of the result, while CMP_MODE specifies in which 3585169689Skan mode the comparison is done in, so it is the mode of the operands. */ 3586169689Skan 3587169689Skanstatic rtx 3588169689Skansimplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode, 3589169689Skan enum machine_mode cmp_mode, rtx op0, rtx op1) 3590169689Skan{ 3591169689Skan enum rtx_code op0code = GET_CODE (op0); 3592169689Skan 3593169689Skan if (GET_CODE (op1) == CONST_INT) 3594169689Skan { 3595169689Skan if (INTVAL (op1) == 0 && COMPARISON_P (op0)) 3596169689Skan { 3597169689Skan /* If op0 is a comparison, extract the comparison arguments 3598169689Skan from it. */ 3599169689Skan if (code == NE) 3600169689Skan { 3601169689Skan if (GET_MODE (op0) == mode) 3602169689Skan return simplify_rtx (op0); 3603169689Skan else 3604169689Skan return simplify_gen_relational (GET_CODE (op0), mode, VOIDmode, 3605169689Skan XEXP (op0, 0), XEXP (op0, 1)); 3606169689Skan } 3607169689Skan else if (code == EQ) 3608169689Skan { 3609169689Skan enum rtx_code new_code = reversed_comparison_code (op0, NULL_RTX); 3610169689Skan if (new_code != UNKNOWN) 3611169689Skan return simplify_gen_relational (new_code, mode, VOIDmode, 3612169689Skan XEXP (op0, 0), XEXP (op0, 1)); 3613169689Skan } 3614169689Skan } 3615169689Skan } 3616169689Skan 3617169689Skan /* (eq/ne (plus x cst1) cst2) simplifies to (eq/ne x (cst2 - cst1)) */ 3618169689Skan if ((code == EQ || code == NE) 3619169689Skan && (op0code == PLUS || op0code == MINUS) 3620169689Skan && CONSTANT_P (op1) 3621169689Skan && CONSTANT_P (XEXP (op0, 1)) 3622169689Skan && (INTEGRAL_MODE_P (cmp_mode) || flag_unsafe_math_optimizations)) 3623169689Skan { 3624169689Skan rtx x = XEXP (op0, 0); 3625169689Skan rtx c = XEXP (op0, 1); 3626169689Skan 3627169689Skan c = simplify_gen_binary (op0code == PLUS ? MINUS : PLUS, 3628169689Skan cmp_mode, op1, c); 3629169689Skan return simplify_gen_relational (code, mode, cmp_mode, x, c); 3630169689Skan } 3631169689Skan 3632169689Skan /* (ne:SI (zero_extract:SI FOO (const_int 1) BAR) (const_int 0))) is 3633169689Skan the same as (zero_extract:SI FOO (const_int 1) BAR). */ 3634169689Skan if (code == NE 3635169689Skan && op1 == const0_rtx 3636169689Skan && GET_MODE_CLASS (mode) == MODE_INT 3637169689Skan && cmp_mode != VOIDmode 3638169689Skan /* ??? Work-around BImode bugs in the ia64 backend. */ 3639169689Skan && mode != BImode 3640169689Skan && cmp_mode != BImode 3641169689Skan && nonzero_bits (op0, cmp_mode) == 1 3642169689Skan && STORE_FLAG_VALUE == 1) 3643169689Skan return GET_MODE_SIZE (mode) > GET_MODE_SIZE (cmp_mode) 3644169689Skan ? simplify_gen_unary (ZERO_EXTEND, mode, op0, cmp_mode) 3645169689Skan : lowpart_subreg (mode, op0, cmp_mode); 3646169689Skan 3647169689Skan /* (eq/ne (xor x y) 0) simplifies to (eq/ne x y). */ 3648169689Skan if ((code == EQ || code == NE) 3649169689Skan && op1 == const0_rtx 3650169689Skan && op0code == XOR) 3651169689Skan return simplify_gen_relational (code, mode, cmp_mode, 3652169689Skan XEXP (op0, 0), XEXP (op0, 1)); 3653169689Skan 3654169689Skan /* (eq/ne (xor x y) x) simplifies to (eq/ne y 0). */ 3655169689Skan if ((code == EQ || code == NE) 3656169689Skan && op0code == XOR 3657169689Skan && rtx_equal_p (XEXP (op0, 0), op1) 3658169689Skan && !side_effects_p (XEXP (op0, 0))) 3659169689Skan return simplify_gen_relational (code, mode, cmp_mode, 3660169689Skan XEXP (op0, 1), const0_rtx); 3661169689Skan 3662169689Skan /* Likewise (eq/ne (xor x y) y) simplifies to (eq/ne x 0). */ 3663169689Skan if ((code == EQ || code == NE) 3664169689Skan && op0code == XOR 3665169689Skan && rtx_equal_p (XEXP (op0, 1), op1) 3666169689Skan && !side_effects_p (XEXP (op0, 1))) 3667169689Skan return simplify_gen_relational (code, mode, cmp_mode, 3668169689Skan XEXP (op0, 0), const0_rtx); 3669169689Skan 3670169689Skan /* (eq/ne (xor x C1) C2) simplifies to (eq/ne x (C1^C2)). */ 3671169689Skan if ((code == EQ || code == NE) 3672169689Skan && op0code == XOR 3673169689Skan && (GET_CODE (op1) == CONST_INT 3674169689Skan || GET_CODE (op1) == CONST_DOUBLE) 3675169689Skan && (GET_CODE (XEXP (op0, 1)) == CONST_INT 3676169689Skan || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE)) 3677169689Skan return simplify_gen_relational (code, mode, cmp_mode, XEXP (op0, 0), 3678169689Skan simplify_gen_binary (XOR, cmp_mode, 3679169689Skan XEXP (op0, 1), op1)); 3680169689Skan 3681169689Skan return NULL_RTX; 3682169689Skan} 3683169689Skan 3684169689Skan/* Check if the given comparison (done in the given MODE) is actually a 3685169689Skan tautology or a contradiction. 3686169689Skan If no simplification is possible, this function returns zero. 3687169689Skan Otherwise, it returns either const_true_rtx or const0_rtx. */ 3688169689Skan 3689169689Skanrtx 3690169689Skansimplify_const_relational_operation (enum rtx_code code, 3691169689Skan enum machine_mode mode, 3692169689Skan rtx op0, rtx op1) 3693169689Skan{ 369490075Sobrien int equal, op0lt, op0ltu, op1lt, op1ltu; 369590075Sobrien rtx tem; 369690075Sobrien rtx trueop0; 369790075Sobrien rtx trueop1; 369890075Sobrien 3699169689Skan gcc_assert (mode != VOIDmode 3700169689Skan || (GET_MODE (op0) == VOIDmode 3701169689Skan && GET_MODE (op1) == VOIDmode)); 370290075Sobrien 370390075Sobrien /* If op0 is a compare, extract the comparison arguments from it. */ 370490075Sobrien if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) 3705169689Skan { 3706169689Skan op1 = XEXP (op0, 1); 3707169689Skan op0 = XEXP (op0, 0); 370890075Sobrien 3709169689Skan if (GET_MODE (op0) != VOIDmode) 3710169689Skan mode = GET_MODE (op0); 3711169689Skan else if (GET_MODE (op1) != VOIDmode) 3712169689Skan mode = GET_MODE (op1); 3713169689Skan else 3714169689Skan return 0; 3715169689Skan } 371690075Sobrien 371790075Sobrien /* We can't simplify MODE_CC values since we don't know what the 371890075Sobrien actual comparison is. */ 3719132718Skan if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC || CC0_P (op0)) 372090075Sobrien return 0; 372190075Sobrien 372290075Sobrien /* Make sure the constant is second. */ 3723169689Skan if (swap_commutative_operands_p (op0, op1)) 372490075Sobrien { 372590075Sobrien tem = op0, op0 = op1, op1 = tem; 372690075Sobrien code = swap_condition (code); 372790075Sobrien } 372890075Sobrien 3729169689Skan trueop0 = avoid_constant_pool_reference (op0); 3730169689Skan trueop1 = avoid_constant_pool_reference (op1); 3731169689Skan 373290075Sobrien /* For integer comparisons of A and B maybe we can simplify A - B and can 373390075Sobrien then simplify a comparison of that with zero. If A and B are both either 373490075Sobrien a register or a CONST_INT, this can't help; testing for these cases will 373590075Sobrien prevent infinite recursion here and speed things up. 373690075Sobrien 3737169689Skan We can only do this for EQ and NE comparisons as otherwise we may 3738169689Skan lose or introduce overflow which we cannot disregard as undefined as 3739169689Skan we do not know the signedness of the operation on either the left or 3740169689Skan the right hand side of the comparison. */ 374190075Sobrien 374290075Sobrien if (INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx 3743169689Skan && (code == EQ || code == NE) 3744169689Skan && ! ((REG_P (op0) || GET_CODE (trueop0) == CONST_INT) 3745169689Skan && (REG_P (op1) || GET_CODE (trueop1) == CONST_INT)) 374690075Sobrien && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1)) 3747169689Skan /* We cannot do this if tem is a nonzero address. */ 3748169689Skan && ! nonzero_address_p (tem)) 3749169689Skan return simplify_const_relational_operation (signed_condition (code), 3750169689Skan mode, tem, const0_rtx); 375190075Sobrien 3752169689Skan if (! HONOR_NANS (mode) && code == ORDERED) 375390075Sobrien return const_true_rtx; 375490075Sobrien 3755169689Skan if (! HONOR_NANS (mode) && code == UNORDERED) 375690075Sobrien return const0_rtx; 375790075Sobrien 3758117395Skan /* For modes without NaNs, if the two operands are equal, we know the 3759132718Skan result except if they have side-effects. */ 3760132718Skan if (! HONOR_NANS (GET_MODE (trueop0)) 3761117395Skan && rtx_equal_p (trueop0, trueop1) 3762117395Skan && ! side_effects_p (trueop0)) 376390075Sobrien equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0; 376490075Sobrien 376590075Sobrien /* If the operands are floating-point constants, see if we can fold 376690075Sobrien the result. */ 376790075Sobrien else if (GET_CODE (trueop0) == CONST_DOUBLE 376890075Sobrien && GET_CODE (trueop1) == CONST_DOUBLE 3769169689Skan && SCALAR_FLOAT_MODE_P (GET_MODE (trueop0))) 377090075Sobrien { 3771117395Skan REAL_VALUE_TYPE d0, d1; 377290075Sobrien 3773117395Skan REAL_VALUE_FROM_CONST_DOUBLE (d0, trueop0); 3774117395Skan REAL_VALUE_FROM_CONST_DOUBLE (d1, trueop1); 377590075Sobrien 3776117395Skan /* Comparisons are unordered iff at least one of the values is NaN. */ 3777117395Skan if (REAL_VALUE_ISNAN (d0) || REAL_VALUE_ISNAN (d1)) 377890075Sobrien switch (code) 377990075Sobrien { 378090075Sobrien case UNEQ: 378190075Sobrien case UNLT: 378290075Sobrien case UNGT: 378390075Sobrien case UNLE: 378490075Sobrien case UNGE: 378590075Sobrien case NE: 378690075Sobrien case UNORDERED: 378790075Sobrien return const_true_rtx; 378890075Sobrien case EQ: 378990075Sobrien case LT: 379090075Sobrien case GT: 379190075Sobrien case LE: 379290075Sobrien case GE: 379390075Sobrien case LTGT: 379490075Sobrien case ORDERED: 379590075Sobrien return const0_rtx; 379690075Sobrien default: 379790075Sobrien return 0; 379890075Sobrien } 379990075Sobrien 3800117395Skan equal = REAL_VALUES_EQUAL (d0, d1); 3801117395Skan op0lt = op0ltu = REAL_VALUES_LESS (d0, d1); 3802117395Skan op1lt = op1ltu = REAL_VALUES_LESS (d1, d0); 380390075Sobrien } 380490075Sobrien 380590075Sobrien /* Otherwise, see if the operands are both integers. */ 380690075Sobrien else if ((GET_MODE_CLASS (mode) == MODE_INT || mode == VOIDmode) 380790075Sobrien && (GET_CODE (trueop0) == CONST_DOUBLE 380890075Sobrien || GET_CODE (trueop0) == CONST_INT) 380990075Sobrien && (GET_CODE (trueop1) == CONST_DOUBLE 381090075Sobrien || GET_CODE (trueop1) == CONST_INT)) 381190075Sobrien { 381290075Sobrien int width = GET_MODE_BITSIZE (mode); 381390075Sobrien HOST_WIDE_INT l0s, h0s, l1s, h1s; 381490075Sobrien unsigned HOST_WIDE_INT l0u, h0u, l1u, h1u; 381590075Sobrien 381690075Sobrien /* Get the two words comprising each integer constant. */ 381790075Sobrien if (GET_CODE (trueop0) == CONST_DOUBLE) 381890075Sobrien { 381990075Sobrien l0u = l0s = CONST_DOUBLE_LOW (trueop0); 382090075Sobrien h0u = h0s = CONST_DOUBLE_HIGH (trueop0); 382190075Sobrien } 382290075Sobrien else 382390075Sobrien { 382490075Sobrien l0u = l0s = INTVAL (trueop0); 382590075Sobrien h0u = h0s = HWI_SIGN_EXTEND (l0s); 382690075Sobrien } 3827117395Skan 382890075Sobrien if (GET_CODE (trueop1) == CONST_DOUBLE) 382990075Sobrien { 383090075Sobrien l1u = l1s = CONST_DOUBLE_LOW (trueop1); 383190075Sobrien h1u = h1s = CONST_DOUBLE_HIGH (trueop1); 383290075Sobrien } 383390075Sobrien else 383490075Sobrien { 383590075Sobrien l1u = l1s = INTVAL (trueop1); 383690075Sobrien h1u = h1s = HWI_SIGN_EXTEND (l1s); 383790075Sobrien } 383890075Sobrien 383990075Sobrien /* If WIDTH is nonzero and smaller than HOST_BITS_PER_WIDE_INT, 384090075Sobrien we have to sign or zero-extend the values. */ 384190075Sobrien if (width != 0 && width < HOST_BITS_PER_WIDE_INT) 384290075Sobrien { 384390075Sobrien l0u &= ((HOST_WIDE_INT) 1 << width) - 1; 384490075Sobrien l1u &= ((HOST_WIDE_INT) 1 << width) - 1; 384590075Sobrien 384690075Sobrien if (l0s & ((HOST_WIDE_INT) 1 << (width - 1))) 384790075Sobrien l0s |= ((HOST_WIDE_INT) (-1) << width); 384890075Sobrien 384990075Sobrien if (l1s & ((HOST_WIDE_INT) 1 << (width - 1))) 385090075Sobrien l1s |= ((HOST_WIDE_INT) (-1) << width); 385190075Sobrien } 385290075Sobrien if (width != 0 && width <= HOST_BITS_PER_WIDE_INT) 385390075Sobrien h0u = h1u = 0, h0s = HWI_SIGN_EXTEND (l0s), h1s = HWI_SIGN_EXTEND (l1s); 385490075Sobrien 385590075Sobrien equal = (h0u == h1u && l0u == l1u); 385690075Sobrien op0lt = (h0s < h1s || (h0s == h1s && l0u < l1u)); 385790075Sobrien op1lt = (h1s < h0s || (h1s == h0s && l1u < l0u)); 385890075Sobrien op0ltu = (h0u < h1u || (h0u == h1u && l0u < l1u)); 385990075Sobrien op1ltu = (h1u < h0u || (h1u == h0u && l1u < l0u)); 386090075Sobrien } 386190075Sobrien 386290075Sobrien /* Otherwise, there are some code-specific tests we can make. */ 386390075Sobrien else 386490075Sobrien { 3865169689Skan /* Optimize comparisons with upper and lower bounds. */ 3866169689Skan if (SCALAR_INT_MODE_P (mode) 3867169689Skan && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) 3868169689Skan { 3869169689Skan rtx mmin, mmax; 3870169689Skan int sign; 3871169689Skan 3872169689Skan if (code == GEU 3873169689Skan || code == LEU 3874169689Skan || code == GTU 3875169689Skan || code == LTU) 3876169689Skan sign = 0; 3877169689Skan else 3878169689Skan sign = 1; 3879169689Skan 3880169689Skan get_mode_bounds (mode, sign, mode, &mmin, &mmax); 3881169689Skan 3882169689Skan tem = NULL_RTX; 3883169689Skan switch (code) 3884169689Skan { 3885169689Skan case GEU: 3886169689Skan case GE: 3887169689Skan /* x >= min is always true. */ 3888169689Skan if (rtx_equal_p (trueop1, mmin)) 3889169689Skan tem = const_true_rtx; 3890169689Skan else 3891169689Skan break; 3892169689Skan 3893169689Skan case LEU: 3894169689Skan case LE: 3895169689Skan /* x <= max is always true. */ 3896169689Skan if (rtx_equal_p (trueop1, mmax)) 3897169689Skan tem = const_true_rtx; 3898169689Skan break; 3899169689Skan 3900169689Skan case GTU: 3901169689Skan case GT: 3902169689Skan /* x > max is always false. */ 3903169689Skan if (rtx_equal_p (trueop1, mmax)) 3904169689Skan tem = const0_rtx; 3905169689Skan break; 3906169689Skan 3907169689Skan case LTU: 3908169689Skan case LT: 3909169689Skan /* x < min is always false. */ 3910169689Skan if (rtx_equal_p (trueop1, mmin)) 3911169689Skan tem = const0_rtx; 3912169689Skan break; 3913169689Skan 3914169689Skan default: 3915169689Skan break; 3916169689Skan } 3917169689Skan if (tem == const0_rtx 3918169689Skan || tem == const_true_rtx) 3919169689Skan return tem; 3920169689Skan } 3921169689Skan 392290075Sobrien switch (code) 392390075Sobrien { 392490075Sobrien case EQ: 3925132718Skan if (trueop1 == const0_rtx && nonzero_address_p (op0)) 392690075Sobrien return const0_rtx; 392790075Sobrien break; 392890075Sobrien 392990075Sobrien case NE: 3930132718Skan if (trueop1 == const0_rtx && nonzero_address_p (op0)) 393190075Sobrien return const_true_rtx; 393290075Sobrien break; 393390075Sobrien 3934117395Skan case LT: 3935117395Skan /* Optimize abs(x) < 0.0. */ 3936169689Skan if (trueop1 == CONST0_RTX (mode) 3937169689Skan && !HONOR_SNANS (mode) 3938169689Skan && (!INTEGRAL_MODE_P (mode) 3939169689Skan || (!flag_wrapv && !flag_trapv && flag_strict_overflow))) 3940117395Skan { 3941117395Skan tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0) 3942117395Skan : trueop0; 3943117395Skan if (GET_CODE (tem) == ABS) 3944169689Skan { 3945169689Skan if (INTEGRAL_MODE_P (mode) 3946169689Skan && (issue_strict_overflow_warning 3947169689Skan (WARN_STRICT_OVERFLOW_CONDITIONAL))) 3948169689Skan warning (OPT_Wstrict_overflow, 3949169689Skan ("assuming signed overflow does not occur when " 3950169689Skan "assuming abs (x) < 0 is false")); 3951169689Skan return const0_rtx; 3952169689Skan } 3953117395Skan } 3954117395Skan break; 3955117395Skan 3956117395Skan case GE: 3957117395Skan /* Optimize abs(x) >= 0.0. */ 3958169689Skan if (trueop1 == CONST0_RTX (mode) 3959169689Skan && !HONOR_NANS (mode) 3960169689Skan && (!INTEGRAL_MODE_P (mode) 3961169689Skan || (!flag_wrapv && !flag_trapv && flag_strict_overflow))) 3962117395Skan { 3963117395Skan tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0) 3964117395Skan : trueop0; 3965117395Skan if (GET_CODE (tem) == ABS) 3966169689Skan { 3967169689Skan if (INTEGRAL_MODE_P (mode) 3968169689Skan && (issue_strict_overflow_warning 3969169689Skan (WARN_STRICT_OVERFLOW_CONDITIONAL))) 3970169689Skan warning (OPT_Wstrict_overflow, 3971169689Skan ("assuming signed overflow does not occur when " 3972169689Skan "assuming abs (x) >= 0 is true")); 3973169689Skan return const_true_rtx; 3974169689Skan } 3975117395Skan } 3976117395Skan break; 3977117395Skan 3978132718Skan case UNGE: 3979132718Skan /* Optimize ! (abs(x) < 0.0). */ 3980132718Skan if (trueop1 == CONST0_RTX (mode)) 3981132718Skan { 3982132718Skan tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0) 3983132718Skan : trueop0; 3984132718Skan if (GET_CODE (tem) == ABS) 3985132718Skan return const_true_rtx; 3986132718Skan } 3987132718Skan break; 3988132718Skan 398990075Sobrien default: 399090075Sobrien break; 399190075Sobrien } 399290075Sobrien 399390075Sobrien return 0; 399490075Sobrien } 399590075Sobrien 399690075Sobrien /* If we reach here, EQUAL, OP0LT, OP0LTU, OP1LT, and OP1LTU are set 399790075Sobrien as appropriate. */ 399890075Sobrien switch (code) 399990075Sobrien { 400090075Sobrien case EQ: 400190075Sobrien case UNEQ: 400290075Sobrien return equal ? const_true_rtx : const0_rtx; 400390075Sobrien case NE: 400490075Sobrien case LTGT: 400590075Sobrien return ! equal ? const_true_rtx : const0_rtx; 400690075Sobrien case LT: 400790075Sobrien case UNLT: 400890075Sobrien return op0lt ? const_true_rtx : const0_rtx; 400990075Sobrien case GT: 401090075Sobrien case UNGT: 401190075Sobrien return op1lt ? const_true_rtx : const0_rtx; 401290075Sobrien case LTU: 401390075Sobrien return op0ltu ? const_true_rtx : const0_rtx; 401490075Sobrien case GTU: 401590075Sobrien return op1ltu ? const_true_rtx : const0_rtx; 401690075Sobrien case LE: 401790075Sobrien case UNLE: 401890075Sobrien return equal || op0lt ? const_true_rtx : const0_rtx; 401990075Sobrien case GE: 402090075Sobrien case UNGE: 402190075Sobrien return equal || op1lt ? const_true_rtx : const0_rtx; 402290075Sobrien case LEU: 402390075Sobrien return equal || op0ltu ? const_true_rtx : const0_rtx; 402490075Sobrien case GEU: 402590075Sobrien return equal || op1ltu ? const_true_rtx : const0_rtx; 402690075Sobrien case ORDERED: 402790075Sobrien return const_true_rtx; 402890075Sobrien case UNORDERED: 402990075Sobrien return const0_rtx; 403090075Sobrien default: 4031169689Skan gcc_unreachable (); 403290075Sobrien } 403390075Sobrien} 403490075Sobrien 403590075Sobrien/* Simplify CODE, an operation with result mode MODE and three operands, 403690075Sobrien OP0, OP1, and OP2. OP0_MODE was the mode of OP0 before it became 403790075Sobrien a constant. Return 0 if no simplifications is possible. */ 403890075Sobrien 403990075Sobrienrtx 4040132718Skansimplify_ternary_operation (enum rtx_code code, enum machine_mode mode, 4041132718Skan enum machine_mode op0_mode, rtx op0, rtx op1, 4042132718Skan rtx op2) 404390075Sobrien{ 404490075Sobrien unsigned int width = GET_MODE_BITSIZE (mode); 404590075Sobrien 404690075Sobrien /* VOIDmode means "infinite" precision. */ 404790075Sobrien if (width == 0) 404890075Sobrien width = HOST_BITS_PER_WIDE_INT; 404990075Sobrien 405090075Sobrien switch (code) 405190075Sobrien { 405290075Sobrien case SIGN_EXTRACT: 405390075Sobrien case ZERO_EXTRACT: 405490075Sobrien if (GET_CODE (op0) == CONST_INT 405590075Sobrien && GET_CODE (op1) == CONST_INT 405690075Sobrien && GET_CODE (op2) == CONST_INT 405790075Sobrien && ((unsigned) INTVAL (op1) + (unsigned) INTVAL (op2) <= width) 405890075Sobrien && width <= (unsigned) HOST_BITS_PER_WIDE_INT) 405990075Sobrien { 406090075Sobrien /* Extracting a bit-field from a constant */ 406190075Sobrien HOST_WIDE_INT val = INTVAL (op0); 406290075Sobrien 406390075Sobrien if (BITS_BIG_ENDIAN) 406490075Sobrien val >>= (GET_MODE_BITSIZE (op0_mode) 406590075Sobrien - INTVAL (op2) - INTVAL (op1)); 406690075Sobrien else 406790075Sobrien val >>= INTVAL (op2); 406890075Sobrien 406990075Sobrien if (HOST_BITS_PER_WIDE_INT != INTVAL (op1)) 407090075Sobrien { 407190075Sobrien /* First zero-extend. */ 407290075Sobrien val &= ((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1; 407390075Sobrien /* If desired, propagate sign bit. */ 407490075Sobrien if (code == SIGN_EXTRACT 407590075Sobrien && (val & ((HOST_WIDE_INT) 1 << (INTVAL (op1) - 1)))) 407690075Sobrien val |= ~ (((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1); 407790075Sobrien } 407890075Sobrien 407990075Sobrien /* Clear the bits that don't belong in our mode, 408090075Sobrien unless they and our sign bit are all one. 408190075Sobrien So we get either a reasonable negative value or a reasonable 408290075Sobrien unsigned value for this mode. */ 408390075Sobrien if (width < HOST_BITS_PER_WIDE_INT 408490075Sobrien && ((val & ((HOST_WIDE_INT) (-1) << (width - 1))) 408590075Sobrien != ((HOST_WIDE_INT) (-1) << (width - 1)))) 408690075Sobrien val &= ((HOST_WIDE_INT) 1 << width) - 1; 408790075Sobrien 4088169689Skan return gen_int_mode (val, mode); 408990075Sobrien } 409090075Sobrien break; 409190075Sobrien 409290075Sobrien case IF_THEN_ELSE: 409390075Sobrien if (GET_CODE (op0) == CONST_INT) 409490075Sobrien return op0 != const0_rtx ? op1 : op2; 409590075Sobrien 4096132718Skan /* Convert c ? a : a into "a". */ 4097132718Skan if (rtx_equal_p (op1, op2) && ! side_effects_p (op0)) 409890075Sobrien return op1; 4099132718Skan 4100132718Skan /* Convert a != b ? a : b into "a". */ 4101132718Skan if (GET_CODE (op0) == NE 4102132718Skan && ! side_effects_p (op0) 4103132718Skan && ! HONOR_NANS (mode) 4104132718Skan && ! HONOR_SIGNED_ZEROS (mode) 4105132718Skan && ((rtx_equal_p (XEXP (op0, 0), op1) 4106132718Skan && rtx_equal_p (XEXP (op0, 1), op2)) 4107132718Skan || (rtx_equal_p (XEXP (op0, 0), op2) 4108132718Skan && rtx_equal_p (XEXP (op0, 1), op1)))) 4109132718Skan return op1; 4110132718Skan 4111132718Skan /* Convert a == b ? a : b into "b". */ 4112132718Skan if (GET_CODE (op0) == EQ 4113132718Skan && ! side_effects_p (op0) 4114132718Skan && ! HONOR_NANS (mode) 4115132718Skan && ! HONOR_SIGNED_ZEROS (mode) 4116132718Skan && ((rtx_equal_p (XEXP (op0, 0), op1) 4117132718Skan && rtx_equal_p (XEXP (op0, 1), op2)) 4118132718Skan || (rtx_equal_p (XEXP (op0, 0), op2) 4119132718Skan && rtx_equal_p (XEXP (op0, 1), op1)))) 412090075Sobrien return op2; 4121132718Skan 4122169689Skan if (COMPARISON_P (op0) && ! side_effects_p (op0)) 412390075Sobrien { 412490075Sobrien enum machine_mode cmp_mode = (GET_MODE (XEXP (op0, 0)) == VOIDmode 412590075Sobrien ? GET_MODE (XEXP (op0, 1)) 412690075Sobrien : GET_MODE (XEXP (op0, 0))); 412790075Sobrien rtx temp; 412890075Sobrien 412990075Sobrien /* Look for happy constants in op1 and op2. */ 413090075Sobrien if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT) 413190075Sobrien { 413290075Sobrien HOST_WIDE_INT t = INTVAL (op1); 413390075Sobrien HOST_WIDE_INT f = INTVAL (op2); 4134117395Skan 413590075Sobrien if (t == STORE_FLAG_VALUE && f == 0) 413690075Sobrien code = GET_CODE (op0); 413790075Sobrien else if (t == 0 && f == STORE_FLAG_VALUE) 413890075Sobrien { 413990075Sobrien enum rtx_code tmp; 414090075Sobrien tmp = reversed_comparison_code (op0, NULL_RTX); 414190075Sobrien if (tmp == UNKNOWN) 414290075Sobrien break; 414390075Sobrien code = tmp; 414490075Sobrien } 414590075Sobrien else 414690075Sobrien break; 414790075Sobrien 4148169689Skan return simplify_gen_relational (code, mode, cmp_mode, 4149169689Skan XEXP (op0, 0), XEXP (op0, 1)); 415090075Sobrien } 4151169689Skan 4152169689Skan if (cmp_mode == VOIDmode) 4153169689Skan cmp_mode = op0_mode; 4154169689Skan temp = simplify_relational_operation (GET_CODE (op0), op0_mode, 4155169689Skan cmp_mode, XEXP (op0, 0), 4156169689Skan XEXP (op0, 1)); 4157169689Skan 4158169689Skan /* See if any simplifications were possible. */ 4159169689Skan if (temp) 4160169689Skan { 4161169689Skan if (GET_CODE (temp) == CONST_INT) 4162169689Skan return temp == const0_rtx ? op2 : op1; 4163169689Skan else if (temp) 4164169689Skan return gen_rtx_IF_THEN_ELSE (mode, temp, op1, op2); 4165169689Skan } 416690075Sobrien } 416790075Sobrien break; 4168132718Skan 4169117395Skan case VEC_MERGE: 4170169689Skan gcc_assert (GET_MODE (op0) == mode); 4171169689Skan gcc_assert (GET_MODE (op1) == mode); 4172169689Skan gcc_assert (VECTOR_MODE_P (mode)); 4173117395Skan op2 = avoid_constant_pool_reference (op2); 4174132718Skan if (GET_CODE (op2) == CONST_INT) 4175117395Skan { 4176117395Skan int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); 4177117395Skan unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); 4178132718Skan int mask = (1 << n_elts) - 1; 417990075Sobrien 4180132718Skan if (!(INTVAL (op2) & mask)) 4181132718Skan return op1; 4182132718Skan if ((INTVAL (op2) & mask) == mask) 4183132718Skan return op0; 4184132718Skan 4185132718Skan op0 = avoid_constant_pool_reference (op0); 4186132718Skan op1 = avoid_constant_pool_reference (op1); 4187132718Skan if (GET_CODE (op0) == CONST_VECTOR 4188132718Skan && GET_CODE (op1) == CONST_VECTOR) 4189132718Skan { 4190132718Skan rtvec v = rtvec_alloc (n_elts); 4191132718Skan unsigned int i; 4192132718Skan 4193132718Skan for (i = 0; i < n_elts; i++) 4194132718Skan RTVEC_ELT (v, i) = (INTVAL (op2) & (1 << i) 4195132718Skan ? CONST_VECTOR_ELT (op0, i) 4196132718Skan : CONST_VECTOR_ELT (op1, i)); 4197132718Skan return gen_rtx_CONST_VECTOR (mode, v); 4198132718Skan } 4199117395Skan } 4200117395Skan break; 4201117395Skan 420290075Sobrien default: 4203169689Skan gcc_unreachable (); 420490075Sobrien } 420590075Sobrien 420690075Sobrien return 0; 420790075Sobrien} 420890075Sobrien 4209132718Skan/* Evaluate a SUBREG of a CONST_INT or CONST_DOUBLE or CONST_VECTOR, 4210132718Skan returning another CONST_INT or CONST_DOUBLE or CONST_VECTOR. 4211132718Skan 4212132718Skan Works by unpacking OP into a collection of 8-bit values 4213132718Skan represented as a little-endian array of 'unsigned char', selecting by BYTE, 4214132718Skan and then repacking them again for OUTERMODE. */ 4215132718Skan 4216132718Skanstatic rtx 4217132718Skansimplify_immed_subreg (enum machine_mode outermode, rtx op, 4218132718Skan enum machine_mode innermode, unsigned int byte) 421990075Sobrien{ 4220132718Skan /* We support up to 512-bit values (for V8DFmode). */ 4221132718Skan enum { 4222132718Skan max_bitsize = 512, 4223132718Skan value_bit = 8, 4224132718Skan value_mask = (1 << value_bit) - 1 4225132718Skan }; 4226132718Skan unsigned char value[max_bitsize / value_bit]; 4227132718Skan int value_start; 4228132718Skan int i; 4229132718Skan int elem; 423090075Sobrien 4231132718Skan int num_elem; 4232132718Skan rtx * elems; 4233132718Skan int elem_bitsize; 4234132718Skan rtx result_s; 4235132718Skan rtvec result_v = NULL; 4236132718Skan enum mode_class outer_class; 4237132718Skan enum machine_mode outer_submode; 423890075Sobrien 4239132718Skan /* Some ports misuse CCmode. */ 4240132718Skan if (GET_MODE_CLASS (outermode) == MODE_CC && GET_CODE (op) == CONST_INT) 424190075Sobrien return op; 424290075Sobrien 4243169689Skan /* We have no way to represent a complex constant at the rtl level. */ 4244169689Skan if (COMPLEX_MODE_P (outermode)) 4245169689Skan return NULL_RTX; 4246169689Skan 4247132718Skan /* Unpack the value. */ 4248132718Skan 4249117395Skan if (GET_CODE (op) == CONST_VECTOR) 4250117395Skan { 4251132718Skan num_elem = CONST_VECTOR_NUNITS (op); 4252132718Skan elems = &CONST_VECTOR_ELT (op, 0); 4253132718Skan elem_bitsize = GET_MODE_BITSIZE (GET_MODE_INNER (innermode)); 4254132718Skan } 4255132718Skan else 4256132718Skan { 4257132718Skan num_elem = 1; 4258132718Skan elems = &op; 4259132718Skan elem_bitsize = max_bitsize; 4260132718Skan } 4261169689Skan /* If this asserts, it is too complicated; reducing value_bit may help. */ 4262169689Skan gcc_assert (BITS_PER_UNIT % value_bit == 0); 4263169689Skan /* I don't know how to handle endianness of sub-units. */ 4264169689Skan gcc_assert (elem_bitsize % BITS_PER_UNIT == 0); 4265132718Skan 4266132718Skan for (elem = 0; elem < num_elem; elem++) 4267132718Skan { 4268132718Skan unsigned char * vp; 4269132718Skan rtx el = elems[elem]; 4270132718Skan 4271132718Skan /* Vectors are kept in target memory order. (This is probably 4272132718Skan a mistake.) */ 4273132718Skan { 4274132718Skan unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT; 4275132718Skan unsigned ibyte = (((num_elem - 1 - elem) * elem_bitsize) 4276132718Skan / BITS_PER_UNIT); 4277132718Skan unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; 4278132718Skan unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; 4279132718Skan unsigned bytele = (subword_byte % UNITS_PER_WORD 4280132718Skan + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); 4281132718Skan vp = value + (bytele * BITS_PER_UNIT) / value_bit; 4282132718Skan } 4283132718Skan 4284132718Skan switch (GET_CODE (el)) 4285117395Skan { 4286132718Skan case CONST_INT: 4287132718Skan for (i = 0; 4288132718Skan i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize; 4289132718Skan i += value_bit) 4290132718Skan *vp++ = INTVAL (el) >> i; 4291132718Skan /* CONST_INTs are always logically sign-extended. */ 4292132718Skan for (; i < elem_bitsize; i += value_bit) 4293132718Skan *vp++ = INTVAL (el) < 0 ? -1 : 0; 4294132718Skan break; 4295132718Skan 4296132718Skan case CONST_DOUBLE: 4297132718Skan if (GET_MODE (el) == VOIDmode) 4298132718Skan { 4299132718Skan /* If this triggers, someone should have generated a 4300132718Skan CONST_INT instead. */ 4301169689Skan gcc_assert (elem_bitsize > HOST_BITS_PER_WIDE_INT); 4302117395Skan 4303132718Skan for (i = 0; i < HOST_BITS_PER_WIDE_INT; i += value_bit) 4304132718Skan *vp++ = CONST_DOUBLE_LOW (el) >> i; 4305132718Skan while (i < HOST_BITS_PER_WIDE_INT * 2 && i < elem_bitsize) 4306132718Skan { 4307132718Skan *vp++ 4308132718Skan = CONST_DOUBLE_HIGH (el) >> (i - HOST_BITS_PER_WIDE_INT); 4309132718Skan i += value_bit; 4310132718Skan } 4311132718Skan /* It shouldn't matter what's done here, so fill it with 4312132718Skan zero. */ 4313161651Skan for (; i < elem_bitsize; i += value_bit) 4314132718Skan *vp++ = 0; 4315132718Skan } 4316169689Skan else 4317132718Skan { 4318132718Skan long tmp[max_bitsize / 32]; 4319132718Skan int bitsize = GET_MODE_BITSIZE (GET_MODE (el)); 4320117395Skan 4321169689Skan gcc_assert (SCALAR_FLOAT_MODE_P (GET_MODE (el))); 4322169689Skan gcc_assert (bitsize <= elem_bitsize); 4323169689Skan gcc_assert (bitsize % value_bit == 0); 4324169689Skan 4325132718Skan real_to_target (tmp, CONST_DOUBLE_REAL_VALUE (el), 4326132718Skan GET_MODE (el)); 4327117395Skan 4328132718Skan /* real_to_target produces its result in words affected by 4329132718Skan FLOAT_WORDS_BIG_ENDIAN. However, we ignore this, 4330132718Skan and use WORDS_BIG_ENDIAN instead; see the documentation 4331132718Skan of SUBREG in rtl.texi. */ 4332132718Skan for (i = 0; i < bitsize; i += value_bit) 4333117395Skan { 4334132718Skan int ibase; 4335132718Skan if (WORDS_BIG_ENDIAN) 4336132718Skan ibase = bitsize - 1 - i; 4337132718Skan else 4338132718Skan ibase = i; 4339132718Skan *vp++ = tmp[ibase / 32] >> i % 32; 4340117395Skan } 4341132718Skan 4342132718Skan /* It shouldn't matter what's done here, so fill it with 4343132718Skan zero. */ 4344132718Skan for (; i < elem_bitsize; i += value_bit) 4345132718Skan *vp++ = 0; 4346117395Skan } 4347132718Skan break; 4348132718Skan 4349132718Skan default: 4350169689Skan gcc_unreachable (); 4351117395Skan } 4352117395Skan } 4353117395Skan 4354132718Skan /* Now, pick the right byte to start with. */ 4355132718Skan /* Renumber BYTE so that the least-significant byte is byte 0. A special 4356132718Skan case is paradoxical SUBREGs, which shouldn't be adjusted since they 4357132718Skan will already have offset 0. */ 4358132718Skan if (GET_MODE_SIZE (innermode) >= GET_MODE_SIZE (outermode)) 435990075Sobrien { 4360132718Skan unsigned ibyte = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode) 4361132718Skan - byte); 4362132718Skan unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; 4363132718Skan unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; 4364132718Skan byte = (subword_byte % UNITS_PER_WORD 4365132718Skan + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); 4366132718Skan } 436790075Sobrien 4368132718Skan /* BYTE should still be inside OP. (Note that BYTE is unsigned, 4369132718Skan so if it's become negative it will instead be very large.) */ 4370169689Skan gcc_assert (byte < GET_MODE_SIZE (innermode)); 4371117395Skan 4372132718Skan /* Convert from bytes to chunks of size value_bit. */ 4373132718Skan value_start = byte * (BITS_PER_UNIT / value_bit); 4374117395Skan 4375132718Skan /* Re-pack the value. */ 4376132718Skan 4377132718Skan if (VECTOR_MODE_P (outermode)) 4378132718Skan { 4379132718Skan num_elem = GET_MODE_NUNITS (outermode); 4380132718Skan result_v = rtvec_alloc (num_elem); 4381132718Skan elems = &RTVEC_ELT (result_v, 0); 4382132718Skan outer_submode = GET_MODE_INNER (outermode); 4383132718Skan } 4384132718Skan else 4385132718Skan { 4386132718Skan num_elem = 1; 4387132718Skan elems = &result_s; 4388132718Skan outer_submode = outermode; 4389132718Skan } 439090075Sobrien 4391132718Skan outer_class = GET_MODE_CLASS (outer_submode); 4392132718Skan elem_bitsize = GET_MODE_BITSIZE (outer_submode); 439390075Sobrien 4394169689Skan gcc_assert (elem_bitsize % value_bit == 0); 4395169689Skan gcc_assert (elem_bitsize + value_start * value_bit <= max_bitsize); 4396117395Skan 4397132718Skan for (elem = 0; elem < num_elem; elem++) 4398132718Skan { 4399132718Skan unsigned char *vp; 4400132718Skan 4401132718Skan /* Vectors are stored in target memory order. (This is probably 4402132718Skan a mistake.) */ 4403132718Skan { 4404132718Skan unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT; 4405132718Skan unsigned ibyte = (((num_elem - 1 - elem) * elem_bitsize) 4406132718Skan / BITS_PER_UNIT); 4407132718Skan unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; 4408132718Skan unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; 4409132718Skan unsigned bytele = (subword_byte % UNITS_PER_WORD 4410132718Skan + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); 4411132718Skan vp = value + value_start + (bytele * BITS_PER_UNIT) / value_bit; 4412132718Skan } 4413117395Skan 4414132718Skan switch (outer_class) 441590075Sobrien { 4416132718Skan case MODE_INT: 4417132718Skan case MODE_PARTIAL_INT: 4418132718Skan { 4419132718Skan unsigned HOST_WIDE_INT hi = 0, lo = 0; 442090075Sobrien 4421132718Skan for (i = 0; 4422132718Skan i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize; 4423132718Skan i += value_bit) 4424132718Skan lo |= (HOST_WIDE_INT)(*vp++ & value_mask) << i; 4425132718Skan for (; i < elem_bitsize; i += value_bit) 4426132718Skan hi |= ((HOST_WIDE_INT)(*vp++ & value_mask) 4427132718Skan << (i - HOST_BITS_PER_WIDE_INT)); 4428132718Skan 4429132718Skan /* immed_double_const doesn't call trunc_int_for_mode. I don't 4430132718Skan know why. */ 4431132718Skan if (elem_bitsize <= HOST_BITS_PER_WIDE_INT) 4432132718Skan elems[elem] = gen_int_mode (lo, outer_submode); 4433169689Skan else if (elem_bitsize <= 2 * HOST_BITS_PER_WIDE_INT) 4434169689Skan elems[elem] = immed_double_const (lo, hi, outer_submode); 4435132718Skan else 4436169689Skan return NULL_RTX; 4437132718Skan } 4438132718Skan break; 4439132718Skan 4440132718Skan case MODE_FLOAT: 4441169689Skan case MODE_DECIMAL_FLOAT: 4442132718Skan { 4443132718Skan REAL_VALUE_TYPE r; 4444132718Skan long tmp[max_bitsize / 32]; 4445132718Skan 4446132718Skan /* real_from_target wants its input in words affected by 4447132718Skan FLOAT_WORDS_BIG_ENDIAN. However, we ignore this, 4448132718Skan and use WORDS_BIG_ENDIAN instead; see the documentation 4449132718Skan of SUBREG in rtl.texi. */ 4450132718Skan for (i = 0; i < max_bitsize / 32; i++) 4451132718Skan tmp[i] = 0; 4452132718Skan for (i = 0; i < elem_bitsize; i += value_bit) 4453132718Skan { 4454132718Skan int ibase; 4455132718Skan if (WORDS_BIG_ENDIAN) 4456132718Skan ibase = elem_bitsize - 1 - i; 4457132718Skan else 4458132718Skan ibase = i; 4459132718Skan tmp[ibase / 32] |= (*vp++ & value_mask) << i % 32; 4460132718Skan } 446190075Sobrien 4462132718Skan real_from_target (&r, tmp, outer_submode); 4463132718Skan elems[elem] = CONST_DOUBLE_FROM_REAL_VALUE (r, outer_submode); 4464132718Skan } 4465132718Skan break; 4466132718Skan 4467132718Skan default: 4468169689Skan gcc_unreachable (); 4469132718Skan } 4470132718Skan } 4471132718Skan if (VECTOR_MODE_P (outermode)) 4472132718Skan return gen_rtx_CONST_VECTOR (outermode, result_v); 4473132718Skan else 4474132718Skan return result_s; 4475132718Skan} 447690075Sobrien 4477132718Skan/* Simplify SUBREG:OUTERMODE(OP:INNERMODE, BYTE) 4478132718Skan Return 0 if no simplifications are possible. */ 4479132718Skanrtx 4480132718Skansimplify_subreg (enum machine_mode outermode, rtx op, 4481132718Skan enum machine_mode innermode, unsigned int byte) 4482132718Skan{ 4483132718Skan /* Little bit of sanity checking. */ 4484169689Skan gcc_assert (innermode != VOIDmode); 4485169689Skan gcc_assert (outermode != VOIDmode); 4486169689Skan gcc_assert (innermode != BLKmode); 4487169689Skan gcc_assert (outermode != BLKmode); 448890075Sobrien 4489169689Skan gcc_assert (GET_MODE (op) == innermode 4490169689Skan || GET_MODE (op) == VOIDmode); 449190075Sobrien 4492169689Skan gcc_assert ((byte % GET_MODE_SIZE (outermode)) == 0); 4493169689Skan gcc_assert (byte < GET_MODE_SIZE (innermode)); 449490075Sobrien 4495132718Skan if (outermode == innermode && !byte) 4496132718Skan return op; 449790075Sobrien 4498132718Skan if (GET_CODE (op) == CONST_INT 4499132718Skan || GET_CODE (op) == CONST_DOUBLE 4500132718Skan || GET_CODE (op) == CONST_VECTOR) 4501132718Skan return simplify_immed_subreg (outermode, op, innermode, byte); 450290075Sobrien 450390075Sobrien /* Changing mode twice with SUBREG => just change it once, 450490075Sobrien or not at all if changing back op starting mode. */ 450590075Sobrien if (GET_CODE (op) == SUBREG) 450690075Sobrien { 450790075Sobrien enum machine_mode innermostmode = GET_MODE (SUBREG_REG (op)); 450890075Sobrien int final_offset = byte + SUBREG_BYTE (op); 4509169689Skan rtx newx; 451090075Sobrien 451190075Sobrien if (outermode == innermostmode 451290075Sobrien && byte == 0 && SUBREG_BYTE (op) == 0) 451390075Sobrien return SUBREG_REG (op); 451490075Sobrien 451590075Sobrien /* The SUBREG_BYTE represents offset, as if the value were stored 451690075Sobrien in memory. Irritating exception is paradoxical subreg, where 451790075Sobrien we define SUBREG_BYTE to be 0. On big endian machines, this 451890075Sobrien value should be negative. For a moment, undo this exception. */ 451990075Sobrien if (byte == 0 && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) 452090075Sobrien { 452190075Sobrien int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode)); 452290075Sobrien if (WORDS_BIG_ENDIAN) 452390075Sobrien final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 452490075Sobrien if (BYTES_BIG_ENDIAN) 452590075Sobrien final_offset += difference % UNITS_PER_WORD; 452690075Sobrien } 452790075Sobrien if (SUBREG_BYTE (op) == 0 452890075Sobrien && GET_MODE_SIZE (innermostmode) < GET_MODE_SIZE (innermode)) 452990075Sobrien { 453090075Sobrien int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (innermode)); 453190075Sobrien if (WORDS_BIG_ENDIAN) 453290075Sobrien final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 453390075Sobrien if (BYTES_BIG_ENDIAN) 453490075Sobrien final_offset += difference % UNITS_PER_WORD; 453590075Sobrien } 453690075Sobrien 453790075Sobrien /* See whether resulting subreg will be paradoxical. */ 453890075Sobrien if (GET_MODE_SIZE (innermostmode) > GET_MODE_SIZE (outermode)) 453990075Sobrien { 454090075Sobrien /* In nonparadoxical subregs we can't handle negative offsets. */ 454190075Sobrien if (final_offset < 0) 454290075Sobrien return NULL_RTX; 454390075Sobrien /* Bail out in case resulting subreg would be incorrect. */ 454490075Sobrien if (final_offset % GET_MODE_SIZE (outermode) 454590075Sobrien || (unsigned) final_offset >= GET_MODE_SIZE (innermostmode)) 454690075Sobrien return NULL_RTX; 454790075Sobrien } 454890075Sobrien else 454990075Sobrien { 455090075Sobrien int offset = 0; 455190075Sobrien int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (outermode)); 455290075Sobrien 455390075Sobrien /* In paradoxical subreg, see if we are still looking on lower part. 455490075Sobrien If so, our SUBREG_BYTE will be 0. */ 455590075Sobrien if (WORDS_BIG_ENDIAN) 455690075Sobrien offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 455790075Sobrien if (BYTES_BIG_ENDIAN) 455890075Sobrien offset += difference % UNITS_PER_WORD; 455990075Sobrien if (offset == final_offset) 456090075Sobrien final_offset = 0; 456190075Sobrien else 456290075Sobrien return NULL_RTX; 456390075Sobrien } 456490075Sobrien 4565132718Skan /* Recurse for further possible simplifications. */ 4566169689Skan newx = simplify_subreg (outermode, SUBREG_REG (op), innermostmode, 4567169689Skan final_offset); 4568169689Skan if (newx) 4569169689Skan return newx; 4570169689Skan if (validate_subreg (outermode, innermostmode, 4571169689Skan SUBREG_REG (op), final_offset)) 4572169689Skan return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset); 4573169689Skan return NULL_RTX; 457490075Sobrien } 457590075Sobrien 4576169689Skan /* Merge implicit and explicit truncations. */ 4577169689Skan 4578169689Skan if (GET_CODE (op) == TRUNCATE 4579169689Skan && GET_MODE_SIZE (outermode) < GET_MODE_SIZE (innermode) 4580169689Skan && subreg_lowpart_offset (outermode, innermode) == byte) 4581169689Skan return simplify_gen_unary (TRUNCATE, outermode, XEXP (op, 0), 4582169689Skan GET_MODE (XEXP (op, 0))); 4583169689Skan 458490075Sobrien /* SUBREG of a hard register => just change the register number 458590075Sobrien and/or mode. If the hard register is not valid in that mode, 458690075Sobrien suppress this simplification. If the hard register is the stack, 458790075Sobrien frame, or argument pointer, leave this as a SUBREG. */ 458890075Sobrien 458990075Sobrien if (REG_P (op) 4590117395Skan && REGNO (op) < FIRST_PSEUDO_REGISTER 4591117395Skan#ifdef CANNOT_CHANGE_MODE_CLASS 4592117395Skan && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), innermode, outermode) 459390075Sobrien && GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT 4594117395Skan && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT) 459590075Sobrien#endif 459690075Sobrien && ((reload_completed && !frame_pointer_needed) 459790075Sobrien || (REGNO (op) != FRAME_POINTER_REGNUM 459890075Sobrien#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM 459990075Sobrien && REGNO (op) != HARD_FRAME_POINTER_REGNUM 460090075Sobrien#endif 460190075Sobrien )) 460290075Sobrien#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM 460390075Sobrien && REGNO (op) != ARG_POINTER_REGNUM 460490075Sobrien#endif 4605132718Skan && REGNO (op) != STACK_POINTER_REGNUM 4606132718Skan && subreg_offset_representable_p (REGNO (op), innermode, 4607132718Skan byte, outermode)) 460890075Sobrien { 4609169689Skan unsigned int regno = REGNO (op); 4610169689Skan unsigned int final_regno 4611169689Skan = regno + subreg_regno_offset (regno, innermode, byte, outermode); 461290075Sobrien 461390075Sobrien /* ??? We do allow it if the current REG is not valid for 461490075Sobrien its mode. This is a kludge to work around how float/complex 4615117395Skan arguments are passed on 32-bit SPARC and should be fixed. */ 461690075Sobrien if (HARD_REGNO_MODE_OK (final_regno, outermode) 4617169689Skan || ! HARD_REGNO_MODE_OK (regno, innermode)) 461890075Sobrien { 4619169689Skan rtx x; 4620169689Skan int final_offset = byte; 462190075Sobrien 4622169689Skan /* Adjust offset for paradoxical subregs. */ 4623169689Skan if (byte == 0 4624169689Skan && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) 4625169689Skan { 4626169689Skan int difference = (GET_MODE_SIZE (innermode) 4627169689Skan - GET_MODE_SIZE (outermode)); 4628169689Skan if (WORDS_BIG_ENDIAN) 4629169689Skan final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; 4630169689Skan if (BYTES_BIG_ENDIAN) 4631169689Skan final_offset += difference % UNITS_PER_WORD; 4632169689Skan } 4633169689Skan 4634169689Skan x = gen_rtx_REG_offset (op, outermode, final_regno, final_offset); 4635169689Skan 463690075Sobrien /* Propagate original regno. We don't have any way to specify 4637132718Skan the offset inside original regno, so do so only for lowpart. 463890075Sobrien The information is used only by alias analysis that can not 463990075Sobrien grog partial register anyway. */ 464090075Sobrien 464190075Sobrien if (subreg_lowpart_offset (outermode, innermode) == byte) 464290075Sobrien ORIGINAL_REGNO (x) = ORIGINAL_REGNO (op); 464390075Sobrien return x; 464490075Sobrien } 464590075Sobrien } 464690075Sobrien 464790075Sobrien /* If we have a SUBREG of a register that we are replacing and we are 464890075Sobrien replacing it with a MEM, make a new MEM and try replacing the 464990075Sobrien SUBREG with it. Don't do this if the MEM has a mode-dependent address 465090075Sobrien or if we would be widening it. */ 465190075Sobrien 4652169689Skan if (MEM_P (op) 465390075Sobrien && ! mode_dependent_address_p (XEXP (op, 0)) 465490075Sobrien /* Allow splitting of volatile memory references in case we don't 465590075Sobrien have instruction to move the whole thing. */ 465690075Sobrien && (! MEM_VOLATILE_P (op) 465790075Sobrien || ! have_insn_for (SET, innermode)) 465890075Sobrien && GET_MODE_SIZE (outermode) <= GET_MODE_SIZE (GET_MODE (op))) 465990075Sobrien return adjust_address_nv (op, outermode, byte); 466090075Sobrien 466190075Sobrien /* Handle complex values represented as CONCAT 466290075Sobrien of real and imaginary part. */ 466390075Sobrien if (GET_CODE (op) == CONCAT) 466490075Sobrien { 4665169689Skan unsigned int inner_size, final_offset; 4666169689Skan rtx part, res; 466790075Sobrien 4668169689Skan inner_size = GET_MODE_UNIT_SIZE (innermode); 4669169689Skan part = byte < inner_size ? XEXP (op, 0) : XEXP (op, 1); 4670169689Skan final_offset = byte % inner_size; 4671169689Skan if (final_offset + GET_MODE_SIZE (outermode) > inner_size) 4672169689Skan return NULL_RTX; 4673169689Skan 467490075Sobrien res = simplify_subreg (outermode, part, GET_MODE (part), final_offset); 467590075Sobrien if (res) 467690075Sobrien return res; 4677169689Skan if (validate_subreg (outermode, GET_MODE (part), part, final_offset)) 4678169689Skan return gen_rtx_SUBREG (outermode, part, final_offset); 4679169689Skan return NULL_RTX; 468090075Sobrien } 468190075Sobrien 4682169689Skan /* Optimize SUBREG truncations of zero and sign extended values. */ 4683169689Skan if ((GET_CODE (op) == ZERO_EXTEND 4684169689Skan || GET_CODE (op) == SIGN_EXTEND) 4685169689Skan && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode)) 4686169689Skan { 4687169689Skan unsigned int bitpos = subreg_lsb_1 (outermode, innermode, byte); 4688169689Skan 4689169689Skan /* If we're requesting the lowpart of a zero or sign extension, 4690169689Skan there are three possibilities. If the outermode is the same 4691169689Skan as the origmode, we can omit both the extension and the subreg. 4692169689Skan If the outermode is not larger than the origmode, we can apply 4693169689Skan the truncation without the extension. Finally, if the outermode 4694169689Skan is larger than the origmode, but both are integer modes, we 4695169689Skan can just extend to the appropriate mode. */ 4696169689Skan if (bitpos == 0) 4697169689Skan { 4698169689Skan enum machine_mode origmode = GET_MODE (XEXP (op, 0)); 4699169689Skan if (outermode == origmode) 4700169689Skan return XEXP (op, 0); 4701169689Skan if (GET_MODE_BITSIZE (outermode) <= GET_MODE_BITSIZE (origmode)) 4702169689Skan return simplify_gen_subreg (outermode, XEXP (op, 0), origmode, 4703169689Skan subreg_lowpart_offset (outermode, 4704169689Skan origmode)); 4705169689Skan if (SCALAR_INT_MODE_P (outermode)) 4706169689Skan return simplify_gen_unary (GET_CODE (op), outermode, 4707169689Skan XEXP (op, 0), origmode); 4708169689Skan } 4709169689Skan 4710169689Skan /* A SUBREG resulting from a zero extension may fold to zero if 4711169689Skan it extracts higher bits that the ZERO_EXTEND's source bits. */ 4712169689Skan if (GET_CODE (op) == ZERO_EXTEND 4713169689Skan && bitpos >= GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0)))) 4714169689Skan return CONST0_RTX (outermode); 4715169689Skan } 4716169689Skan 4717169689Skan /* Simplify (subreg:QI (lshiftrt:SI (sign_extend:SI (x:QI)) C), 0) into 4718169689Skan to (ashiftrt:QI (x:QI) C), where C is a suitable small constant and 4719169689Skan the outer subreg is effectively a truncation to the original mode. */ 4720169689Skan if ((GET_CODE (op) == LSHIFTRT 4721169689Skan || GET_CODE (op) == ASHIFTRT) 4722169689Skan && SCALAR_INT_MODE_P (outermode) 4723169689Skan /* Ensure that OUTERMODE is at least twice as wide as the INNERMODE 4724169689Skan to avoid the possibility that an outer LSHIFTRT shifts by more 4725169689Skan than the sign extension's sign_bit_copies and introduces zeros 4726169689Skan into the high bits of the result. */ 4727169689Skan && (2 * GET_MODE_BITSIZE (outermode)) <= GET_MODE_BITSIZE (innermode) 4728169689Skan && GET_CODE (XEXP (op, 1)) == CONST_INT 4729169689Skan && GET_CODE (XEXP (op, 0)) == SIGN_EXTEND 4730169689Skan && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode 4731169689Skan && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode) 4732169689Skan && subreg_lsb_1 (outermode, innermode, byte) == 0) 4733169689Skan return simplify_gen_binary (ASHIFTRT, outermode, 4734169689Skan XEXP (XEXP (op, 0), 0), XEXP (op, 1)); 4735169689Skan 4736169689Skan /* Likewise (subreg:QI (lshiftrt:SI (zero_extend:SI (x:QI)) C), 0) into 4737169689Skan to (lshiftrt:QI (x:QI) C), where C is a suitable small constant and 4738169689Skan the outer subreg is effectively a truncation to the original mode. */ 4739169689Skan if ((GET_CODE (op) == LSHIFTRT 4740169689Skan || GET_CODE (op) == ASHIFTRT) 4741169689Skan && SCALAR_INT_MODE_P (outermode) 4742169689Skan && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode) 4743169689Skan && GET_CODE (XEXP (op, 1)) == CONST_INT 4744169689Skan && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND 4745169689Skan && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode 4746169689Skan && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode) 4747169689Skan && subreg_lsb_1 (outermode, innermode, byte) == 0) 4748169689Skan return simplify_gen_binary (LSHIFTRT, outermode, 4749169689Skan XEXP (XEXP (op, 0), 0), XEXP (op, 1)); 4750169689Skan 4751169689Skan /* Likewise (subreg:QI (ashift:SI (zero_extend:SI (x:QI)) C), 0) into 4752169689Skan to (ashift:QI (x:QI) C), where C is a suitable small constant and 4753169689Skan the outer subreg is effectively a truncation to the original mode. */ 4754169689Skan if (GET_CODE (op) == ASHIFT 4755169689Skan && SCALAR_INT_MODE_P (outermode) 4756169689Skan && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode) 4757169689Skan && GET_CODE (XEXP (op, 1)) == CONST_INT 4758169689Skan && (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND 4759169689Skan || GET_CODE (XEXP (op, 0)) == SIGN_EXTEND) 4760169689Skan && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode 4761169689Skan && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode) 4762169689Skan && subreg_lsb_1 (outermode, innermode, byte) == 0) 4763169689Skan return simplify_gen_binary (ASHIFT, outermode, 4764169689Skan XEXP (XEXP (op, 0), 0), XEXP (op, 1)); 4765169689Skan 476690075Sobrien return NULL_RTX; 476790075Sobrien} 4768132718Skan 476990075Sobrien/* Make a SUBREG operation or equivalent if it folds. */ 477090075Sobrien 477190075Sobrienrtx 4772132718Skansimplify_gen_subreg (enum machine_mode outermode, rtx op, 4773132718Skan enum machine_mode innermode, unsigned int byte) 477490075Sobrien{ 4775169689Skan rtx newx; 477690075Sobrien 4777169689Skan newx = simplify_subreg (outermode, op, innermode, byte); 4778169689Skan if (newx) 4779169689Skan return newx; 478090075Sobrien 4781169689Skan if (GET_CODE (op) == SUBREG 4782169689Skan || GET_CODE (op) == CONCAT 4783169689Skan || GET_MODE (op) == VOIDmode) 478490075Sobrien return NULL_RTX; 478590075Sobrien 4786169689Skan if (validate_subreg (outermode, innermode, op, byte)) 4787169689Skan return gen_rtx_SUBREG (outermode, op, byte); 478890075Sobrien 4789169689Skan return NULL_RTX; 4790169689Skan} 479190075Sobrien 479290075Sobrien/* Simplify X, an rtx expression. 479390075Sobrien 479490075Sobrien Return the simplified expression or NULL if no simplifications 479590075Sobrien were possible. 479690075Sobrien 479790075Sobrien This is the preferred entry point into the simplification routines; 479890075Sobrien however, we still allow passes to call the more specific routines. 479990075Sobrien 4800132718Skan Right now GCC has three (yes, three) major bodies of RTL simplification 480190075Sobrien code that need to be unified. 480290075Sobrien 480390075Sobrien 1. fold_rtx in cse.c. This code uses various CSE specific 480490075Sobrien information to aid in RTL simplification. 480590075Sobrien 480690075Sobrien 2. simplify_rtx in combine.c. Similar to fold_rtx, except that 480790075Sobrien it uses combine specific information to aid in RTL 480890075Sobrien simplification. 480990075Sobrien 481090075Sobrien 3. The routines in this file. 481190075Sobrien 481290075Sobrien 481390075Sobrien Long term we want to only have one body of simplification code; to 481490075Sobrien get to that state I recommend the following steps: 481590075Sobrien 481690075Sobrien 1. Pour over fold_rtx & simplify_rtx and move any simplifications 481790075Sobrien which are not pass dependent state into these routines. 481890075Sobrien 481990075Sobrien 2. As code is moved by #1, change fold_rtx & simplify_rtx to 482090075Sobrien use this routine whenever possible. 482190075Sobrien 482290075Sobrien 3. Allow for pass dependent state to be provided to these 482390075Sobrien routines and add simplifications based on the pass dependent 482490075Sobrien state. Remove code from cse.c & combine.c that becomes 482590075Sobrien redundant/dead. 482690075Sobrien 482790075Sobrien It will take time, but ultimately the compiler will be easier to 482890075Sobrien maintain and improve. It's totally silly that when we add a 482990075Sobrien simplification that it needs to be added to 4 places (3 for RTL 483090075Sobrien simplification and 1 for tree simplification. */ 4831117395Skan 483290075Sobrienrtx 4833132718Skansimplify_rtx (rtx x) 483490075Sobrien{ 483590075Sobrien enum rtx_code code = GET_CODE (x); 483690075Sobrien enum machine_mode mode = GET_MODE (x); 483790075Sobrien 483890075Sobrien switch (GET_RTX_CLASS (code)) 483990075Sobrien { 4840169689Skan case RTX_UNARY: 484190075Sobrien return simplify_unary_operation (code, mode, 484290075Sobrien XEXP (x, 0), GET_MODE (XEXP (x, 0))); 4843169689Skan case RTX_COMM_ARITH: 484490075Sobrien if (swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1))) 4845132718Skan return simplify_gen_binary (code, mode, XEXP (x, 1), XEXP (x, 0)); 484690075Sobrien 4847132718Skan /* Fall through.... */ 484890075Sobrien 4849169689Skan case RTX_BIN_ARITH: 485090075Sobrien return simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1)); 485190075Sobrien 4852169689Skan case RTX_TERNARY: 4853169689Skan case RTX_BITFIELD_OPS: 485490075Sobrien return simplify_ternary_operation (code, mode, GET_MODE (XEXP (x, 0)), 485590075Sobrien XEXP (x, 0), XEXP (x, 1), 485690075Sobrien XEXP (x, 2)); 485790075Sobrien 4858169689Skan case RTX_COMPARE: 4859169689Skan case RTX_COMM_COMPARE: 4860169689Skan return simplify_relational_operation (code, mode, 4861169689Skan ((GET_MODE (XEXP (x, 0)) 4862169689Skan != VOIDmode) 4863169689Skan ? GET_MODE (XEXP (x, 0)) 4864169689Skan : GET_MODE (XEXP (x, 1))), 4865169689Skan XEXP (x, 0), 4866169689Skan XEXP (x, 1)); 4867132718Skan 4868169689Skan case RTX_EXTRA: 486990075Sobrien if (code == SUBREG) 4870117395Skan return simplify_gen_subreg (mode, SUBREG_REG (x), 487190075Sobrien GET_MODE (SUBREG_REG (x)), 487290075Sobrien SUBREG_BYTE (x)); 4873132718Skan break; 4874132718Skan 4875169689Skan case RTX_OBJ: 4876132718Skan if (code == LO_SUM) 4877132718Skan { 4878132718Skan /* Convert (lo_sum (high FOO) FOO) to FOO. */ 4879132718Skan if (GET_CODE (XEXP (x, 0)) == HIGH 4880132718Skan && rtx_equal_p (XEXP (XEXP (x, 0), 0), XEXP (x, 1))) 4881132718Skan return XEXP (x, 1); 4882132718Skan } 4883132718Skan break; 4884132718Skan 488590075Sobrien default: 4886132718Skan break; 488790075Sobrien } 4888132718Skan return NULL; 488990075Sobrien} 4890169689Skan 4891