+2012-07-25  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * expr.c (expand_expr_real_1): Do not expand operand #1 and #2
+       of BIT_FIELD_REF for ignored results.
+       * fold-const.c (fold_ternary_loc) <BIT_FIELD_REF>: Check that the
+       CONSTRUCTOR has vector type before using vector accessors on it.
+       * gimplify.c (gimplify_compound_lval): Do not gimplify operand #1 and
+       #2 of BIT_FIELD_REF.
+       (gimplify_expr) <BIT_FIELD_REF>: Likewise.
+       * tree-nested.c (convert_nonlocal_reference_op) <BIT_FIELD_REF>: Do
+       not process operand #1 and #2.
+       (convert_local_reference_op): Likewise.
+       * tree-ssa-pre.c (create_component_ref_by_pieces_1): Remove superfluous
+       breaks throughout.
+       <BIT_FIELD_REF>: Reuse operand #1 and #2 directly.
+       * tree.c (stabilize_reference) <BIT_FIELD_REF>: Do not stabilize
+       operand #1 and #2.
+       (UPDATE_FLAGS): Do not consider operand #2 of BIT_FIELD_REF.
+       (build6_stat): Delete.
+       * tree.h (build6_stat, build6, build6_stat_loc, build6_loc): Likewise.
+
 2012-07-25 Marc Glisse <marc.glisse@inria.fr>
 
        PR tree-optimization/30318
 
+2012-07-25  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc-interface/utils2.c (gnat_stabilize_reference) <BIT_FIELD_REF>: Do
+       not stabilize operand #1 and #2.
+
 2012-07-23  Tristan Gingold  <gingold@adacore.com>
 
        * gcc-interface/trans.c (Handled_Sequence_Of_Statements_to_gnu): Use
 
       result = build3 (BIT_FIELD_REF, type,
                       gnat_stabilize_reference (TREE_OPERAND (ref, 0), force,
                                                 success),
-                      gnat_stabilize_reference_1 (TREE_OPERAND (ref, 1),
-                                                  force),
-                      gnat_stabilize_reference_1 (TREE_OPERAND (ref, 2),
-                                                  force));
+                      TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2));
       break;
 
     case ARRAY_REF:
 
        }
 
       if (TREE_CODE_CLASS (code) == tcc_unary
-         || code == COMPONENT_REF || code == INDIRECT_REF)
+         || code == BIT_FIELD_REF
+         || code == COMPONENT_REF
+         || code == INDIRECT_REF)
        return expand_expr (treeop0, const0_rtx, VOIDmode,
                            modifier);
 
          expand_expr (treeop1, const0_rtx, VOIDmode, modifier);
          return const0_rtx;
        }
-      else if (code == BIT_FIELD_REF)
-       {
-         expand_expr (treeop0, const0_rtx, VOIDmode, modifier);
-         expand_expr (treeop1, const0_rtx, VOIDmode, modifier);
-         expand_expr (treeop2, const0_rtx, VOIDmode, modifier);
-         return const0_rtx;
-       }
 
       target = 0;
     }
 
 
     case BIT_FIELD_REF:
       if ((TREE_CODE (arg0) == VECTOR_CST
-          || TREE_CODE (arg0) == CONSTRUCTOR)
+          || (TREE_CODE (arg0) == CONSTRUCTOR
+              && TREE_CODE (TREE_TYPE (arg0)) == VECTOR_TYPE))
          && (type == TREE_TYPE (TREE_TYPE (arg0))
              || (TREE_CODE (type) == VECTOR_TYPE
                  && TREE_TYPE (type) == TREE_TYPE (TREE_TYPE (arg0)))))
 
                        fallback | fb_lvalue);
   ret = MIN (ret, tret);
 
-  /* And finally, the indices and operands to BIT_FIELD_REF.  During this
+  /* And finally, the indices and operands of ARRAY_REF.  During this
      loop we also remove any useless conversions.  */
   for (; VEC_length (tree, stack) > 0; )
     {
              ret = MIN (ret, tret);
            }
        }
-      else if (TREE_CODE (t) == BIT_FIELD_REF)
-       {
-         tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
-                               is_gimple_val, fb_rvalue);
-         ret = MIN (ret, tret);
-         tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
-                               is_gimple_val, fb_rvalue);
-         ret = MIN (ret, tret);
-       }
 
       STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0));
 
          break;
 
        case BIT_FIELD_REF:
