This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 6/7]: Remaining support for clobber high


This patch simply adds the remainder of clobber high checks.
Happy to split this into smaller patches if required (there didn't
seem anything obvious to split into).


Alan.

2017-11-16  Alan Hayward  <alan.hayward@arm.com>

	* alias.c (record_set): Check for clobber high.
	* cfgexpand.c (expand_gimple_stmt): Likewise.
	* combine-stack-adj.c (single_set_for_csa): Likewise.
	* combine.c (find_single_use_1): Likewise.
	(set_nonzero_bits_and_sign_copies): Likewise.
	(get_combine_src_dest): Likewise.
	(is_parallel_of_n_reg_sets): Likewise.
	(try_combine): Likewise.
	(record_dead_and_set_regs_1): Likewise.
	(reg_dead_at_p_1): Likewise.
	(reg_dead_at_p): Likewise.
	* dce.c (deletable_insn_p): Likewise.
	(mark_nonreg_stores_1): Likewise.
	(mark_nonreg_stores_2): Likewise.
	* df-scan.c (df_find_hard_reg_defs): Likewise.
	(df_uses_record): Likewise.
	(df_get_call_refs): Likewise.
	* dwarf2out.c (mem_loc_descriptor): Likewise.
	* haifa-sched.c (haifa_classify_rtx): Likewise.
	* ira-build.c (create_insn_allocnos): Likewise.
	* ira-costs.c (scan_one_insn): Likewise.
	* ira.c (equiv_init_movable_p): Likewise.
	(rtx_moveable_p): Likewise.
	(interesting_dest_for_shprep): Likewise.
	* jump.c (mark_jump_label_1): Likewise.
	* postreload-gcse.c (record_opr_changes): Likewise.
	* postreload.c (reload_cse_simplify): Likewise.
	(struct reg_use): Add source expr.
	(reload_combine): Check for clobber high.
	(reload_combine_note_use): Likewise.
	(reload_cse_move2add): Likewise.
	(move2add_note_store): Likewise.
	* print-rtl.c (print_pattern): Likewise.
	* recog.c (decode_asm_operands): Likewise.
	(store_data_bypass_p): Likewise.
	(if_test_bypass_p): Likewise.
	* regcprop.c (kill_clobbered_value): Likewise.
	(kill_set_value): Likewise.
	* reginfo.c (reg_scan_mark_refs): Likewise.
	* reload1.c (maybe_fix_stack_asms): Likewise.
	(eliminate_regs_1): Likewise.
	(elimination_effects): Likewise.
	(mark_not_eliminable): Likewise.
	(scan_paradoxical_subregs): Likewise.
	(forget_old_reloads_1): Likewise.
	* reorg.c (find_end_label): Likewise.
	(try_merge_delay_insns): Likewise.
	(redundant_insn): Likewise.
	(own_thread_p): Likewise.
	(fill_simple_delay_slots): Likewise.
	(fill_slots_from_thread): Likewise.
	(dbr_schedule): Likewise.
	* resource.c (update_live_status): Likewise.
	(mark_referenced_resources): Likewise.
	(mark_set_resources): Likewise.
	* rtl.c (copy_rtx): Likewise.
	* rtlanal.c (reg_referenced_p): Likewise.
	(single_set_2): Likewise.
	(noop_move_p): Likewise.
	(note_stores): Likewise.
	* sched-deps.c (sched_analyze_reg): Likewise.
	(sched_analyze_insn): Likewise.


diff --git a/gcc/alias.c b/gcc/alias.c
index c69ef410edac2ab0ab93e8ec9fe4c89a7078c001..6a6734bd7d5732c255c009be47e68aa073a9ebb1 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -1554,6 +1554,17 @@ record_set (rtx dest, const_rtx set, void *data ATTRIBUTE_UNUSED)
 	  new_reg_base_value[regno] = 0;
 	  return;
 	}
+      /* A CLOBBER_HIGH only wipes out the old value if the mode of the old
+	 value is greater than that of the clobber.  */
+      else if (GET_CODE (set) == CLOBBER_HIGH)
+	{
+	  if (new_reg_base_value[regno] != 0
+	      && reg_is_clobbered_by_clobber_high (
+		   regno, GET_MODE (new_reg_base_value[regno]), XEXP (set, 0)))
+	    new_reg_base_value[regno] = 0;
+	  return;
+	}
+
       src = SET_SRC (set);
     }
   else
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 06a8af8a1663c9e518a8169650a0c9969990df1f..ea6fc265f757543cff635a805fd4045a10add23e 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -3803,6 +3803,7 @@ expand_gimple_stmt (gimple *stmt)
 	      /* If we want exceptions for non-call insns, any
 		 may_trap_p instruction may throw.  */
 	      && GET_CODE (PATTERN (insn)) != CLOBBER
+	      && GET_CODE (PATTERN (insn)) != CLOBBER_HIGH
 	      && GET_CODE (PATTERN (insn)) != USE
 	      && insn_could_throw_p (insn))
 	    make_reg_eh_region_note (insn, 0, lp_nr);
diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c
index 09f0be814f98922b6926a929401894809a890f61..595e83c73760a97e0f8ebd99e12b1853d1d52b92 100644
--- a/gcc/combine-stack-adj.c
+++ b/gcc/combine-stack-adj.c
@@ -133,6 +133,7 @@ single_set_for_csa (rtx_insn *insn)
 	  && SET_SRC (this_rtx) == SET_DEST (this_rtx))
 	;
       else if (GET_CODE (this_rtx) != CLOBBER
+	       && GET_CODE (this_rtx) != CLOBBER_HIGH
 	       && GET_CODE (this_rtx) != USE)
 	return NULL_RTX;
     }
diff --git a/gcc/combine.c b/gcc/combine.c
index 99cc343192ec4e2f8bdca0667858fbdf11baaffb..8b17349c240bea7a752cfd58f392f5a9dbfd53d6 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -573,6 +573,7 @@ find_single_use_1 (rtx dest, rtx *loc)
     case SYMBOL_REF:
     CASE_CONST_ANY:
     case CLOBBER:
+    case CLOBBER_HIGH:
       return 0;

     case SET:
@@ -1755,6 +1756,9 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data)
 	  return;
 	}

+      /* Should not happen as we only using pseduo registers.  */
+      gcc_assert (GET_CODE (set) != CLOBBER_HIGH);
+
       /* If this register is being initialized using itself, and the
 	 register is uninitialized in this basic block, and there are
 	 no LOG_LINKS which set the register, then part of the
@@ -1853,6 +1857,7 @@ get_combine_src_dest (combine_insn *insnc, rtx *pdest, rtx *psrc)

 	      /* We can ignore CLOBBERs.  */
 	    case CLOBBER:
+	    case CLOBBER_HIGH:
 	      break;

 	    case SET:
@@ -2715,10 +2720,17 @@ is_parallel_of_n_reg_sets (rtx pat, int n)
 	|| !REG_P (SET_DEST (XVECEXP (pat, 0, i))))
       return false;
   for ( ; i < len; i++)
-    if (GET_CODE (XVECEXP (pat, 0, i)) != CLOBBER
-	|| XEXP (XVECEXP (pat, 0, i), 0) == const0_rtx)
-      return false;
-
+    switch (GET_CODE (XVECEXP (pat, 0, i)))
+      {
+      case CLOBBER:
+	if (XEXP (XVECEXP (pat, 0, i), 0) == const0_rtx)
+	  return false;
+	break;
+      case CLOBBER_HIGH:
+	break;
+      default:
+	return false;
+      }
   return true;
 }

@@ -3099,7 +3111,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
       for (i = 0; ok && i < XVECLEN (p2, 0); i++)
 	{
 	  if ((GET_CODE (XVECEXP (p2, 0, i)) == SET
-	       || GET_CODE (XVECEXP (p2, 0, i)) == CLOBBER)
+	       || GET_CODE (XVECEXP (p2, 0, i)) == CLOBBER
+	       || GET_CODE (XVECEXP (p2, 0, i)) == CLOBBER_HIGH)
 	      && reg_overlap_mentioned_p (SET_DEST (PATTERN (i3)),
 					  SET_DEST (XVECEXP (p2, 0, i))))
 	    ok = false;
@@ -13553,6 +13566,15 @@ record_dead_and_set_regs_1 (rtx dest, const_rtx setter, void *data)
 	record_value_for_reg (dest, record_dead_insn,
 			      gen_lowpart (GET_MODE (dest),
 						       SET_SRC (setter)));
+      else if (GET_CODE (setter) == CLOBBER_HIGH)
+	{
+	  reg_stat_type *rsp = &reg_stat[REGNO (dest)];
+	  if (rsp->last_set_value
+	      && reg_is_clobbered_by_clobber_high
+		   (REGNO (dest), GET_MODE (rsp->last_set_value),
+		    XEXP (setter, 0)))
+	    record_value_for_reg (dest, NULL, NULL_RTX);
+	}
       else
 	record_value_for_reg (dest, record_dead_insn, NULL_RTX);
     }
@@ -14030,6 +14052,7 @@ use_crosses_set_p (const_rtx x, rtx_insn *from, rtx_insn *to)

 static unsigned int reg_dead_regno, reg_dead_endregno;
 static int reg_dead_flag;
+rtx reg_dead_reg;

 /* Function called via note_stores from reg_dead_at_p.

@@ -14044,6 +14067,10 @@ reg_dead_at_p_1 (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
   if (!REG_P (dest))
     return;

+  if (GET_CODE (x) == CLOBBER_HIGH
+      && !reg_is_clobbered_by_clobber_high (reg_dead_reg, x))
+    return;
+
   regno = REGNO (dest);
   endregno = END_REGNO (dest);
   if (reg_dead_endregno > regno && reg_dead_regno < endregno)
@@ -14067,6 +14094,7 @@ reg_dead_at_p (rtx reg, rtx_insn *insn)
   /* Set variables for reg_dead_at_p_1.  */
   reg_dead_regno = REGNO (reg);
   reg_dead_endregno = END_REGNO (reg);
+  reg_dead_reg = reg;

   reg_dead_flag = 0;

