+ if (TREE_CODE_CLASS (code) == 's')
+ TREE_SIDE_EFFECTS (t) = 1;
+ else switch (code)
+ {
+ case INIT_EXPR:
+ case MODIFY_EXPR:
+ case VA_ARG_EXPR:
+ case RTL_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ /* All of these have side-effects, no matter what their
+ operands are. */
+ TREE_SIDE_EFFECTS (t) = 1;
+ TREE_READONLY (t) = 0;
+ break;
+
+ case INDIRECT_REF:
+ /* Whether a dereference is readonly has nothing to do with whether
+ its operand is readonly. */
+ TREE_READONLY (t) = 0;
+ break;
+
+ case ADDR_EXPR:
+ if (node)
+ {
+ /* The address of a volatile decl or reference does not have
+ side-effects. But be careful not to ignore side-effects from
+ other sources deeper in the expression--if node is a _REF and
+ one of its operands has side-effects, so do we. */
+ if (TREE_THIS_VOLATILE (node))
+ {
+ TREE_SIDE_EFFECTS (t) = 0;
+ if (!DECL_P (node))
+ {
+ int i = first_rtl_op (TREE_CODE (node)) - 1;
+ for (; i >= 0; --i)
+ {
+ if (TREE_SIDE_EFFECTS (TREE_OPERAND (node, i)))
+ TREE_SIDE_EFFECTS (t) = 1;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ if (TREE_CODE_CLASS (code) == '1' && node && !TYPE_P (node)
+ && TREE_CONSTANT (node))
+ TREE_CONSTANT (t) = 1;
+ break;
+ }
+
+ return t;
+}
+
+#define PROCESS_ARG(N) \
+ do { \
+ TREE_OPERAND (t, N) = arg##N; \
+ if (arg##N &&!TYPE_P (arg##N) && fro > N) \
+ { \
+ if (TREE_SIDE_EFFECTS (arg##N)) \
+ side_effects = 1; \
+ if (!TREE_READONLY (arg##N)) \
+ read_only = 0; \
+ if (!TREE_CONSTANT (arg##N)) \
+ constant = 0; \
+ } \
+ } while (0)
+
+tree
+build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
+{
+ bool constant, read_only, side_effects;
+ tree t;
+ int fro;
+
+#ifdef ENABLE_CHECKING
+ if (TREE_CODE_LENGTH (code) != 2)
+ abort ();
+#endif
+
+ t = make_node_stat (code PASS_MEM_STAT);
+ TREE_TYPE (t) = tt;
+
+ /* Below, we automatically set TREE_SIDE_EFFECTS and TREE_READONLY for the
+ result based on those same flags for the arguments. But if the
+ arguments aren't really even `tree' expressions, we shouldn't be trying
+ to do this. */
+ fro = first_rtl_op (code);
+
+ /* Expressions without side effects may be constant if their
+ arguments are as well. */
+ constant = (TREE_CODE_CLASS (code) == '<'
+ || TREE_CODE_CLASS (code) == '2');
+ read_only = 1;
+ side_effects = TREE_SIDE_EFFECTS (t);
+
+ PROCESS_ARG(0);
+ PROCESS_ARG(1);
+
+ if (code == CALL_EXPR && !side_effects)
+ {
+ tree node;
+ int i;
+
+ /* Calls have side-effects, except those to const or
+ pure functions. */
+ i = call_expr_flags (t);
+ if (!(i & (ECF_CONST | ECF_PURE)))
+ side_effects = 1;
+
+ /* And even those have side-effects if their arguments do. */
+ else for (node = TREE_OPERAND (t, 1); node; node = TREE_CHAIN (node))
+ if (TREE_SIDE_EFFECTS (TREE_VALUE (node)))
+ {
+ side_effects = 1;
+ break;
+ }
+ }
+
+ TREE_READONLY (t) = read_only;
+ TREE_CONSTANT (t) = constant;
+ TREE_SIDE_EFFECTS (t) = side_effects;
+
+ return t;
+}
+
+tree
+build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
+ tree arg2 MEM_STAT_DECL)
+{
+ bool constant, read_only, side_effects;
+ tree t;
+ int fro;
+
+ /* ??? Quite a lot of existing code passes one too many arguments to
+ CALL_EXPR. Not going to fix them, because CALL_EXPR is about to
+ grow a new argument, so it would just mean changing them back. */
+ if (code == CALL_EXPR)
+ {
+ if (arg2 != NULL_TREE)
+ abort ();
+ return build2 (code, tt, arg0, arg1);
+ }
+
+#ifdef ENABLE_CHECKING
+ if (TREE_CODE_LENGTH (code) != 3)
+ abort ();
+#endif
+
+ t = make_node_stat (code PASS_MEM_STAT);
+ TREE_TYPE (t) = tt;
+
+ fro = first_rtl_op (code);
+
+ side_effects = TREE_SIDE_EFFECTS (t);
+
+ PROCESS_ARG(0);
+ PROCESS_ARG(1);
+ PROCESS_ARG(2);
+
+ TREE_SIDE_EFFECTS (t) = side_effects;
+
+ return t;
+}
+
+tree
+build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
+ tree arg2, tree arg3 MEM_STAT_DECL)
+{
+ bool constant, read_only, side_effects;
+ tree t;
+ int fro;
+
+#ifdef ENABLE_CHECKING
+ if (TREE_CODE_LENGTH (code) != 4)
+ abort ();
+#endif
+
+ t = make_node_stat (code PASS_MEM_STAT);
+ TREE_TYPE (t) = tt;
+
+ fro = first_rtl_op (code);
+
+ side_effects = TREE_SIDE_EFFECTS (t);
+
+ PROCESS_ARG(0);
+ PROCESS_ARG(1);
+ PROCESS_ARG(2);
+ PROCESS_ARG(3);
+
+ TREE_SIDE_EFFECTS (t) = side_effects;
+
+ return t;
+}
+
+/* Backup definition for non-gcc build compilers. */
+
+tree
+(build) (enum tree_code code, tree tt, ...)
+{
+ tree t, arg0, arg1, arg2, arg3;
+ int length = TREE_CODE_LENGTH (code);
+ va_list p;
+
+ va_start (p, tt);
+ switch (length)