-         {
-           enum gimplify_status r0, r1, r2;
-
-           r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
-                               post_p, is_gimple_lvalue, fb_either);
-           r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
-                               post_p, is_gimple_val, fb_rvalue);
-           r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
-                               post_p, is_gimple_val, fb_rvalue);
-           recalculate_side_effects (*expr_p);
-
-           ret = MIN (r0, MIN (r1, r2));
-         }
+         ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+                              post_p, is_gimple_lvalue, fb_either);
+         recalculate_side_effects (*expr_p);
          break;
 
        case TARGET_MEM_REF:
 
              walk_tree (&TREE_OPERAND (t, 3), convert_nonlocal_reference_op,
                         wi, NULL);
            }
-         else if (TREE_CODE (t) == BIT_FIELD_REF)
-           {
-             walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference_op,
-                        wi, NULL);
-             walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference_op,
-                        wi, NULL);
-           }
        }
       wi->val_only = false;
       walk_tree (tp, convert_nonlocal_reference_op, wi, NULL);
              walk_tree (&TREE_OPERAND (t, 3), convert_local_reference_op, wi,
                         NULL);
            }
-         else if (TREE_CODE (t) == BIT_FIELD_REF)
-           {
-             walk_tree (&TREE_OPERAND (t, 1), convert_local_reference_op, wi,
-                        NULL);
-             walk_tree (&TREE_OPERAND (t, 2), convert_local_reference_op, wi,
-                        NULL);
-           }
        }
       wi->val_only = false;
       walk_tree (tp, convert_local_reference_op, wi, NULL);
 
          CALL_EXPR_STATIC_CHAIN (folded) = sc;
        return folded;
       }
-      break;
+
     case MEM_REF:
       {
        tree baseop = create_component_ref_by_pieces_1 (block, ref, operand,
          }
        return fold_build2 (MEM_REF, currop->type, baseop, offset);
       }
-      break;
+
     case TARGET_MEM_REF:
       {
        pre_expr op0expr, op1expr;
        return build5 (TARGET_MEM_REF, currop->type,
                       baseop, currop->op2, genop0, currop->op1, genop1);
       }