diff --git a/gcc/dce.c b/gcc/dce.c
index 9f3021f13fe5171e0eaa26918eaee6bb690a3eb0..b0518a7d23d677e7192c173375473e03e68812cd 100644
--- a/gcc/dce.c
+++ b/gcc/dce.c
@@ -139,6 +139,7 @@ deletable_insn_p (rtx_insn *insn, bool fast, bitmap arg_stores)
       return false;

     case CLOBBER:
+    case CLOBBER_HIGH:
       if (fast)
 	{
 	  /* A CLOBBER of a dead pseudo register serves no purpose.
@@ -207,7 +208,10 @@ static void
 mark_nonreg_stores_1 (rtx dest, const_rtx pattern, void *data)
 {
   if (GET_CODE (pattern) != CLOBBER && !REG_P (dest))
-    mark_insn ((rtx_insn *) data, true);
+    {
+      gcc_checking_assert (GET_CODE (pattern) != CLOBBER_HIGH);
+      mark_insn ((rtx_insn *) data, true);
+    }
 }


@@ -218,7 +222,10 @@ static void
 mark_nonreg_stores_2 (rtx dest, const_rtx pattern, void *data)
 {
   if (GET_CODE (pattern) != CLOBBER && !REG_P (dest))
-    mark_insn ((rtx_insn *) data, false);
+    {
+      gcc_checking_assert (GET_CODE (pattern) != CLOBBER_HIGH);
+      mark_insn ((rtx_insn *) data, false);
+    }
 }


diff --git a/gcc/df-scan.c b/gcc/df-scan.c
index 8ab3d716ea2975ed687e1e3cf61ab3233e378f63..3962d5ab49cf321a4d8e866ec84f3867c0f34248 100644
--- a/gcc/df-scan.c
+++ b/gcc/df-scan.c
@@ -2777,6 +2777,7 @@ df_find_hard_reg_defs (rtx x, HARD_REG_SET *defs)
       break;

     case CLOBBER:
+    case CLOBBER_HIGH:
       df_find_hard_reg_defs_1 (XEXP (x, 0), defs);
       break;

@@ -2836,6 +2837,10 @@ df_uses_record (struct df_collection_rec *collection_rec,
       /* If we're clobbering a REG then we have a def so ignore.  */
       return;

+    case CLOBBER_HIGH:
+      gcc_assert (REG_P (XEXP (x, 0)));
+      return;
+
     case MEM:
       df_uses_record (collection_rec,
 		      &XEXP (x, 0), DF_REF_REG_MEM_LOAD,
@@ -3132,6 +3137,7 @@ df_get_call_refs (struct df_collection_rec *collection_rec,
   for (note = CALL_INSN_FUNCTION_USAGE (insn_info->insn); note;
        note = XEXP (note, 1))
     {
+      gcc_assert (GET_CODE (XEXP (note, 0)) != CLOBBER_HIGH);
       if (GET_CODE (XEXP (note, 0)) == USE)
         df_uses_record (collection_rec, &XEXP (XEXP (note, 0), 0),
 			DF_REF_REG_USE, bb, insn_info, flags);
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c0f93d763f5163cff5db2241df383c48777803ac..78811a6861e6100ebaaeb7ed4b143da55657d6e1 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -15663,6 +15663,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
     case CONST_FIXED:
     case CLRSB:
     case CLOBBER:
+    case CLOBBER_HIGH:
       /* If delegitimize_address couldn't do anything with the UNSPEC, we
 	 can't express it in the debug info.  This can happen e.g. with some
 	 TLS UNSPECs.  */
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index f5c06a95bb6742475bf7d1f2c5ea16456fa21efe..81c9ae378333079e99372153b64e5ffb1a088fc5 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -529,6 +529,9 @@ haifa_classify_rtx (const_rtx x)
 	  /* Test if it is a 'store'.  */
 	  tmp_class = may_trap_exp (XEXP (x, 0), 1);
 	  break;
+	case CLOBBER_HIGH:
+	  gcc_assert (REG_P (XEXP (x, 0)));
+	  break;
 	case SET:
 	  /* Test if it is a store.  */
 	  tmp_class = may_trap_exp (SET_DEST (x), 1);
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index 67c0305a1685d432904e93d2057b38daf7fac315..8a1f2bac04600bc18cc0e3d6b45fb75c0be2ad97 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -1876,6 +1876,11 @@ create_insn_allocnos (rtx x, rtx outer, bool output_p)
       create_insn_allocnos (XEXP (x, 0), NULL, true);
       return;
     }
+  else if (code == CLOBBER_HIGH)
+    {
+      gcc_assert (REG_P (XEXP (x, 0)) && HARD_REGISTER_P (XEXP (x, 0)));
+      return;
+    }
   else if (code == MEM)
     {
       create_insn_allocnos (XEXP (x, 0), NULL, false);
diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c
index e24dbc2e01be3048dbec379c0823c90271d7e768..9f03036e18b1abc03dc043c8deee023fa7a82fd4 100644
--- a/gcc/ira-costs.c
+++ b/gcc/ira-costs.c
@@ -1444,6 +1444,13 @@ scan_one_insn (rtx_insn *insn)
       return insn;
     }

+  if (pat_code == CLOBBER_HIGH)
+    {
+      gcc_assert (REG_P (XEXP (PATTERN (insn), 0))
+		  && HARD_REGISTER_P (XEXP (PATTERN (insn), 0)));
+      return insn;
+    }
+
   counted_mem = false;
   set = single_set (insn);
   extract_insn (insn);
diff --git a/gcc/ira.c b/gcc/ira.c
index 93d02093757c2db1e0133db2a2f388cea81e497a..bb6421853a7a7a049a79f0c6e82ef82f667f8321 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -3086,6 +3086,7 @@ equiv_init_movable_p (rtx x, int regno)

     case CC0:
     case CLOBBER:
+    case CLOBBER_HIGH:
       return 0;

     case PRE_INC:
@@ -4411,6 +4412,7 @@ rtx_moveable_p (rtx *loc, enum op_type type)
 	      && rtx_moveable_p (&XEXP (x, 2), OP_IN));

     case CLOBBER:
+    case CLOBBER_HIGH:
       return rtx_moveable_p (&SET_DEST (x), OP_OUT);

     case UNSPEC_VOLATILE:
@@ -4863,7 +4865,9 @@ interesting_dest_for_shprep (rtx_insn *insn, basic_block call_dom)
   for (int i = 0; i < XVECLEN (pat, 0); i++)
     {
       rtx sub = XVECEXP (pat, 0, i);
-      if (GET_CODE (sub) == USE || GET_CODE (sub) == CLOBBER)
+      if (GET_CODE (sub) == USE
+	  || GET_CODE (sub) == CLOBBER
+	  || GET_CODE (sub) == CLOBBER_HIGH)
 	continue;
       if (GET_CODE (sub) != SET
 	  || side_effects_p (sub))
diff --git a/gcc/jump.c b/gcc/jump.c
index b5392011b533e83ae7094e0f5870b281e35c2bea..03fc1c20840832c65d65711151c47dbde7c2acef 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -1105,6 +1105,7 @@ mark_jump_label_1 (rtx x, rtx_insn *insn, bool in_mem, bool is_target)
     case CC0:
     case REG:
     case CLOBBER:
+    case CLOBBER_HIGH:
     case CALL:
       return;

diff --git a/gcc/postreload-gcse.c b/gcc/postreload-gcse.c
index 15fdb7e0cfe7767e559cd9ef6d5f66d3501ffd90..f4f6af75ea56d79a7579a971a3019c586fc9bfc1 100644
--- a/gcc/postreload-gcse.c
+++ b/gcc/postreload-gcse.c
@@ -791,15 +791,18 @@ record_opr_changes (rtx_insn *insn)
 	record_last_reg_set_info_regno (insn, regno);

       for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
-	if (GET_CODE (XEXP (link, 0)) == CLOBBER)
-	  {
-	    x = XEXP (XEXP (link, 0), 0);
-	    if (REG_P (x))
-	      {
-		gcc_assert (HARD_REGISTER_P (x));
-		record_last_reg_set_info (insn, x);
-	      }
-	  }
+	{
+	  gcc_assert (GET_CODE (XEXP (link, 0)) != CLOBBER_HIGH);
+	  if (GET_CODE (XEXP (link, 0)) == CLOBBER)
+	    {
+	      x = XEXP (XEXP (link, 0), 0);
+	      if (REG_P (x))
+		{
+		  gcc_assert (HARD_REGISTER_P (x));
+		  record_last_reg_set_info (insn, x);
+		}
+	    }
+	}

       if (! RTL_CONST_OR_PURE_CALL_P (insn))
 	record_last_mem_set_info (insn);
diff --git a/gcc/postreload.c b/gcc/postreload.c
index a70d11a6c878871fea86a1afe0caec4507c0d394..6bdb4a4f3217b1d263f1cedf0234500f20b1516e 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -133,6 +133,8 @@ reload_cse_simplify (rtx_insn *insn, rtx testreg)
 	  for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
 	    {
 	      rtx part = XVECEXP (body, 0, i);
+	      /* asms can only have full clobbers, not clobber_highs.  */
+	      gcc_assert (GET_CODE (part) != CLOBBER_HIGH);
 	      if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0)))
 		cselib_invalidate_rtx (XEXP (part, 0));
 	    }
