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]

Re: fix alpha gcc.dg/20040123-1.c


Hello Richard,

Excuse me.
I'm using m32r-elf-gcc (3.4, 4.0, mainline).
It has a same problem (FAIL: gcc.dg/20040123-1.c).
Would you give me some idea to fix the problem?

It seems that it always forces symbol_ref into register.

Regards,

Kazuhiro Inaoka

Richard Henderson wrote:
The problem here is that we turn

	&x == 0x40000
into
	&x - 0x40000 == 0

because it looks quicker to implement in the hardware.
This gets folded to

(const (plus (symbol_ref "x") (const_int -0x40000)))

which, since x is not weak, is automatically considered non-null.

The best solution I could think of is to disable this alpha-specific
transform if op0 is a pointer.  I tried just looking for symbol_ref,
but there's code that fires at -O2 that forces all symbols into
registers.  But that's ok, since adding the alignment bits to the
register data is a good idea anyway.

The splitters that I delete don't ever seem to be a win to me, most
of the time.  In particular,

(ne (lt reg reg) 0) -> (lt (minus reg reg) 0)

is a lose on ev5, where compare and logical type instructions have a special bypass to cmove and branch type instruction. On other cpu
revisions the transform is neutral. Similarly,


	(a > 0xffff)	 	-> 	t = a & ~0xffff; t != 0
	ldah	t, 1			zap	a, 0xfc, t
	cmplt	a, t, r			bne	t, dest
	bne	r, dest

is a lose on ev4/ev5 because of shifter latency/overcommitment.

Bootstrapped and tested on alphaev67-linux on mainline.


r~



* explow.c (force_reg): Call mark_reg_pointer as appropriate. * config/alpha/alpha.c (alpha_emit_conditional_branch): Don't use (op0-op1) == 0 if op0 is a pointer. * config/alpha/alpha.md (cmpdi): Use some_operand. (three comparison combine splits): Remove.