-      break;
+
     case ADDR_EXPR:
       if (currop->op0)
        {
     case IMAGPART_EXPR:
     case VIEW_CONVERT_EXPR:
       {
-       tree folded;
        tree genop0 = create_component_ref_by_pieces_1 (block, ref,
                                                        operand,
                                                        stmts, domstmt);
        if (!genop0)
          return NULL_TREE;
-       folded = fold_build1 (currop->opcode, currop->type,
-                             genop0);
-       return folded;
+
+       return fold_build1 (currop->opcode, currop->type, genop0);
       }
-      break;
+
     case WITH_SIZE_EXPR:
       {
        tree genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
 
        return fold_build2 (currop->opcode, currop->type, genop0, genop1);
       }
-      break;
+
     case BIT_FIELD_REF:
       {
-       tree folded;
        tree genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
                                                        stmts, domstmt);
-       pre_expr op1expr = get_or_alloc_expr_for (currop->op0);
-       pre_expr op2expr = get_or_alloc_expr_for (currop->op1);
-       tree genop1;
-       tree genop2;
+       tree op1 = currop->op0;
+       tree op2 = currop->op1;
 
        if (!genop0)
          return NULL_TREE;
-       genop1 = find_or_generate_expression (block, op1expr, stmts, domstmt);
-       if (!genop1)
-         return NULL_TREE;
-       genop2 = find_or_generate_expression (block, op2expr, stmts, domstmt);
-       if (!genop2)
-         return NULL_TREE;
-       folded = fold_build3 (BIT_FIELD_REF, currop->type, genop0, genop1,
-                             genop2);
-       return folded;
+
+       return fold_build3 (BIT_FIELD_REF, currop->type, genop0, op1, op2);
       }
 
       /* For array ref vn_reference_op's, operand 1 of the array ref
              return NULL_TREE;
          }
 
-       return fold_build3 (COMPONENT_REF, TREE_TYPE (op1), op0, op1,
-                           genop2);
+       return fold_build3 (COMPONENT_REF, TREE_TYPE (op1), op0, op1, genop2);
       }
-      break;
+
     case SSA_NAME:
       {
        pre_expr op0expr = get_or_alloc_expr_for (currop->op0);
 
     case BIT_FIELD_REF:
       result = build_nt (BIT_FIELD_REF,
                         stabilize_reference (TREE_OPERAND (ref, 0)),
-                        stabilize_reference_1 (TREE_OPERAND (ref, 1)),
-                        stabilize_reference_1 (TREE_OPERAND (ref, 2)));
+                        TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2));
       break;
 
     case ARRAY_REF:
          if (TREE_OPERAND (node, 2))
            UPDATE_FLAGS (TREE_OPERAND (node, 2));
        }
-      else if (TREE_CODE (node) == BIT_FIELD_REF)
-       UPDATE_FLAGS (TREE_OPERAND (node, 2));
     }
 
   node = lang_hooks.expr_to_decl (node, &tc, &se);
   return t;
 }
 
-tree
-build6_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
-            tree arg2, tree arg3, tree arg4, tree arg5 MEM_STAT_DECL)
-{
-  bool constant, read_only, side_effects;
-  tree t;
-
-  gcc_assert (code == TARGET_MEM_REF);
-
-  t = make_node_stat (code PASS_MEM_STAT);
-  TREE_TYPE (t) = tt;
-
-  side_effects = TREE_SIDE_EFFECTS (t);
-
-  PROCESS_ARG(0);
-  PROCESS_ARG(1);
-  PROCESS_ARG(2);
-  PROCESS_ARG(3);
-  PROCESS_ARG(4);
-  if (code == TARGET_MEM_REF)
-    side_effects = 0;
-  PROCESS_ARG(5);
-
-  TREE_SIDE_EFFECTS (t) = side_effects;
-  TREE_THIS_VOLATILE (t)
-    = (code == TARGET_MEM_REF
-       && arg5 && TREE_THIS_VOLATILE (arg5));
-
-  return t;
-}
-
 /* Build a simple MEM_REF tree with the sematics of a plain INDIRECT_REF
    on the pointer PTR.  */
 
 
 extern tree build5_stat (enum tree_code, tree, tree, tree, tree, tree,
                         tree MEM_STAT_DECL);
 #define build5(c,t1,t2,t3,t4,t5,t6) build5_stat (c,t1,t2,t3,t4,t5,t6 MEM_STAT_INFO)
-extern tree build6_stat (enum tree_code, tree, tree, tree, tree, tree,
-                        tree, tree MEM_STAT_DECL);
-#define build6(c,t1,t2,t3,t4,t5,t6,t7) \
-  build6_stat (c,t1,t2,t3,t4,t5,t6,t7 MEM_STAT_INFO)
 
-/* _loc versions of build[1-6].  */
+/* _loc versions of build[1-5].  */
 
 static inline tree
 build1_stat_loc (location_t loc, enum tree_code code, tree type,
 #define build5_loc(l,c,t1,t2,t3,t4,t5,t6) \
   build5_stat_loc (l,c,t1,t2,t3,t4,t5,t6 MEM_STAT_INFO)
 
-static inline tree
-build6_stat_loc (location_t loc, enum tree_code code, tree type, tree arg0,
-                tree arg1, tree arg2, tree arg3, tree arg4,
-                tree arg5 MEM_STAT_DECL)
-{
-  tree t = build6_stat (code, type, arg0, arg1, arg2, arg3, arg4,
-                       arg5 PASS_MEM_STAT);
-  if (CAN_HAVE_LOCATION_P (t))
-    SET_EXPR_LOCATION (t, loc);
-  return t;
-}
-#define build6_loc(l,c,t1,t2,t3,t4,t5,t6,t7) \
-  build6_stat_loc (l,c,t1,t2,t3,t4,t5,t6,t7 MEM_STAT_INFO)
-
 extern tree build_var_debug_value_stat (tree, tree MEM_STAT_DECL);
 #define build_var_debug_value(t1,t2) \
   build_var_debug_value_stat (t1,t2 MEM_STAT_INFO)