aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config/i386/i386.c59
-rw-r--r--gcc/config/i386/i386.md38
-rw-r--r--gcc/testsuite/gcc.dg/pr99104.c15
3 files changed, 39 insertions, 73 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 2fe182f..aa50cf7 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -14754,11 +14754,6 @@ distance_non_agu_define (unsigned int regno1, unsigned int regno2,
}
}
- /* get_attr_type may modify recog data. We want to make sure
- that recog data is valid for instruction INSN, on which
- distance_non_agu_define is called. INSN is unchanged here. */
- extract_insn_cached (insn);
-
if (!found)
return -1;
@@ -14928,17 +14923,15 @@ ix86_lea_outperforms (rtx_insn *insn, unsigned int regno0, unsigned int regno1,
return true;
}
- rtx_insn *rinsn = recog_data.insn;
+ /* Remember recog_data content. */
+ struct recog_data_d recog_data_save = recog_data;
dist_define = distance_non_agu_define (regno1, regno2, insn);
dist_use = distance_agu_use (regno0, insn);
- /* distance_non_agu_define can call extract_insn_cached. If this function
- is called from define_split conditions, that can break insn splitting,
- because split_insns works by clearing recog_data.insn and then modifying
- recog_data.operand array and match the various split conditions. */
- if (recog_data.insn != rinsn)
- recog_data.insn = NULL;
+ /* distance_non_agu_define can call get_attr_type which can call
+ recog_memoized, restore recog_data back to previous content. */
+ recog_data = recog_data_save;
if (dist_define < 0 || dist_define >= LEA_MAX_STALL)
{
@@ -14968,38 +14961,6 @@ ix86_lea_outperforms (rtx_insn *insn, unsigned int regno0, unsigned int regno1,
return dist_define >= dist_use;
}
-/* Return true if it is legal to clobber flags by INSN and
- false otherwise. */
-
-static bool
-ix86_ok_to_clobber_flags (rtx_insn *insn)
-{
- basic_block bb = BLOCK_FOR_INSN (insn);
- df_ref use;
- bitmap live;
-
- while (insn)
- {
- if (NONDEBUG_INSN_P (insn))
- {
- FOR_EACH_INSN_USE (use, insn)
- if (DF_REF_REG_USE_P (use) && DF_REF_REGNO (use) == FLAGS_REG)
- return false;
-
- if (insn_defines_reg (FLAGS_REG, INVALID_REGNUM, insn))
- return true;
- }
-
- if (insn == BB_END (bb))
- break;
-
- insn = NEXT_INSN (insn);
- }
-
- live = df_get_live_out(bb);
- return !REGNO_REG_SET_P (live, FLAGS_REG);
-}
-
/* Return true if we need to split op0 = op1 + op2 into a sequence of
move and add to avoid AGU stalls. */
@@ -15012,10 +14973,6 @@ ix86_avoid_lea_for_add (rtx_insn *insn, rtx operands[])
if (!TARGET_OPT_AGU || optimize_function_for_size_p (cfun))
return false;
- /* Check it is correct to split here. */
- if (!ix86_ok_to_clobber_flags(insn))
- return false;
-
regno0 = true_regnum (operands[0]);
regno1 = true_regnum (operands[1]);
regno2 = true_regnum (operands[2]);
@@ -15051,7 +15008,7 @@ ix86_use_lea_for_mov (rtx_insn *insn, rtx operands[])
}
/* Return true if we need to split lea into a sequence of
- instructions to avoid AGU stalls. */
+ instructions to avoid AGU stalls during peephole2. */
bool
ix86_avoid_lea_for_addr (rtx_insn *insn, rtx operands[])
@@ -15071,10 +15028,6 @@ ix86_avoid_lea_for_addr (rtx_insn *insn, rtx operands[])
&& REG_P (XEXP (operands[1], 0))))
return false;
- /* Check if it is OK to split here. */
- if (!ix86_ok_to_clobber_flags (insn))
- return false;
-
ok = ix86_decompose_address (operands[1], &parts);
gcc_assert (ok);
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index b60784a..333dc9a 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -5176,7 +5176,7 @@
;; Load effective address instructions
-(define_insn_and_split "*lea<mode>"
+(define_insn "*lea<mode>"
[(set (match_operand:SWI48 0 "register_operand" "=r")
(match_operand:SWI48 1 "address_no_seg_operand" "Ts"))]
"ix86_hardreg_mov_ok (operands[0], operands[1])"
@@ -5189,38 +5189,36 @@
else
return "lea{<imodesuffix>}\t{%E1, %0|%0, %E1}";
}
- "reload_completed && ix86_avoid_lea_for_addr (insn, operands)"
+ [(set_attr "type" "lea")
+ (set (attr "mode")
+ (if_then_else
+ (match_operand 1 "SImode_address_operand")
+ (const_string "SI")
+ (const_string "<MODE>")))])
+
+(define_peephole2
+ [(set (match_operand:SWI48 0 "register_operand")
+ (match_operand:SWI48 1 "address_no_seg_operand"))]
+ "ix86_hardreg_mov_ok (operands[0], operands[1])
+ && peep2_regno_dead_p (0, FLAGS_REG)
+ && ix86_avoid_lea_for_addr (peep2_next_insn (0), operands)"
[(const_int 0)]
{
machine_mode mode = <MODE>mode;
- rtx pat;
-
- /* ix86_avoid_lea_for_addr re-recognizes insn and may
- change operands[] array behind our back. */
- pat = PATTERN (curr_insn);
-
- operands[0] = SET_DEST (pat);
- operands[1] = SET_SRC (pat);
/* Emit all operations in SImode for zero-extended addresses. */
if (SImode_address_operand (operands[1], VOIDmode))
mode = SImode;
- ix86_split_lea_for_addr (curr_insn, operands, mode);
+ ix86_split_lea_for_addr (peep2_next_insn (0), operands, mode);
/* Zero-extend return register to DImode for zero-extended addresses. */
if (mode != <MODE>mode)
- emit_insn (gen_zero_extendsidi2
- (operands[0], gen_lowpart (mode, operands[0])));
+ emit_insn (gen_zero_extendsidi2 (operands[0],
+ gen_lowpart (mode, operands[0])));
DONE;
-}
- [(set_attr "type" "lea")
- (set (attr "mode")
- (if_then_else
- (match_operand 1 "SImode_address_operand")
- (const_string "SI")
- (const_string "<MODE>")))])
+})
;; Add instructions
diff --git a/gcc/testsuite/gcc.dg/pr99104.c b/gcc/testsuite/gcc.dg/pr99104.c
new file mode 100644
index 0000000..807e1da
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr99104.c
@@ -0,0 +1,15 @@
+/* PR target/99104 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -fsel-sched-pipelining -fselective-scheduling2 -funroll-loops" } */
+
+__int128 a;
+int b;
+int foo (void);
+
+int __attribute__ ((simd))
+bar (void)
+{
+ a = ~a;
+ if (foo ())
+ b = 0;
+}