Index: gcc/explow.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/explow.c,v
retrieving revision 1.118
diff -c -p -d -r1.118 explow.c
*** gcc/explow.c 13 Dec 2003 04:11:20 -0000 1.118
--- gcc/explow.c 26 Feb 2004 01:40:31 -0000
*************** force_reg (enum machine_mode mode, rtx x
*** 721,726 ****
--- 721,760 ----
&& ! rtx_equal_p (x, SET_SRC (set)))
set_unique_reg_note (insn, REG_EQUAL, x);
+ /* Let optimizers know that TEMP is a pointer, and if so, the
+ known alignment of that pointer. */
+ {
+ unsigned align = 0;
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ align = BITS_PER_UNIT;
+ if (SYMBOL_REF_DECL (x) && DECL_P (SYMBOL_REF_DECL (x)))
+ align = DECL_ALIGN (SYMBOL_REF_DECL (x));
+ }
+ else if (GET_CODE (x) == LABEL_REF)
+ align = BITS_PER_UNIT;
+ else if (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+ {
+ rtx s = XEXP (XEXP (x, 0), 0);
+ rtx c = XEXP (XEXP (x, 0), 1);
+ unsigned sa, ca;
+ + sa = BITS_PER_UNIT;
+ if (SYMBOL_REF_DECL (s) && DECL_P (SYMBOL_REF_DECL (s)))
+ sa = DECL_ALIGN (SYMBOL_REF_DECL (s));
+ + ca = exact_log2 (INTVAL (c) & -INTVAL (c)) * BITS_PER_UNIT;
+ + align = MIN (sa, ca);
+ }
+ + if (align)
+ mark_reg_pointer (temp, align);
+ }
+ return temp;
}
Index: gcc/config/alpha/alpha.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.352
diff -c -p -d -r1.352 alpha.c
*** gcc/config/alpha/alpha.c 8 Feb 2004 23:08:37 -0000 1.352
--- gcc/config/alpha/alpha.c 26 Feb 2004 01:40:32 -0000
*************** alpha_emit_conditional_branch (enum rtx_
*** 3179,3185 ****
/* If the constants doesn't fit into an immediate, but can
be generated by lda/ldah, we adjust the argument and
compare against zero, so we can use beq/bne directly. */
! else if (GET_CODE (op1) == CONST_INT && (code == EQ || code == NE))
{
HOST_WIDE_INT v = INTVAL (op1), n = -v;
--- 3179,3191 ----
/* If the constants doesn't fit into an immediate, but can
be generated by lda/ldah, we adjust the argument and
compare against zero, so we can use beq/bne directly. */
! /* ??? Don't do this when comparing against symbols, otherwise
! we'll reduce (&x == 0x1234) to (&x-0x1234 == 0), which will
! be declared false out of hand (at least for non-weak). */
! else if (GET_CODE (op1) == CONST_INT
! && (code == EQ || code == NE)
! && !(symbolic_operand (op0, VOIDmode)
! || (GET_CODE (op0) == REG && REG_POINTER (op0))))
{
HOST_WIDE_INT v = INTVAL (op1), n = -v;
Index: gcc/config/alpha/alpha.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.md,v
retrieving revision 1.219
diff -c -p -d -r1.219 alpha.md
*** gcc/config/alpha/alpha.md 20 Feb 2004 22:12:56 -0000 1.219
--- gcc/config/alpha/alpha.md 26 Feb 2004 01:40:32 -0000
***************
*** 3827,3834 ****
})
(define_expand "cmpdi"
! [(set (cc0) (compare (match_operand:DI 0 "general_operand" "")
! (match_operand:DI 1 "general_operand" "")))]
""
{
alpha_compare.op0 = operands[0];
--- 3827,3834 ----
})
(define_expand "cmpdi"
! [(set (cc0) (compare (match_operand:DI 0 "some_operand" "")
! (match_operand:DI 1 "some_operand" "")))]
""
{
alpha_compare.op0 = operands[0];
***************
*** 4158,4257 ****
operands[7] = gen_rtx_SIGN_EXTEND (DImode, tem);
operands[8] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
operands[6], const0_rtx);
- })
- - (define_split
- [(set (pc)
- (if_then_else
- (match_operator 1 "comparison_operator"
- [(match_operand:DI 2 "reg_or_0_operand" "")
- (match_operand:DI 3 "reg_or_cint_operand" "")])
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (clobber (match_operand:DI 4 "register_operand" ""))]
- "operands[3] != const0_rtx"
- [(set (match_dup 4) (match_dup 5))
- (set (pc) (if_then_else (match_dup 6) (label_ref (match_dup 0)) (pc)))]
- {
- enum rtx_code code = GET_CODE (operands[1]);
- int unsignedp = (code == GEU || code == LEU || code == GTU || code == LTU);
- - if (code == NE || code == EQ
- || (extended_count (operands[2], DImode, unsignedp) >= 1
- && extended_count (operands[3], DImode, unsignedp) >= 1))
- {
- if (GET_CODE (operands[3]) == CONST_INT)
- operands[5] = gen_rtx_PLUS (DImode, operands[2],
- GEN_INT (- INTVAL (operands[3])));
- else
- operands[5] = gen_rtx_MINUS (DImode, operands[2], operands[3]);
- - operands[6] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx);
- }
- - else if (code == EQ || code == LE || code == LT
- || code == LEU || code == LTU)
- {
- operands[5] = gen_rtx_fmt_ee (code, DImode, operands[2], operands[3]);
- operands[6] = gen_rtx_NE (VOIDmode, operands[4], const0_rtx);
- }
- else
- {
- operands[5] = gen_rtx_fmt_ee (reverse_condition (code), DImode,
- operands[2], operands[3]);
- operands[6] = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx);
- }
- })
- - (define_split
- [(set (pc)
- (if_then_else
- (match_operator 1 "comparison_operator"
- [(match_operand:SI 2 "reg_or_0_operand" "")
- (match_operand:SI 3 "const_int_operand" "")])
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (clobber (match_operand:DI 4 "register_operand" ""))]
- "operands[3] != const0_rtx
- && (GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)"
- [(set (match_dup 4) (match_dup 5))
- (set (pc) (if_then_else (match_dup 6) (label_ref (match_dup 0)) (pc)))]
- {
- rtx tem;
- - if (GET_CODE (operands[3]) == CONST_INT)
- tem = gen_rtx_PLUS (SImode, operands[2],
- GEN_INT (- INTVAL (operands[3])));
- else
- tem = gen_rtx_MINUS (SImode, operands[2], operands[3]);
- - operands[5] = gen_rtx_SIGN_EXTEND (DImode, tem);
- operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
- operands[4], const0_rtx);
- })
- - ;; We can convert such things as "a > 0xffff" to "t = a & ~ 0xffff; t != 0".
- ;; This eliminates one, and sometimes two, insns when the AND can be done
- ;; with a ZAP.
- (define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (match_operator:DI 1 "comparison_operator"
- [(match_operand:DI 2 "register_operand" "")
- (match_operand:DI 3 "const_int_operand" "")]))
- (clobber (match_operand:DI 4 "register_operand" ""))]
- "exact_log2 (INTVAL (operands[3]) + 1) >= 0
- && (GET_CODE (operands[1]) == GTU
- || GET_CODE (operands[1]) == LEU
- || ((GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == LE)
- && extended_count (operands[2], DImode, 1) > 0))"
- [(set (match_dup 4) (and:DI (match_dup 2) (match_dup 5)))
- (set (match_dup 0) (match_dup 6))]
- {
- operands[5] = GEN_INT (~ INTVAL (operands[3]));
- operands[6] = gen_rtx_fmt_ee (((GET_CODE (operands[1]) == GTU
- || GET_CODE (operands[1]) == GT)
- ? NE : EQ),
- DImode, operands[4], const0_rtx);
})
;; Prefer to use cmp and arithmetic when possible instead of a cmove.
--- 4158,4163 ----


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