Factor common RTL parsing out of the existing macro-fusion
recognizers. Preserve aggressive destination overmatching before
register allocation while checking real producer-consumer dependencies
in both scheduling passes.
Use parameterized arithmetic and memory classifiers so later fusion
recognizers can share structural matching without duplicating
microarchitecture-specific constraints.
gcc/ChangeLog:
* config/riscv/riscv-fusion.cc: Include insn-attr.h.
(riscv_fuse_sets_p): New function.
(riscv_set_extract_word_binary_p): Likewise.
(riscv_regno): Likewise.
(riscv_fuse_same_reg_p): Likewise.
(riscv_fuse_same_dest_p): Rename from
riscv_fusion_same_dest_p and handle hard-register SUBREGs. Preserve
preallocation destination overmatching and optionally check the
first-source dependency.
(riscv_set_is_addiw_p): New function.
(riscv_insn_is_mv_li_p): Likewise.
(riscv_insn_is_addi_type_p): Likewise.
(riscv_set_is_shift_p): Likewise.
(riscv_set_is_slli_p): Likewise.
(riscv_set_is_srli_p): Likewise.
(riscv_set_is_srai_p): Likewise.
(enum sched_fusion_type): New enum.
(riscv_fusion_mem_info): New struct.
(riscv_fuse_extract_address): New function.
(riscv_fuse_mem_p): Likewise.
(riscv_fuse_zext_common): Require RV64 and use the common
helpers.
(riscv_fuse_zextw): Update accordingly.
(riscv_fuse_zextws): Likewise.
(riscv_fuse_zexth): Likewise.
(riscv_fuse_ldindexed): Use the common helpers.
(riscv_fuse_expanded_ld): Likewise.
(riscv_fuse_ldpreincrement): Likewise. Check the update dependency.
(riscv_fuse_lui_addi): Reuse the ADDI matcher, check the source
dependency, and reject zero-valued LUI patterns.
(riscv_fuse_auipc_addi): Reuse the ADDI matcher and check the source
dependency.
(riscv_fuse_lui_ld): Use the common helpers.
(riscv_fuse_auipc_ld): Likewise. Check the address dependency.
(riscv_fuse_aligned_std): Use the common helpers.
(riscv_fuse_bfext): Likewise.
(riscv_fuse_b_alui): Likewise.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/fusion-lui-addi-prera-rtl.c: New test.
Signed-off-by: Jin Ma <[email protected]>
---
gcc/config/riscv/riscv-fusion.cc | 847 ++++++++++++------
.../riscv/fusion-lui-addi-prera-rtl.c | 63 ++
2 files changed, 648 insertions(+), 262 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-lui-addi-prera-rtl.c
diff --git a/gcc/config/riscv/riscv-fusion.cc b/gcc/config/riscv/riscv-fusion.cc
index 2ce9b965974..88735b580f1 100644
--- a/gcc/config/riscv/riscv-fusion.cc
+++ b/gcc/config/riscv/riscv-fusion.cc
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see
#include "rtl.h"
#include "regs.h"
#include "insn-config.h"
+#include "insn-attr.h"
#include "recog.h"
#include "function.h"
#include "memmodel.h"
@@ -51,25 +52,160 @@ riscv_fusion_enabled_p (enum riscv_fusion_pairs op)
return riscv_get_fusible_ops () & op;
}
-/* Return true if PREV_SET and CURR_SET satisfy the same-dest constraint
- required by most fusion rules: when we are past register allocation
- (i.e. can_create_pseudo_p () is false), the destination registers of
- the two sets must be the same physical register. */
+/* Extract the single sets from PREV and CURR. Reject conditional jumps,
+ which cannot form a fusion pair. */
static bool
-riscv_fusion_same_dest_p (rtx prev_set, rtx curr_set)
+riscv_fuse_sets_p (rtx_insn *prev, rtx_insn *curr,
+ rtx *prev_set_out = NULL,
+ rtx *curr_set_out = NULL)
{
+ rtx prev_set = single_set (prev);
+ rtx curr_set = single_set (curr);
+ if (prev_set_out)
+ *prev_set_out = prev_set;
+ if (curr_set_out)
+ *curr_set_out = curr_set;
+ return prev_set && curr_set && !any_condjump_p (curr);
+}
+
+/* Extract a word-form binary operation with code CODE:
+ (set (reg:DI rd)
+ (sign_extend:DI (op:SI operand1 operand2)))
+ or
+ (set (reg:DI rd)
+ (sign_extend:DI (truncate:SI (op:DI operand1 operand2))))
+ or
+ (set (reg:DI rd)
+ (sign_extend:DI (subreg:SI (op:DI operand1 operand2) 0)))
+ Store the binary operation in *BINARY_SRC. */
+
+static bool
+riscv_set_extract_word_binary_p (rtx set, rtx_code code, rtx *binary_src)
+{
+ if (!TARGET_64BIT)
+ return false;
+
+ rtx src = SET_SRC (set);
+ *binary_src = NULL_RTX;
+
+ if (GET_CODE (src) != SIGN_EXTEND
+ || GET_MODE (src) != DImode)
+ return false;
+
+ src = XEXP (src, 0);
+ if (GET_CODE (src) == code && GET_MODE (src) == SImode)
+ {
+ *binary_src = src;
+ return true;
+ }
+
+ if (GET_MODE (src) != SImode)
+ return false;
+
+ if (GET_CODE (src) == TRUNCATE)
+ src = XEXP (src, 0);
+ else if (SUBREG_P (src) && subreg_lowpart_p (src))
+ src = SUBREG_REG (src);
+ else
+ return false;
+
+ if (GET_CODE (src) == code && GET_MODE (src) == DImode)
+ {
+ *binary_src = src;
+ return true;
+ }
+
+ return false;
+}
+
+/* Return a comparable register number for X, accounting for hard-register
+ SUBREG offsets, or INVALID_REGNUM. */
+
+static unsigned int
+riscv_regno (rtx x)
+{
+ int regno = true_regnum (x);
+ if (regno >= 0
+ && (can_create_pseudo_p () || regno < FIRST_PSEUDO_REGISTER))
+ return regno;
+
+ /* Before allocation, use an unassigned pseudo's identity. Treat every
+ SUBREG of the pseudo alike so that matching remains deliberately
+ permissive until the final hard register is known. */
if (can_create_pseudo_p ())
- return true;
+ {
+ rtx reg = SUBREG_P (x) ? SUBREG_REG (x) : x;
+ if (REG_P (reg) && !HARD_REGISTER_P (reg))
+ return REGNO (reg);
+ }
+
+ return INVALID_REGNUM;
+}
+
+/* Return true if X and Y refer to the same comparable register. */
- unsigned int prev_dest_regno = (REG_P (SET_DEST (prev_set))
- ? REGNO (SET_DEST (prev_set))
- : FIRST_PSEUDO_REGISTER);
- unsigned int curr_dest_regno = (REG_P (SET_DEST (curr_set))
- ? REGNO (SET_DEST (curr_set))
- : FIRST_PSEUDO_REGISTER);
+static bool
+riscv_fuse_same_reg_p (rtx x, rtx y)
+{
+ unsigned int x_regno = riscv_regno (x);
+ unsigned int y_regno = riscv_regno (y);
- return prev_dest_regno == curr_dest_regno;
+ return (x_regno != INVALID_REGNUM
+ && y_regno != INVALID_REGNUM
+ && x_regno == y_regno);
+}
+
+/* Return true if PREV_SET and CURR_SET satisfy the same-destination
+ constraint. Before allocation, defer the destination-register comparison
+ so that the scheduler can keep potential fusion pairs together. If
+ USED_IN_SRC_P, always require CURR_SET to use PREV_SET's destination as its
+ first source operand. After allocation, also require the hard-register
+ destinations to match. */
+
+static bool
+riscv_fuse_same_dest_p (rtx prev_set, rtx curr_set,
+ bool used_in_src_p = false)
+{
+ rtx prev_dest = SET_DEST (prev_set);
+ rtx curr_dest = SET_DEST (curr_set);
+ unsigned int prev_dest_regno = riscv_regno (prev_dest);
+ if (prev_dest_regno == INVALID_REGNUM
+ || riscv_regno (curr_dest) == INVALID_REGNUM)
+ return false;
+
+ if (used_in_src_p)
+ {
+ rtx src = SET_SRC (curr_set);
+ rtx word_add_src;
+ if (riscv_set_extract_word_binary_p (curr_set, PLUS,
+ &word_add_src))
+ src = XEXP (word_add_src, 0);
+ else
+ {
+ while (GET_CODE (src) == SIGN_EXTEND
+ || GET_CODE (src) == ZERO_EXTEND)
+ src = XEXP (src, 0);
+
+ if (GET_CODE (src) == NOT
+ || BINARY_P (src)
+ || GET_CODE (src) == LO_SUM
+ || GET_CODE (src) == ZERO_EXTRACT)
+ src = XEXP (src, 0);
+
+ while (GET_CODE (src) == SIGN_EXTEND
+ || GET_CODE (src) == ZERO_EXTEND)
+ src = XEXP (src, 0);
+ }
+
+ if (!riscv_fuse_same_reg_p (src, prev_dest))
+ return false;
+ }
+
+ if (can_create_pseudo_p ())
+ return true;
+
+ return riscv_fuse_same_reg_p (prev_dest, curr_dest);
}
/* Matches an add:
@@ -147,28 +283,324 @@ riscv_set_is_shNadduw_p (rtx set)
&& REG_P (SET_DEST (set)));
}
+/* Matches an addiw:
+ (set (reg:DI rd)
+ (sign_extend:DI (plus:SI (reg:SI rs1) (const_int imm12))))
+ or an equivalent word-add RTL form. */
+
+static bool
+riscv_set_is_addiw_p (rtx set, rtx *src0 = NULL)
+{
+ if (!TARGET_64BIT)
+ return false;
+
+ rtx src;
+ if (riscv_set_extract_word_binary_p (set, PLUS, &src)
+ && REG_P (XEXP (src, 0))
+ && CONST_INT_P (XEXP (src, 1))
+ && REG_P (SET_DEST (set)))
+ {
+ if (src0)
+ *src0 = XEXP (src, 0);
+ return true;
+ }
+
+ return false;
+}
+
+/* Matches an mv or li instruction:
+ (set (reg rd) (reg rs1))
+ or:
+ (set (reg rd) (const_int imm12)). */
+
+static bool
+riscv_insn_is_mv_li_p (rtx_insn *insn)
+{
+ rtx set = single_set (insn);
+ if (!set)
+ return false;
+
+ rtx dest = SET_DEST (set);
+ rtx src = SET_SRC (set);
+
+ /* Pseudos are valid GPR candidates before register allocation. */
+ if (get_attr_type (insn) != TYPE_MOVE
+ || get_attr_length (insn) > 4
+ || !REG_P (dest)
+ || (HARD_REGISTER_P (dest) && !GP_REG_P (REGNO (dest))))
+ return false;
+
+ enum attr_move_type move_type = get_attr_move_type (insn);
+ if (move_type == MOVE_TYPE_MOVE
+ && REG_P (src)
+ && (!HARD_REGISTER_P (src)
+ || GP_REG_P (REGNO (src))))
+ return true;
+
+ if (move_type == MOVE_TYPE_CONST
+ && CONST_INT_P (src)
+ /* Distinguish an ADDI-based LI from other single-insn constants. */
+ && SMALL_OPERAND (INTVAL (src)))
+ return true;
+
+ return false;
+}
+
+/* Matches an addi-type instruction:
+ (set (reg rd) (plus (reg rs1) (const_int imm12)))
+ or:
+ (set (reg rd) (lo_sum (reg rs1) symbol))
+ or an accepted addiw, mv, or li form. ALLOW_WORD_P controls whether
+ ADDIW is accepted. Store the register source in *SRC0 when available. */
+
+static bool
+riscv_insn_is_addi_type_p (rtx_insn *insn, bool allow_word_p = true,
+ rtx *src0 = NULL)
+{
+ rtx set = single_set (insn);
+ if (!set)
+ return false;
+
+ rtx src = SET_SRC (set);
+ if (riscv_insn_is_mv_li_p (insn))
+ {
+ if (src0 && REG_P (src))
+ *src0 = src;
+ return true;
+ }
+
+ if (get_attr_type (insn) != TYPE_ARITH)
+ return false;
+
+ if (GET_CODE (src) == LO_SUM
+ && GET_MODE (src) == Pmode
+ && REG_P (XEXP (src, 0)))
+ {
+ if (src0)
+ *src0 = XEXP (src, 0);
+ return true;
+ }
+
+ if (riscv_set_is_addi_p (set))
+ {
+ if (!allow_word_p && GET_MODE (src) != Pmode)
+ return false;
+ if (src0)
+ *src0 = XEXP (src, 0);
+ return true;
+ }
+
+ if (allow_word_p
+ && riscv_set_is_addiw_p (set, src0))
+ return true;
+
+ return false;
+}
+
+/* Return true if SET is a non-wrapped scalar shift of CODE. */
+
+static bool
+riscv_set_is_shift_p (rtx set, rtx_code code)
+{
+ rtx src = SET_SRC (set);
+ machine_mode mode = GET_MODE (src);
+
+ if (GET_CODE (src) != code || !CONST_INT_P (XEXP (src, 1)))
+ return false;
+
+ if (((TARGET_64BIT && mode == DImode) || mode == SImode)
+ && riscv_regno (XEXP (src, 0)) != INVALID_REGNUM
+ && REG_P (SET_DEST (set)))
+ return true;
+
+ return false;
+}
+
+/* Matches an slli:
+ (set (reg rd) (ashift (reg rs1) (const_int shamt))). */
+
+static bool
+riscv_set_is_slli_p (rtx set)
+{
+ return riscv_set_is_shift_p (set, ASHIFT);
+}
+
+/* Matches an srli:
+ (set (reg rd) (lshiftrt (reg rs1) (const_int shamt))). */
+
+static bool
+riscv_set_is_srli_p (rtx set)
+{
+ return riscv_set_is_shift_p (set, LSHIFTRT);
+}
+
+/* Matches an srai:
+ (set (reg rd) (ashiftrt (reg rs1) (const_int shamt))). */
+
+static bool
+riscv_set_is_srai_p (rtx set)
+{
+ return riscv_set_is_shift_p (set, ASHIFTRT);
+}
+
+/* Load/store classes used by fusion checks. */
+enum sched_fusion_type
+{
+ SCHED_FUSION_LD_SIGN_EXTEND = 0,
+ SCHED_FUSION_LD_ZERO_EXTEND,
+ SCHED_FUSION_LD,
+ SCHED_FUSION_ST
+};
+
+/* Fusion-relevant information about a scalar load or store. */
+
+struct riscv_fusion_mem_info
+{
+ enum sched_fusion_type type;
+ struct riscv_address_info addr;
+ machine_mode mode;
+ bool fp_p;
+};
+
+/* Extract fusion-relevant information from scalar load/store address X. */
+
+static bool
+riscv_fuse_extract_address (rtx x, struct riscv_address_info *addr)
+{
+ switch (GET_CODE (x))
+ {
+ case REG:
+ case SUBREG:
+ addr->type = ADDRESS_REG;
+ addr->reg = x;
+ addr->offset = const0_rtx;
+ break;
+
+ case PLUS:
+ if (!CONST_INT_P (XEXP (x, 1)))
+ return false;
+
+ addr->type = ADDRESS_REG;
+ addr->reg = XEXP (x, 0);
+ addr->offset = XEXP (x, 1);
+ break;
+
+ case LO_SUM:
+ addr->type = ADDRESS_LO_SUM;
+ addr->reg = XEXP (x, 0);
+ addr->offset = XEXP (x, 1);
+ break;
+
+ default:
+ return false;
+ }
+
+ return riscv_regno (addr->reg) != INVALID_REGNUM;
+}
+
+/* Extract a scalar integer or floating-point load/store into *INFO:
+ (set (reg rd) (mem addr))
+ or:
+ (set (reg rd) (any_extend (mem addr)))
+ or:
+ (set (reg frd) (mem addr))
+ or:
+ (set (mem addr) (reg rs1))
+ or:
+ (set (mem addr) (const_int 0))
+ or:
+ (set (mem addr) (reg frs1)). */
+
+static bool
+riscv_fuse_mem_p (rtx_insn *insn, struct riscv_fusion_mem_info *info)
+{
+ gcc_assert (INSN_P (insn));
+
+ rtx set = single_set (insn);
+ if (!set)
+ return false;
+
+ rtx dest = SET_DEST (set);
+ rtx src = SET_SRC (set);
+ info->type = SCHED_FUSION_LD;
+
+ if (GET_CODE (src) == SIGN_EXTEND
+ || GET_CODE (src) == ZERO_EXTEND)
+ {
+ info->type = (GET_CODE (src) == SIGN_EXTEND
+ ? SCHED_FUSION_LD_SIGN_EXTEND
+ : SCHED_FUSION_LD_ZERO_EXTEND);
+ src = XEXP (src, 0);
+ if (!MEM_P (src))
+ return false;
+ }
+
+ /* Exclude RVV loads and stores. */
+ if (riscv_vector_mode_p (GET_MODE (dest))
+ || riscv_vector_mode_p (GET_MODE (src)))
+ return false;
+
+ if (!MEM_P (src) && !MEM_P (dest))
+ return false;
+
+ rtx mem = MEM_P (src) ? src : dest;
+ poly_uint64 mode_size = GET_MODE_SIZE (GET_MODE (mem));
+ /* Reject wide moves that split into multiple instructions, except for
+ single 64-bit FPR or Zilsd moves on RV32. */
+ if (get_attr_length (insn) > 4
+ && known_gt (mode_size, 0U + UNITS_PER_WORD)
+ && (!known_eq (mode_size, 8U)
+ || riscv_split_64bit_move_p (dest, src)))
+ return false;
+
+ bool isload_p = MEM_P (src);
+ if (isload_p)
+ {
+ if (riscv_regno (dest) == INVALID_REGNUM)
+ return false;
+ }
+ else
+ {
+ if (src != const0_rtx && riscv_regno (src) == INVALID_REGNUM)
+ return false;
+ info->type = SCHED_FUSION_ST;
+ }
+
+ info->mode = GET_MODE (mem);
+ if (!riscv_fuse_extract_address (XEXP (mem, 0), &info->addr))
+ return false;
+
+ enum attr_type type = get_attr_type (insn);
+ if (type == (isload_p ? TYPE_LOAD : TYPE_STORE))
+ info->fp_p = false;
+ else if (type == (isload_p ? TYPE_FPLOAD : TYPE_FPSTORE))
+ info->fp_p = true;
+ else
+ return false;
+
+ return true;
+}
+
/* Check the common RTL for ZEXTW, ZEXTWS and ZEXTH fusion. */
static bool
riscv_fuse_zext_common (rtx_insn *prev, rtx_insn *curr,
- int shl_amount, bool zextws_p)
+ int shl_amount, bool zextws_p)
{
- rtx prev_set = single_set (prev);
- rtx curr_set = single_set (curr);
- if (!prev_set || !curr_set || any_condjump_p (curr))
+ if (!TARGET_64BIT)
return false;
- if (!riscv_fusion_same_dest_p (prev_set, curr_set))
+ rtx prev_set, curr_set;
+ if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
return false;
- if (GET_CODE (SET_SRC (prev_set)) == ASHIFT
- && GET_CODE (SET_SRC (curr_set)) == LSHIFTRT
- && REG_P (SET_DEST (prev_set))
- && REG_P (SET_DEST (curr_set))
- && REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (curr_set))
- && CONST_INT_P (XEXP (SET_SRC (prev_set), 1))
- && CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
+ if (!riscv_fuse_same_dest_p (prev_set, curr_set, true))
+ return false;
+
+ if (riscv_set_is_slli_p (prev_set)
+ && riscv_set_is_srli_p (curr_set)
+ && GET_MODE (SET_SRC (prev_set)) == DImode
+ && GET_MODE (SET_SRC (curr_set)) == DImode
&& INTVAL (XEXP (SET_SRC (prev_set), 1)) == shl_amount
&& (zextws_p
? INTVAL (XEXP (SET_SRC (curr_set), 1)) < shl_amount
@@ -178,6 +610,8 @@ riscv_fuse_zext_common (rtx_insn *prev, rtx_insn *curr,
return false;
}
+/* Fusion recognizers. */
+
/* Check for RISCV_FUSE_ZEXTW fusion.
prev (slli) == (set (reg:DI rd1)
(ashift:DI (reg:DI rs1) (const_int 32)))
@@ -237,35 +671,22 @@ riscv_fuse_zexth (rtx_insn *prev, rtx_insn *curr)
static bool
riscv_fuse_ldindexed (rtx_insn *prev, rtx_insn *curr)
{
- rtx prev_set = single_set (prev);
- rtx curr_set = single_set (curr);
- if (!prev_set || !curr_set || any_condjump_p (curr))
+ rtx prev_set, curr_set;
+ if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
return false;
- if (!riscv_fusion_same_dest_p (prev_set, curr_set))
+ if (!riscv_fuse_same_dest_p (prev_set, curr_set))
return false;
- if (MEM_P (SET_SRC (curr_set))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set))
- && GET_CODE (SET_SRC (prev_set)) == PLUS
- && REG_P (XEXP (SET_SRC (prev_set), 0))
- && REG_P (XEXP (SET_SRC (prev_set), 1)))
- return true;
+ struct riscv_fusion_mem_info mem;
- /* curr (lw) == (set (reg:DI rd2)
- (any_extend:DI (mem:SUBX (reg:DI rd1)))). */
- if ((GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND
- || (GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND))
- && MEM_P (XEXP (SET_SRC (curr_set), 0))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && REG_P (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- && (REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- == REGNO (SET_DEST (prev_set)))
- && GET_CODE (SET_SRC (prev_set)) == PLUS
- && REG_P (XEXP (SET_SRC (prev_set), 0))
- && REG_P (XEXP (SET_SRC (prev_set), 1)))
+ if (riscv_fuse_mem_p (curr, &mem)
+ && mem.type != SCHED_FUSION_ST
+ && !mem.fp_p
+ && mem.addr.type == ADDRESS_REG
+ && INTVAL (mem.addr.offset) == 0
+ && riscv_set_is_add_p (prev_set)
+ && riscv_fuse_same_reg_p (mem.addr.reg, SET_DEST (prev_set)))
return true;
return false;
@@ -299,72 +720,29 @@ riscv_fuse_ldindexed (rtx_insn *prev, rtx_insn *curr)
static bool
riscv_fuse_expanded_ld (rtx_insn *prev, rtx_insn *curr)
{
- rtx prev_set = single_set (prev);
- rtx curr_set = single_set (curr);
- if (!prev_set || !curr_set || any_condjump_p (curr))
+ rtx prev_set, curr_set;
+ if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
return false;
- if (!riscv_fusion_same_dest_p (prev_set, curr_set))
+ if (!riscv_fuse_same_dest_p (prev_set, curr_set))
return false;
- /* Match a load with displacement:
- curr (load) == (set (reg rd2)
- (mem (plus (reg rd1) (const_int offset)))) */
- if (MEM_P (SET_SRC (curr_set))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS
- && REG_P (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- && (REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- == REGNO (SET_DEST (prev_set))))
- {
- if (riscv_set_is_add_p (prev_set)
- || riscv_set_is_addi_p (prev_set)
- || riscv_set_is_shNadd_p (prev_set))
- return true;
- }
-
- /* Match a load without displacement:
- curr (load) == (set (reg rd2) (mem (reg rd1))). */
- if (MEM_P (SET_SRC (curr_set))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set)))
- {
- if (riscv_set_is_addi_p (prev_set)
- || riscv_set_is_shNadd_p (prev_set))
- return true;
- }
+ struct riscv_fusion_mem_info mem;
+ if (!riscv_fuse_mem_p (curr, &mem)
+ || mem.type == SCHED_FUSION_ST
+ || mem.fp_p
+ || mem.addr.type != ADDRESS_REG
+ || !riscv_fuse_same_reg_p (mem.addr.reg, SET_DEST (prev_set)))
+ return false;
- /* Match lw with displacement. */
- if ((GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND
- || (GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND))
- && MEM_P (XEXP (SET_SRC (curr_set), 0))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && GET_CODE (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == PLUS
- && REG_P (XEXP (XEXP (XEXP (SET_SRC (curr_set), 0), 0), 0))
- && (REGNO (XEXP (XEXP (XEXP (SET_SRC (curr_set), 0), 0), 0))
- == REGNO (SET_DEST (prev_set))))
- {
- if (riscv_set_is_adduw_p (prev_set)
- || riscv_set_is_shNadduw_p (prev_set))
- return true;
- }
+ bool displaced_p = INTVAL (mem.addr.offset) != 0;
+ if (mem.type == SCHED_FUSION_LD)
+ return ((displaced_p && riscv_set_is_add_p (prev_set))
+ || riscv_set_is_addi_p (prev_set)
+ || riscv_set_is_shNadd_p (prev_set));
- /* Match lw without displacement. */
- if ((GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND
- || (GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND))
- && MEM_P (XEXP (SET_SRC (curr_set), 0))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && REG_P (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- && (REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- == REGNO (SET_DEST (prev_set))))
- {
- if (riscv_set_is_adduw_p (prev_set)
- || riscv_set_is_shNadduw_p (prev_set))
- return true;
- }
-
- return false;
+ return (riscv_set_is_adduw_p (prev_set)
+ || riscv_set_is_shNadduw_p (prev_set));
}
/* Check for RISCV_FUSE_LDPREINCREMENT fusion.
@@ -378,21 +756,24 @@ riscv_fuse_expanded_ld (rtx_insn *prev, rtx_insn *curr)
static bool
riscv_fuse_ldpreincrement (rtx_insn *prev, rtx_insn *curr)
{
- rtx prev_set = single_set (prev);
- rtx curr_set = single_set (curr);
- if (!prev_set || !curr_set || any_condjump_p (curr))
+ rtx prev_set, curr_set;
+ if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
return false;
- if (!riscv_fusion_same_dest_p (prev_set, curr_set))
+ if (!riscv_fuse_same_dest_p (prev_set, curr_set))
return false;
- if (MEM_P (SET_SRC (curr_set))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set))
- && GET_CODE (SET_SRC (prev_set)) == PLUS
- && REG_P (XEXP (SET_SRC (prev_set), 0))
- && CONST_INT_P (XEXP (SET_SRC (prev_set), 1)))
+ struct riscv_fusion_mem_info mem;
+
+ if (riscv_fuse_mem_p (curr, &mem)
+ && mem.type == SCHED_FUSION_LD
+ && !mem.fp_p
+ && mem.addr.type == ADDRESS_REG
+ && INTVAL (mem.addr.offset) == 0
+ && riscv_set_is_addi_p (prev_set)
+ && riscv_fuse_same_reg_p (XEXP (SET_SRC (prev_set), 0),
+ SET_DEST (prev_set))
+ && riscv_fuse_same_reg_p (mem.addr.reg, SET_DEST (prev_set)))
return true;
return false;
@@ -403,33 +784,31 @@ riscv_fuse_ldpreincrement (rtx_insn *prev, rtx_insn *curr)
(lui) == (set (reg rd1) (const_int imm20))
(lui) == (set (reg rd1) (high symbol1))
curr (one of the following):
- (addi) == (set (reg rd2)
- (plus (reg rd1) (const_int imm12)))
+ (addi/addiw) == (set (reg rd2)
+ (plus (reg rd1) (const_int imm12)))
(addi) == (set (reg rd2)
(lo_sum (reg rd1) symbol2))
+ (self-mv) == (set (reg rd2) (reg rd1))
Constraints:
rd1 == rd2
- rd1 != x0
imm20 != 0 for the constant form. */
static bool
riscv_fuse_lui_addi (rtx_insn *prev, rtx_insn *curr)
{
- rtx prev_set = single_set (prev);
- rtx curr_set = single_set (curr);
- if (!prev_set || !curr_set || any_condjump_p (curr))
+ rtx prev_set, curr_set;
+ if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
return false;
- if (!riscv_fusion_same_dest_p (prev_set, curr_set))
+ if (!riscv_fuse_same_dest_p (prev_set, curr_set, true))
return false;
- if ((GET_CODE (SET_SRC (curr_set)) == LO_SUM
- || (GET_CODE (SET_SRC (curr_set)) == PLUS
- && CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
- && SMALL_OPERAND (INTVAL (XEXP (SET_SRC (curr_set), 1)))))
+ if (riscv_insn_is_addi_type_p (curr)
&& (GET_CODE (SET_SRC (prev_set)) == HIGH
|| (CONST_INT_P (SET_SRC (prev_set))
+ && (SET_SRC (prev_set)
+ != CONST0_RTX (GET_MODE (SET_DEST (prev_set))))
&& LUI_OPERAND (INTVAL (SET_SRC (prev_set))))))
return true;
@@ -443,28 +822,24 @@ riscv_fuse_lui_addi (rtx_insn *prev, rtx_insn *curr)
(plus (reg rd1) (const_int imm12)))
(addi) == (set (reg rd2)
(lo_sum (reg rd1) symbol))
+ (self-mv) == (set (reg rd2) (reg rd1))
Constraints:
- rd1 == rd2
- rd1 != x0. */
+ rd1 == rd2. */
static bool
riscv_fuse_auipc_addi (rtx_insn *prev, rtx_insn *curr)
{
- rtx prev_set = single_set (prev);
- rtx curr_set = single_set (curr);
- if (!prev_set || !curr_set || any_condjump_p (curr))
+ rtx prev_set, curr_set;
+ if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
return false;
- if (!riscv_fusion_same_dest_p (prev_set, curr_set))
+ if (!riscv_fuse_same_dest_p (prev_set, curr_set, true))
return false;
- if (GET_CODE (SET_SRC (prev_set)) == UNSPEC
- && XINT (SET_SRC (prev_set), 1) == UNSPEC_AUIPC
- && (GET_CODE (SET_SRC (curr_set)) == LO_SUM
- || (GET_CODE (SET_SRC (curr_set)) == PLUS
- && CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
- && SMALL_OPERAND (INTVAL (XEXP (SET_SRC (curr_set), 1))))))
+ if (riscv_insn_is_addi_type_p (curr, false)
+ && GET_CODE (SET_SRC (prev_set)) == UNSPEC
+ && XINT (SET_SRC (prev_set), 1) == UNSPEC_AUIPC)
return true;
return false;
@@ -489,12 +864,18 @@ riscv_fuse_auipc_addi (rtx_insn *prev, rtx_insn *curr)
static bool
riscv_fuse_lui_ld (rtx_insn *prev, rtx_insn *curr)
{
- rtx prev_set = single_set (prev);
- rtx curr_set = single_set (curr);
- if (!prev_set || !curr_set || any_condjump_p (curr))
+ rtx prev_set, curr_set;
+ if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
+ return false;
+
+ if (!riscv_fuse_same_dest_p (prev_set, curr_set))
return false;
- if (!riscv_fusion_same_dest_p (prev_set, curr_set))
+ struct riscv_fusion_mem_info mem;
+ if (!riscv_fuse_mem_p (curr, &mem)
+ || mem.type == SCHED_FUSION_ST
+ || mem.fp_p
+ || !riscv_fuse_same_reg_p (mem.addr.reg, SET_DEST (prev_set)))
return false;
/* A LUI_OPERAND accepts (const_int 0), but we won't emit that as LUI.
@@ -502,32 +883,13 @@ riscv_fuse_lui_ld (rtx_insn *prev, rtx_insn *curr)
if (CONST_INT_P (SET_SRC (prev_set))
&& SET_SRC (prev_set) != CONST0_RTX (GET_MODE (SET_DEST (prev_set)))
&& LUI_OPERAND (INTVAL (SET_SRC (prev_set)))
- && MEM_P (SET_SRC (curr_set))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS
- && REG_P (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- && (REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- == REGNO (SET_DEST (prev_set))))
- return true;
-
- if (GET_CODE (SET_SRC (prev_set)) == HIGH
- && MEM_P (SET_SRC (curr_set))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == LO_SUM
- && REG_P (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- && (REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- == REGNO (SET_DEST (prev_set))))
+ && mem.type == SCHED_FUSION_LD
+ && mem.addr.type == ADDRESS_REG
+ && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS)
return true;
if (GET_CODE (SET_SRC (prev_set)) == HIGH
- && (GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND
- || GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND)
- && MEM_P (XEXP (SET_SRC (curr_set), 0))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && (GET_CODE (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == LO_SUM
- && REG_P (XEXP (XEXP (XEXP (SET_SRC (curr_set), 0), 0), 0))
- && (REGNO (XEXP (XEXP (XEXP (SET_SRC (curr_set), 0), 0), 0))
- == REGNO (SET_DEST (prev_set)))))
+ && mem.addr.type == ADDRESS_LO_SUM)
return true;
return false;
@@ -543,19 +905,23 @@ riscv_fuse_lui_ld (rtx_insn *prev, rtx_insn *curr)
static bool
riscv_fuse_auipc_ld (rtx_insn *prev, rtx_insn *curr)
{
- rtx prev_set = single_set (prev);
- rtx curr_set = single_set (curr);
- if (!prev_set || !curr_set || any_condjump_p (curr))
+ rtx prev_set, curr_set;
+ if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
return false;
- if (!riscv_fusion_same_dest_p (prev_set, curr_set))
+ if (!riscv_fuse_same_dest_p (prev_set, curr_set))
return false;
+ struct riscv_fusion_mem_info mem;
+
if (GET_CODE (SET_SRC (prev_set)) == UNSPEC
&& XINT (SET_SRC (prev_set), 1) == UNSPEC_AUIPC
- && MEM_P (SET_SRC (curr_set))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS)
+ && riscv_fuse_mem_p (curr, &mem)
+ && mem.type == SCHED_FUSION_LD
+ && !mem.fp_p
+ && mem.addr.type == ADDRESS_REG
+ && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS
+ && riscv_fuse_same_reg_p (mem.addr.reg, SET_DEST (prev_set)))
return true;
return false;
@@ -573,50 +939,34 @@ riscv_fuse_auipc_ld (rtx_insn *prev, rtx_insn *curr)
static bool
riscv_fuse_aligned_std (rtx_insn *prev, rtx_insn *curr)
{
- rtx prev_set = single_set (prev);
- rtx curr_set = single_set (curr);
- if (!prev_set || !curr_set || any_condjump_p (curr))
+ if (!riscv_fuse_sets_p (prev, curr))
return false;
- if (MEM_P (SET_DEST (prev_set))
- && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
- && MEM_P (SET_DEST (curr_set))
- /* Stores must have the same width. */
- && GET_MODE (SET_DEST (curr_set)) == GET_MODE (SET_DEST (prev_set)))
- {
- rtx base_prev, base_curr, offset_prev, offset_curr;
- unsigned mode_size;
-
- extract_base_offset_in_addr (SET_DEST (prev_set),
- &base_prev, &offset_prev);
- extract_base_offset_in_addr (SET_DEST (curr_set),
- &base_curr, &offset_curr);
-
- /* Proceed only if we find both bases, both bases
- are registers and bases are the same register. */
- if (base_prev != NULL_RTX && base_curr != NULL_RTX
- && REG_P (base_prev) && REG_P (base_curr)
- && REGNO (base_prev) == REGNO (base_curr))
- {
- machine_mode mode = GET_MODE (SET_DEST (curr_set));
- mode_size = estimated_poly_value (GET_MODE_SIZE (mode));
-
- HOST_WIDE_INT offset_prev_int = INTVAL (offset_prev);
- HOST_WIDE_INT offset_curr_int = INTVAL (offset_curr);
-
- /* Get the smaller offset into OFFSET_PREV_INT. */
- if (offset_prev_int > offset_curr_int)
- std::swap (offset_prev_int, offset_curr_int);
-
- /* We've normalized, so we need to check that the lower
- address is aligned to 2X the size of the object. The
- higher address must be the lower address plus the
- size of the object. */
- if (((offset_prev_int % (2 * mode_size)) == 0)
- && offset_prev_int + mode_size == offset_curr_int)
- return true;
- }
- }
+ struct riscv_fusion_mem_info prev_mem, curr_mem;
+
+ if (!riscv_fuse_mem_p (prev, &prev_mem)
+ || !riscv_fuse_mem_p (curr, &curr_mem)
+ || prev_mem.type != SCHED_FUSION_ST
+ || curr_mem.type != SCHED_FUSION_ST
+ || prev_mem.fp_p
+ || curr_mem.fp_p
+ || !SCALAR_INT_MODE_P (prev_mem.mode)
+ || prev_mem.mode != curr_mem.mode
+ || prev_mem.addr.type != ADDRESS_REG
+ || curr_mem.addr.type != ADDRESS_REG
+ || !riscv_fuse_same_reg_p (prev_mem.addr.reg, curr_mem.addr.reg))
+ return false;
+
+ unsigned int mode_size
+ = estimated_poly_value (GET_MODE_SIZE (curr_mem.mode));
+ HOST_WIDE_INT prev_offset = INTVAL (prev_mem.addr.offset);
+ HOST_WIDE_INT curr_offset = INTVAL (curr_mem.addr.offset);
+ if (prev_offset > curr_offset)
+ std::swap (prev_offset, curr_offset);
+
+ if (prev_offset % (2 * mode_size) == 0
+ && prev_offset + mode_size == curr_offset)
+ return true;
return false;
}
@@ -638,22 +988,16 @@ riscv_fuse_aligned_std (rtx_insn *prev, rtx_insn *curr)
static bool
riscv_fuse_bfext (rtx_insn *prev, rtx_insn *curr)
{
- rtx prev_set = single_set (prev);
- rtx curr_set = single_set (curr);
- if (!prev_set || !curr_set || any_condjump_p (curr))
+ rtx prev_set, curr_set;
+ if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
return false;
- if (!riscv_fusion_same_dest_p (prev_set, curr_set))
+ if (!riscv_fuse_same_dest_p (prev_set, curr_set, true))
return false;
- if (GET_CODE (SET_SRC (prev_set)) == ASHIFT
- && (GET_CODE (SET_SRC (curr_set)) == LSHIFTRT
- || GET_CODE (SET_SRC (curr_set)) == ASHIFTRT)
- && REG_P (SET_DEST (prev_set))
- && REG_P (SET_DEST (curr_set))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set))
- && CONST_INT_P (XEXP (SET_SRC (prev_set), 1))
- && CONST_INT_P (XEXP (SET_SRC (curr_set), 1)))
+ if (riscv_set_is_slli_p (prev_set)
+ && (riscv_set_is_srli_p (curr_set)
+ || riscv_set_is_srai_p (curr_set)))
return true;
return false;
@@ -684,33 +1028,24 @@ riscv_fuse_bfext (rtx_insn *prev, rtx_insn *curr)
static bool
riscv_fuse_b_alui (rtx_insn *prev, rtx_insn *curr)
{
- rtx prev_set = single_set (prev);
- rtx curr_set = single_set (curr);
- if (!prev_set || !curr_set || any_condjump_p (curr))
+ rtx prev_set, curr_set;
+ if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
return false;
- if (!riscv_fusion_same_dest_p (prev_set, curr_set))
+ if (!riscv_fuse_same_dest_p (prev_set, curr_set, true))
return false;
/* orc.b + not. */
if (GET_CODE (SET_SRC (prev_set)) == UNSPEC
&& GET_CODE (SET_SRC (curr_set)) == NOT
- && XINT (SET_SRC (prev_set), 1) == UNSPEC_ORC_B
- && REG_P (SET_DEST (prev_set))
- && REG_P (SET_DEST (curr_set))
- && REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set)))
+ && XINT (SET_SRC (prev_set), 1) == UNSPEC_ORC_B)
return true;
/* ctz + andi. */
if (GET_CODE (SET_SRC (prev_set)) == CTZ
&& GET_CODE (SET_SRC (curr_set)) == AND
&& CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
- && INTVAL (XEXP (SET_SRC (curr_set), 1)) == 63
- && REG_P (SET_DEST (prev_set))
- && REG_P (SET_DEST (curr_set))
- && REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set)))
+ && INTVAL (XEXP (SET_SRC (curr_set), 1)) == 63)
return true;
/* sub + smax (abs pattern). */
@@ -718,27 +1053,15 @@ riscv_fuse_b_alui (rtx_insn *prev, rtx_insn *curr)
&& (XEXP (SET_SRC (prev_set), 0)
== CONST0_RTX (GET_MODE (SET_SRC (prev_set))))
&& GET_CODE (SET_SRC (curr_set)) == SMAX
- && REG_P (SET_DEST (prev_set))
- && REG_P (SET_DEST (curr_set))
- && REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set))
- && REG_P (XEXP (SET_SRC (prev_set), 1))
- && REG_P (XEXP (SET_SRC (curr_set), 1))
- && (REGNO (XEXP (SET_SRC (prev_set), 1))
- == REGNO (XEXP (SET_SRC (curr_set), 1))))
+ && riscv_fuse_same_reg_p (XEXP (SET_SRC (prev_set), 1),
+ XEXP (SET_SRC (curr_set), 1)))
return true;
/* neg + smax (abs pattern). */
if (GET_CODE (SET_SRC (prev_set)) == NEG
&& GET_CODE (SET_SRC (curr_set)) == SMAX
- && REG_P (SET_DEST (prev_set))
- && REG_P (SET_DEST (curr_set))
- && REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set))
- && REG_P (XEXP (SET_SRC (prev_set), 0))
- && REG_P (XEXP (SET_SRC (curr_set), 1))
- && (REGNO (XEXP (SET_SRC (prev_set), 0))
- == REGNO (XEXP (SET_SRC (curr_set), 1))))
+ && riscv_fuse_same_reg_p (XEXP (SET_SRC (prev_set), 0),
+ XEXP (SET_SRC (curr_set), 1)))
return true;
return false;
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-lui-addi-prera-rtl.c
b/gcc/testsuite/gcc.target/riscv/fusion-lui-addi-prera-rtl.c
new file mode 100644
index 00000000000..187be1c24f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-lui-addi-prera-rtl.c
@@ -0,0 +1,63 @@
+/* Check preallocation overmatching without dropping source dependencies. */
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O2 -fno-dce -mcmodel=medany
-mexplicit-relocs -mtune=sifive-p600-series -fdump-rtl-sched1-details
-fdump-rtl-sched2-details" } */
+/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_LUI_ADDI" 1 "sched1" } } */
+/* { dg-final { scan-rtl-dump-not "RISCV_FUSE_LUI_ADDI" "sched2" } } */
+
+long __RTL (startwith ("sched1"))
+test_lui_addi_prera (void)
+{
+(function "test_lui_addi_prera"
+ (insn-chain
+ (block 2
+ (edge-from entry (flags "FALLTHRU"))
+ (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (cnote 2 NOTE_INSN_FUNCTION_BEG)
+ (cinsn 3 (set (reg:DI a1)
+ (const_int 305418240)))
+ (cinsn 4 (set (reg:DI a0)
+ (plus:DI (reg:DI a1)
+ (const_int 1656))))
+ (cinsn 5 (use (reg:DI a0)))
+ (cinsn 6 (use (reg:DI a1)))
+ (cjump_insn 7 (simple_return))
+ (edge-to exit)
+ ) ;; block 2
+ (cbarrier 8)
+ ) ;; insn-chain
+ (crtl
+ (return_rtx
+ (reg/i:DI a0)
+ ) ;; return_rtx
+ ) ;; crtl
+) ;; function "test_lui_addi_prera"
+}
+
+long __RTL (startwith ("sched1"))
+test_lui_addi_source_mismatch (void)
+{
+(function "test_lui_addi_source_mismatch"
+ (insn-chain
+ (block 2
+ (edge-from entry (flags "FALLTHRU"))
+ (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (cnote 2 NOTE_INSN_FUNCTION_BEG)
+ (cinsn 3 (set (reg:DI a0)
+ (const_int 305418240)))
+ (cinsn 4 (set (reg:DI a0)
+ (plus:DI (reg:DI a1)
+ (const_int 1656))))
+ (cinsn 5 (use (reg:DI a0)))
+ (cjump_insn 6 (simple_return))
+ (edge-to exit)
+ ) ;; block 2
+ (cbarrier 7)
+ ) ;; insn-chain
+ (crtl
+ (return_rtx
+ (reg/i:DI a0)
+ ) ;; return_rtx
+ ) ;; crtl
+) ;; function "test_lui_addi_source_mismatch"
+}
--
2.52.0