Hi!

As described in PR 71779 and PR 70903 we have a wrong code issue on aarch64
which is triggered by a paradoxical subreg that can be created in
store_bit_field_using_insv when the target has an EP_insv bitfield instruction.

The attached patch changes this insn...

(insn 1047 1046 1048 (set (reg:DI 481)
        (subreg:DI (reg/f:SI 479) 0)) y.c:12702 -1
     (nil))

... into a more simple insn:

(insn 1047 1046 1048 (set (reg:DI 479)
        (zero_extend:DI (reg:SI 480))) isl_input.c:2496 -1
     (nil))

which manages to fix two bugs at the same time.

The patch does not include a test case, as I was looking at the PR 71779
just by curiosity, and I have only a theoretical interest in aarch64. However,
it should be easy to extract one from PR 70903 at least, but I can't do that by
myself.

Therefore I would like to leave the test case(s) to Cristina Tamar from ARM,
and/or Andreas Schwab, who have also helped out with bootstrapping and
reg-testing on aarch64 and aarch64-ilp32.

Bootstrap and reg-test on x86_64-linux-gnu with no regressions.
Successfully bootstrapped on aarch64_ilp32 and the ISL testsuite passes.
Also successfully bootstrapped on an aarch64 juno board and no regressions.


Is it OK for trunk?


Thanks
Bernd.
2016-07-25  Bernd Edlinger  <bernd.edlin...@hotmail.de>

	PR rtl-optimization/71779
	PR rtl-optimization/70903
	* expmed.c (store_bit_field_using_insv): Don't generate a paradoxical
	subreg.

Index: gcc/calls.c
Index: expmed.c
===================================================================
--- expmed.c	(revision 238694)
+++ expmed.c	(working copy)
@@ -664,14 +664,7 @@ store_bit_field_using_insv (const extraction_insn
 	     if we must narrow it, be sure we do it correctly.  */
 
 	  if (GET_MODE_SIZE (GET_MODE (value)) < GET_MODE_SIZE (op_mode))
-	    {
-	      tmp = simplify_subreg (op_mode, value1, GET_MODE (value), 0);
-	      if (! tmp)
-		tmp = simplify_gen_subreg (op_mode,
-					   force_reg (GET_MODE (value),
-						      value1),
-					   GET_MODE (value), 0);
-	    }
+	    tmp = convert_to_mode (op_mode, value1, 1);
 	  else
 	    {
 	      tmp = gen_lowpart_if_possible (op_mode, value1);


Reply via email to