https://gcc.gnu.org/g:4371f656288f461335c47e98b8c038937a89764a
commit r15-3415-g4371f656288f461335c47e98b8c038937a89764a Author: Jeff Law <j...@ventanamicro.com> Date: Tue Sep 3 06:45:30 2024 -0600 [PR target/115921] Improve reassociation for rv64 As Jovan pointed out in pr115921, we're not reassociating expressions like this on rv64: (x & 0x3e) << 12 It generates something like this: li a5,258048 slli a0,a0,12 and a0,a0,a5 We have a pattern that's designed to clean this up. Essentially reassociating the operations so that we don't need to load the constant resulting in something like this: andi a0,a0,63 slli a0,a0,12 That pattern wasn't working for certain constants due to its condition. The condition is trying to avoid cases where this kind of reassociation would hinder shadd generation on rv64. That condition was just written poorly. This patch tightens up that condition in a few ways. First, there's no need to worry about shadd cases if ZBA is not enabled. Second we can't use shadd if the shift value isn't 1, 2 or 3. Finally rather than open-coding one of the tests, we can use an existing operand predicate. The net is we'll start performing this transformation in more cases on rv64 while still avoiding reassociation if it would spoil shadd generation. PR target/115921 gcc/ * config/riscv/riscv.md (reassociate bitwise ops): Tighten test for cases we do not want reassociate. gcc/testsuite/ * gcc.target/riscv/pr115921.c: New test. Diff: --- gcc/J | 1064 +++++++++++++++++++++++++++++ gcc/config/riscv/riscv.md | 10 +- gcc/testsuite/gcc.target/riscv/pr115921.c | 13 + 3 files changed, 1083 insertions(+), 4 deletions(-) diff --git a/gcc/J b/gcc/J new file mode 100644 index 000000000000..6b6332dd2c13 --- /dev/null +++ b/gcc/J @@ -0,0 +1,1064 @@ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 1) /* RTL-based forward propagation pass for GNU compiler. +a945c346f57b gcc/fwprop.cc (Jakub Jelinek 2024-01-03 12:19:35 +0100 2) Copyright (C) 2005-2024 Free Software Foundation, Inc. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 3) Contributed by Paolo Bonzini and Steven Bosscher. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 4) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 5) This file is part of GCC. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 6) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 7) GCC is free software; you can redistribute it and/or modify it under +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 8) the terms of the GNU General Public License as published by the Free +9dcd6f09a3dd gcc/fwprop.c (Nick Clifton 2007-07-26 08:37:01 +0000 9) Software Foundation; either version 3, or (at your option) any later +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 10) version. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 11) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 12) GCC is distributed in the hope that it will be useful, but WITHOUT ANY +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 13) WARRANTY; without even the implied warranty of MERCHANTABILITY or +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 14) FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 15) for more details. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 16) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 17) You should have received a copy of the GNU General Public License +9dcd6f09a3dd gcc/fwprop.c (Nick Clifton 2007-07-26 08:37:01 +0000 18) along with GCC; see the file COPYING3. If not see +9dcd6f09a3dd gcc/fwprop.c (Nick Clifton 2007-07-26 08:37:01 +0000 19) <http://www.gnu.org/licenses/>. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 20) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 21) #define INCLUDE_ALGORITHM +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 22) #define INCLUDE_FUNCTIONAL +d6849aa92666 gcc/fwprop.cc (Richard Sandiford 2024-07-25 13:25:32 +0100 23) #define INCLUDE_ARRAY +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 24) #include "config.h" +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 25) #include "system.h" +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 26) #include "coretypes.h" +c7131fb2b58a gcc/fwprop.c (Andrew MacLeod 2015-07-08 00:53:03 +0000 27) #include "backend.h" +c7131fb2b58a gcc/fwprop.c (Andrew MacLeod 2015-07-08 00:53:03 +0000 28) #include "rtl.h" +1815e313a8fb gcc/fwprop.cc (Uros Bizjak 2023-07-14 11:46:22 +0200 29) #include "rtlanal.h" +c7131fb2b58a gcc/fwprop.c (Andrew MacLeod 2015-07-08 00:53:03 +0000 30) #include "df.h" +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 31) #include "rtl-ssa.h" +957060b5c5d2 gcc/fwprop.c (Andrew MacLeod 2015-10-29 13:57:32 +0000 32) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 33) #include "predict.h" +60393bbc613a gcc/fwprop.c (Andrew MacLeod 2014-10-27 12:41:01 +0000 34) #include "cfgrtl.h" +60393bbc613a gcc/fwprop.c (Andrew MacLeod 2014-10-27 12:41:01 +0000 35) #include "cfgcleanup.h" +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 36) #include "cfgloop.h" +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 37) #include "tree-pass.h" +aa4e2d7ef068 gcc/fwprop.c (Richard Sandiford 2014-08-28 06:23:26 +0000 38) #include "rtl-iter.h" +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 39) #include "target.h" +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 40) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 41) /* This pass does simple forward propagation and simplification when an +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 42) operand of an insn can only come from a single def. This pass uses +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 43) RTL SSA, so it is global. However, we only do limited analysis of +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 44) available expressions. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 45) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 46) 1) The pass tries to propagate the source of the def into the use, +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 47) and checks if the result is independent of the substituted value. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 48) For example, the high word of a (zero_extend:DI (reg:SI M)) is always +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 49) zero, independent of the source register. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 50) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 51) In particular, we propagate constants into the use site. Sometimes +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 52) RTL expansion did not put the constant in the same insn on purpose, +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 53) to satisfy a predicate, and the result will fail to be recognized; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 54) but this happens rarely and in this case we can still create a +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 55) REG_EQUAL note. For multi-word operations, this +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 56) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 57) (set (subreg:SI (reg:DI 120) 0) (const_int 0)) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 58) (set (subreg:SI (reg:DI 120) 4) (const_int -1)) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 59) (set (subreg:SI (reg:DI 122) 0) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 60) (ior:SI (subreg:SI (reg:DI 119) 0) (subreg:SI (reg:DI 120) 0))) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 61) (set (subreg:SI (reg:DI 122) 4) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 62) (ior:SI (subreg:SI (reg:DI 119) 4) (subreg:SI (reg:DI 120) 4))) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 63) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 64) can be simplified to the much simpler +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 65) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 66) (set (subreg:SI (reg:DI 122) 0) (subreg:SI (reg:DI 119))) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 67) (set (subreg:SI (reg:DI 122) 4) (const_int -1)) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 68) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 69) This particular propagation is also effective at putting together +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 70) complex addressing modes. We are more aggressive inside MEMs, in +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 71) that all definitions are propagated if the use is in a MEM; if the +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 72) result is a valid memory address we check address_cost to decide +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 73) whether the substitution is worthwhile. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 74) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 75) 2) The pass propagates register copies. This is not as effective as +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 76) the copy propagation done by CSE's canon_reg, which works by walking +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 77) the instruction chain, it can help the other transformations. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 78) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 79) We should consider removing this optimization, and instead reorder the +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 80) RTL passes, because GCSE does this transformation too. With some luck, +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 81) the CSE pass at the end of rest_of_handle_gcse could also go away. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 82) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 83) 3) The pass looks for paradoxical subregs that are actually unnecessary. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 84) Things like this: +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 85) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 86) (set (reg:QI 120) (subreg:QI (reg:SI 118) 0)) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 87) (set (reg:QI 121) (subreg:QI (reg:SI 119) 0)) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 88) (set (reg:SI 122) (plus:SI (subreg:SI (reg:QI 120) 0) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 89) (subreg:SI (reg:QI 121) 0))) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 90) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 91) are very common on machines that can only do word-sized operations. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 92) For each use of a paradoxical subreg (subreg:WIDER (reg:NARROW N) 0), +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 93) if it has a single def and it is (subreg:NARROW (reg:WIDE M) 0), +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 94) we can replace the paradoxical subreg with simply (reg:WIDE M). The +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 95) above will simplify this to +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 96) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 97) (set (reg:QI 120) (subreg:QI (reg:SI 118) 0)) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 98) (set (reg:QI 121) (subreg:QI (reg:SI 119) 0)) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 99) (set (reg:SI 122) (plus:SI (reg:SI 118) (reg:SI 119))) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 100) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 101) where the first two insns are now dead. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 102) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 103) using namespace rtl_ssa; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 104) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 105) static int num_changes; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 106) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 107) /* Do not try to replace constant addresses or addresses of local and +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 108) argument slots. These MEM expressions are made only once and inserted +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 109) in many instructions, as well as being used to control symbol table +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 110) output. It is not safe to clobber them. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 111) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 112) There are some uncommon cases where the address is already in a register +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 113) for some reason, but we cannot take advantage of that because we have +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 114) no easy way to unshare the MEM. In addition, looking up all stack +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 115) addresses is costly. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 116) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 117) static bool +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 118) can_simplify_addr (rtx addr) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 119) { +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 120) rtx reg; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 121) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 122) if (CONSTANT_ADDRESS_P (addr)) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 123) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 124) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 125) if (GET_CODE (addr) == PLUS) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 126) reg = XEXP (addr, 0); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 127) else +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 128) reg = addr; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 129) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 130) return (!REG_P (reg) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 131) || (REGNO (reg) != FRAME_POINTER_REGNUM +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 132) && REGNO (reg) != HARD_FRAME_POINTER_REGNUM +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 133) && REGNO (reg) != ARG_POINTER_REGNUM)); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 134) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 135) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 136) /* MEM is the result of an address simplification, and temporarily +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 137) undoing changes OLD_NUM_CHANGES onwards restores the original address. +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 138) Return whether it is good to use the new address instead of the +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 139) old one. INSN is the containing instruction. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 140) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 141) static bool +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 142) should_replace_address (int old_num_changes, rtx mem, rtx_insn *insn) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 143) { +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 144) int gain; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 145) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 146) /* Prefer the new address if it is less expensive. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 147) bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 148) temporarily_undo_changes (old_num_changes); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 149) gain = address_cost (XEXP (mem, 0), GET_MODE (mem), +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 150) MEM_ADDR_SPACE (mem), speed); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 151) redo_changes (old_num_changes); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 152) gain -= address_cost (XEXP (mem, 0), GET_MODE (mem), +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 153) MEM_ADDR_SPACE (mem), speed); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 154) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 155) /* If the addresses have equivalent cost, prefer the new address +5e8f01f434e5 gcc/fwprop.c (Richard Sandiford 2011-08-18 12:37:27 +0000 156) if it has the highest `set_src_cost'. That has the potential of +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 157) eliminating the most insns without additional costs, and it +e53b6e564aab gcc/fwprop.cc (Martin Liska 2022-01-14 16:57:02 +0100 158) is the same that cse.cc used to do. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 159) if (gain == 0) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 160) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 161) gain = set_src_cost (XEXP (mem, 0), VOIDmode, speed); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 162) temporarily_undo_changes (old_num_changes); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 163) gain -= set_src_cost (XEXP (mem, 0), VOIDmode, speed); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 164) redo_changes (old_num_changes); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 165) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 166) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 167) return (gain > 0); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 168) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 169) +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 170) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 171) namespace +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 172) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 173) class fwprop_propagation : public insn_propagation +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 174) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 175) public: +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 176) static const uint16_t CHANGED_MEM = FIRST_SPARE_RESULT; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 177) static const uint16_t CONSTANT = FIRST_SPARE_RESULT << 1; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 178) static const uint16_t PROFITABLE = FIRST_SPARE_RESULT << 2; +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 179) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 180) fwprop_propagation (insn_info *, set_info *, rtx, rtx); +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 181) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 182) bool changed_mem_p () const { return result_flags & CHANGED_MEM; } +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 183) bool folded_to_constants_p () const; +86de9b66480b gcc/fwprop.cc (Roger Sayle 2024-01-21 21:22:28 +0000 184) bool likely_profitable_p () const; +f40751dd3417 gcc/fwprop.c (Jan Hubicka 2008-08-31 11:44:25 +0200 185) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 186) bool check_mem (int, rtx) final override; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 187) void note_simplification (int, uint16_t, rtx, rtx) final override; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 188) uint16_t classify_result (rtx, rtx); +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 189) +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 190) private: +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 191) const bool single_use_p; +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 192) const bool single_ebb_p; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 193) }; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 194) } +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 195) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 196) /* Prepare to replace FROM with TO in USE_INSN. */ +75da268e1a56 gcc/fwprop.c (Prathamesh Kulkarni 2019-07-04 06:48:42 +0000 197) +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 198) fwprop_propagation::fwprop_propagation (insn_info *use_insn, +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 199) set_info *def, rtx from, rtx to) +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 200) : insn_propagation (use_insn->rtl (), from, to), +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 201) single_use_p (def->single_nondebug_use ()), +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 202) single_ebb_p (use_insn->ebb () == def->ebb ()) +75da268e1a56 gcc/fwprop.c (Prathamesh Kulkarni 2019-07-04 06:48:42 +0000 203) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 204) should_check_mems = true; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 205) should_note_simplifications = true; +75da268e1a56 gcc/fwprop.c (Prathamesh Kulkarni 2019-07-04 06:48:42 +0000 206) } +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 207) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 208) /* MEM is the result of an address simplification, and temporarily +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 209) undoing changes OLD_NUM_CHANGES onwards restores the original address. +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 210) Return true if the propagation should continue, false if it has failed. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 211) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 212) bool +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 213) fwprop_propagation::check_mem (int old_num_changes, rtx mem) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 214) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 215) if (!memory_address_addr_space_p (GET_MODE (mem), XEXP (mem, 0), +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 216) MEM_ADDR_SPACE (mem))) +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 217) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 218) failure_reason = "would create an invalid MEM"; +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 219) return false; +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 220) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 221) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 222) temporarily_undo_changes (old_num_changes); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 223) bool can_simplify = can_simplify_addr (XEXP (mem, 0)); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 224) redo_changes (old_num_changes); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 225) if (!can_simplify) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 226) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 227) failure_reason = "would replace a frame address"; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 228) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 229) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 230) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 231) /* Copy propagations are always ok. Otherwise check the costs. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 232) if (!(REG_P (from) && REG_P (to)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 233) && !should_replace_address (old_num_changes, mem, insn)) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 234) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 235) failure_reason = "would increase the cost of a MEM"; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 236) return false; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 237) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 238) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 239) result_flags |= CHANGED_MEM; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 240) return true; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 241) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 242) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 243) /* OLDX has been simplified to NEWX. Describe the change in terms of +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 244) result_flags. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 245) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 246) uint16_t +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 247) fwprop_propagation::classify_result (rtx old_rtx, rtx new_rtx) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 248) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 249) if (CONSTANT_P (new_rtx)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 250) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 251) /* If OLD_RTX is a LO_SUM, then it presumably exists for a reason, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 252) and NEW_RTX is likely not a legitimate address. We want it to +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 253) disappear if it is invalid. +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 254) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 255) ??? Using the mode of the LO_SUM as the mode of the address +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 256) seems odd, but it was what the pre-SSA code did. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 257) if (GET_CODE (old_rtx) == LO_SUM +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 258) && !memory_address_p (GET_MODE (old_rtx), new_rtx)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 259) return CONSTANT; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 260) return CONSTANT | PROFITABLE; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 261) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 262) +712a93d637f8 gcc/fwprop.c (Richard Biener 2016-07-12 08:56:14 +0000 263) /* Allow replacements that simplify operations on a vector or complex +712a93d637f8 gcc/fwprop.c (Richard Biener 2016-07-12 08:56:14 +0000 264) value to a component. The most prominent case is +712a93d637f8 gcc/fwprop.c (Richard Biener 2016-07-12 08:56:14 +0000 265) (subreg ([vec_]concat ...)). */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 266) if (REG_P (new_rtx) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 267) && !HARD_REGISTER_P (new_rtx) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 268) && (VECTOR_MODE_P (GET_MODE (from)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 269) || COMPLEX_MODE_P (GET_MODE (from))) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 270) && GET_MODE (new_rtx) == GET_MODE_INNER (GET_MODE (from))) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 271) return PROFITABLE; +712a93d637f8 gcc/fwprop.c (Richard Biener 2016-07-12 08:56:14 +0000 272) +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 273) /* Allow (subreg (mem)) -> (mem) simplifications with the following +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 274) exceptions: +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 275) 1) Propagating (mem)s into multiple uses is not profitable. +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 276) 2) Propagating (mem)s across EBBs may not be profitable if the source EBB +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 277) runs less frequently. +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 278) 3) Propagating (mem)s into paradoxical (subreg)s is not profitable. +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 279) 4) Creating new (mem/v)s is not correct, since DCE will not remove the old +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 280) ones. */ +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 281) if (single_use_p +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 282) && single_ebb_p +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 283) && SUBREG_P (old_rtx) +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 284) && !paradoxical_subreg_p (old_rtx) +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 285) && MEM_P (new_rtx) +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 286) && !MEM_VOLATILE_P (new_rtx)) +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 287) return PROFITABLE; +efb6bc55a93a gcc/fwprop.c (Ilya Leoshkevich 2021-01-15 00:14:56 +0100 288) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 289) return 0; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 290) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 291) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 292) /* Record that OLD_RTX has been simplified to NEW_RTX. OLD_NUM_CHANGES +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 293) is the number of unrelated changes that had been made before processing +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 294) OLD_RTX and its subrtxes. OLD_RESULT_FLAGS is the value that result_flags +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 295) had at that point. */ +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 296) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 297) void +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 298) fwprop_propagation::note_simplification (int old_num_changes, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 299) uint16_t old_result_flags, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 300) rtx old_rtx, rtx new_rtx) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 301) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 302) result_flags &= ~(CONSTANT | PROFITABLE); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 303) uint16_t new_flags = classify_result (old_rtx, new_rtx); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 304) if (old_num_changes) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 305) new_flags &= old_result_flags; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 306) result_flags |= new_flags; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 307) } +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 308) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 309) /* Return true if all substitutions eventually folded to constants. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 310) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 311) bool +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 312) fwprop_propagation::folded_to_constants_p () const +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 313) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 314) /* If we're propagating a HIGH, require it to be folded with a +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 315) partnering LO_SUM. For example, a REG_EQUAL note with a register +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 316) replaced by an unfolded HIGH is not useful. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 317) if (CONSTANT_P (to) && GET_CODE (to) != HIGH) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 318) return true; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 319) return !(result_flags & UNSIMPLIFIED) && (result_flags & CONSTANT); +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 320) } +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 321) +460d667de96a gcc/fwprop.c (Paolo Bonzini 2008-04-02 09:53:34 +0000 322) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 323) /* Return true if it is worth keeping the result of the propagation, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 324) false if it would increase the complexity of the pattern too much. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 325) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 326) bool +86de9b66480b gcc/fwprop.cc (Roger Sayle 2024-01-21 21:22:28 +0000 327) fwprop_propagation::likely_profitable_p () const +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 328) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 329) if (changed_mem_p ()) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 330) return true; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 331) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 332) if (!(result_flags & UNSIMPLIFIED) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 333) && (result_flags & PROFITABLE)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 334) return true; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 335) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 336) if (REG_P (to)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 337) return true; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 338) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 339) if (GET_CODE (to) == SUBREG +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 340) && REG_P (SUBREG_REG (to)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 341) && !paradoxical_subreg_p (to)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 342) return true; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 343) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 344) if (CONSTANT_P (to)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 345) return true; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 346) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 347) return false; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 348) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 349) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 350) /* Check that X has a single def. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 351) +6fb5fa3cbc0d gcc/fwprop.c (Daniel Berlin 2007-06-11 18:02:15 +0000 352) static bool +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 353) reg_single_def_p (rtx x) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 354) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 355) return REG_P (x) && crtl->ssa->single_dominating_def (REGNO (x)); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 356) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 357) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 358) /* Try to substitute (set DEST SRC), which defines DEF, into note NOTE of +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 359) USE_INSN. Return the number of substitutions on success, otherwise return +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 360) -1 and leave USE_INSN unchanged. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 361) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 362) If REQUIRE_CONSTANT is true, require all substituted occurrences of SRC +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 363) to fold to a constant, so that the note does not use any more registers +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 364) than it did previously. If REQUIRE_CONSTANT is false, also allow the +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 365) substitution if it's something we'd normally allow for the main +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 366) instruction pattern. */ +692e7e54e095 gcc/fwprop.c (Richard Biener 2018-11-05 08:04:49 +0000 367) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 368) static int +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 369) try_fwprop_subst_note (insn_info *use_insn, set_info *def, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 370) rtx note, rtx dest, rtx src, bool require_constant) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 371) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 372) rtx_insn *use_rtl = use_insn->rtl (); +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 373) insn_info *def_insn = def->insn (); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 374) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 375) insn_change_watermark watermark; +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 376) fwprop_propagation prop (use_insn, def, dest, src); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 377) if (!prop.apply_to_rvalue (&XEXP (note, 0))) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 378) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 379) if (dump_file && (dump_flags & TDF_DETAILS)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 380) fprintf (dump_file, "cannot propagate from insn %d into" +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 381) " notes of insn %d: %s\n", def_insn->uid (), +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 382) use_insn->uid (), prop.failure_reason); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 383) return -1; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 384) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 385) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 386) if (prop.num_replacements == 0) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 387) return 0; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 388) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 389) if (require_constant) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 390) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 391) if (!prop.folded_to_constants_p ()) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 392) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 393) if (dump_file && (dump_flags & TDF_DETAILS)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 394) fprintf (dump_file, "cannot propagate from insn %d into" +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 395) " notes of insn %d: %s\n", def_insn->uid (), +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 396) use_insn->uid (), "wouldn't fold to constants"); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 397) return -1; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 398) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 399) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 400) else +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 401) { +86de9b66480b gcc/fwprop.cc (Roger Sayle 2024-01-21 21:22:28 +0000 402) if (!prop.folded_to_constants_p () && !prop.likely_profitable_p ()) +6fb5fa3cbc0d gcc/fwprop.c (Daniel Berlin 2007-06-11 18:02:15 +0000 403) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 404) if (dump_file && (dump_flags & TDF_DETAILS)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 405) fprintf (dump_file, "cannot propagate from insn %d into" +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 406) " notes of insn %d: %s\n", def_insn->uid (), +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 407) use_insn->uid (), "would increase complexity of node"); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 408) return -1; +6fb5fa3cbc0d gcc/fwprop.c (Daniel Berlin 2007-06-11 18:02:15 +0000 409) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 410) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 411) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 412) if (dump_file && (dump_flags & TDF_DETAILS)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 413) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 414) fprintf (dump_file, "\nin notes of insn %d, replacing:\n ", +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 415) INSN_UID (use_rtl)); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 416) temporarily_undo_changes (0); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 417) print_inline_rtx (dump_file, note, 2); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 418) redo_changes (0); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 419) fprintf (dump_file, "\n with:\n "); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 420) print_inline_rtx (dump_file, note, 2); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 421) fprintf (dump_file, "\n"); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 422) } +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 423) watermark.keep (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 424) return prop.num_replacements; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 425) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 426) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 427) /* Try to substitute (set DEST SRC), which defines DEF, into location LOC of +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 428) USE_INSN's pattern. Return true on success, otherwise leave USE_INSN +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 429) unchanged. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 430) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 431) static bool +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 432) try_fwprop_subst_pattern (obstack_watermark &attempt, insn_change &use_change, +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 433) set_info *def, rtx *loc, rtx dest, rtx src) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 434) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 435) insn_info *use_insn = use_change.insn (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 436) rtx_insn *use_rtl = use_insn->rtl (); +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 437) insn_info *def_insn = def->insn (); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 438) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 439) insn_change_watermark watermark; +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 440) fwprop_propagation prop (use_insn, def, dest, src); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 441) if (!prop.apply_to_pattern (loc)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 442) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 443) if (dump_file && (dump_flags & TDF_DETAILS)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 444) fprintf (dump_file, "cannot propagate from insn %d into" +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 445) " insn %d: %s\n", def_insn->uid (), use_insn->uid (), +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 446) prop.failure_reason); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 447) return false; +dc007c1fd21c gcc/fwprop.c (Paolo Bonzini 2010-11-22 16:20:16 +0000 448) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 449) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 450) if (prop.num_replacements == 0) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 451) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 452) +86de9b66480b gcc/fwprop.cc (Roger Sayle 2024-01-21 21:22:28 +0000 453) if (!prop.likely_profitable_p () +86de9b66480b gcc/fwprop.cc (Roger Sayle 2024-01-21 21:22:28 +0000 454) && (prop.changed_mem_p () +3e3e4156a5f9 gcc/fwprop.cc (Jakub Jelinek 2024-03-09 13:04:26 +0100 455) || contains_mem_rtx_p (src) +86de9b66480b gcc/fwprop.cc (Roger Sayle 2024-01-21 21:22:28 +0000 456) || use_insn->is_asm () +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 457) || use_insn->is_debug_insn ())) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 458) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 459) if (dump_file && (dump_flags & TDF_DETAILS)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 460) fprintf (dump_file, "cannot propagate from insn %d into" +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 461) " insn %d: %s\n", def_insn->uid (), use_insn->uid (), +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 462) "would increase complexity of pattern"); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 463) return false; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 464) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 465) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 466) if (dump_file && (dump_flags & TDF_DETAILS)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 467) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 468) fprintf (dump_file, "\npropagating insn %d into insn %d, replacing:\n", +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 469) def_insn->uid (), use_insn->uid ()); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 470) temporarily_undo_changes (0); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 471) print_rtl_single (dump_file, PATTERN (use_rtl)); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 472) redo_changes (0); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 473) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 474) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 475) bool ok = recog (attempt, use_change); +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 476) if (ok +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 477) && !prop.changed_mem_p () +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 478) && !use_insn->is_asm () +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 479) && !use_insn->is_debug_insn ()) +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 480) { +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 481) bool strict_p = !prop.likely_profitable_p (); +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 482) if (!change_is_worthwhile (use_change, strict_p)) +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 483) { +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 484) if (dump_file) +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 485) fprintf (dump_file, "change not profitable"); +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 486) ok = false; +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 487) } +ea8061f46a30 gcc/fwprop.cc (Haochen Gui 2024-06-24 13:12:51 +0800 488) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 489) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 490) if (!ok) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 491) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 492) /* The pattern didn't match, but if all uses of SRC folded to +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 493) constants, we can add a REG_EQUAL note for the result, if there +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 494) isn't one already. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 495) if (!prop.folded_to_constants_p ()) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 496) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 497) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 498) /* Test this first to avoid creating an unnecessary copy of SRC. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 499) if (find_reg_note (use_rtl, REG_EQUAL, NULL_RTX)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 500) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 501) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 502) rtx set = set_for_reg_notes (use_rtl); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 503) if (!set || !REG_P (SET_DEST (set))) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 504) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 505) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 506) rtx value = copy_rtx (SET_SRC (set)); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 507) cancel_changes (0); +dc007c1fd21c gcc/fwprop.c (Paolo Bonzini 2010-11-22 16:20:16 +0000 508) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 509) /* If there are any paradoxical SUBREGs, drop the REG_EQUAL note, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 510) because the bits in there can be anything and so might not +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 511) match the REG_EQUAL note content. See PR70574. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 512) if (contains_paradoxical_subreg_p (SET_SRC (set))) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 513) return false; +dc007c1fd21c gcc/fwprop.c (Paolo Bonzini 2010-11-22 16:20:16 +0000 514) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 515) if (dump_file && (dump_flags & TDF_DETAILS)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 516) fprintf (dump_file, " Setting REG_EQUAL note\n"); +dc007c1fd21c gcc/fwprop.c (Paolo Bonzini 2010-11-22 16:20:16 +0000 517) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 518) return set_unique_reg_note (use_rtl, REG_EQUAL, value); +dc007c1fd21c gcc/fwprop.c (Paolo Bonzini 2010-11-22 16:20:16 +0000 519) } +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 520) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 521) rtx *note_ptr = ®_NOTES (use_rtl); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 522) while (rtx note = *note_ptr) +dc007c1fd21c gcc/fwprop.c (Paolo Bonzini 2010-11-22 16:20:16 +0000 523) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 524) if ((REG_NOTE_KIND (note) == REG_EQUAL +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 525) || REG_NOTE_KIND (note) == REG_EQUIV) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 526) && try_fwprop_subst_note (use_insn, def, note, dest, src, false) < 0) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 527) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 528) *note_ptr = XEXP (note, 1); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 529) free_EXPR_LIST_node (note); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 530) } +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 531) else +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 532) note_ptr = &XEXP (note, 1); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 533) } +dc007c1fd21c gcc/fwprop.c (Paolo Bonzini 2010-11-22 16:20:16 +0000 534) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 535) confirm_change_group (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 536) crtl->ssa->change_insn (use_change); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 537) num_changes++; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 538) return true; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 539) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 540) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 541) /* Try to substitute (set DEST SRC), which defines DEF, into USE_INSN's notes, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 542) given that it was not possible to do this for USE_INSN's main pattern. +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 543) Return true on success, otherwise leave USE_INSN unchanged. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 544) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 545) static bool +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 546) try_fwprop_subst_notes (insn_info *use_insn, set_info *def, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 547) rtx dest, rtx src) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 548) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 549) rtx_insn *use_rtl = use_insn->rtl (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 550) for (rtx note = REG_NOTES (use_rtl); note; note = XEXP (note, 1)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 551) if ((REG_NOTE_KIND (note) == REG_EQUAL +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 552) || REG_NOTE_KIND (note) == REG_EQUIV) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 553) && try_fwprop_subst_note (use_insn, def, note, dest, src, true) > 0) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 554) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 555) confirm_change_group (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 556) return true; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 557) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 558) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 559) return false; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 560) } +dc007c1fd21c gcc/fwprop.c (Paolo Bonzini 2010-11-22 16:20:16 +0000 561) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 562) /* Check whether we could validly substitute (set DEST SRC), which defines DEF, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 563) into USE. If so, first try performing the substitution in location LOC +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 564) of USE->insn ()'s pattern. If that fails, try instead to substitute +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 565) into the notes. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 566) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 567) Return true on success, otherwise leave USE_INSN unchanged. */ +de266950570f gcc/fwprop.c (Paolo Bonzini 2007-11-09 13:02:25 +0000 568) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 569) static bool +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 570) try_fwprop_subst (use_info *use, set_info *def, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 571) rtx *loc, rtx dest, rtx src) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 572) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 573) insn_info *use_insn = use->insn (); +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 574) insn_info *def_insn = def->insn (); +de266950570f gcc/fwprop.c (Paolo Bonzini 2007-11-09 13:02:25 +0000 575) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 576) auto attempt = crtl->ssa->new_change_attempt (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 577) use_array src_uses = remove_note_accesses (attempt, def_insn->uses ()); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 578) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 579) /* ??? Not really a meaningful test: it means we can propagate arithmetic +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 580) involving hard registers but not bare references to them. A better +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 581) test would be to iterate over src_uses looking for hard registers +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 582) that are not fixed. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 583) if (REG_P (src) && HARD_REGISTER_P (src)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 584) return false; +de266950570f gcc/fwprop.c (Paolo Bonzini 2007-11-09 13:02:25 +0000 585) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 586) /* ??? It would be better to make this EBB-based instead. That would +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 587) involve checking for equal EBBs rather than equal BBs and trying +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 588) to make the uses available at use_insn->ebb ()->first_bb (). */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 589) if (def_insn->bb () != use_insn->bb ()) +de266950570f gcc/fwprop.c (Paolo Bonzini 2007-11-09 13:02:25 +0000 590) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 591) src_uses = crtl->ssa->make_uses_available (attempt, src_uses, +c97351c0cf48 gcc/fwprop.c (Richard Sandiford 2021-04-29 17:24:57 +0100 592) use_insn->bb (), +c97351c0cf48 gcc/fwprop.c (Richard Sandiford 2021-04-29 17:24:57 +0100 593) use_insn->is_debug_insn ()); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 594) if (!src_uses.is_valid ()) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 595) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 596) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 597) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 598) insn_change use_change (use_insn); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 599) use_change.new_uses = merge_access_arrays (attempt, use_change.new_uses, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 600) src_uses); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 601) if (!use_change.new_uses.is_valid ()) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 602) return false; +1a13c0a284ea gcc/fwprop.c (Jakub Jelinek 2016-04-08 19:21:17 +0200 603) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 604) /* ??? We could allow movement within the EBB by adding: +de266950570f gcc/fwprop.c (Paolo Bonzini 2007-11-09 13:02:25 +0000 605) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 606) use_change.move_range = use_insn->ebb ()->insn_range (); */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 607) if (!restrict_movement (use_change)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 608) return false; +dc007c1fd21c gcc/fwprop.c (Paolo Bonzini 2010-11-22 16:20:16 +0000 609) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 610) return (try_fwprop_subst_pattern (attempt, use_change, def, loc, dest, src) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 611) || try_fwprop_subst_notes (use_insn, def, dest, src)); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 612) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 613) +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 614) /* For the given single_set INSN, containing SRC known to be a +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 615) ZERO_EXTEND or SIGN_EXTEND of a register, return true if INSN +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 616) is redundant due to the register being set by a LOAD_EXTEND_OP +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 617) load from memory. */ +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 618) +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 619) static bool +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 620) free_load_extend (rtx src, insn_info *insn) +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 621) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 622) rtx reg = XEXP (src, 0); +3712c7a30197 gcc/fwprop.c (Richard Sandiford 2016-11-15 18:13:56 +0000 623) if (load_extend_op (GET_MODE (reg)) != GET_CODE (src)) +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 624) return false; +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 625) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 626) def_info *def = nullptr; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 627) for (use_info *use : insn->uses ()) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 628) if (use->regno () == REGNO (reg)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 629) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 630) def = use->def (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 631) break; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 632) } +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 633) +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 634) if (!def) +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 635) return false; +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 636) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 637) insn_info *def_insn = def->insn (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 638) if (def_insn->is_artificial ()) +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 639) return false; +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 640) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 641) rtx_insn *def_rtl = def_insn->rtl (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 642) if (NONJUMP_INSN_P (def_rtl)) +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 643) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 644) rtx patt = PATTERN (def_rtl); +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 645) +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 646) if (GET_CODE (patt) == SET +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 647) && GET_CODE (SET_SRC (patt)) == MEM +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 648) && rtx_equal_p (SET_DEST (patt), reg)) +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 649) return true; +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 650) } +e85122be92f7 gcc/fwprop.c (Alan Modra 2009-08-30 06:09:42 +0000 651) return false; +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 652) } +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 653) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 654) /* Subroutine of forward_propagate_subreg that handles a use of DEST +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 655) in REF. The other parameters are the same. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 656) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 657) static bool +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 658) forward_propagate_subreg (use_info *use, set_info *def, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 659) rtx dest, rtx src, df_ref ref) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 660) { +6b9c3decc38f gcc/fwprop.c (Richard Sandiford 2017-08-30 11:11:42 +0000 661) scalar_int_mode int_use_mode, src_mode; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 662) +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 663) /* Only consider subregs... */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 664) rtx use_reg = DF_REF_REG (ref); +ef4bddc299ea gcc/fwprop.c (Richard Sandiford 2014-10-29 12:02:45 +0000 665) machine_mode use_mode = GET_MODE (use_reg); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 666) if (GET_CODE (use_reg) != SUBREG +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 667) || GET_MODE (SUBREG_REG (use_reg)) != GET_MODE (dest)) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 668) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 669) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 670) /* ??? Replacing throughout the pattern would help for match_dups. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 671) rtx *loc = DF_REF_LOC (ref); +03a956218445 gcc/fwprop.c (Richard Sandiford 2017-08-22 16:14:48 +0000 672) if (paradoxical_subreg_p (use_reg)) +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 673) { +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 674) /* If this is a paradoxical SUBREG, we have no idea what value the +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 675) extra bits would have. However, if the operand is equivalent to +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 676) a SUBREG whose operand is the same as our mode, and all the modes +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 677) are within a word, we can just use the inner operand because +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 678) these SUBREGs just say how to treat the register. */ +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 679) if (GET_CODE (src) == SUBREG +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 680) && REG_P (SUBREG_REG (src)) +509a31f8e558 gcc/fwprop.c (H.J. Lu 2011-07-05 12:47:35 +0000 681) && REGNO (SUBREG_REG (src)) >= FIRST_PSEUDO_REGISTER +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 682) && GET_MODE (SUBREG_REG (src)) == use_mode +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 683) && subreg_lowpart_p (src)) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 684) return try_fwprop_subst (use, def, loc, use_reg, SUBREG_REG (src)); +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 685) } +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 686) +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 687) /* If this is a SUBREG of a ZERO_EXTEND or SIGN_EXTEND, and the SUBREG +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 688) is the low part of the reg being extended then just use the inner +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 689) operand. Don't do this if the ZERO_EXTEND or SIGN_EXTEND insn will +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 690) be removed due to it matching a LOAD_EXTEND_OP load from memory, +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 691) or due to the operation being a no-op when applied to registers. +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 692) For example, if we have: +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 693) +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 694) A: (set (reg:DI X) (sign_extend:DI (reg:SI Y))) +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 695) B: (... (subreg:SI (reg:DI X)) ...) +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 696) +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 697) and mode_rep_extended says that Y is already sign-extended, +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 698) the backend will typically allow A to be combined with the +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 699) definition of Y or, failing that, allow A to be deleted after +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 700) reload through register tying. Introducing more uses of Y +7a613929211d gcc/fwprop.c (Richard Sandiford 2011-12-19 22:05:28 +0000 701) prevents both optimisations. */ +6b9c3decc38f gcc/fwprop.c (Richard Sandiford 2017-08-30 11:11:42 +0000 702) else if (is_a <scalar_int_mode> (use_mode, &int_use_mode) +6b9c3decc38f gcc/fwprop.c (Richard Sandiford 2017-08-30 11:11:42 +0000 703) && subreg_lowpart_p (use_reg)) +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 704) { +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 705) if ((GET_CODE (src) == ZERO_EXTEND +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 706) || GET_CODE (src) == SIGN_EXTEND) +6b9c3decc38f gcc/fwprop.c (Richard Sandiford 2017-08-30 11:11:42 +0000 707) && is_a <scalar_int_mode> (GET_MODE (src), &src_mode) +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 708) && REG_P (XEXP (src, 0)) +509a31f8e558 gcc/fwprop.c (H.J. Lu 2011-07-05 12:47:35 +0000 709) && REGNO (XEXP (src, 0)) >= FIRST_PSEUDO_REGISTER +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 710) && GET_MODE (XEXP (src, 0)) == use_mode +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 711) && !free_load_extend (src, def->insn ()) +6b9c3decc38f gcc/fwprop.c (Richard Sandiford 2017-08-30 11:11:42 +0000 712) && (targetm.mode_rep_extended (int_use_mode, src_mode) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 713) != (int) GET_CODE (src))) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 714) return try_fwprop_subst (use, def, loc, use_reg, XEXP (src, 0)); +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 715) } +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 716) +e25b7843ec71 gcc/fwprop.c (Alan Modra 2009-08-23 02:57:26 +0000 717) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 718) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 719) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 720) /* Try to substitute (set DEST SRC), which defines DEF, into USE and simplify +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 721) the result, handling cases where DEST is used in a subreg and where +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 722) applying that subreg to SRC results in a useful simplification. */ +ce372372f42e gcc/fwprop.c (Jakub Jelinek 2009-04-26 20:56:14 +0200 723) +ce372372f42e gcc/fwprop.c (Jakub Jelinek 2009-04-26 20:56:14 +0200 724) static bool +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 725) forward_propagate_subreg (use_info *use, set_info *def, rtx dest, rtx src) +ce372372f42e gcc/fwprop.c (Jakub Jelinek 2009-04-26 20:56:14 +0200 726) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 727) if (!use->includes_subregs () || !REG_P (dest)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 728) return false; +ce372372f42e gcc/fwprop.c (Jakub Jelinek 2009-04-26 20:56:14 +0200 729) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 730) if (GET_CODE (src) != SUBREG +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 731) && GET_CODE (src) != ZERO_EXTEND +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 732) && GET_CODE (src) != SIGN_EXTEND) +ce372372f42e gcc/fwprop.c (Jakub Jelinek 2009-04-26 20:56:14 +0200 733) return false; +ce372372f42e gcc/fwprop.c (Jakub Jelinek 2009-04-26 20:56:14 +0200 734) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 735) rtx_insn *use_rtl = use->insn ()->rtl (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 736) df_ref ref; +ce372372f42e gcc/fwprop.c (Jakub Jelinek 2009-04-26 20:56:14 +0200 737) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 738) FOR_EACH_INSN_USE (ref, use_rtl) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 739) if (DF_REF_REGNO (ref) == use->regno () +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 740) && forward_propagate_subreg (use, def, dest, src, ref)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 741) return true; +ce372372f42e gcc/fwprop.c (Jakub Jelinek 2009-04-26 20:56:14 +0200 742) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 743) FOR_EACH_INSN_EQ_USE (ref, use_rtl) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 744) if (DF_REF_REGNO (ref) == use->regno () +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 745) && forward_propagate_subreg (use, def, dest, src, ref)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 746) return true; +ce372372f42e gcc/fwprop.c (Jakub Jelinek 2009-04-26 20:56:14 +0200 747) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 748) return false; +ce372372f42e gcc/fwprop.c (Jakub Jelinek 2009-04-26 20:56:14 +0200 749) } +ce372372f42e gcc/fwprop.c (Jakub Jelinek 2009-04-26 20:56:14 +0200 750) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 751) /* Try to substitute (set DEST SRC), which defines DEF, into USE and +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 752) simplify the result. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 753) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 754) static bool +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 755) forward_propagate_and_simplify (use_info *use, set_info *def, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 756) rtx dest, rtx src) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 757) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 758) insn_info *use_insn = use->insn (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 759) rtx_insn *use_rtl = use_insn->rtl (); +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 760) insn_info *def_insn = def->insn (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 761) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 762) /* ??? This check seems unnecessary. We should be able to propagate +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 763) into any kind of instruction, regardless of whether it's a single set. +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 764) It seems odd to be more permissive with asms than normal instructions. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 765) bool need_single_set = (!use_insn->is_asm () && !use_insn->is_debug_insn ()); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 766) rtx use_set = single_set (use_rtl); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 767) if (need_single_set && !use_set) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 768) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 769) +bd1cd0d0e0fe gcc/fwprop.c (Segher Boessenkool 2021-04-23 19:59:00 +0000 770) /* Do not propagate into PC etc. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 771) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 772) ??? This too seems unnecessary. The current code should work correctly +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 773) without it, including cases where jumps become unconditional. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 774) if (use_set && GET_MODE (SET_DEST (use_set)) == VOIDmode) +8e8af9b74d52 gcc/fwprop.c (Richard Sandiford 2011-09-27 17:24:03 +0000 775) return false; +8e8af9b74d52 gcc/fwprop.c (Richard Sandiford 2011-09-27 17:24:03 +0000 776) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 777) /* In __asm don't replace if src might need more registers than +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 778) reg, as that could increase register pressure on the __asm. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 779) if (use_insn->is_asm () && def_insn->uses ().size () > 1) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 780) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 781) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 782) /* Check if the def is loading something from the constant pool; in this +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 783) case we would undo optimization such as compress_float_constant. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 784) Still, we can set a REG_EQUAL note. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 785) if (MEM_P (src) && MEM_READONLY_P (src)) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 786) { +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 787) rtx x = avoid_constant_pool_reference (src); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 788) rtx note_set; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 789) if (x != src +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 790) && (note_set = set_for_reg_notes (use_rtl)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 791) && REG_P (SET_DEST (note_set)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 792) && !contains_paradoxical_subreg_p (SET_SRC (note_set))) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 793) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 794) rtx note = find_reg_note (use_rtl, REG_EQUAL, NULL_RTX); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 795) rtx old_rtx = note ? XEXP (note, 0) : SET_SRC (note_set); +605642891863 gcc/fwprop.c (Kaveh R. Ghazi 2008-07-15 17:51:00 +0000 796) rtx new_rtx = simplify_replace_rtx (old_rtx, src, x); +605642891863 gcc/fwprop.c (Kaveh R. Ghazi 2008-07-15 17:51:00 +0000 797) if (old_rtx != new_rtx) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 798) set_unique_reg_note (use_rtl, REG_EQUAL, copy_rtx (new_rtx)); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 799) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 800) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 801) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 802) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 803) /* ??? Unconditionally propagating into PATTERN would work better +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 804) for instructions that have match_dups. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 805) rtx *loc = need_single_set ? &use_set : &PATTERN (use_rtl); +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 806) return try_fwprop_subst (use, def, loc, dest, src); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 807) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 808) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 809) /* Given a use USE of an insn, if it has a single reaching +7360d2ac8dae gcc/fwprop.c (Jakub Jelinek 2011-01-21 20:34:03 +0100 810) definition, try to forward propagate it into that insn. +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 811) Return true if something changed. +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 812) +75da268e1a56 gcc/fwprop.c (Prathamesh Kulkarni 2019-07-04 06:48:42 +0000 813) REG_PROP_ONLY is true if we should only propagate register copies. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 814) +7360d2ac8dae gcc/fwprop.c (Jakub Jelinek 2011-01-21 20:34:03 +0100 815) static bool +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 816) forward_propagate_into (use_info *use, bool reg_prop_only = false) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 817) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 818) if (use->includes_read_writes ()) +7360d2ac8dae gcc/fwprop.c (Jakub Jelinek 2011-01-21 20:34:03 +0100 819) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 820) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 821) /* Disregard uninitialized uses. */ +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 822) set_info *def = use->def (); +00952e9784e4 gcc/fwprop.c (Paolo Bonzini 2009-05-08 12:22:30 +0000 823) if (!def) +7360d2ac8dae gcc/fwprop.c (Jakub Jelinek 2011-01-21 20:34:03 +0100 824) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 825) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 826) /* Only consider single-register definitions. This could be relaxed, +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 827) but it should rarely be needed before RA. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 828) def = look_through_degenerate_phi (def); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 829) if (def->includes_multiregs ()) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 830) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 831) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 832) /* Only consider uses whose definition comes from a real instruction. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 833) insn_info *def_insn = def->insn (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 834) if (def_insn->is_artificial ()) +7360d2ac8dae gcc/fwprop.c (Jakub Jelinek 2011-01-21 20:34:03 +0100 835) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 836) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 837) rtx_insn *def_rtl = def_insn->rtl (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 838) if (!NONJUMP_INSN_P (def_rtl)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 839) return false; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 840) /* ??? This seems an unnecessary restriction. We can easily tell +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 841) which set the definition comes from. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 842) if (multiple_sets (def_rtl)) +7360d2ac8dae gcc/fwprop.c (Jakub Jelinek 2011-01-21 20:34:03 +0100 843) return false; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 844) rtx def_set = simple_regno_set (PATTERN (def_rtl), def->regno ()); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 845) if (!def_set) +7360d2ac8dae gcc/fwprop.c (Jakub Jelinek 2011-01-21 20:34:03 +0100 846) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 847) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 848) rtx dest = SET_DEST (def_set); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 849) rtx src = SET_SRC (def_set); +a0e945888d97 gcc/fwprop.cc (Haochen Gui 2024-03-08 09:30:35 +0800 850) if (volatile_refs_p (src)) +a0e945888d97 gcc/fwprop.cc (Haochen Gui 2024-03-08 09:30:35 +0800 851) return false; +75da268e1a56 gcc/fwprop.c (Prathamesh Kulkarni 2019-07-04 06:48:42 +0000 852) +75da268e1a56 gcc/fwprop.c (Prathamesh Kulkarni 2019-07-04 06:48:42 +0000 853) /* Allow propagations into a loop only for reg-to-reg copies, since +e7a7dbb5ca5d gcc/fwprop.c (liuhongt 2021-12-20 11:13:38 +0800 854) replacing one register by another shouldn't increase the cost. +e7a7dbb5ca5d gcc/fwprop.c (liuhongt 2021-12-20 11:13:38 +0800 855) Propagations from inner loop to outer loop should also be ok. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 856) struct loop *def_loop = def_insn->bb ()->cfg_bb ()->loop_father; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 857) struct loop *use_loop = use->bb ()->cfg_bb ()->loop_father; +e7a7dbb5ca5d gcc/fwprop.c (liuhongt 2021-12-20 11:13:38 +0800 858) if ((reg_prop_only +e7a7dbb5ca5d gcc/fwprop.c (liuhongt 2021-12-20 11:13:38 +0800 859) || (def_loop != use_loop +e7a7dbb5ca5d gcc/fwprop.c (liuhongt 2021-12-20 11:13:38 +0800 860) && !flow_loop_nested_p (use_loop, def_loop))) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 861) && (!reg_single_def_p (dest) || !reg_single_def_p (src))) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 862) return false; +75da268e1a56 gcc/fwprop.c (Prathamesh Kulkarni 2019-07-04 06:48:42 +0000 863) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 864) /* Don't substitute into a non-local goto, this confuses CFG. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 865) insn_info *use_insn = use->insn (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 866) rtx_insn *use_rtl = use_insn->rtl (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 867) if (JUMP_P (use_rtl) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 868) && find_reg_note (use_rtl, REG_NON_LOCAL_GOTO, NULL_RTX)) +75da268e1a56 gcc/fwprop.c (Prathamesh Kulkarni 2019-07-04 06:48:42 +0000 869) return false; +75da268e1a56 gcc/fwprop.c (Prathamesh Kulkarni 2019-07-04 06:48:42 +0000 870) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 871) if (forward_propagate_and_simplify (use, def, dest, src) +b61461ac7f9b gcc/fwprop.c (Ilya Leoshkevich 2021-03-02 23:37:26 +0100 872) || forward_propagate_subreg (use, def, dest, src)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 873) return true; +a5a9046deb1a gcc/fwprop.c (Segher Boessenkool 2017-04-01 00:49:53 +0200 874) +7360d2ac8dae gcc/fwprop.c (Jakub Jelinek 2011-01-21 20:34:03 +0100 875) return false; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 876) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 877) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 878) static void +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 879) fwprop_init (void) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 880) { +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 881) num_changes = 0; +6e0b633f6c2b gcc/fwprop.c (Paolo Bonzini 2006-11-14 08:46:26 +0000 882) calculate_dominance_info (CDI_DOMINATORS); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 883) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 884) /* We do not always want to propagate into loops, so we have to find +c5f4be845ac0 gcc/fwprop.c (Steven Bosscher 2013-01-31 20:16:07 +0000 885) loops and be careful about them. Avoid CFG modifications so that +c5f4be845ac0 gcc/fwprop.c (Steven Bosscher 2013-01-31 20:16:07 +0000 886) we don't have to update dominance information afterwards for +c5f4be845ac0 gcc/fwprop.c (Steven Bosscher 2013-01-31 20:16:07 +0000 887) build_single_def_use_links. */ +c5f4be845ac0 gcc/fwprop.c (Steven Bosscher 2013-01-31 20:16:07 +0000 888) loop_optimizer_init (AVOID_CFG_MODIFICATIONS); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 889) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 890) df_analyze (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 891) crtl->ssa = new rtl_ssa::function_info (cfun); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 892) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 893) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 894) static void +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 895) fwprop_done (void) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 896) { +fb4061627b2c gcc/fwprop.c (Paolo Bonzini 2007-03-20 08:31:13 +0000 897) loop_optimizer_finalize (); +6fb5fa3cbc0d gcc/fwprop.c (Daniel Berlin 2007-06-11 18:02:15 +0000 898) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 899) crtl->ssa->perform_pending_updates (); +6e0b633f6c2b gcc/fwprop.c (Paolo Bonzini 2006-11-14 08:46:26 +0000 900) free_dominance_info (CDI_DOMINATORS); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 901) cleanup_cfg (0); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 902) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 903) delete crtl->ssa; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 904) crtl->ssa = nullptr; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 905) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 906) delete_trivially_dead_insns (get_insns (), max_reg_num ()); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 907) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 908) if (dump_file) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 909) fprintf (dump_file, +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 910) "\nNumber of successful forward propagations: %d\n\n", +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 911) num_changes); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 912) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 913) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 914) /* Try to optimize INSN, returning true if something changes. +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 915) FWPROP_ADDR_P is true if we are running fwprop_addr rather than +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 916) the full fwprop. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 917) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 918) static bool +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 919) fwprop_insn (insn_info *insn, bool fwprop_addr_p) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 920) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 921) for (use_info *use : insn->uses ()) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 922) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 923) if (use->is_mem ()) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 924) continue; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 925) /* ??? The choices here follow those in the pre-SSA code. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 926) if (!use->includes_address_uses ()) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 927) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 928) if (forward_propagate_into (use, fwprop_addr_p)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 929) return true; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 930) } +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 931) else +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 932) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 933) struct loop *loop = insn->bb ()->cfg_bb ()->loop_father; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 934) /* The outermost loop is not really a loop. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 935) if (loop == NULL || loop_outer (loop) == NULL) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 936) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 937) if (forward_propagate_into (use, fwprop_addr_p)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 938) return true; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 939) } +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 940) else if (fwprop_addr_p) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 941) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 942) if (forward_propagate_into (use, false)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 943) return true; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 944) } +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 945) } +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 946) } +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 947) return false; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 948) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 949) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 950) /* Main entry point. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 951) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 952) static bool +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 953) gate_fwprop (void) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 954) { +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 955) return optimize > 0 && flag_forward_propagate; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 956) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 957) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 958) static unsigned int +75da268e1a56 gcc/fwprop.c (Prathamesh Kulkarni 2019-07-04 06:48:42 +0000 959) fwprop (bool fwprop_addr_p) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 960) { +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 961) fwprop_init (); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 962) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 963) /* Go through all the instructions (including debug instructions) looking +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 964) for uses that we could propagate into. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 965) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 966) Do not forward propagate addresses into loops until after unrolling. +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 967) CSE did so because it was able to fix its own mess, but we are not. */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 968) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 969) insn_info *next; +75da268e1a56 gcc/fwprop.c (Prathamesh Kulkarni 2019-07-04 06:48:42 +0000 970) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 971) /* ??? This code uses a worklist in order to preserve the behavior +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 972) of the pre-SSA implementation. It would be better to instead +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 973) iterate on each instruction until no more propagations are +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 974) possible, then move on to the next. */ +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 975) auto_vec<insn_info *> worklist; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 976) for (insn_info *insn = crtl->ssa->first_insn (); insn; insn = next) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 977) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 978) next = insn->next_any_insn (); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 979) if (insn->can_be_optimized () || insn->is_debug_insn ()) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 980) if (fwprop_insn (insn, fwprop_addr_p)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 981) worklist.safe_push (insn); +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 982) } +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 983) for (unsigned int i = 0; i < worklist.length (); ++i) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 984) { +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 985) insn_info *insn = worklist[i]; +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 986) if (fwprop_insn (insn, fwprop_addr_p)) +0b76990a9d75 gcc/fwprop.c (Richard Sandiford 2020-12-17 00:15:12 +0000 987) worklist.safe_push (insn); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 988) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 989) +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 990) fwprop_done (); +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 991) return 0; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 992) } +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 993) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 994) namespace { +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 995) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 996) const pass_data pass_data_rtl_fwprop = +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 997) { +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 998) RTL_PASS, /* type */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 999) "fwprop1", /* name */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1000) OPTGROUP_NONE, /* optinfo_flags */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1001) TV_FWPROP, /* tv_id */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1002) 0, /* properties_required */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1003) 0, /* properties_provided */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1004) 0, /* properties_destroyed */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1005) 0, /* todo_flags_start */ +3bea341fbd27 gcc/fwprop.c (Richard Biener 2014-05-06 13:35:40 +0000 1006) TODO_df_finish, /* todo_flags_finish */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 1007) }; +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 1008) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1009) class pass_rtl_fwprop : public rtl_opt_pass +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1010) { +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1011) public: +c3284718808c gcc/fwprop.c (Richard Sandiford 2013-09-28 08:42:34 +0000 1012) pass_rtl_fwprop (gcc::context *ctxt) +c3284718808c gcc/fwprop.c (Richard Sandiford 2013-09-28 08:42:34 +0000 1013) : rtl_opt_pass (pass_data_rtl_fwprop, ctxt) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1014) {} +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1015) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1016) /* opt_pass methods: */ +725793af7806 gcc/fwprop.cc (David Malcolm 2022-06-27 17:00:33 -0400 1017) bool gate (function *) final override { return gate_fwprop (); } +725793af7806 gcc/fwprop.cc (David Malcolm 2022-06-27 17:00:33 -0400 1018) unsigned int execute (function *) final override { return fwprop (false); } +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1019) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1020) }; // class pass_rtl_fwprop +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1021) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1022) } // anon namespace +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1023) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1024) rtl_opt_pass * +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1025) make_pass_rtl_fwprop (gcc::context *ctxt) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1026) { +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1027) return new pass_rtl_fwprop (ctxt); +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1028) } +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1029) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1030) namespace { +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1031) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1032) const pass_data pass_data_rtl_fwprop_addr = +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 1033) { +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1034) RTL_PASS, /* type */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1035) "fwprop2", /* name */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1036) OPTGROUP_NONE, /* optinfo_flags */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1037) TV_FWPROP, /* tv_id */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1038) 0, /* properties_required */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1039) 0, /* properties_provided */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1040) 0, /* properties_destroyed */ +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1041) 0, /* todo_flags_start */ +3bea341fbd27 gcc/fwprop.c (Richard Biener 2014-05-06 13:35:40 +0000 1042) TODO_df_finish, /* todo_flags_finish */ +a52b023a5f03 gcc/fwprop.c (Paolo Bonzini 2006-11-04 08:36:45 +0000 1043) }; +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1044) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1045) class pass_rtl_fwprop_addr : public rtl_opt_pass +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1046) { +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1047) public: +c3284718808c gcc/fwprop.c (Richard Sandiford 2013-09-28 08:42:34 +0000 1048) pass_rtl_fwprop_addr (gcc::context *ctxt) +c3284718808c gcc/fwprop.c (Richard Sandiford 2013-09-28 08:42:34 +0000 1049) : rtl_opt_pass (pass_data_rtl_fwprop_addr, ctxt) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1050) {} +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1051) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1052) /* opt_pass methods: */ +725793af7806 gcc/fwprop.cc (David Malcolm 2022-06-27 17:00:33 -0400 1053) bool gate (function *) final override { return gate_fwprop (); } +725793af7806 gcc/fwprop.cc (David Malcolm 2022-06-27 17:00:33 -0400 1054) unsigned int execute (function *) final override { return fwprop (true); } +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1055) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1056) }; // class pass_rtl_fwprop_addr +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1057) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1058) } // anon namespace +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1059) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1060) rtl_opt_pass * +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1061) make_pass_rtl_fwprop_addr (gcc::context *ctxt) +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1062) { +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1063) return new pass_rtl_fwprop_addr (ctxt); +27a4cd485d37 gcc/fwprop.c (David Malcolm 2013-08-05 20:16:05 +0000 1064) } diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 789faf66cb8e..6f7efafb8abe 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -2925,7 +2925,9 @@ ;; for IOR/XOR. It probably doesn't matter for AND. ;; ;; We also don't want to do this if the immediate already fits in a simm12 -;; field. +;; field, or is a single bit operand, or when we might be able to generate +;; a shift-add sequence via the splitter in bitmanip.md +;; in bitmanip.md for masks that are a run of consecutive ones. (define_insn_and_split "<optab>_shift_reverse<X:mode>" [(set (match_operand:X 0 "register_operand" "=r") (any_bitwise:X (ashift:X (match_operand:X 1 "register_operand" "r") @@ -2934,9 +2936,9 @@ "(!SMALL_OPERAND (INTVAL (operands[3])) && SMALL_OPERAND (INTVAL (operands[3]) >> INTVAL (operands[2])) && popcount_hwi (INTVAL (operands[3])) > 1 - && (!TARGET_64BIT - || (exact_log2 ((INTVAL (operands[3]) >> INTVAL (operands[2])) + 1) - == -1)) + && (!(TARGET_64BIT && TARGET_ZBA) + || !consecutive_bits_operand (operands[3], VOIDmode) + || !imm123_operand (operands[2], VOIDmode)) && (INTVAL (operands[3]) & ((1ULL << INTVAL (operands[2])) - 1)) == 0)" "#" "&& 1" diff --git a/gcc/testsuite/gcc.target/riscv/pr115921.c b/gcc/testsuite/gcc.target/riscv/pr115921.c new file mode 100644 index 000000000000..e508e7ce790f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr115921.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc_zba" { target { rv64 } } } */ +/* { dg-options "-O2 -march=rv32gc_zba" { target { rv32 } } } */ + +typedef unsigned long target_wide_uint_t; + +target_wide_uint_t test_ashift_and(target_wide_uint_t x) { + return (x & 0x3f) << 12; +} + +/* { dg-final { scan-assembler-times "\\sandi" 1 } } */ +/* { dg-final { scan-assembler-times "\\sslli" 1 } } */ +