Hi,

this is a regression introduced by the canonicalization of BIT_FIELD_REF in 
match.pd, which totally disregards the REF_REVERSE_STORAGE_ORDER flag, and 
visible as the failure of gnat.dg/sso/q[23].adb on SPARC 64-bit.  But the 
underlying issue of the missing propagation of the flag during GIMPLE folding 
has probably been latent for quite some time on all active branches.

Tested on x86-64/Linux and SPARC/Solaris, OK for mainline?  And branches?


2018-09-28  Eric Botcazou  <ebotca...@adacore.com>

        PR tree-optimization/86659
        * gimple-match.h (struct gimple_match_op): Add reverse field.
        (gimple_match_op::set_op): New overloaded method.
        * gimple-match-head.c (maybe_build_generic_op) <BIT_FIELD_REF>: Set
        the REF_REVERSE_STORAGE_ORDER flag on the value.
        (gimple_simplify) <GIMPLE_ASSIGN>: For BIT_FIELD_REF, propagate the
        REF_REVERSE_STORAGE_ORDER flag and avoid simplifying if it is set.

-- 
Eric Botcazou
Index: gimple-match.h
===================================================================
--- gimple-match.h	(revision 264686)
+++ gimple-match.h	(working copy)
@@ -98,6 +98,7 @@ struct gimple_match_op
   void set_op (code_helper, tree, tree);
   void set_op (code_helper, tree, tree, tree);
   void set_op (code_helper, tree, tree, tree, tree);
+  void set_op (code_helper, tree, tree, tree, tree, bool);
   void set_op (code_helper, tree, tree, tree, tree, tree);
   void set_op (code_helper, tree, tree, tree, tree, tree, tree);
   void set_value (tree);
@@ -117,6 +118,10 @@ struct gimple_match_op
   /* The type of the result.  */
   tree type;
 
+  /* For a BIT_FIELD_REF, whether the group of bits is stored in reverse order
+     from the target order.  */
+  bool reverse;
+
   /* The number of operands to CODE.  */
   unsigned int num_ops;
 
@@ -243,6 +248,19 @@ gimple_match_op::set_op (code_helper cod
   num_ops = 3;
   ops[0] = op0;
   ops[1] = op1;
+  ops[2] = op2;
+}
+
+inline void
+gimple_match_op::set_op (code_helper code_in, tree type_in,
+			 tree op0, tree op1, tree op2, bool reverse_in)
+{
+  code = code_in;
+  type = type_in;
+  reverse = reverse_in;
+  num_ops = 3;
+  ops[0] = op0;
+  ops[1] = op1;
   ops[2] = op2;
 }
 
Index: gimple-match-head.c
===================================================================
--- gimple-match-head.c	(revision 264686)
+++ gimple-match-head.c	(working copy)
@@ -445,16 +445,20 @@ void
 maybe_build_generic_op (gimple_match_op *res_op)
 {
   tree_code code = (tree_code) res_op->code;
+  tree val;
   switch (code)
     {
     case REALPART_EXPR:
     case IMAGPART_EXPR:
     case VIEW_CONVERT_EXPR:
-      res_op->set_value (build1 (code, res_op->type, res_op->ops[0]));
+      val = build1 (code, res_op->type, res_op->ops[0]);
+      res_op->set_value (val);
       break;
     case BIT_FIELD_REF:
-      res_op->set_value (build3 (code, res_op->type, res_op->ops[0],
-				 res_op->ops[1], res_op->ops[2]));
+      val = build3 (code, res_op->type, res_op->ops[0], res_op->ops[1],
+		    res_op->ops[2]);
+      REF_REVERSE_STORAGE_ORDER (val) = res_op->reverse;
+      res_op->set_value (val);
       break;
     default:;
     }
@@ -853,7 +857,10 @@ gimple_simplify (gimple *stmt, gimple_ma
 		op0 = do_valueize (op0, top_valueize, valueized);
 		res_op->set_op (code, type, op0,
 				TREE_OPERAND (rhs1, 1),
-				TREE_OPERAND (rhs1, 2));
+				TREE_OPERAND (rhs1, 2),
+				REF_REVERSE_STORAGE_ORDER (rhs1));
+		if (res_op->reverse)
+		  return valueized;
 		return (gimple_resimplify3 (seq, res_op, valueize)
 			|| valueized);
 	      }

Reply via email to