diff mbox

[SH,committed] Fix PR 70416

Message ID 1459688148.21967.16.camel@t-online.de
State New
Headers show

Commit Message

Oleg Endo April 3, 2016, 12:55 p.m. UTC
Hi,

The attached patch fixes PR 70416.  For details, please see the PR
audit trail.

Tested on sh-elf with
make -k check RUNTESTFLAGS="--target_board=sh-sim\{-m2/-ml,-m2/-mb,
-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"

and no new failures.
Committed to trunk as r234702.  Backport to GCC 5 branch will follow
after a while.

Cheers,
Oleg

gcc/ChangeLog:
	PR target/70416
	PR target/67391
	* config/sh/sh.md (*addsi3): Allow pattern when reload_in_progress is
	set, but not for SP_REG operands.

gcc/testsuite/ChangeLog:
	PR target/70416
	PR target/67391
	* gcc.target/sh/torture/pr70416.c: New.

Comments

Oleg Endo April 9, 2016, 2:47 a.m. UTC | #1
On Sun, 2016-04-03 at 21:55 +0900, Oleg Endo wrote:

> The attached patch fixes PR 70416.  For details, please see the PR
> audit trail.
> 
> Tested on sh-elf with
> make -k check RUNTESTFLAGS="--target_board=sh-sim\{-m2/-ml,-m2/-mb,
> -m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"
> 
> and no new failures.
> Committed to trunk as r234702.  Backport to GCC 5 branch will follow
> after a while.

Backport to GCC 5 branch committed as r234847.

Cheers,
Oleg
diff mbox

Patch

Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md	(revision 234701)
+++ gcc/config/sh/sh.md	(working copy)
@@ -2242,14 +2242,23 @@ 
   [(set_attr "type" "arith")])
 
 ;; Old reload might generate add insns directly (not through the expander) for
-;; the memory address of complex insns like atomic insns when reloading.
+;; address register calculations when reloading, in which case it won't try
+;; the addsi_scr pattern.  Because reload will sometimes try to validate
+;; the generated insns and their constraints, this pattern must be
+;; recognizable during and after reload.  However, when reload generates
+;; address register calculations for the stack pointer, we don't allow this
+;; pattern.  This will make reload prefer using indexed @(reg + reg) address
+;; modes when the displacement of a @(disp + reg) doesn't fit.
 (define_insn_and_split "*addsi3"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
 	(plus:SI (match_operand:SI 1 "arith_reg_operand" "r")
 		 (match_operand:SI 2 "arith_or_int_operand" "rn")))]
   "TARGET_SH1 && !sh_lra_p ()