@@ -156,6 +158,7 @@ reload_cse_simplify (rtx_insn *insn, rtx testreg)
 		}
 	    }
 	  else if (GET_CODE (part) != CLOBBER
+		   && GET_CODE (part) != CLOBBER_HIGH
 		   && GET_CODE (part) != USE)
 	    break;
 	}
@@ -667,7 +670,8 @@ struct reg_use
    STORE_RUID is always meaningful if we only want to use a value in a
    register in a different place: it denotes the next insn in the insn
    stream (i.e. the last encountered) that sets or clobbers the register.
-   REAL_STORE_RUID is similar, but clobbers are ignored when updating it.  */
+   REAL_STORE_RUID is similar, but clobbers are ignored when updating it.
+   EXPR is the expression used when storing the register.  */
 static struct
   {
     struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
@@ -677,6 +681,7 @@ static struct
     int real_store_ruid;
     int use_ruid;
     bool all_offsets_match;
+    rtx expr;
   } reg_state[FIRST_PSEUDO_REGISTER];

 /* Reverse linear uid.  This is increased in reload_combine while scanning
@@ -1339,6 +1344,10 @@ reload_combine (void)
 	    {
 	      rtx setuse = XEXP (link, 0);
 	      rtx usage_rtx = XEXP (setuse, 0);
+	      /* We could support CLOBBER_HIGH and treat it in the same way as
+		 HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that yet.  */
+	      gcc_assert (GET_CODE (setuse) != CLOBBER_HIGH);
+
 	      if ((GET_CODE (setuse) == USE || GET_CODE (setuse) == CLOBBER)
 		  && REG_P (usage_rtx))
 	        {
@@ -1514,6 +1523,10 @@ reload_combine_note_use (rtx *xp, rtx_insn *insn, int ruid, rtx containing_mem)
 	}
       break;

