This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] MIPS: remove comparison modes in branches + combiner fix
- From: Adam Nemet <anemet at sonic dot net>
- To: Jim Wilson <wilson at specifix dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 15 Dec 2005 00:37:25 -0800
- Subject: [PATCH] MIPS: remove comparison modes in branches + combiner fix
- References: <17299.59498.920492.969027@localhost.localdomain> <4394DC47.4030002@specifix.com>
Jim Wilson writes:
> Yes, it looks like fixing the combiner problem would make it
> possible to remove the mistaken mode checks.
Jim,
Thanks again for confirming this. Below is the patch for the combine
issue(s) and the actual backend change.
In turns out I had to fix another missed TRULY_NOOP_TRUNCATION check
in combine for the testcase to work.
What I mentioned in my previous email too is that simplify_comparison
<AND> transforms this
(ne:DI (and:DI (reg:DI 4) (const_int 0xffffffff)) (const_int 0))
into this:
(ne:DI (reg:SI 4) (const_int 0))
After I added the check for TRULY_NOOP_TRUNCATION I still got the same
wrong assembly output because there is a similar transformation in
make_compound_operation <AND>. make_extraction is called from there
to extract the lower 16 bits and it returns a subreg. So for the AND
part of the expression we get:
(zero_extend:DI (reg:SI 4))
Strictly speaking this is already incorrect but it still works on
MIPS. The actual wrong code we get when simplify_comparison
<ZERO_EXTEND> removes the zero-extension since it is unnecessary when
comparing to zero.
I changed make_extraction to only return a subreg is
TRULY_NOOP_TRUNCATION permits it.
Regression-tested on mips64-elf. Tested and bootstrapped on
i686-pc-linux-gnu.
Is it OK to apply?
Adam
* gcc.c-torture/execute/20051213-1.c: New test.
* combine.c (make_extraction): Check TRULY_NOOP_TRUNCATION before
start using a subreg.
(simplify_comparison <AND>): Likewise.
* config/mips/mips.md (*branch_zero<mode>,
*branch_zero<mode>_inverted, *branch_equality<mode>,
*branch_equality<mode>_inverted, *branch_equality<mode>_mips16):
Remove mode check from comparisons.
Index: gcc/testsuite/gcc.c-torture/execute/20051213-1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/20051213-1.c (revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/20051213-1.c (revision 0)
@@ -0,0 +1,17 @@
+void abort ();
+
+void
+f (long long a)
+{
+ if ((a & 0xffffffffLL) != 0)
+ abort ();
+}
+
+long long a = 0x1234567800000000LL;
+
+int
+main ()
+{
+ f (a);
+ return 0;
+}
Index: gcc/combine.c
===================================================================
--- gcc/combine.c (revision 108488)
+++ gcc/combine.c (working copy)
@@ -6356,7 +6356,9 @@ make_extraction (enum machine_mode mode,
}
else if (REG_P (inner))
{
- if (tmode != inner_mode)
+ if (tmode != inner_mode
+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (tmode),
+ GET_MODE_BITSIZE (inner_mode)))
{
/* We can't call gen_lowpart in a DEST since we
always want a SUBREG (see below) and it would sometimes
@@ -10547,7 +10549,9 @@ simplify_comparison (enum rtx_code code,
& GET_MODE_MASK (mode))
+ 1)) >= 0
&& const_op >> i == 0
- && (tmode = mode_for_size (i, MODE_INT, 1)) != BLKmode)
+ && (tmode = mode_for_size (i, MODE_INT, 1)) != BLKmode
+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (tmode),
+ GET_MODE_BITSIZE (GET_MODE (op0))))
{
op0 = gen_lowpart (tmode, XEXP (op0, 0));
continue;
Index: gcc/config/mips/mips.md
===================================================================
--- gcc/config/mips/mips.md (revision 108488)
+++ gcc/config/mips/mips.md (working copy)
@@ -4291,9 +4291,9 @@ (define_insn "branch_fp_inverted"
(define_insn "*branch_zero<mode>"
[(set (pc)
(if_then_else
- (match_operator:GPR 0 "comparison_operator"
- [(match_operand:GPR 2 "register_operand" "d")
- (const_int 0)])
+ (match_operator 0 "comparison_operator"
+ [(match_operand:GPR 2 "register_operand" "d")
+ (const_int 0)])
(label_ref (match_operand 1 "" ""))
(pc)))]
"!TARGET_MIPS16"
@@ -4311,9 +4311,9 @@ (define_insn "*branch_zero<mode>"
(define_insn "*branch_zero<mode>_inverted"
[(set (pc)
(if_then_else
- (match_operator:GPR 0 "comparison_operator"
- [(match_operand:GPR 2 "register_operand" "d")
- (const_int 0)])
+ (match_operator 0 "comparison_operator"
+ [(match_operand:GPR 2 "register_operand" "d")
+ (const_int 0)])
(pc)
(label_ref (match_operand 1 "" ""))))]
"!TARGET_MIPS16"
@@ -4333,9 +4333,9 @@ (define_insn "*branch_zero<mode>_inverte
(define_insn "*branch_equality<mode>"
[(set (pc)
(if_then_else
- (match_operator:GPR 0 "equality_operator"
- [(match_operand:GPR 2 "register_operand" "d")
- (match_operand:GPR 3 "register_operand" "d")])
+ (match_operator 0 "equality_operator"
+ [(match_operand:GPR 2 "register_operand" "d")
+ (match_operand:GPR 3 "register_operand" "d")])
(label_ref (match_operand 1 "" ""))
(pc)))]
"!TARGET_MIPS16"
@@ -4353,9 +4353,9 @@ (define_insn "*branch_equality<mode>"
(define_insn "*branch_equality<mode>_inverted"
[(set (pc)
(if_then_else
- (match_operator:GPR 0 "equality_operator"
- [(match_operand:GPR 2 "register_operand" "d")
- (match_operand:GPR 3 "register_operand" "d")])
+ (match_operator 0 "equality_operator"
+ [(match_operand:GPR 2 "register_operand" "d")
+ (match_operand:GPR 3 "register_operand" "d")])
(pc)
(label_ref (match_operand 1 "" ""))))]
"!TARGET_MIPS16"
@@ -4375,9 +4375,9 @@ (define_insn "*branch_equality<mode>_inv
(define_insn "*branch_equality<mode>_mips16"
[(set (pc)
(if_then_else
- (match_operator:GPR 0 "equality_operator"
- [(match_operand:GPR 1 "register_operand" "d,t")
- (const_int 0)])
+ (match_operator 0 "equality_operator"
+ [(match_operand:GPR 1 "register_operand" "d,t")
+ (const_int 0)])
(match_operand 2 "pc_or_label_operand" "")
(match_operand 3 "pc_or_label_operand" "")))]
"TARGET_MIPS16"