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]

[committed] Fix H8 call pattern problems


This fixes a minor problem with the H8 call patterns that shows up as an
assembler syntax error in a couple of the c-torture tests.

The H8 call patterns indicated they accepted any offsettable operand.
That is not correct.  It's not even close to correct.  The H8 can call
to a SYMBOL_REF or REG (SYMBOL_REF + offset is potentially possible as
well, though I'm not sure if the assembler/linker handle it properly,
CONST_INT & LABEL_REF ought to work, but almost certainly wouldn't occur
in practice).

As some of you may know, call patterns are a bit weird with the way they
handle operands.  Rather than fight with the weirdness, the easiest way
forward is to have an expander which placates the RTL expansion phase
and to have a matching pattern where we can ignore the weirdness imposed
by the RTL expanders on the call address operand.  This is consistent
with how several other ports handle similar issues.


This fixes a couple dozen testsuite failures with no regressions.
Installing on the trunk.

Jeff
commit 6275ce7dca530d44a37606780cf02d532a14949f
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Wed Nov 28 17:26:03 2018 +0000

            * config/h8300/constraints.md: Add "C" constraint for call insns.
            * config/h8300/h8300.md (call, call_value): Turn into a define_expand
            and define_insn pair.  Move invalid call targets into a register in
            the expander and fix constraints in the matching pattern.
            * config/h8300/predicates.md (call_expander_operand): Renamed from
            call_insn_operand.  Reject things we shouldn't be trying to handle.
            (call_insn_operand): New predicate for use by the call/call_value
            insns.
            (small_call_insn_operand): Update appropriately.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@266571 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2e4af6f97f7..6456facbacb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,7 +1,19 @@
+2018-11-28  Jeff Law  <law@redhat.com>
+
+	* config/h8300/constraints.md: Add "C" constraint for call insns.
+	* config/h8300/h8300.md (call, call_value): Turn into a define_expand
+	and define_insn pair.  Move invalid call targets into a register in
+	the expander and fix constraints in the matching pattern.
+	* config/h8300/predicates.md (call_expander_operand): Renamed from
+	call_insn_operand.  Reject things we shouldn't be trying to handle.
+	(call_insn_operand): New predicate for use by the call/call_value
+	insns.
+	(small_call_insn_operand): Update appropriately.
+
 2018-11-28  Sam Tebbs  <sam.tebbs@arm.com>
 
 	* config/aarch64/aarch64.c (aarch64_process_target_attr): Replace
-		calls to strtok with strtok_r.
+	calls to strtok with strtok_r.
 
 2018-11-28  Richard Biener  <rguenther@suse.de>
 
diff --git a/gcc/config/h8300/constraints.md b/gcc/config/h8300/constraints.md
index 9d0ac42fdaa..4175c832ef3 100644
--- a/gcc/config/h8300/constraints.md
+++ b/gcc/config/h8300/constraints.md
@@ -158,6 +158,10 @@
   (and (match_code "const_int")
        (match_test "!h8300_shift_needs_scratch_p (ival, QImode)")))
 
