diff options
Diffstat (limited to 'gcc/ada/gcc-interface/utils2.c')
-rw-r--r-- | gcc/ada/gcc-interface/utils2.c | 87 |
1 files changed, 86 insertions, 1 deletions
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c index cf290a3..4679ea8 100644 --- a/gcc/ada/gcc-interface/utils2.c +++ b/gcc/ada/gcc-interface/utils2.c @@ -798,7 +798,7 @@ build_binary_op (enum tree_code op_code, tree result_type, /* Then convert the right operand to its base type. This will prevent unneeded sign conversions when sizetype is wider than integer. */ right_operand = convert (right_base_type, right_operand); - right_operand = convert (sizetype, right_operand); + right_operand = convert_to_index_type (right_operand); modulus = NULL_TREE; break; @@ -2598,3 +2598,88 @@ gnat_stabilize_reference (tree ref, bool force, bool *success) return result; } + +/* If EXPR is an expression that is invariant in the current function, in the + sense that it can be evaluated anywhere in the function and any number of + times, return EXPR or an equivalent expression. Otherwise return NULL. */ + +tree +gnat_invariant_expr (tree expr) +{ + tree type = TREE_TYPE (expr), t; + + STRIP_NOPS (expr); + + while ((TREE_CODE (expr) == CONST_DECL + || (TREE_CODE (expr) == VAR_DECL && TREE_READONLY (expr))) + && decl_function_context (expr) == current_function_decl + && DECL_INITIAL (expr)) + { + expr = DECL_INITIAL (expr); + STRIP_NOPS (expr); + } + + if (TREE_CONSTANT (expr)) + return fold_convert (type, expr); + + t = expr; + + while (true) + { + switch (TREE_CODE (t)) + { + case COMPONENT_REF: + if (TREE_OPERAND (t, 2) != NULL_TREE) + return NULL_TREE; + break; + + case ARRAY_REF: + case ARRAY_RANGE_REF: + if (!TREE_CONSTANT (TREE_OPERAND (t, 1)) + || TREE_OPERAND (t, 2) != NULL_TREE + || TREE_OPERAND (t, 3) != NULL_TREE) + return NULL_TREE; + break; + + case BIT_FIELD_REF: + case VIEW_CONVERT_EXPR: + case REALPART_EXPR: + case IMAGPART_EXPR: + break; + + case INDIRECT_REF: + if (!TREE_READONLY (t) + || TREE_SIDE_EFFECTS (t) + || !TREE_THIS_NOTRAP (t)) + return NULL_TREE; + break; + + default: + goto object; + } + + t = TREE_OPERAND (t, 0); + } + +object: + if (TREE_SIDE_EFFECTS (t)) + return NULL_TREE; + + if (TREE_CODE (t) == CONST_DECL + && (DECL_EXTERNAL (t) + || decl_function_context (t) != current_function_decl)) + return fold_convert (type, expr); + + if (!TREE_READONLY (t)) + return NULL_TREE; + + if (TREE_CODE (t) == PARM_DECL) + return fold_convert (type, expr); + + if (TREE_CODE (t) == VAR_DECL + && (DECL_EXTERNAL (t) + || decl_function_context (t) != current_function_decl)) + return fold_convert (type, expr); + + return NULL_TREE; +} |