-   && reload_completed
-   && !reg_overlap_mentioned_p (operands[0], operands[1])"
+   && (reload_completed || reload_in_progress)
+   && !reg_overlap_mentioned_p (operands[0], operands[1])
+   && (!reload_in_progress
+       || ((!REG_P (operands[1]) || REGNO (operands[1]) != SP_REG)
+	   && (!REG_P (operands[2]) || REGNO (operands[2]) != SP_REG)))"
   "#"
   "&& 1"
   [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
Index: gcc/testsuite/gcc.target/sh/torture/pr70416.c
===================================================================
--- gcc/testsuite/gcc.target/sh/torture/pr70416.c	(revision 0)
+++ gcc/testsuite/gcc.target/sh/torture/pr70416.c	(working copy)
@@ -0,0 +1,136 @@ 
+/* { dg-additional-options "-std=gnu99 -fpic" }  */
+/* { dg-do compile }  */
+
+typedef unsigned long VALUE;
+typedef unsigned long ID;
+
+typedef struct rb_callable_method_entry_struct
+{
+  ID called_id;
+  const VALUE owner;
+} rb_callable_method_entry_t;
+
+typedef struct rb_iseq_struct rb_iseq_t;
+
+struct __jmp_buf_tag { int xx; };
+typedef struct __jmp_buf_tag jmp_buf[1];
+
+struct rb_iseq_struct
+{
+  const struct iseq_catch_table *catch_table;
+};
+
+typedef struct rb_control_frame_struct
+{
+  const VALUE *pc;
+  VALUE *sp;
+  const rb_iseq_t *iseq;
+  VALUE flag;
+  VALUE *ep;
+} rb_control_frame_t;
+
+typedef jmp_buf rb_jmpbuf_t;
+struct rb_vm_tag
+{
+  rb_jmpbuf_t buf;
+}rb_ensure_list_t;
+
+typedef struct rb_thread_struct
+{
+  rb_control_frame_t *cfp;
+  struct rb_vm_tag *tag;
+} rb_thread_t;
+
+struct iseq_catch_table_entry
+{
+  const rb_iseq_t *iseq;
+};
+
+struct iseq_catch_table
+{
+  unsigned int size;
+};
+
+extern unsigned long long __sdt_unsp;
+extern unsigned short ruby_cmethod__return_semaphore;
+
+struct ruby_dtrace_method_hook_args
+{
+  const char *classname;
+  const char *methodname;
+  const char *filename;
+  int line_no;
+};
+
+int ruby_th_dtrace_setup(rb_thread_t *th, VALUE klass, ID id, struct ruby_dtrace_method_hook_args *args);
+int rb_threadptr_tag_state (rb_thread_t *th);
+VALUE vm_exec_core (rb_thread_t *th, VALUE initial);
+const rb_callable_method_entry_t *rb_vm_frame_method_entry (const rb_control_frame_t *cfp);
+
+struct vm_throw_data;
+const rb_control_frame_t * THROW_DATA_CATCH_FRAME(const struct vm_throw_data *obj);
+rb_control_frame_t * vm_push_frame(rb_thread_t *th, const rb_iseq_t *iseq, VALUE type, VALUE self, VALUE specval, VALUE cref_or_me, const VALUE *pc, VALUE *sp, int local_size, int stack_max);
+
+
+VALUE vm_exec(rb_thread_t *th)
+{
+  int state;
+  VALUE result;
+  VALUE initial = 0;
+  struct vm_throw_data *err;
+  rb_thread_t * const _th = (th);
+  struct rb_vm_tag _tag;
+
+  if ((state = (__builtin_setjmp((_tag.buf)) ? rb_threadptr_tag_state((_th)) : ((void)(_th->tag = &_tag), 0))) == 0)
+  {
+    result = vm_exec_core(th, initial);
+  }
+  else
+  {
+    unsigned int i;
+    const struct iseq_catch_table_entry *entry;
+    const struct iseq_catch_table *ct;
+    unsigned long epc, cont_pc, cont_sp;
+    const rb_iseq_t *catch_iseq;
+    rb_control_frame_t *cfp;
+    const rb_control_frame_t *escape_cfp;
+
+    while (th->cfp->pc == 0 || th->cfp->iseq == 0)
+    {
+      if (ruby_cmethod__return_semaphore)
+      {
+        struct ruby_dtrace_method_hook_args args;
+        if (ruby_th_dtrace_setup(th, rb_vm_frame_method_entry(th->cfp)->owner, rb_vm_frame_method_entry(th->cfp)->called_id, &args))
+        {
+          __asm__ __volatile__ (
+             ".asciz \"%n[_SDT_S1]@%[_SDT_A1] %n[_SDT_S2]@%[_SDT_A2] %n[_SDT_S3]@%[_SDT_A3] %n[_SDT_S4]@%[_SDT_A4]\"\n"
+             :
+             : [_SDT_S1] "n" (((!__extension__ (__builtin_constant_p ((((unsigned long long) (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.classname ) + 3) & -4) == 4, ( args.classname ), 0U))) __sdt_unsp) & ((unsigned long long)1 << (sizeof (unsigned long long) * 8 - 1))) == 0) || (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.classname ) + 3) & -4) == 4, ( args.classname ), 0U))) -1 > (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.classname ) + 3) & -4) == 4, ( args.classname ), 0U))) 0)) ? 1 : -1) * (int) ((__builtin_classify_type ( args.classname ) == 14 || __builtin_classify_type ( args.classname ) == 5) ? sizeof (void *) : sizeof ( args.classname ))),
+               [_SDT_A1] "nor" (( args.classname )),
+               [_SDT_S2] "n" (((!__extension__ (__builtin_constant_p ((((unsigned long long) (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.methodname ) + 3) & -4) == 4, ( args.methodname ), 0U))) __sdt_unsp) & ((unsigned long long)1 << (sizeof (unsigned long long) * 8 - 1))) == 0) || (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.methodname ) + 3) & -4) == 4, ( args.methodname ), 0U))) -1 > (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.methodname ) + 3) & -4) == 4, ( args.methodname ), 0U))) 0)) ? 1 : -1) * (int) ((__builtin_classify_type ( args.methodname ) == 14 || __builtin_classify_type ( args.methodname ) == 5) ? sizeof (void *) : sizeof ( args.methodname ))),
+               [_SDT_A2] "nor" (( args.methodname )),
+               [_SDT_S3] "n" (((!__extension__ (__builtin_constant_p ((((unsigned long long) (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.filename ) + 3) & -4) == 4, ( args.filename ), 0U))) __sdt_unsp) & ((unsigned long long)1 << (sizeof (unsigned long long) * 8 - 1))) == 0) || (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.filename ) + 3) & -4) == 4, ( args.filename ), 0U))) -1 > (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.filename ) + 3) & -4) == 4, ( args.filename ), 0U))) 0)) ? 1 : -1) * (int) ((__builtin_classify_type ( args.filename ) == 14 || __builtin_classify_type ( args.filename ) == 5) ? sizeof (void *) : sizeof ( args.filename ))),
+               [_SDT_A3] "nor" (( args.filename )),
+               [_SDT_S4] "n" (((!__extension__ (__builtin_constant_p ((((unsigned long long) (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.line_no ) + 3) & -4) == 4, ( args.line_no ), 0U))) __sdt_unsp) & ((unsigned long long)1 << (sizeof (unsigned long long) * 8 - 1))) == 0) || (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.line_no ) + 3) & -4) == 4, ( args.line_no ), 0U))) -1 > (__typeof (__builtin_choose_expr (((__builtin_classify_type ( args.line_no ) + 3) & -4) == 4, ( args.line_no ), 0U))) 0)) ? 1 : -1) * (int) ((__builtin_classify_type ( args.line_no ) == 14 || __builtin_classify_type ( args.line_no ) == 5) ? sizeof (void *) : sizeof ( args.line_no ))),
+               [_SDT_A4] "nor" (( args.line_no ))
+          );
+        }
+      }
+    }
+
+    if (cfp == escape_cfp && !(((cfp)->flag & 0x0200) != 0))
+      catch_iseq = entry->iseq;
+
+    if (state == 6)
+    {
+      escape_cfp = THROW_DATA_CATCH_FRAME(err);
+
+      if (ct)
+        for (i = 0; i < ct->size; i++) { }
+    }
+    else
+      ct = cfp->iseq->catch_table;
+
+    vm_push_frame(th, catch_iseq, 0xb1, 0, 1, 0, 0, 0, 5, 123);
+  }
+}