Hi,
I am trying to understand why the MIPS backend's handling of
comparison modes seems to be different from what rtl.texi says:
The mode of the comparison operation is independent of the mode
of the data being compared. If the comparison operation is being tested
(e.g., the first operand of an @code{if_then_else}), the mode must be
@code{VOIDmode}.
In the MIPS backend conditional branches based on integer comparisons
are valid only if the mode of the comparison matches the mode of the
operands, e.g. in 64-bit mode (if_then_else (eq:DI (reg:DI 1)
(const_int 0)) ...).
This is relevant because combine could optimize this:
(set (reg:DI 2) (and:DI (reg:DI 1) (const_int 1)))
(set (reg:SI 3) (truncate:SI (reg:DI 2)))
(set (pc) (if_then_else (eq:SI (reg:SI 3) (const_int 0)) ...))
into this:
(set (reg:DI 2) (and:DI (regDI 1) (const_int 1)))
(set (pc) (if_then_else (eq:SI (reg:DI 2) (const_int 0)) ...))
I think this is a valid transformation on MIPS64 too. In fact I
believe that as long as we compare valid SImode or DImode values the
64-bit comparison should work fine.
If I remove the comparison modes from the conditional branch patterns
regression testing on mips64-elf does not show any problem (diff is
attached for reference). When I however compare the assembly output
it is clear that some of the changes are incorrect. This is
a simplified testcase illustrating the problem:
f (long long a)
{
if ((a & 0xffffffff) != 0)
abort ();
}
long long a = 0x1234567800000000LL;
main ()
{
f (a);
}
What happens is that combine.c:simplify_comparison <AND> noticing the
zero-extension 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))
And now we do allow comparison like this in conditional branches.
On targets where DI->SI mode-switch is not a nop I think the
transformation in simplify_comparison is incorrect. We need an
explicit truncate here to enforce valid SI values:
(ne:DI (truncate:SI (reg:DI 4)) (const_int 0)).
Now if I am correct and this last thing is really a bug then the
obvious question is whether it has anything to do with the more
restrictive form for conditional branches on MIPS64? And of course if
I fix it then whether it would be OK to lift the mode restrictions in
the conditional branch patterns.
Thanks,
Adam
Index: mips.md
===================================================================
--- mips.md (revision 107758)
+++ mips.md (working copy)
@@ -4291,7 +4291,7 @@
(define_insn "*branch_zero<mode>"
[(set (pc)
(if_then_else
- (match_operator:GPR 0 "comparison_operator"
+ (match_operator 0 "comparison_operator"
[(match_operand:GPR 2 "register_operand" "d")
(const_int 0)])
(label_ref (match_operand 1 "" ""))
@@ -4311,7 +4311,7 @@
(define_insn "*branch_zero<mode>_inverted"
[(set (pc)
(if_then_else
- (match_operator:GPR 0 "comparison_operator"
+ (match_operator 0 "comparison_operator"
[(match_operand:GPR 2 "register_operand" "d")
(const_int 0)])
(pc)
@@ -4333,7 +4333,7 @@
(define_insn "*branch_equality<mode>"
[(set (pc)
(if_then_else
- (match_operator:GPR 0 "equality_operator"
+ (match_operator 0 "equality_operator"
[(match_operand:GPR 2 "register_operand" "d")
(match_operand:GPR 3 "register_operand" "d")])
(label_ref (match_operand 1 "" ""))
@@ -4353,7 +4353,7 @@
(define_insn "*branch_equality<mode>_inverted"
[(set (pc)
(if_then_else
- (match_operator:GPR 0 "equality_operator"
+ (match_operator 0 "equality_operator"
[(match_operand:GPR 2 "register_operand" "d")
(match_operand:GPR 3 "register_operand" "d")])
(pc)