===================================================================
@@ -1,13 +1,20 @@
/* { dg-do assemble } */
-/* { dg-final { scan-assembler "movu.w \\\$r10,\\\$" } } */
-/* { dg-final { scan-assembler "and.w 2047,\\\$" } } */
+/* { dg-final { scan-assembler "movu.w \\\$r10,\\\$|movu.w 2047," } } */
+/* { dg-final { scan-assembler "and.w 2047,\\\$|and.d \\\$r10," } } */
/* { dg-final { scan-assembler-not "move.d \\\$r10,\\\$" } } */
-/* { dg-final { scan-assembler "movu.b \\\$r10,\\\$" } } */
-/* { dg-final { scan-assembler "and.b 95,\\\$" } } */
+/* { dg-final { scan-assembler "movu.b \\\$r10,\\\$|movu.b 95," } } */
+/* { dg-final { scan-assembler "and.b 95,\\\$|and.d \\\$r10," } } */
/* { dg-final { scan-assembler "andq -2,\\\$" } } */
+/* { dg-final { scan-assembler-not "movu.b 254,\\\$" } } */
/* { dg-options "-O2 -save-temps" } */
-/* Test the "andu" peephole2 trivially, register operand. */
+/* Originally used to test the "andu" peephole2 trivially, register operand.
+ Due to reload changes (r186861), the suboptimal sequence isn't
+ generated and the peephole2 doesn't trig for this trivial code
+ anymore. Another minimal sequence is generated, where the constant
+ is loaded to a free register first. Instead another case is exposed;
+ handled by the "andqu" peephole2, trigged by and_peep2_q (the andq
+ and scan-assembler-not-movu.b lines above). */
unsigned int
and_peep2_hi (unsigned int y, unsigned int *x)
===================================================================
@@ -4936,17 +4936,17 @@ (define_peephole2 ; op3 (peephole casesi
"operands[7]
= rtx_equal_p (operands[3], operands[0]) ? operands[4] : operands[3];")
-;; I cannot tell GCC (2.1, 2.7.2) how to correctly reload an instruction
-;; that looks like
-;; and.b some_byte,const,reg_32
-;; where reg_32 is the destination of the "three-address" code optimally.
+;; There seems to be no other way to make GCC (including 4.8/trunk at
+;; r186932) optimally reload an instruction that looks like
+;; and.d reg_or_mem,const_32__65535,other_reg
+;; where other_reg is the destination.
;; It should be:
-;; movu.b some_byte,reg_32
-;; and.b const,reg_32
+;; movu.[bw] reg_or_mem,reg_32
+;; and.[bw] trunc_int_for_mode([bw], const_32__65535),reg_32 ;; or andq
;; but it turns into:
-;; move.b some_byte,reg_32
-;; and.d const,reg_32
-;; Fix it here.
+;; move.d reg_or_mem,reg_32
+;; and.d const_32__65535,reg_32
+;; Fix it with these two peephole2's.
;; Testcases: gcc.dg/cris-peep2-andu1.c gcc.dg/cris-peep2-andu2.c
(define_peephole2 ; andu (casesi+45)
@@ -4982,6 +4982,36 @@ (define_peephole2 ; andu (casesi+45)
GEN_INT (trunc_int_for_mode (INTVAL (operands[3]),
amode == SImode
? QImode : amode)));
+})
+
+;; Since r186861, gcc.dg/cris-peep2-andu2.c trigs this pattern, with which
+;; we fix up e.g.:
+;; movu.b 254,$r9.
+;; and.d $r10,$r9
+;; into:
+;; movu.b $r10,$r9
+;; andq -2,$r9.
+;; Only do this for values fitting the quick immediate operand.
+(define_peephole2 ; andqu (casesi+46)
+ [(set (match_operand:SI 0 "register_operand")
+ (match_operand:SI 1 "const_int_operand"))
+ (set (match_dup 0)
+ (and:SI (match_dup 0) (match_operand:SI 2 "nonimmediate_operand")))]
+ ;; Since the size of the memory access will be made different here,
+ ;; don't do this for a volatile access or a post-incremented address.
+ "satisfies_constraint_O (operands[1])
+ && !side_effects_p (operands[2])
+ && !reg_overlap_mentioned_p (operands[0], operands[2])"
+ [(set (match_dup 0) (match_dup 3))
+ (set (match_dup 0) (and:SI (match_dup 0) (match_dup 4)))]
+{
+ enum machine_mode zmode = INTVAL (operands[2]) <= 255 ? QImode : HImode;
+ rtx op1
+ = (REG_S_P (operands[2])
+ ? gen_rtx_REG (zmode, REGNO (operands[2]))
+ : adjust_address (operands[2], zmode, 0));
+ operands[3] = gen_rtx_ZERO_EXTEND (SImode, op1);
+ operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]), QImode));
})
;; Try and avoid GOTPLT reads escaping a call: transform them into