+    case CLOBBER_HIGH:
+      gcc_assert (REG_P (SET_DEST (x)));
+      return;
+
     case PLUS:
       /* We are interested in (plus (reg) (const_int)) .  */
       if (!REG_P (XEXP (x, 0))
@@ -2133,6 +2146,9 @@ reload_cse_move2add (rtx_insn *first)
 	    {
 	      rtx setuse = XEXP (link, 0);
 	      rtx usage_rtx = XEXP (setuse, 0);
+	      /* CALL_INSN_FUNCTION_USAGEs can only have full clobbers, not
+		 clobber_highs.  */
+	      gcc_assert (GET_CODE (setuse) != CLOBBER_HIGH);
 	      if (GET_CODE (setuse) == CLOBBER
 		  && REG_P (usage_rtx))
 	        {
@@ -2295,6 +2311,13 @@ move2add_note_store (rtx dst, const_rtx set, void *data)

       move2add_record_mode (dst);
     }
+  else if (GET_CODE (set) == CLOBBER_HIGH)
+    {
+      /* Only invalidate if actually clobbered.  */
+      if (reg_mode[regno] == BLKmode
+	  || reg_is_clobbered_by_clobber_high (regno, reg_mode[regno], dst))
+	 goto invalidate;
+    }
   else
     {
     invalidate:
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 2ecdbb4299e2c64e8eea76a4534fe264fce613c4..5920165ceb416e7eec370e6863ffe887161f4b92 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -1715,6 +1715,7 @@ print_pattern (pretty_printer *pp, const_rtx x, int verbose)
       print_exp (pp, x, verbose);
       break;
     case CLOBBER:
+    case CLOBBER_HIGH:
     case USE:
       pp_printf (pp, "%s ", GET_RTX_NAME (GET_CODE (x)));
       print_value (pp, XEXP (x, 0), verbose);
diff --git a/gcc/recog.c b/gcc/recog.c
index 05e69134236c2266b966744a54b7ca7e9ed26fa1..769f462d0407673781a2634218c5c62579fb4ac1 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -1600,6 +1600,7 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
 	      {
 		if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
 		  break;		/* Past last SET */
+		gcc_assert (GET_CODE (XVECEXP (body, 0, i)) == SET);
 		if (operands)
 		  operands[i] = SET_DEST (XVECEXP (body, 0, i));
 		if (operand_locs)
@@ -3690,7 +3691,8 @@ store_data_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
           {
             out_exp = XVECEXP (out_pat, 0, i);

-            if (GET_CODE (out_exp) == CLOBBER)
+	    if (GET_CODE (out_exp) == CLOBBER
+		|| GET_CODE (out_exp) == CLOBBER_HIGH)
               continue;

             gcc_assert (GET_CODE (out_exp) == SET);
@@ -3709,7 +3711,8 @@ store_data_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
 	{
 	  in_exp = XVECEXP (in_pat, 0, i);

-	  if (GET_CODE (in_exp) == CLOBBER)
+	  if (GET_CODE (in_exp) == CLOBBER
+	      || GET_CODE (in_exp) == CLOBBER_HIGH)
 	    continue;

 	  gcc_assert (GET_CODE (in_exp) == SET);
@@ -3732,7 +3735,8 @@ store_data_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
                 {
                   out_exp = XVECEXP (out_pat, 0, j);

-                  if (GET_CODE (out_exp) == CLOBBER)
+		  if (GET_CODE (out_exp) == CLOBBER
+		      || GET_CODE (out_exp) == CLOBBER_HIGH)
                     continue;

                   gcc_assert (GET_CODE (out_exp) == SET);
@@ -3787,7 +3791,7 @@ if_test_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
 	{
 	  rtx exp = XVECEXP (out_pat, 0, i);

-	  if (GET_CODE (exp) == CLOBBER)
+	  if (GET_CODE (exp) == CLOBBER  || GET_CODE (exp) == CLOBBER_HIGH)
 	    continue;

 	  gcc_assert (GET_CODE (exp) == SET);
diff --git a/gcc/regcprop.c b/gcc/regcprop.c
index 4ca10f58a58aa4c7605b001ec851c79a25fd6a8c..85b474544b22c915af9ea55230443186563dd624 100644
--- a/gcc/regcprop.c
+++ b/gcc/regcprop.c
@@ -237,7 +237,11 @@ static void
 kill_clobbered_value (rtx x, const_rtx set, void *data)
 {
   struct value_data *const vd = (struct value_data *) data;
-  if (GET_CODE (set) == CLOBBER)
+  gcc_assert (GET_CODE (set) != CLOBBER_HIGH || REG_P (x));
+
+  if (GET_CODE (set) == CLOBBER
+      || (GET_CODE (set) == CLOBBER_HIGH
+	  && reg_is_clobbered_by_clobber_high (x, XEXP (set, 0))))
     kill_value (x, vd);
 }

@@ -257,7 +261,9 @@ kill_set_value (rtx x, const_rtx set, void *data)
   struct kill_set_value_data *ksvd = (struct kill_set_value_data *) data;
   if (rtx_equal_p (x, ksvd->ignore_set_reg))
     return;
-  if (GET_CODE (set) != CLOBBER)
+
+  gcc_assert (GET_CODE (set) != CLOBBER_HIGH || REG_P (x));
+  if (GET_CODE (set) != CLOBBER && GET_CODE (set) != CLOBBER_HIGH)
     {
       kill_value (x, ksvd->vd);
       if (REG_P (x))
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index 847305ebe61fd3cd0cf02c01a02c537ad8b22c4a..bd9dd05e53404490b795b86b473e3b252bde1b50 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -1100,6 +1100,10 @@ reg_scan_mark_refs (rtx x, rtx_insn *insn)
 	reg_scan_mark_refs (XEXP (XEXP (x, 0), 0), insn);
       break;

+    case CLOBBER_HIGH:
+      gcc_assert (!(MEM_P (XEXP (x, 0))));
+      break;
+
     case SET:
       /* Count a set of the destination if it is a register.  */
       for (dest = SET_DEST (x);
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 902d940245dfcb73c10de8670adb22375fbfe098..68b16ca8bd747511589a74529c1ac922acf04215 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -1339,6 +1339,8 @@ maybe_fix_stack_asms (void)
 	  rtx t = XVECEXP (pat, 0, i);
 	  if (GET_CODE (t) == CLOBBER && STACK_REG_P (XEXP (t, 0)))
 	    SET_HARD_REG_BIT (clobbered, REGNO (XEXP (t, 0)));
+	  /* CLOBBER_HIGH is only supported for LRA.  */
+	  gcc_assert (GET_CODE (t) != CLOBBER_HIGH);
 	}

       /* Get the operand values and constraints out of the insn.  */
@@ -2879,6 +2881,7 @@ eliminate_regs_1 (rtx x, machine_mode mem_mode, rtx insn,
       return x;

     case CLOBBER:
+    case CLOBBER_HIGH:
     case ASM_OPERANDS:
       gcc_assert (insn && DEBUG_INSN_P (insn));
       break;
@@ -3089,6 +3092,10 @@ elimination_effects (rtx x, machine_mode mem_mode)
       elimination_effects (XEXP (x, 0), mem_mode);
       return;

+    case CLOBBER_HIGH:
+      /* CLOBBER_HIGH is only supported for LRA.  */
+      return;
+
     case SET:
       /* Check for setting a register that we know about.  */
       if (REG_P (SET_DEST (x)))
@@ -3810,6 +3817,9 @@ mark_not_eliminable (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
   if (dest == hard_frame_pointer_rtx)
     return;

+  /* CLOBBER_HIGH is only supported for LRA.  */
+  gcc_assert (GET_CODE (x) != CLOBBER_HIGH);
+
   for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
     if (reg_eliminate[i].can_eliminate && dest == reg_eliminate[i].to_rtx
 	&& (GET_CODE (x) != SET
@@ -4445,6 +4455,7 @@ scan_paradoxical_subregs (rtx x)
     case PC:
     case USE:
     case CLOBBER:
+    case CLOBBER_HIGH:
       return;

     case SUBREG:
@@ -4899,7 +4910,7 @@ reload_as_needed (int live_known)
    to be forgotten later.  */

 static void
-forget_old_reloads_1 (rtx x, const_rtx ignored ATTRIBUTE_UNUSED,
+forget_old_reloads_1 (rtx x, const_rtx setter,
 		      void *data)
 {
   unsigned int regno;
@@ -4919,6 +4930,9 @@ forget_old_reloads_1 (rtx x, const_rtx ignored ATTRIBUTE_UNUSED,
   if (!REG_P (x))
     return;

+  /* CLOBBER_HIGH is only supported for LRA.  */
+  gcc_assert (GET_CODE (setter) != CLOBBER_HIGH);
+
   regno = REGNO (x);

   if (regno >= FIRST_PSEUDO_REGISTER)
diff --git a/gcc/reorg.c b/gcc/reorg.c
index 5914af655b6bbbddc98f23f53c0d1e6e496dc2eb..4f97e78b2a3c03db89a1bd2fa10bf8e83c374ae7 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -396,7 +396,8 @@ find_end_label (rtx kind)
   while (NOTE_P (insn)
 	 || (NONJUMP_INSN_P (insn)
 	     && (GET_CODE (PATTERN (insn)) == USE
-		 || GET_CODE (PATTERN (insn)) == CLOBBER)))
+		 || GET_CODE (PATTERN (insn)) == CLOBBER
+		 || GET_CODE (PATTERN (insn)) == CLOBBER_HIGH)))
     insn = PREV_INSN (insn);

   /* When a target threads its epilogue we might already have a
@@ -1290,7 +1291,8 @@ try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)

       /* TRIAL must be a CALL_INSN or INSN.  Skip USE and CLOBBER.  */
       if (NONJUMP_INSN_P (trial)
-	  && (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER))
+	  && (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+	      || GET_CODE (pat) == CLOBBER_HIGH))
 	continue;

       if (GET_CODE (next_to_match) == GET_CODE (trial)
@@ -1484,7 +1486,8 @@ redundant_insn (rtx insn, rtx_insn *target, const vec<rtx_insn *> &delay_list)
       --insns_to_search;

       pat = PATTERN (trial);
-      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
+      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+	  || GET_CODE (pat) == CLOBBER_HIGH)
 	continue;

       if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (pat))
@@ -1579,7 +1582,8 @@ redundant_insn (rtx insn, rtx_insn *target, const vec<rtx_insn *> &delay_list)
       --insns_to_search;

       pat = PATTERN (trial);
-      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
+      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+	  || GET_CODE (pat) == CLOBBER_HIGH)
 	continue;

       if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (pat))
@@ -1688,7 +1692,8 @@ own_thread_p (rtx thread, rtx label, int allow_fallthrough)
 	|| LABEL_P (insn)
 	|| (NONJUMP_INSN_P (insn)
 	    && GET_CODE (PATTERN (insn)) != USE
-	    && GET_CODE (PATTERN (insn)) != CLOBBER))
+	    && GET_CODE (PATTERN (insn)) != CLOBBER
+	    && GET_CODE (PATTERN (insn)) != CLOBBER_HIGH))
       return 0;

   return 1;
@@ -2013,7 +2018,8 @@ fill_simple_delay_slots (int non_jumps_p)
 	      pat = PATTERN (trial);

 	      /* Stand-alone USE and CLOBBER are just for flow.  */
-	      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
+	      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+		  || GET_CODE (pat) == CLOBBER_HIGH)
 		continue;

 	      /* Check for resource conflict first, to avoid unnecessary
@@ -2135,7 +2141,8 @@ fill_simple_delay_slots (int non_jumps_p)
 	      pat = PATTERN (trial);

 	      /* Stand-alone USE and CLOBBER are just for flow.  */
-	      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
+	      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+		  || GET_CODE (pat) == CLOBBER_HIGH)
 		continue;

 	      /* If this already has filled delay slots, get the insn needing
@@ -2400,7 +2407,8 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
 	}

       pat = PATTERN (trial);
-      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
+      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+	  || GET_CODE (pat) == CLOBBER_HIGH)
 	continue;

       /* If TRIAL conflicts with the insns ahead of it, we lose.  Also,
@@ -3790,7 +3798,8 @@ dbr_schedule (rtx_insn *first)
 	  if (! insn->deleted ()
 	      && NONJUMP_INSN_P (insn)
 	      && GET_CODE (PATTERN (insn)) != USE
-	      && GET_CODE (PATTERN (insn)) != CLOBBER)
+	      && GET_CODE (PATTERN (insn)) != CLOBBER
+	      && GET_CODE (PATTERN (insn)) != CLOBBER_HIGH)
 	    {
 	      if (GET_CODE (PATTERN (insn)) == SEQUENCE)
 		{
diff --git a/gcc/resource.c b/gcc/resource.c
index 95911c5c718f8ae79a401c782624ec8a01a9e8ab..463e370b2d8610787ba21b4be3925aa1ae86e71e 100644
--- a/gcc/resource.c
+++ b/gcc/resource.c
@@ -108,6 +108,11 @@ update_live_status (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
   if (GET_CODE (x) == CLOBBER)
     for (i = first_regno; i < last_regno; i++)
       CLEAR_HARD_REG_BIT (current_live_regs, i);
+  else if (GET_CODE (x) == CLOBBER_HIGH)
+    /* No current target supports both branch delay slots and CLOBBER_HIGH.
+       We'd need more elaborate liveness tracking to handle that
+       combination.  */
+    gcc_unreachable ();
   else
     for (i = first_regno; i < last_regno; i++)
       {
@@ -292,6 +297,7 @@ mark_referenced_resources (rtx x, struct resources *res,
       return;

     case CLOBBER:
+    case CLOBBER_HIGH:
       return;

     case CALL_INSN:
@@ -665,9 +671,15 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,

 	  for (link = CALL_INSN_FUNCTION_USAGE (call_insn);
 	       link; link = XEXP (link, 1))
-	    if (GET_CODE (XEXP (link, 0)) == CLOBBER)
-	      mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1,
-				  MARK_SRC_DEST);
+	    {
+	      /* We could support CLOBBER_HIGH and treat it in the same way as
+		 HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that
+		 yet.  */
+	      gcc_assert (GET_CODE (XEXP (link, 0)) != CLOBBER_HIGH);
+	      if (GET_CODE (XEXP (link, 0)) == CLOBBER)
+		mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1,
+				    MARK_SRC_DEST);
+	    }

 	  /* Check for a REG_SETJMP.  If it exists, then we must
 	     assume that this call can clobber any register.  */
@@ -710,6 +722,12 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,
       mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
       return;

+    case CLOBBER_HIGH:
+      /* No current target supports both branch delay slots and CLOBBER_HIGH.
+	 We'd need more elaborate liveness tracking to handle that
+	 combination.  */
+      gcc_unreachable ();
+
     case SEQUENCE:
       {
         rtx_sequence *seq = as_a <rtx_sequence *> (x);
diff --git a/gcc/rtl.c b/gcc/rtl.c
index 6db84f99627bb8617c6e227892ca44076f4e729b..12a01e8ed1f9005e5c0dfeb0f86c762069520284 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -307,6 +307,10 @@ copy_rtx (rtx orig)
 	return orig;
       break;

+    case CLOBBER_HIGH:
+	gcc_assert (REG_P (XEXP (orig, 0)));
+	return orig;
+
     case CONST:
       if (shared_const_p (orig))
 	return orig;
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 923e3314d25c05f9055907c61b4a24186701cc23..d907d636ed5f22d9cdc7237d66fdb05da9922f60 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -1196,6 +1196,10 @@ reg_referenced_p (const_rtx x, const_rtx body)
 	  return 1;
       return 0;

+    case CLOBBER_HIGH:
+      gcc_assert (REG_P (XEXP (body, 0)));
+      return 0;
+
     case COND_EXEC:
       if (reg_overlap_mentioned_p (x, COND_EXEC_TEST (body)))
 	return 1;
@@ -1507,6 +1511,7 @@ single_set_2 (const rtx_insn *insn, const_rtx pat)
 	    {
 	    case USE:
 	    case CLOBBER:
+	    case CLOBBER_HIGH:
 	      break;

 	    case SET:
@@ -1660,7 +1665,8 @@ noop_move_p (const rtx_insn *insn)
 	  rtx tem = XVECEXP (pat, 0, i);

 	  if (GET_CODE (tem) == USE
-	      || GET_CODE (tem) == CLOBBER)
+	      || GET_CODE (tem) == CLOBBER
+	      || GET_CODE (tem) == CLOBBER_HIGH)
 	    continue;

 	  if (GET_CODE (tem) != SET || ! set_noop_p (tem))
@@ -1892,7 +1898,9 @@ note_stores (const_rtx x, void (*fun) (rtx, const_rtx, void *), void *data)
   if (GET_CODE (x) == COND_EXEC)
     x = COND_EXEC_CODE (x);

-  if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
+  if (GET_CODE (x) == SET
+      || GET_CODE (x) == CLOBBER
+      || GET_CODE (x) == CLOBBER_HIGH)
     {
       rtx dest = SET_DEST (x);

diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index a64e4e17bbc8115982d253d041032243e9506802..8eb0ed350557d3c0af87bbba674cefd4478d97aa 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -2319,6 +2319,13 @@ sched_analyze_reg (struct deps_desc *deps, int regno, machine_mode mode,
 	  while (--i >= 0)
 	    note_reg_use (regno + i);
 	}
+      else if (ref == CLOBBER_HIGH)
+	{
+	  gcc_assert (i == 1);
+	  /* We don't know the current state of the register, so have to treat
+	     the clobber high as a full clobber.  */
+	  note_reg_clobber (regno);
+	}
       else
 	{
 	  while (--i >= 0)
@@ -2342,6 +2349,8 @@ sched_analyze_reg (struct deps_desc *deps, int regno, machine_mode mode,
       else if (ref == USE)
 	note_reg_use (regno);
       else
+	/* For CLOBBER_HIGH, we don't know the current state of the register,
+	   so have to treat it as a full clobber.  */
 	note_reg_clobber (regno);

       /* Pseudos that are REG_EQUIV to something may be replaced
@@ -2953,7 +2962,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx_insn *insn)
 	      sub = COND_EXEC_CODE (sub);
 	      code = GET_CODE (sub);
 	    }
-	  if (code == SET || code == CLOBBER)
+	  else if (code == SET || code == CLOBBER || code == CLOBBER_HIGH)
 	    sched_analyze_1 (deps, sub, insn);
 	  else
 	    sched_analyze_2 (deps, sub, insn);
@@ -2969,6 +2978,10 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx_insn *insn)
 	{
 	  if (GET_CODE (XEXP (link, 0)) == CLOBBER)
 	    sched_analyze_1 (deps, XEXP (link, 0), insn);
+	  else if (GET_CODE (XEXP (link, 0)) == CLOBBER_HIGH)
+	    /* We could support CLOBBER_HIGH and treat it in the same way as
+	      HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that yet.  */
+	    gcc_unreachable ();
 	  else if (GET_CODE (XEXP (link, 0)) != SET)
 	    sched_analyze_2 (deps, XEXP (link, 0), insn);
 	}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]