+(define_constraint "C"
+  "@internal"
+  (match_code "symbol_ref"))
+
 (define_constraint "S"
   "@internal"
   (and (match_code "const_int")
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index 70f96c7481f..0686f25d71d 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -2064,16 +2064,30 @@
 
 ;; ??? Even though we use HImode here, this works on the H8/300H and H8S.
 
-(define_insn "call"
-  [(call (match_operand:QI 0 "call_insn_operand" "or")
-	 (match_operand:HI 1 "general_operand" "g"))]
+(define_expand "call"
+  [(call (match_operand:QI 0 "call_expander_operand" "")
+	 (match_operand:HI 1 "general_operand" ""))]
+  ""
+  {
+    if (!register_operand (XEXP (operands[0], 0), Pmode)
+	&& GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
+      XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
+  })
+
+(define_insn "call_insn"
+  [(call (mem:QI (match_operand 0 "call_insn_operand" "Cr"))
+	         (match_operand:HI 1 "general_operand" "g"))]
   ""
 {
-  if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
-      && (SYMBOL_REF_FLAGS (XEXP (operands[0], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
-    return "jsr\\t@%0:8";
+  rtx xoperands[1];
+  xoperands[0] = gen_rtx_MEM (QImode, operands[0]);
+  gcc_assert (GET_MODE (operands[0]) == Pmode);
+  if (GET_CODE (XEXP (xoperands[0], 0)) == SYMBOL_REF
+      && (SYMBOL_REF_FLAGS (XEXP (xoperands[0], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
+    output_asm_insn ("jsr\\t@%0:8", xoperands);
   else
-    return "jsr\\t%0";
+    output_asm_insn ("jsr\\t%0", xoperands);
+  return "";
 }
   [(set_attr "type" "call")
    (set (attr "length")
@@ -2086,17 +2100,33 @@
 
 ;; ??? Even though we use HImode here, this works on the H8/300H and H8S.
 
-(define_insn "call_value"
+(define_expand "call_value"
+  [(set (match_operand 0 "" "")
+	(call (match_operand:QI 1 "call_expander_operand" "")
+	      (match_operand:HI 2 "general_operand" "")))]
+  ""
+  {
+    if (!register_operand (XEXP (operands[1], 0), Pmode)
+	&& GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
+      XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
+  })
+
+(define_insn "call_value_insn"
   [(set (match_operand 0 "" "=r")
-	(call (match_operand:QI 1 "call_insn_operand" "or")
-	      (match_operand:HI 2 "general_operand" "g")))]
+	(call (mem:QI (match_operand 1 "call_insn_operand" "Cr"))
+		      (match_operand:HI 2 "general_operand" "g")))]
   ""
 {
-  if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
-      && (SYMBOL_REF_FLAGS (XEXP (operands[1], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
-    return "jsr\\t@%1:8";
+  rtx xoperands[2];
+  gcc_assert (GET_MODE (operands[1]) == Pmode);
+  xoperands[0] = operands[0];
+  xoperands[1] = gen_rtx_MEM (QImode, operands[1]);
+  if (GET_CODE (XEXP (xoperands[1], 0)) == SYMBOL_REF
+      && (SYMBOL_REF_FLAGS (XEXP (xoperands[1], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
+    output_asm_insn ("jsr\\t@%1:8", xoperands);
   else
-    return "jsr\\t%1";
+    output_asm_insn ("jsr\\t%1", xoperands);
+  return "";
 }
   [(set_attr "type" "call")
    (set (attr "length")
diff --git a/gcc/config/h8300/predicates.md b/gcc/config/h8300/predicates.md
index 698cdee1ddf..217189ad1f5 100644
--- a/gcc/config/h8300/predicates.md
+++ b/gcc/config/h8300/predicates.md
@@ -216,7 +216,7 @@
 
 ;; Return true if OP is a valid call operand.
 
-(define_predicate "call_insn_operand"
+(define_predicate "call_expander_operand"
   (match_code "mem")
 {
   if (GET_CODE (op) == MEM)
@@ -224,31 +224,37 @@
       rtx inside = XEXP (op, 0);
       if (register_operand (inside, Pmode))
 	return 1;
-      if (CONSTANT_ADDRESS_P (inside))
+      if (SYMBOL_REF_P (inside))
 	return 1;
     }
   return 0;
 })
 
+(define_predicate "call_insn_operand"
+  (match_code "reg,symbol_ref")
+{
+  if (register_operand (op, Pmode))
+    return 1;
+  if (SYMBOL_REF_P (op))
+    return 1;
+  return 0;
+})
+
 ;; Return true if OP is a valid call operand, and OP represents an
 ;; operand for a small call (4 bytes instead of 6 bytes).
 
 (define_predicate "small_call_insn_operand"
-  (match_code "mem")
+  (match_code "reg,symbol_ref")
 {
-  if (GET_CODE (op) == MEM)
-    {
-      rtx inside = XEXP (op, 0);
+  /* Register indirect is a small call.  */
+  if (register_operand (op, Pmode))
+    return 1;
 
-      /* Register indirect is a small call.  */
-      if (register_operand (inside, Pmode))
-	return 1;
+  /* A call through the function vector is a small call too.  */
+  if (GET_CODE (op) == SYMBOL_REF
+      && (SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
+    return 1;
 
-      /* A call through the function vector is a small call too.  */
-      if (GET_CODE (inside) == SYMBOL_REF
-	  && (SYMBOL_REF_FLAGS (inside) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
-	return 1;
-    }
   /* Otherwise it's a large call.  */
   return 0;
 })

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