This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
i386 ffs patch
- To: drepper at cygnus dot com
- Subject: i386 ffs patch
- From: Richard Henderson <rth at cygnus dot com>
- Date: Thu, 26 Mar 1998 23:27:53 -0800
- Cc: scox at cygnus dot com, egcs at cygnus dot com
- Reply-To: Richard Henderson <rth at cygnus dot com>
Here's a better patch for the LFFSSI0 label bogosity you mentioned
to me earlier today. Here we expand the entire pattern into rtl at
the beginning, which makes for happier code.
r~
Thu Mar 26 23:24:47 1998 Richard Henderson <rth@cygnus.com>
* i386.c (notice_update_cc): Recognize (unspec [] 5) as the
bsf primitive.
* i386.md (ffssi2): Expand the entire test and branch into rtl.
(ffshi2): Likewise.
Index: i386.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/i386/i386.c,v
retrieving revision 1.16
diff -c -p -d -r1.16 i386.c
*** i386.c 1998/03/12 12:43:41 1.16
--- i386.c 1998/03/27 07:21:17
*************** print_operand_address (file, addr)
*** 3550,3556 ****
/* Set the cc_status for the results of an insn whose pattern is EXP.
On the 80386, we assume that only test and compare insns, as well
! as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT,
ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
Also, we assume that jumps, moves and sCOND don't affect the condition
codes. All else clobbers the condition codes, by assumption.
--- 3553,3559 ----
/* Set the cc_status for the results of an insn whose pattern is EXP.
On the 80386, we assume that only test and compare insns, as well
! as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, FFS, ASHIFT,
ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
Also, we assume that jumps, moves and sCOND don't affect the condition
codes. All else clobbers the condition codes, by assumption.
*************** notice_update_cc (exp)
*** 3644,3649 ****
--- 3647,3663 ----
cc_status.flags = CC_NO_OVERFLOW;
cc_status.value1 = SET_SRC (exp);
cc_status.value2 = SET_DEST (exp);
+ break;
+
+ case UNSPEC:
+ /* This is the FFS primitive. */
+ if (XINT(SET_SRC (exp), 1) == 5)
+ {
+ cc_status.flags = CC_NO_OVERFLOW;
+ cc_status.value1 = XVECEXP(SET_SRC (exp), 0, 0);
+ }
+ else
+ CC_STATUS_INIT;
break;
default:
Index: i386.md
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.13
diff -c -p -d -r1.13 i386.md
*** i386.md 1998/03/12 12:43:42 1.13
--- i386.md 1998/03/27 07:21:18
*************** byte_xor_operation:
*** 6963,7065 ****
}")
- (define_expand "ffssi2"
- [(set (match_dup 2)
- (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" ""))
- (const_int -1)))
- (set (match_operand:SI 0 "general_operand" "")
- (plus:SI (match_dup 2) (const_int 1)))]
- ""
- "operands[2] = gen_reg_rtx (SImode);")
-
;; Note, you cannot optimize away the branch following the bsfl by assuming
;; that the destination is not modified if the input is 0, since not all
;; x86 implementations do this.
! (define_insn ""
! [(set (match_operand:SI 0 "register_operand" "=&r")
! (plus:SI (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))
! (const_int -1)))]
""
! "*
{
! rtx xops[3];
! static int ffssi_label_number;
! char buffer[30];
! xops[0] = operands[0];
! xops[1] = operands[1];
! xops[2] = constm1_rtx;
! output_asm_insn (AS2 (bsf%L0,%1,%0), xops);
! #ifdef LOCAL_LABEL_PREFIX
! sprintf (buffer, \"jnz %sLFFSSI%d\",
! LOCAL_LABEL_PREFIX, ffssi_label_number);
! #else
! sprintf (buffer, \"jnz %sLFFSSI%d\",
! \"\", ffssi_label_number);
! #endif
! output_asm_insn (buffer, xops);
! output_asm_insn (AS2 (mov%L0,%2,%0), xops);
! #ifdef LOCAL_LABEL_PREFIX
! sprintf (buffer, \"%sLFFSSI%d:\",
! LOCAL_LABEL_PREFIX, ffssi_label_number);
! #else
! sprintf (buffer, \"%sLFFSSI%d:\",
! \"\", ffssi_label_number);
! #endif
! output_asm_insn (buffer, xops);
! ffssi_label_number++;
! CC_STATUS_INIT;
! return \"\";
}")
! (define_expand "ffshi2"
! [(set (match_dup 2)
! (plus:HI (ffs:HI (match_operand:HI 1 "general_operand" ""))
! (const_int -1)))
! (set (match_operand:HI 0 "general_operand" "")
! (plus:HI (match_dup 2) (const_int 1)))]
""
! "operands[2] = gen_reg_rtx (HImode);")
! (define_insn ""
! [(set (match_operand:HI 0 "register_operand" "=&r")
! (plus:HI (ffs:HI (match_operand:SI 1 "nonimmediate_operand" "rm"))
! (const_int -1)))]
""
! "*
{
! rtx xops[3];
! static int ffshi_label_number;
! char buffer[30];
! xops[0] = operands[0];
! xops[1] = operands[1];
! xops[2] = constm1_rtx;
! output_asm_insn (AS2 (bsf%W0,%1,%0), xops);
! #ifdef LOCAL_LABEL_PREFIX
! sprintf (buffer, \"jnz %sLFFSHI%d\",
! LOCAL_LABEL_PREFIX, ffshi_label_number);
! #else
! sprintf (buffer, \"jnz %sLFFSHI%d\",
! \"\", ffshi_label_number);
! #endif
! output_asm_insn (buffer, xops);
! output_asm_insn (AS2 (mov%W0,%2,%0), xops);
! #ifdef LOCAL_LABEL_PREFIX
! sprintf (buffer, \"%sLFFSHI%d:\",
! LOCAL_LABEL_PREFIX, ffshi_label_number);
! #else
! sprintf (buffer, \"%sLFFSHI%d:\",
! \"\", ffshi_label_number);
! #endif
! output_asm_insn (buffer, xops);
! ffshi_label_number++;
! CC_STATUS_INIT;
! return \"\";
}")
;; These patterns match the binary 387 instructions for addM3, subM3,
;; mulM3 and divM3. There are three patterns for each of DFmode and
--- 6963,7025 ----
}")
;; Note, you cannot optimize away the branch following the bsfl by assuming
;; that the destination is not modified if the input is 0, since not all
;; x86 implementations do this.
! (define_expand "ffssi2"
! [(set (match_operand:SI 0 "general_operand" "")
! (ffs:SI (match_operand:SI 1 "general_operand" "")))]
""
! "
{
! rtx label = gen_label_rtx (), temp = gen_reg_rtx (SImode);
! emit_insn (gen_ffssi_1 (temp, operands[1]));
! emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, SImode, 0, 0);
! emit_jump_insn (gen_bne (label));
! emit_move_insn (temp, constm1_rtx);
! emit_label (label);
! temp = expand_binop (SImode, add_optab, temp, const1_rtx,
! operands[0], 0, OPTAB_WIDEN);
! if (temp != operands[0])
! emit_move_insn (operands[0], temp);
! DONE;
}")
! (define_insn "ffssi_1"
! [(set (match_operand:SI 0 "register_operand" "=r")
! (unspec:SI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))]
""
! "* return AS2 (bsf%L0,%1,%0);")
! (define_expand "ffshi2"
! [(set (match_operand:SI 0 "general_operand" "")
! (ffs:HI (match_operand:HI 1 "general_operand" "")))]
""
! "
{
! rtx label = gen_label_rtx (), temp = gen_reg_rtx (HImode);
! emit_insn (gen_ffshi_1 (temp, operands[1]));
! emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, HImode, 0, 0);
! emit_jump_insn (gen_bne (label));
! emit_move_insn (temp, constm1_rtx);
! emit_label (label);
! temp = expand_binop (HImode, add_optab, temp, const1_rtx,
! operands[0], 0, OPTAB_WIDEN);
! if (temp != operands[0])
! emit_move_insn (operands[0], temp);
! DONE;
}")
+
+ (define_insn "ffshi_1"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (unspec:HI [(match_operand:HI 1 "nonimmediate_operand" "rm")] 5))]
+ ""
+ "* return AS2 (bsf%W0,%1,%0);")
;; These patterns match the binary 387 instructions for addM3, subM3,
;; mulM3 and divM3. There are three patterns for each of DFmode and