aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-gimple.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-gimple.c')
-rw-r--r--gcc/tree-gimple.c89
1 files changed, 83 insertions, 6 deletions
diff --git a/gcc/tree-gimple.c b/gcc/tree-gimple.c
index d1e47f6..93e99e6 100644
--- a/gcc/tree-gimple.c
+++ b/gcc/tree-gimple.c
@@ -167,17 +167,13 @@ is_gimple_addressable (tree t)
|| INDIRECT_REF_P (t));
}
-/* Return true if T is a GIMPLE minimal invariant. It's a restricted
- form of function invariant. */
+/* Return true if T is a valid gimple constant. */
bool
-is_gimple_min_invariant (const_tree t)
+is_gimple_constant (const_tree t)
{
switch (TREE_CODE (t))
{
- case ADDR_EXPR:
- return TREE_INVARIANT (t);
-
case INTEGER_CST:
case REAL_CST:
case FIXED_CST:
@@ -198,6 +194,87 @@ is_gimple_min_invariant (const_tree t)
}
}
+/* Return true if T is a gimple invariant address. */
+
+bool
+is_gimple_invariant_address (const_tree t)
+{
+ tree op;
+
+ if (TREE_CODE (t) != ADDR_EXPR)
+ return false;
+
+ op = TREE_OPERAND (t, 0);
+ while (handled_component_p (op))
+ {
+ switch (TREE_CODE (op))
+ {
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ if (!is_gimple_constant (TREE_OPERAND (op, 1))
+ || TREE_OPERAND (op, 2) != NULL_TREE
+ || TREE_OPERAND (op, 3) != NULL_TREE)
+ return false;
+ break;
+
+ case COMPONENT_REF:
+ if (TREE_OPERAND (op, 2) != NULL_TREE)
+ return false;
+ break;
+
+ default:;
+ }
+ op = TREE_OPERAND (op, 0);
+ }
+
+ if (CONSTANT_CLASS_P (op))
+ return true;
+
+ if (INDIRECT_REF_P (op))
+ return false;
+
+ switch (TREE_CODE (op))
+ {
+ case PARM_DECL:
+ case RESULT_DECL:
+ case LABEL_DECL:
+ case FUNCTION_DECL:
+ return true;
+
+ case VAR_DECL:
+ if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
+ && ! DECL_DLLIMPORT_P (op))
+ || DECL_THREAD_LOCAL_P (op)
+ || DECL_CONTEXT (op) == current_function_decl
+ || decl_function_context (op) == current_function_decl)
+ return true;
+ break;
+
+ case CONST_DECL:
+ if ((TREE_STATIC (op) || DECL_EXTERNAL (op))
+ || decl_function_context (op) == current_function_decl)
+ return true;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return false;
+}
+
+/* Return true if T is a GIMPLE minimal invariant. It's a restricted
+ form of function invariant. */
+
+bool
+is_gimple_min_invariant (const_tree t)
+{
+ if (TREE_CODE (t) == ADDR_EXPR)
+ return is_gimple_invariant_address (t);
+
+ return is_gimple_constant (t);
+}
+
/* Return true if T looks like a valid GIMPLE statement. */
bool