[PATCH, ARM] PR47855 Compute attr "length" for some thumb2 insns, 2/3
Carrot Wei
carrot@google.com
Fri Apr 8 09:57:00 GMT 2011
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.
The patch has been tested on qemu with both ARM and thumb mode.
thanks
Carrot
ChangeLog:
2011-04-08 Wei Guozhi <carrot@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"
More information about the Gcc-patches
mailing list