[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avr-gcc-list] new patch for loop and jump optimisation
From: |
Andy Hutchinson |
Subject: |
[avr-gcc-list] new patch for loop and jump optimisation |
Date: |
Wed, 16 Feb 2005 22:20:23 -0500 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax) |
Here is a new avr gcc patch to try out.
If I did everything correctly it should change avr.c and avr.h on HEAD.
This includes fixes for the following missed/broken optimisation:
1) SBxx and CPSE will now be used to skip 2 and 3 word instructions
2) SBxx Rx,7 (..15..31) will not be used at end of doloop in preference
to more efficient BRPL/BRMI. This was caused by the SBxx optimisation
being applied to all sign tests - even when we knew what sign was.
3) Removal of some redundant TST instructions related to above.
I am unaware of any speed/size optimisation regressions. There shouldn't
be any.
It will still miss a few situations where a skip can be used - I
already know how to make it perfect but I want this version checked first.
At present this patch folds sign test of SF (float) into a test of bit
31. This will not work if we are using signed zeros. However it is
easily fixed (see below)
This change also replaces the current asm peephole sign tests with a
single RTL peephole2. This helps avr move away from use of the
deprecated asm peephole usage.
I have chosen to use the new mode macros for 4.0. This allows a single
instruction pattern to be used for several mode. In this case
QI,HI,SI,SF (- and thats where the float sign test is!)
There are now two jump_over_one_insn... functions. One is used by
peephole and the other by peephole2. Both use the same logic. peephole
(ie asm peepholes) can get at address of instructions. But you cant do
that when the peephole2 (RTL) is used. Instead I use instruction length
and a forward search.
The function jump_over_one_insn_p2 can totally replace the other one.
This would remove nearly all the asm peephole patterns. (I beleive the
only ones left would be CPSE). I have not done this yet as it would
involve changing a lot of things at once! It would not affect generated
code.
Can you try this?
*** avr.c 9 Feb 2005 14:43:28 -0000 1.129
--- avr.c 17 Feb 2005 01:48:23 -0000
***************
*** 5519,5525 ****
}
}
}
! else if (true_regnum (SET_SRC (pattern)) >= 0)
{
/* This is a tst insn */
rtx next = next_real_insn (insn);
--- 5519,5525 ----
}
}
}
! else if (0&&true_regnum (SET_SRC (pattern)) >= 0)//awh disable TST
REVERSAL
{
/* This is a tst insn */
rtx next = next_real_insn (insn);
***************
*** 5624,5639 ****
return 0;
}
int
jump_over_one_insn_p (rtx insn, rtx dest)
{
int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
? XEXP (dest, 0)
: 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;
}
/* Returns 1 if a value of mode MODE can be stored starting with hard
--- 5624,5784 ----
return 0;
}
+ /* Check if dest label is ok for skip instruction destination in this
instruction insn
+ SBxx is only valid over one asm (not RTL) instruction. One asm insn can be
1,2 or 3 words.
+ return number of asm words skipped as true, 0= false if we can't work it
out
+ or jump is too far
+ Ideally we need addresses to find displacement - we can only do this with
+ a code peephole not a peephole2 (as addresses are not yet calculated). To
get around this
+ we get the length of following instructions from length attribute. If
length is 1
+ it is skippable. We also look for specific patterns we know are one
instruction long
+ this includes (call, r<=[mem], [mem]<=r and jump). Finally we look for the
label.
+ This wont catch all of the possibilities
+ TODO use adjust_Ins_length for more accurate length?????
+ */
+
+ int jump_over_one_insn_p2(rtx insn, rtx operands[], rtx dest )
+
+ {
+ /* This is wrapper to get around problem where get_attr_length clobbers
operand list! */
+ rtx ops[2];
+ ops[0]=operands[0];
+ ops[1]=operands[1];
+ ops[2]=operands[2];
+ int ret =jump_over_one_insn_pxx(insn,dest);
+ operands[0]=ops[0];
+ operands[1]=ops[1];
+ operands[2]=ops[2];
+ return ret;
+ }
int
+ jump_over_one_insn_pxx (rtx insn, rtx dest)
+ {
+ /* get dest instruction uid */
+ int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
+ ? XEXP (dest, 0)
+ : dest);
+
+ /* skip next real instruction - should be the jump*/
+ rtx nexti=next_real_insn(insn);
+
+ /*return false if there isn't one (bad md file)*/
+ if (!nexti) return 0;
+
+ /* next real instruction is perhaps one we can skip*/
+ nexti=next_real_insn(nexti);
+
+ /*return false if there isn't one */
+ if (!nexti) return 0;
+
+ /* length in words of skippable instruction */
+ int len =0;
+
+ rtx next= PATTERN(nexti);
+
+
+ /* ok skipping byte stores of zero or register into direct memory STS */
+ if (GET_CODE(next)==SET)
+ if (GET_MODE(XEXP(next,0))==QImode)
+ if (GET_CODE(XEXP(next,0))==MEM)
+ if (CONSTANT_P(XEXP(XEXP(next,0),0)))
+ if ((GET_CODE(XEXP(next,1))==REG)||(XEXP(next,1)==const0_rtx))
+ len=2;
+
+
+ /* ok skipping byte loads of register from direct mem LDS */
+ if (GET_CODE(next)==SET)
+ if (GET_MODE(XEXP(next,1))==QImode)
+ if (GET_CODE(XEXP(next,1))==MEM)
+ if (CONSTANT_P(XEXP(XEXP(next,1),0)))
+ if ((GET_CODE(XEXP(next,0))==REG))
+ len= 2;
+
+ /*ok skipping over any non conditional jump - JUMP */
+ if (GET_CODE(next)==SET)
+ if (GET_CODE(XEXP(next,0))==PC)
+ if (GET_CODE(XEXP(next,1))==LABEL_REF)
+ len=2;
+
+ /* ok skipping calls which are always ONE instruction but sometimes 2
words*/
+ if (GET_CODE(nexti)==CALL_INSN) len=2;
+
+
+ /*finally single word RTL instructions are one asm instruction */
+ int l=get_attr_length(nexti);
+ if (l==1) len=1;
+
+
+ /* exit if instruction is not skippable */
+ if (!len) return 0;
+
+ /* jump target must be next non-note instruction */
+ while ((nexti=NEXT_INSN(nexti)))
+ {
+ if (uid==INSN_UID(nexti))
+ return len;
+ else if INSN_P (nexti)
+ return 0;
+ }
+
+ /* lable target was not found */
+ return 0;
+ }
+ /* This is the same function but uses instruction addresses */
+ int
jump_over_one_insn_p (rtx insn, rtx dest)
{
int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
? XEXP (dest, 0)
: dest);
!
! /* skip notes and look at next real instruction */
! rtx nexti=next_real_insn(insn);
!
! /*return false if there isn't one */
! if (!nexti) return 0;
!
! /* Use this as baseline for displacment calculation */
! int jump_addr = INSN_ADDRESSES (INSN_UID (nexti));
int dest_addr = INSN_ADDRESSES (uid);
! int disp = dest_addr - jump_addr;
!
! /* valid displacments are 1,2 or 3 words */
! if ((disp <= 0)||(disp>3)) return 0;
!
! /* one word displacment always means only one asm instruction */
! if (disp == 1) return 1;
!
! /* ok skipping calls which are always ONE instruction but sometimes 2
words*/
! if (GET_CODE(nexti)==CALL_INSN)
! if (disp == 2) return 2;
!
! rtx next= PATTERN(next_real_insn(insn));
! /* ok skipping byte stores of zero or register into direct memory STS */
! if (GET_CODE(next)==SET)
! if (GET_MODE(XEXP(next,0))==QImode)
! if (GET_CODE(XEXP(next,0))==MEM)
! if (CONSTANT_P(XEXP(XEXP(next,0),0)))
! if ((GET_CODE(XEXP(next,1))==REG)||(XEXP(next,1)==const0_rtx))
! if (disp == 2) return 2;
!
! /* ok skipping byte loads of register from direct mem LDS */
! if (GET_CODE(next)==SET)
! if (GET_MODE(XEXP(next,1))==QImode)
! if (GET_CODE(XEXP(next,1))==MEM)
! if (CONSTANT_P(XEXP(XEXP(next,1),0)))
! if ((GET_CODE(XEXP(next,0))==REG))
! if (disp == 2) return 2;
!
! /*ok skipping over any non conditional jump to label - JUMP */
! /*ok skipping over any non conditional jump - JUMP */
! if (GET_CODE(next)==SET)
! if (GET_CODE(XEXP(next,0))==PC)
! if (GET_CODE(XEXP(next,1))==LABEL_REF)
! if (disp == 2) return 2;
!
! return 0;
}
/* Returns 1 if a value of mode MODE can be stored starting with hard
*** avr.md 27 Jan 2005 18:22:25 -0000 1.49
--- avr.md 17 Feb 2005 02:18:27 -0000
***************
*** 1903,1985 ****
(const_int 4))))
(set_attr "cc" "clobber")])
- ;; Convert sign tests to bit 7/15/31 tests that match the above insns.
- (define_peephole2
- [(set (cc0) (match_operand:QI 0 "register_operand" ""))
- (set (pc) (if_then_else (ge (cc0) (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- ""
- [(set (pc) (if_then_else (eq (zero_extract (match_dup 0)
- (const_int 1)
- (const_int 7))
- (const_int 0))
- (label_ref (match_dup 1))
- (pc)))]
- "")
- (define_peephole2
- [(set (cc0) (match_operand:QI 0 "register_operand" ""))
- (set (pc) (if_then_else (lt (cc0) (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- ""
- [(set (pc) (if_then_else (ne (zero_extract (match_dup 0)
- (const_int 1)
- (const_int 7))
- (const_int 0))
- (label_ref (match_dup 1))
- (pc)))]
- "")
! (define_peephole2
! [(set (cc0) (match_operand:HI 0 "register_operand" ""))
! (set (pc) (if_then_else (ge (cc0) (const_int 0))
! (label_ref (match_operand 1 "" ""))
! (pc)))]
! ""
! [(set (pc) (if_then_else (eq (and:HI (match_dup 0) (const_int -32768))
! (const_int 0))
! (label_ref (match_dup 1))
! (pc)))]
! "")
(define_peephole2
! [(set (cc0) (match_operand:HI 0 "register_operand" ""))
! (set (pc) (if_then_else (lt (cc0) (const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))]
""
! [(set (pc) (if_then_else (ne (and:HI (match_dup 0) (const_int -32768))
! (const_int 0))
(label_ref (match_dup 1))
! (pc)))]
! "")
! (define_peephole2
! [(set (cc0) (match_operand:SI 0 "register_operand" ""))
! (set (pc) (if_then_else (ge (cc0) (const_int 0))
! (label_ref (match_operand 1 "" ""))
! (pc)))]
! ""
! [(set (pc) (if_then_else (eq (and:SI (match_dup 0) (match_dup 2))
! (const_int 0))
! (label_ref (match_dup 1))
! (pc)))]
! "operands[2] = GEN_INT (-2147483647 - 1);")
- (define_peephole2
- [(set (cc0) (match_operand:SI 0 "register_operand" ""))
- (set (pc) (if_then_else (lt (cc0) (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- ""
- [(set (pc) (if_then_else (ne (and:SI (match_dup 0) (match_dup 2))
- (const_int 0))
- (label_ref (match_dup 1))
- (pc)))]
- "operands[2] = GEN_INT (-2147483647 - 1);")
;; ************************************************************************
;; Implementation of conditional jumps here.
;; Compare with 0 (test) jumps
--- 1903,1955 ----
(const_int 4))))
(set_attr "cc" "clobber")])
! ;; Convert sign tests to bit 7/15/31 tests that match the above insns.
! ;; but only if we have a forward jump within skip range
! ;; TODO - I think this pattern could handle i/o tests
! ;;
! (define_mode_macro BMODES [ QI HI SI SF])
(define_peephole2
! [(set (cc0) (match_operand:BMODES 0 "register_operand" ""))
! (set (pc) (if_then_else (match_operator 2 "comparison_operator" [(cc0)
(const_int 0)])
(label_ref (match_operand 1 "" ""))
(pc)))]
""
! [(set (pc) (if_then_else (match_dup 0)
(label_ref (match_dup 1))
! (pc)
! ))]
! "{
! enum rtx_code cond =GET_CODE(operands[2]);
! rtx hibyte=operands[0];
! rtx dest=operands[1];
! enum machine_mode mode=GET_MODE(operands[0]);
!
! int ret =jump_over_one_insn_p2(curr_insn,operands,operands[1]);
! if (!ret) FAIL;
!
! if (mode!=QImode)
! hibyte=gen_rtx_SUBREG(QImode,hibyte, GET_MODE_SIZE(mode)-1);
!
! rtx bit=gen_rtx_ZERO_EXTRACT(QImode,hibyte,GEN_INT(1),GEN_INT(7));
!
! if (cond==GE)
! operands[0]=gen_rtx_EQ(QImode,bit,const0_rtx);
! else if (cond==LT)
! operands[0]=gen_rtx_NE(QImode,bit,const0_rtx);
! else
! FAIL;
! operands[1]=dest;
! }
! "
! )
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;;
;; ************************************************************************
;; Implementation of conditional jumps here.
;; Compare with 0 (test) jumps
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [avr-gcc-list] new patch for loop and jump optimisation,
Andy Hutchinson <=