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,M32C] : Arithmetic, logical and peephole implementations.


Hi,

Following patch generates some new instructions and enhances some
instructions which are already implemented for M32C(ELF) targets. GCC 
currently uses mov, shift etc. instructions to implement logical
operations on 32 bit values. This patch changes the current
implementation to use the 
most effective instructions in such cases (e.g. use of two consecutive
16 
bits logical instructions). 
Also, while performing arithmetic operations, the present M32C compiler 
calls the library routines. This increases the overall code size. 
This patch adds a support for new arithmetic assembly instructions into
the 
M32C compiler which leads to avoid the calls to library routines. This 
results into considerable reduction in overall code size. Thus the code 
efficiency of the toolchain increases to a great extent. 

The instructions that are implemented in this patch are as follows:

M32C
1. add.l
2. sub.l
3. and.w
4. or.w
5. xor.w
6. Peephole to generate two mov.l instructions instead of four mov.w
while    initializing a double variable at the time of its declaration.

M16C and R8C
1. adcf.w
2. adc.w
3. sbb.w
4. and.w
5. or.w
6. xor.w

The new instructions added are add.l, sub.l, adcf.w ,adc.w ,sbb.w while 
and.w ,or.w  and xor.w are enhanced for the implementation of 32 bit
values 
in this patch. Two new peepholes are also added that helps to optimize
the 
code.

No new regressions found.

=======================Start of Patch================================
ChangeLog
2006-03-03   Naveen.H.S <naveenh@kpitcummins.com>
		 Jayant Sonar <jayants@kpitcummins.com>
		 Jaydeep Vipradas <jaydeepv@kpitcummins.com>
       	* gcc/config/m32c/addsub.md: New instructions for  
              add.l,adcf.w,adc.w,sub.l,sbb.w are implemented.
		* gcc/config/m32c/bitops.md: and.w,or.w,xor.w are
enhanced for 
              32 bit operations.
		* gcc/config/h8300/mov.md: For global and local double  
              variables, two peepholes are defined to optimize two mov.w

              instructions into a single mov.l, while initializing them
at 
              the time of declaration itself.

--- gcc-4.2-20060204/gcc/config/m32c/addsub.md	2006-01-13
03:10:27.000000000 +0530
+++ gcc-4.2-20060204/gcc/config/m32c/addsub.md	2006-02-24
12:56:22.000000000 +0530
@@ -71,7 +71,91 @@
    #"
   [(set_attr "flags" "oszc,oszc,oszc,*,*,oszc,oszc")]
   )
