diff mbox

[AVR] : Fix PR49939: Skip 2-word insns

Message ID 4E9487B2.2050202@gjlay.de
State New
Headers show

Commit Message

Georg-Johann Lay Oct. 11, 2011, 6:15 p.m. UTC
This patch teaches avr-gcc to skip 2-word instructions like STS and LDS.

It's just about looking into an 2-word insn and check if it's a 2-word
instruction or not.

Passes without regression. Ok to install?

Johann

	PR target/49939
	* config/avr/avr.md (*movqi): Rename to movqi_insn.
	(*call_insn): Rename to call_insn.
	(*call_value_insn): Rename to call_value_insn.
	* config/avr/avr.c (avr_2word_insn_p): New static function.
	(jump_over_one_insn_p): Use it.

Comments

Denis Chertykov Oct. 12, 2011, 9:25 a.m. UTC | #1
2011/10/11 Georg-Johann Lay <avr@gjlay.de>:
> This patch teaches avr-gcc to skip 2-word instructions like STS and LDS.
>
> It's just about looking into an 2-word insn and check if it's a 2-word
> instruction or not.
>
> Passes without regression. Ok to install?

Please commit.

Denis.
Georg-Johann Lay Oct. 12, 2011, 10:07 a.m. UTC | #2
Denis Chertykov schrieb:
> 2011/10/11 Georg-Johann Lay <avr@gjlay.de>:
>> This patch teaches avr-gcc to skip 2-word instructions like STS and LDS.
>>
>> It's just about looking into an 2-word insn and check if it's a 2-word
>> instruction or not.
>>
>> Passes without regression. Ok to install?
> 
> Please commit.
> 
> Denis.

Committed with the following change:

-              && avr_2word_insn_p (next_nonnote_nondebug_insn (insn))));
+              && avr_2word_insn_p (next_active_insn (insn))));

Otherwise a code label would knock out the optimization like in


char c;

void foo (char a, char b)
{
    if (a || b)
        c = b;
}

which now compiles to

foo:
	tst r24
	brne .L4
	cpse r22,__zero_reg__
.L4:
	sts c,r22
.L3:
	ret

Johann
Denis Chertykov Oct. 12, 2011, 12:47 p.m. UTC | #3
2011/10/12 Georg-Johann Lay <avr@gjlay.de>:
> Denis Chertykov schrieb:
>> 2011/10/11 Georg-Johann Lay <avr@gjlay.de>:
>>> This patch teaches avr-gcc to skip 2-word instructions like STS and LDS.
>>>
>>> It's just about looking into an 2-word insn and check if it's a 2-word
>>> instruction or not.
>>>
>>> Passes without regression. Ok to install?
>>
>> Please commit.
>>
>> Denis.
>
> Committed with the following change:
>
> -              && avr_2word_insn_p (next_nonnote_nondebug_insn (insn))));
> +              && avr_2word_insn_p (next_active_insn (insn))));
>

It was discussed in another thread.

Denis.
diff mbox

Patch

Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md	(revision 179765)
+++ config/avr/avr.md	(working copy)
@@ -295,7 +295,7 @@  (define_expand "movqi"
        operands[1] = copy_to_mode_reg(QImode, operand1);
   ")
 
-(define_insn "*movqi"
+(define_insn "movqi_insn"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r")
 	(match_operand:QI 1 "general_operand"       "rL,i,rL,Qm,r,q,i"))]
   "(register_operand (operands[0],QImode)
@@ -3628,7 +3628,7 @@  (define_expand "sibcall_value"
   ""
   "")
 
-(define_insn "*call_insn"
+(define_insn "call_insn"
   [(parallel[(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "z,s,z,s"))
                    (match_operand:HI 1 "general_operand"           "X,X,X,X"))
              (use (match_operand:HI 2 "const_int_operand"          "L,L,P,P"))])]
@@ -3651,7 +3651,7 @@  (define_insn "*call_insn"
                                         (const_int 2)
                                         (const_int 1))])])
 
-(define_insn "*call_value_insn"
+(define_insn "call_value_insn"
   [(parallel[(set (match_operand 0 "register_operand"                   "=r,r,r,r")
                   (call (mem:HI (match_operand:HI 1 "nonmemory_operand"  "z,s,z,s"))
                         (match_operand:HI 2 "general_operand"            "X,X,X,X")))
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 179765)
+++ config/avr/avr.c	(working copy)
@@ -7123,6 +7123,56 @@  test_hard_reg_class (enum reg_class rcla
 }
 
 
+/* Helper for jump_over_one_insn_p:  Test if INSN is a 2-word instruction
+   and thus is suitable to be skipped by CPSE, SBRC, etc.  */
+
+static bool
+avr_2word_insn_p (rtx insn)
+{
+  if (avr_current_device->errata_skip
+      || !insn
+      || !INSN_P (insn)
+      || 2 != get_attr_length (insn))
+    {
+      return false;
+    }
+
+  switch (INSN_CODE (insn))
+    {
+    default:
+      break;
+      
+    case CODE_FOR_movqi_insn:
+      {
+        rtx set  = single_set (insn);
+        rtx src  = SET_SRC (set);
+        rtx dest = SET_DEST (set);
+        
+        /* Factor out LDS and STS from movqi_insn.  */
+        
+        if (MEM_P (dest)
+            && (REG_P (src) || src == const0_rtx))
+          {
+            return CONSTANT_ADDRESS_P (XEXP (dest, 0));
+          }
+        else if (REG_P (dest)
+                 && MEM_P (src))
+          {
+            return CONSTANT_ADDRESS_P (XEXP (src, 0));
+          }
+        
+        break;
+      }
+
+    case CODE_FOR_call_insn:
+    case CODE_FOR_call_value_insn:
+      return true;
+    }
+
+  return false;
+}
+
+
 int
 jump_over_one_insn_p (rtx insn, rtx dest)
 {
@@ -7131,7 +7181,11 @@  jump_over_one_insn_p (rtx insn, rtx dest
 		      : dest);
   int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
   int dest_addr = INSN_ADDRESSES (uid);
-  return dest_addr - jump_addr == get_attr_length (insn) + 1;
+  int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
+  
+  return (jump_offset == 1
+          || (jump_offset == 2
+              && avr_2word_insn_p (next_nonnote_nondebug_insn (insn))));
 }
 
 /* Returns 1 if a value of mode MODE can be stored starting with hard