On 08/04/11 10:57, Carrot Wei wrote:
Hi
This is the second part of the fixing for
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47855
This patch contains the length computation for insn patterns "*arm_movqi_insn"
and "*arm_addsi3". Since the alternatives and encodings are much more complex,
the attribute length is computed in separate C functions.
Sorry, no. This is potentially a maintenance pain. It hardcodes
alternatives from a pattern elsewhere in the C file. I don't like doing
this unless we have to with the sync primitives or with push_multi. In
this case I'm not convinced we need such functions in the .c file.
Why can't we use the "enabled" attribute here with appropriate
constraints for everything other than the memory cases (even there we
might be able to invent some new constraints) ?
Also a note about programming style. There are the helper macros like
REG_P, CONST_INT_P and MEM_P which remove the necessity for checks like
GET_CODE (x) == y where y E { REG, CONST_INT, MEM}
cheers
Ramana
The patch has been tested on qemu with both ARM and thumb mode.
thanks
Carrot
ChangeLog:
2011-04-08 Wei Guozhi<car...@google.com>
PR target/47855
* config/arm/arm-protos.h (arm_attr_length_movqi): New prototype.
(arm_attr_length_addsi3): Likewise.
* config/arm/arm.c (arm_attr_length_movqi): New function.
(arm_attr_length_addsi3): Likewise.
* config/arm/arm.md (*arm_movqi_insn): Compute attr "length".
(*arm_addsi3): Change "length" computation by calling C function.
Index: arm.c
===================================================================
--- arm.c (revision 172017)
+++ arm.c (working copy)
@@ -23694,4 +23694,179 @@ arm_preferred_rename_class (reg_class_t
return NO_REGS;
}
+/* Compute the atrribute "length" of insn "*arm_movqi_insn".
+ So this function MUST be kept in sync with that insn pattern. */
+int
+arm_attr_length_movqi (rtx dst, rtx src)
+{
+ enum rtx_code dst_code = GET_CODE (dst);
+ enum rtx_code src_code = GET_CODE (src);
+ rtx address, reg_op, base;
+
+ /* ARM mode. */
+ if (TARGET_ARM)
+ return 4;
+
+ /* Thumb2 mode. */
+ /* Register move. */
+ if ((dst_code == REG)&& (src_code == REG))
+ return 2;
+
+ /* Load an immediate. */
+ if ((dst_code == REG)&& (src_code == CONST_INT))
+ {
+ HOST_WIDE_INT i = INTVAL (src);
+ if ((arm_regno_class (REGNO (dst)) == LO_REGS)&& (i>= 0)&& (i<= 255))
+ return 2;
+ else
+ return 4;
+ }
+
+ /* Load/store a byte from/to memory. */
+ if ((dst_code == REG)&& (src_code == MEM))
+ {
+ reg_op = dst;
+ address = XEXP (src, 0);
+ }
+ else
+ {
+ gcc_assert ((dst_code == MEM)&& (src_code == REG));
+ reg_op = src;
+ address = XEXP (dst, 0);
+ }
+
+ if (GET_CODE (address) == PLUS)
+ {
+ rtx op1 = XEXP (address, 1);
+ base = XEXP (address, 0);
+ if (GET_CODE (op1) == REG)
+ {
+ if (arm_regno_class (REGNO (op1)) != LO_REGS)
+ return 4;
+ }
+ else if ((GET_CODE (op1) != CONST_INT)
+ || (INTVAL (op1)< 0) || (INTVAL (op1)> 31))
+ return 4;
+ }
+ else
+ base = address;
+
+ if (GET_CODE (base) != REG)
+ return 4;
+ if ((arm_regno_class (REGNO (base)) == LO_REGS)
+&& (arm_regno_class (REGNO (reg_op)) == LO_REGS))
+ return 2;
+
+ return 4;
+}
+
+/* Compute the atrribute "length" of insn "*arm_addsi3".
+ So this function MUST be kept in sync with that insn pattern. */
+int
+arm_attr_length_addsi3 (rtx dst, rtx src1, rtx src2)
+{
+ HOST_WIDE_INT v;
+
+ /* The splite case. */
+ if (which_alternative == 5)
+ return 16;
+
+ /* ARM mode. */
+ if (TARGET_ARM)
+ return 4;
+
+ /* Thumb2 mode. */
+ if (which_alternative == 4)
+ {
+ /* SUB (SP minus immediate). */
+ v = -INTVAL (src2);
+ gcc_assert (v>= 0);
+ if (((v& 3) == 0)&& (v< 512))
+ return 2;
+ return 4;
+ }
+ else if (which_alternative == 3)
+ {
+ /* SUB immediate. */
+ HOST_WIDE_INT max_offset = 7;
+ v = -INTVAL (src2);
+ gcc_assert (v>= 0);
+ if (REGNO (dst) == REGNO (src1))
+ max_offset = 255;
+ if ((arm_regno_class (REGNO (dst)) == LO_REGS)
+ && (arm_regno_class (REGNO (src1)) == LO_REGS)
+ && (v<= max_offset))
+ return 2;
+ return 4;
+ }
+ else if (which_alternative == 1)
+ {
+ if (REG_P (src2)) /* ADD SP,SP,<Rm>*/
+ return 2;
+ v = INTVAL (src2);
+ if (((v& 3) == 0)&& (v< 1024)) /* ADD SP,SP,#<imm> */
+ return 2;
+ return 4;
+ }
+ else
+ {
+ if (which_alternative == 2)
+ {
+ rtx tmp = src1; src1 = src2; src2 = tmp;
+ }
+ /* Now we are in the most general case, (which_alternative == 0). */
+ gcc_assert (REG_P (src1));
+ if (REGNO (src1) == SP_REGNUM)
+ {
+ if (REG_P (src2))
+ {
+ /* ADD<Rdm>, SP,<Rdm> */
+ if (REGNO (src2) == REGNO (src1))
+ return 2;
+ return 4;
+ }
+ else
+ {
+ gcc_assert (GET_CODE (src2) == CONST_INT);
+ v = INTVAL (src2);
+ /* ADD<Rd>, SP, #<imm> */
+ if ((arm_regno_class (REGNO (dst)) == LO_REGS)
+ && ((v& 3) == 0)&& (v< 1024))
+ return 2;
+ return 4;
+ }
+ }
+ else
+ {
+ if (REG_P (src2))
+ {
+ /* ADD<Rdn>,<Rm> */
+ if ((REGNO (dst) == REGNO (src1))
+ || (REGNO (dst) == REGNO (src2)))
+ return 2;
+ /* ADDS<Rd>,<Rn>,<Rm> */
+ else if ((arm_regno_class (REGNO (dst)) == LO_REGS)
+ && (arm_regno_class (REGNO (src1)) == LO_REGS)
+ && (arm_regno_class (REGNO (src2)) == LO_REGS))
+ return 2;
+ return 4;
+ }
+ else
+ {
+ /* ADD immediate. */
+ HOST_WIDE_INT max_offset = 7;
+ gcc_assert (GET_CODE (src2) == CONST_INT);
+ v = INTVAL (src2);
+ if (REGNO (dst) == REGNO (src1))
+ max_offset = 255;
+ if ((arm_regno_class (REGNO (dst)) == LO_REGS)
+ && (arm_regno_class (REGNO (src1)) == LO_REGS)
+ && (v<= max_offset))
+ return 2;
+ return 4;
+ }
+ }
+ }
+}
+
#include "gt-arm.h"
Index: arm-protos.h
===================================================================
--- arm-protos.h (revision 172017)
+++ arm-protos.h (working copy)
@@ -152,6 +152,8 @@ extern void arm_expand_sync (enum machin
extern const char *arm_output_memory_barrier (rtx *);
extern const char *arm_output_sync_insn (rtx, rtx *);
extern unsigned int arm_sync_loop_insns (rtx , rtx *);
+extern int arm_attr_length_movqi (rtx, rtx);
+extern int arm_attr_length_addsi3 (rtx, rtx, rtx);
#if defined TREE_CODE
extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
Index: arm.md
===================================================================
--- arm.md (revision 172017)
+++ arm.md (working copy)
@@ -730,8 +730,10 @@
operands[1], 0);
DONE;
"
- [(set_attr "length" "4,4,4,4,4,16")
- (set_attr "predicable" "yes")]
+ [(set_attr "predicable" "yes")
+ (set (attr "length")
+ (symbol_ref
+ "arm_attr_length_addsi3 (operands[0], operands[1], operands[2])"))]
)
(define_insn_and_split "*thumb1_addsi3"
@@ -5958,7 +5960,9 @@
str%(b%)\\t%1, %0"
[(set_attr "type" "*,*,load1,store1")
(set_attr "insn" "mov,mvn,*,*")
- (set_attr "predicable" "yes")]
+ (set_attr "predicable" "yes")
+ (set (attr "length")
+ (symbol_ref "arm_attr_length_movqi (operands[0], operands[1])"))]
)
(define_insn "*thumb1_movqi_insn"