-
+;;---------------------------------------------------------------------
-
+(define_expand "addsi3"
+  [(set (match_operand:SI 0 "mra_operand" "=RsiSd,RsiSd,??Rmm,??Rmm")
+        (plus:SI (match_operand:SI 1 "mra_operand" "%0,0,0,0")
+                   (match_operand:SI 2 "mrai_operand"
"iRsiSd,?Rmm,iRsiSd,?Rmm")))]
+  "TARGET_M32C ||TARGET_A16"
+  ""
+  )
+ 
+(define_insn "addsi3_2"
+  [(set (match_operand:SI 0 "mra_operand"
"=RsiSd,RsiSd,??Rmm,??Rmm,RsiSd")
+        (plus:SI (match_operand:SI 1 "mra_operand" "%0,0,0,0,0")
+                   (match_operand:SI 2 "mrai_operand"
"i,?Rmm,iRsiSd,?Rmm,RsiSd")))]
+ "TARGET_A16"
+"*
+{ 
+ if (which_alternative == 0)
+   {
+   output_asm_insn (\"add.w %X2,%h0\",operands);
+    operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
+    return \"adc.w %X2,%H0\";
+   }
+   if (which_alternative == 1)
+   {
+  return \"add.w %h2,%h0\;adc.w %H2,%H0\";
+   }
+   if (which_alternative == 2)
+   {
+    output_asm_insn (\"add.w %X2,%h0\",operands);
+    operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
+    return \"adc.w %X2,%H0\";
+   }
+  if (which_alternative == 3)
+   {
+ return \"add.w %h2,%h0\;adc.w %H2,%H0\";
+   }
+  if (which_alternative == 4)
+   {
+ return \"add.w %h2,%h0\;adc.w %H2,%H0\";
+   }
+}"
+ [(set_attr "flags" "oszc,oszc,oszc,oszc,oszc")]
+)
+
+(define_insn "addsi3_1"
+  [(set (match_operand:SI 0 "mra_operand"
"=RsiSd,RsiSd,??Rmm,??Rmm,RsiSd")
+        (plus:SI (match_operand:SI 1 "mra_operand" "%0,0,0,0,0")
+                 (match_operand 2 "mrai_operand"
"i,?Rmm,iRsiSd,?Rmm,RsiSd")))]
+ "TARGET_A16 && INTVAL(operands[2]) < 0xffff"
+ "*
+{
+ if(which_alternative == 0)
+  {
+  return \"add.w %X2,%h0\;adcf.w %H0\";
+  }
+ if(which_alternative == 1)
+  {
+  return \"add.w %h2,%h0\;adcf.w %H0\";
+  }
+ if(which_alternative == 2)
+  {
+  return \"add.w %X2,%h0\;adcf.w %H0\";
+  }
+ if(which_alternative == 3)
+ {
+  return \"add.w %h2,%h0\;adcf.w %H0\";
+  }
+  if(which_alternative == 4)
+ {
+  return \"add.w %h2,%h0\;adcf.w %H0\";
+  }
+}
+"
+ [(set_attr "flags" "oszc,oszc,oszc,oszc,oszc")]
+)
+
+(define_insn "addsi3_3"
+  [(set (match_operand:SI 0 "mra_operand" "=RsiSd,RsiSd,??Rmm,??Rmm")
+        (plus:SI (match_operand:SI 1 "mra_operand" "%0,0,0,0")
+                   (match_operand:SI 2 "mrai_operand"
"iRsiSd,?Rmm,iRsiSd,?Rmm")))]
+  "TARGET_M32C"
+  "add.l\t%2,%0"
+  [(set_attr "flags" "oszc")]
+  )
+;;---------------------------------------------------------------------
--
 ; This is needed for reloading large frames.
 (define_split
   [(set (match_operand:PSI 0 "ra_operand" "")
@@ -136,7 +220,60 @@
   "sub.%&\t%2,%0"
   [(set_attr "flags" "oszc")]
   )
+;;---------------------------------------------------------------------
-------
+(define_expand "subsi3"
+  [(set (match_operand:SI 0 "mra_operand" "=RsiSd,RsiSd,??Rmm,??Rmm")
+        (minus:SI (match_operand:SI 1 "mra_operand" "0,0,0,0")
+                   (match_operand:SI 2 "mrai_operand"
"iRsiSd,?Rmm,iRsiSd,?Rmm")))]
+  "TARGET_M32C ||TARGET_A16"
+  ""
+  )
 
+(define_insn "subsi3_1"
+  [(set (match_operand:SI 0 "mra_operand"
"=RsiSd,RsiSd,??Rmm,??Rmm,RsiSd")
+        (minus:SI (match_operand:SI 1 "mra_operand" "0,0,0,0,0")
+                   (match_operand:SI 2 "mrai_operand"
"i,?Rmm,iRsiSd,?Rmm,RsiSd")))]
+ "TARGET_A16"
+"*
+{
+ if (which_alternative == 0)
+   {
+   output_asm_insn (\"sub.w %X2,%h0\",operands);
+    operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
+    return \"sbb.w %X2,%H0\";
+   }
+   if (which_alternative == 1)
+   {
+  return \"sub.w %h2,%h0\;sbb.w %H2,%H0\";
+   }
+   if (which_alternative == 2)
+   {
+    output_asm_insn (\"sub.w %X2,%h0\",operands);
+    operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
+    return \"sbb.w %X2,%H0\";
+   }
+  if (which_alternative == 3)
+   {
+ return \"sub.w %h2,%h0\;sbb.w %H2,%H0\";
+   }
+  if (which_alternative == 4)
+   {
+ return \"sub.w %h2,%h0\;sbb.w %H2,%H0\";
+   }
+
+}"
+ [(set_attr "flags" "oszc,oszc,oszc,oszc,oszc")]
+)
+
+(define_insn "subsi3_2"
+  [(set (match_operand:SI 0 "mra_operand" "=RsiSd,RsiSd,??Rmm,??Rmm")
+        (minus:SI (match_operand:SI 1 "mra_operand" "0,0,0,0")
+                   (match_operand:SI 2 "mrai_operand"
"iRsiSd,?Rmm,iRsiSd,?Rmm")))]
+  "TARGET_M32C"
+   "sub.l\t%2,%0"
+  [(set_attr "flags" "oszc,oszc,oszc,oszc")]
+  )
+;;---------------------------------------------------------------------
-------
 (define_insn "negqi2"
   [(set (match_operand:QI 0 "mra_operand" "=SdRhl,??Rmm")
 	(neg:QI (match_operand:QI 1 "mra_operand" "0,0")))]
--- gcc-4.2-20060204/gcc/config/m32c/bitops.md	2005-07-21
04:57:02.000000000 +0530
+++ gcc-4.2-20060204/gcc/config/m32c/bitops.md	2006-02-28
21:16:56.000000000 +0530
@@ -40,6 +40,43 @@
   [(set_attr "flags" "sz,sz,sz,sz")]
   )
 
+;;---------------------------------------------------------------------
----
+(define_insn "andsi3"
+  [(set (match_operand:SI 0 "mra_operand"
"=RsiSd,RsiSd,??Rmm,??Rmm,RsiSd")
+        (and:SI (match_operand:SI 1 "mra_operand" "%0,0,0,0,0")
+                   (match_operand:SI 2 "mrai_operand"
"i,?Rmm,iRsiSd,?Rmm,RsiSd")))]
+ "TARGET_A16 ||TARGET_M32C"
+"*
+{ 
+ if (which_alternative == 0)
+   {
+   output_asm_insn (\"and.w %X2,%h0\",operands);
+    operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
+    return \"and.w %X2,%H0\";
+   }
+   if (which_alternative == 1)
+   {
+  return \"and.w %h2,%h0\;and.w %H2,%H0\";
+   }
+   if (which_alternative == 2)
+   {
+    output_asm_insn (\"and.w %X2,%h0\",operands);
+    operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
+    return \"and.w %X2,%H0\";
+   }
+  if (which_alternative == 3)
+   {
+ return \"and.w %h2,%h0\;and.w %H2,%H0\";
+   }
+  if (which_alternative == 4)
+   {
+ return \"and.w %h2,%h0\;and.w %H2,%H0\";
+   }
+}"
+ [(set_attr "flags" "sz,sz,sz,sz,sz")]
+)
+
+;;---------------------------------------------------------------------
-----
 (define_insn "iorqi3"
   [(set (match_operand:QI 0 "mra_operand" "=RqiSd,??Rmm,RqiSd,??Rmm")
 	(ior:QI (match_operand:QI 1 "mra_operand" "%0,0,0,0")
@@ -58,6 +95,43 @@
   [(set_attr "flags" "sz,sz,sz,sz")]
   )
 
+;;---------------------------------------------------------------------
----
+(define_insn "iorsi3"
+  [(set (match_operand:SI 0 "mra_operand"
"=RsiSd,RsiSd,??Rmm,??Rmm,RsiSd")
+        (ior:SI (match_operand:SI 1 "mra_operand" "%0,0,0,0,0")
+                   (match_operand:SI 2 "mrai_operand"
"i,?Rmm,iRsiSd,?Rmm,RsiSd")))]
+ "TARGET_A16 ||TARGET_M32C"
+"*
+{
+ if (which_alternative == 0)
+   {
+   output_asm_insn (\"or.w %X2,%h0\",operands);
+    operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
+    return \"or.w %X2,%H0\";
+   }
+   if (which_alternative == 1)
+   {
+  return \"or.w %h2,%h0\;or.w %H2,%H0\";
+   }
+   if (which_alternative == 2)
+   {
+    output_asm_insn (\"or.w %X2,%h0\",operands);
+    operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
+    return \"or.w %X2,%H0\";
+   }
+  if (which_alternative == 3)
+   {
+ return \"or.w %h2,%h0\;or.w %H2,%H0\";
+   }
+  if (which_alternative == 4)
+   {
+ return \"or.w %h2,%h0\;or.w %H2,%H0\";
+   }
+}"
+ [(set_attr "flags" "sz,sz,sz,sz,sz")]
+)
+
+;;---------------------------------------------------------------------
-----
 (define_insn "xorqi3"
   [(set (match_operand:QI 0 "mra_operand" "=RhlSd,RhlSd,??Rmm,??Rmm")
 	(xor:QI (match_operand:QI 1 "mra_operand" "%0,0,0,0")
@@ -76,6 +150,43 @@
   [(set_attr "flags" "sz,sz,sz,sz")]
   )
 
+;;---------------------------------------------------------------------
----
+(define_insn "xorsi3"
+  [(set (match_operand:SI 0 "mra_operand"
"=RsiSd,RsiSd,??Rmm,??Rmm,RsiSd")
+        (xor:SI (match_operand:SI 1 "mra_operand" "%0,0,0,0,0")
+                   (match_operand:SI 2 "mrai_operand"
"i,?Rmm,iRsiSd,?Rmm,RsiSd")))]
+ "TARGET_A16 ||TARGET_M32C"
+"*
+{
+ if (which_alternative == 0)
+   {
+   output_asm_insn (\"xor.w %X2,%h0\",operands);
+    operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
+    return \"xor.w %X2,%H0\";
+   }
+   if (which_alternative == 1)
+   {
+  return \"xor.w %h2,%h0\;xor.w %H2,%H0\";
+   }
+   if (which_alternative == 2)
+   {
+    output_asm_insn (\"xor.w %X2,%h0\",operands);
+    operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
+    return \"xor.w %X2,%H0\";
+   }
+  if (which_alternative == 3)
+   {
+ return \"xor.w %h2,%h0\;xor.w %H2,%H0\";
+   }
+  if (which_alternative == 4)
+   {
+ return \"xor.w %h2,%h0\;xor.w %H2,%H0\";
+   }
+}"
+ [(set_attr "flags" "sz,sz,sz,sz,sz")]
+)
+
+;;---------------------------------------------------------------------
-----
 (define_insn "one_cmplqi2"
   [(set (match_operand:QI 0 "mra_operand" "=RhlSd,??Rmm")
 	(not:QI (match_operand:QI 1 "mra_operand" "0,0")))]
@@ -91,3 +202,5 @@
   "not.w\t%0"
   [(set_attr "flags" "sz,sz")]
   )
+
+ 
--- gcc-4.2-20060204/gcc/config/m32c/mov.md	2006-01-13
03:10:27.000000000 +0530
+++ gcc-4.2-20060204/gcc/config/m32c/mov.md	2006-02-22
12:53:07.000000000 +0530
@@ -138,6 +138,73 @@
 	(match_dup 3))]
   "")
 
+;; Peephole to optimize moving an immediate value to a global variable 
+;; of type DOUBLE, using two mov.l instead of four mov.w
+
+(define_peephole
+  [(set (mem:HI (match_operand:PSI 0 "symbol_operand" ""))
+		(match_operand 1 "immediate_operand" ""))
+   (set (mem:HI (const:PSI (plus:PSI (match_operand:PSI 2
"symbol_operand" "")
+	              		     (match_operand 3
"const_int_operand" ""))))
+		(match_operand 4 "const_int_operand" ""))
+   (set (mem:HI (const:PSI (plus:PSI (match_operand:PSI 5
"symbol_operand" "")
+	              		     (match_operand 6
"const_int_operand" ""))))
+		(match_operand 7 "const_int_operand" ""))
+   (set (mem:HI (const:PSI (plus:PSI (match_operand:PSI 8
"symbol_operand" "")
+	              		     (match_operand 9
"const_int_operand" ""))))
+		(match_operand 10 "const_int_operand" ""))]
+   "TARGET_A24 && INTVAL (operands[3]) == 2 && INTVAL (operands[6]) ==
4 && INTVAL (operands[9]) == 6"
+   "*
+     char pattern[50],newstr[50];
+     char * str = XSTR (operands[0], 0);
+     int offset = INTVAL (operands[6]);
+     sprintf(newstr, \"%s+%d\", str, offset);
+     long low1 = INTVAL (operands[1]) & 0xFFFF;
+     long low2 = INTVAL (operands[7]) & 0xFFFF;
+     long high1 = INTVAL (operands[4]);
+     long high2 = INTVAL (operands[10]);
+     high1 = high1 << 16;
+     high2 = high2 << 16;
+     long num1 = high1 + low1;
+     long num2 = high2 + low2;
+     sprintf (pattern, \"mov.l\t#%ld,_%s\;mov.l\t#%ld,_%s\",num2,
newstr, num1, str);
+     output_asm_insn (pattern, operands);
+     return \"\";
+     ")
+
+;; Peephole to optimize moving an immediate value to a local volatile 
+;; variable of type DOUBLE, using two mov.l instead of four mov.w
+
+(define_peephole
+   [(set (mem:HI (plus:PSI (match_operand:PSI 0 "cr_operand" "")
+                           (match_operand 1 "const_int_operand" "")))
+                 (match_operand 2 "const_int_operand" ""))
+    (set (mem:HI (plus:PSI (match_operand:PSI 3 "cr_operand" "")
+                           (match_operand 4 "const_int_operand" "")))
+                 (match_operand 5 "const_int_operand" ""))
+    (set (mem:HI (plus:PSI (match_operand:PSI 6 "cr_operand" "")
+                           (match_operand 7 "const_int_operand" "")))
+                 (match_operand 8 "const_int_operand" ""))
+    (set (mem:HI (plus:PSI (match_operand:PSI 9 "cr_operand" "")
+                           (match_operand 10 "const_int_operand" "")))
+                 (match_operand 11 "const_int_operand" ""))]
+   "TARGET_A24 && (INTVAL (operands[4])- INTVAL(operands[1]) == 2) &&
(INTVAL (operands[7])- INTVAL(operands[4]) == 2) && (INTVAL
(operands[10])- INTVAL(operands[7]) == 2)"
+   "*
+     char pattern[50];
+     int offset_low = INTVAL (operands[1]);
+     int offset_high = INTVAL (operands[7]);
+     long low_lsb = INTVAL (operands[2]) & 0xFFFF;
+     long low_msb = INTVAL (operands[8]) & 0xFFFF;
+     long high_lsb = INTVAL (operands[5]);
+     long high_msb = INTVAL (operands[11]);
+     high_lsb = high_lsb << 16;
+     high_msb = high_msb << 16;
+     long num1 = high_lsb + low_lsb;
+     long num2 = high_msb + low_msb;
+     sprintf (pattern, \"mov.l\t#%ld,%d[fb]\;mov.l\t#%ld,%d[fb]\",num2,
offset_high, num1, offset_low);
+     output_asm_insn (pattern, operands);
+     return \"\";
+     ")
 
 ; Some PSI moves must be split.
 (define_split
=======================End Of Patch================================

Regards,
Naveen H.S.
KPIT Cummins InfoSystems Ltd.
Pune, India

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Free download of GNU based tool-chains for Renesas' SH and H8 Series.
The following site also offers free technical support to its users. 
Visit http://www.kpitgnutools.com for details. 
Latest versions of KPIT GNU tools were released on February 1, 2006.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


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