+/* compute state based on ECF FLAGS and store to STATE and LOOPING. */
+
+static void
+state_from_flags (enum pure_const_state_e *state, bool *looping,
+ int flags, bool cannot_lead_to_return)
+{
+ *looping = false;
+ if (flags & ECF_LOOPING_CONST_OR_PURE)
+ {
+ *looping = true;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " looping");
+ }
+ if (flags & ECF_CONST)
+ {
+ *state = IPA_CONST;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " const\n");
+ }
+ else if (flags & ECF_PURE)
+ {
+ *state = IPA_PURE;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " pure\n");
+ }
+ else if (cannot_lead_to_return)
+ {
+ *state = IPA_PURE;
+ *looping = true;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " ignoring side effects->pure looping\n");
+ }
+ else
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " neihter\n");
+ *state = IPA_NEITHER;
+ *looping = true;
+ }
+}
+
+/* Merge STATE and STATE2 and LOOPING and LOOPING2 and store
+ into STATE and LOOPING better of the two variants.
+ Be sure to merge looping correctly. IPA_NEITHER functions
+ have looping 0 even if they don't have to return. */
+
+static inline void
+better_state (enum pure_const_state_e *state, bool *looping,
+ enum pure_const_state_e state2, bool looping2)
+{
+ if (state2 < *state)
+ {
+ if (*state == IPA_NEITHER)
+ *looping = looping2;
+ else
+ *looping = MIN (*looping, looping2);
+ }
+ else if (state2 != IPA_NEITHER)
+ *looping = MIN (*looping, looping2);
+}
+
+/* Merge STATE and STATE2 and LOOPING and LOOPING2 and store
+ into STATE and LOOPING worse of the two variants. */
+
+static inline void
+worse_state (enum pure_const_state_e *state, bool *looping,
+ enum pure_const_state_e state2, bool looping2)
+{
+ *state = MAX (*state, state2);
+ *looping = MAX (*looping, looping2);
+}
+
+/* Recognize special cases of builtins that are by themselves not pure or const
+ but function using them is. */
+static bool
+special_builtin_state (enum pure_const_state_e *state, bool *looping,
+ tree callee)
+{
+ if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
+ switch (DECL_FUNCTION_CODE (callee))
+ {
+ case BUILT_IN_RETURN:
+ case BUILT_IN_UNREACHABLE:
+ case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
+ case BUILT_IN_STACK_SAVE:
+ case BUILT_IN_STACK_RESTORE:
+ case BUILT_IN_EH_POINTER:
+ case BUILT_IN_EH_FILTER:
+ case BUILT_IN_UNWIND_RESUME:
+ case BUILT_IN_CXA_END_CLEANUP:
+ case BUILT_IN_EH_COPY_VALUES:
+ case BUILT_IN_FRAME_ADDRESS:
+ case BUILT_IN_APPLY:
+ case BUILT_IN_APPLY_ARGS:
+ *looping = false;
+ *state = IPA_CONST;
+ return true;
+ case BUILT_IN_PREFETCH:
+ *looping = true;
+ *state = IPA_CONST;
+ return true;
+ }
+ return false;
+}
+