diff options
author | hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-07-23 19:37:40 +0000 |
---|---|---|
committer | hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-07-23 19:37:40 +0000 |
commit | 10ada81fea4490f94ba2eb5923bf5baa367a38bd (patch) | |
tree | 437dca120093cc7b1f6debf6f6b31779526c7192 /gcc/fold-const.c | |
parent | 95a236de8aa10bf009e9368dfd28f95a980e5570 (diff) | |
parent | 3bd7a983695352a99f7dd597725eb5b839d4b4cf (diff) | |
download | gcc-ifunc.tar.gz |
Merged with trunk at revision 162480.ifunc
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/ifunc@162483 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index e2b30f90e8d..9ca5eff554e 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "tm_p.h" #include "target.h" +#include "diagnostic-core.h" #include "toplev.h" #include "intl.h" #include "ggc.h" @@ -60,6 +61,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "md5.h" #include "gimple.h" +#include "tree-flow.h" /* Nonzero if we are folding constants inside an initializer; zero otherwise. */ @@ -2040,8 +2042,8 @@ maybe_lvalue_p (const_tree x) case SSA_NAME: case COMPONENT_REF: + case MEM_REF: case INDIRECT_REF: - case ALIGN_INDIRECT_REF: case MISALIGNED_INDIRECT_REF: case ARRAY_REF: case ARRAY_RANGE_REF: @@ -2585,12 +2587,22 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) switch (TREE_CODE (arg0)) { case INDIRECT_REF: - case ALIGN_INDIRECT_REF: case MISALIGNED_INDIRECT_REF: case REALPART_EXPR: case IMAGPART_EXPR: return OP_SAME (0); + case MEM_REF: + /* Require equal access sizes. We can have incomplete types + for array references of variable-sized arrays from the + Fortran frontent though. */ + return ((TYPE_SIZE (TREE_TYPE (arg0)) == TYPE_SIZE (TREE_TYPE (arg1)) + || (TYPE_SIZE (TREE_TYPE (arg0)) + && TYPE_SIZE (TREE_TYPE (arg1)) + && operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)), + TYPE_SIZE (TREE_TYPE (arg1)), flags))) + && OP_SAME (0) && OP_SAME (1)); + case ARRAY_REF: case ARRAY_RANGE_REF: /* Operands 2 and 3 may be null. @@ -7584,7 +7596,6 @@ build_fold_addr_expr_with_type_loc (location_t loc, tree t, tree ptrtype) if (TREE_CODE (t) == WITH_SIZE_EXPR) t = TREE_OPERAND (t, 0); - /* Note: doesn't apply to ALIGN_INDIRECT_REF */ if (TREE_CODE (t) == INDIRECT_REF || TREE_CODE (t) == MISALIGNED_INDIRECT_REF) { @@ -7596,6 +7607,9 @@ build_fold_addr_expr_with_type_loc (location_t loc, tree t, tree ptrtype) SET_EXPR_LOCATION (t, loc); } } + else if (TREE_CODE (t) == MEM_REF + && integer_zerop (TREE_OPERAND (t, 1))) + return TREE_OPERAND (t, 0); else if (TREE_CODE (t) == VIEW_CONVERT_EXPR) { t = build_fold_addr_expr_loc (loc, TREE_OPERAND (t, 0)); @@ -8014,6 +8028,9 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) if (TREE_CODE (op0) == VIEW_CONVERT_EXPR) return fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, TREE_OPERAND (op0, 0)); + if (TREE_CODE (op0) == MEM_REF) + return fold_build2_loc (loc, MEM_REF, type, + TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1)); /* For integral conversions with the same precision or pointer conversions use a NOP_EXPR instead. */ @@ -8665,6 +8682,11 @@ fold_comparison (location_t loc, enum tree_code code, tree type, else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR) { base0 = TREE_OPERAND (arg0, 0); + if (TREE_CODE (base0) == ADDR_EXPR) + { + base0 = TREE_OPERAND (base0, 0); + indirect_base0 = true; + } offset0 = TREE_OPERAND (arg0, 1); } @@ -8682,6 +8704,11 @@ fold_comparison (location_t loc, enum tree_code code, tree type, else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR) { base1 = TREE_OPERAND (arg1, 0); + if (TREE_CODE (base1) == ADDR_EXPR) + { + base1 = TREE_OPERAND (base1, 0); + indirect_base1 = true; + } offset1 = TREE_OPERAND (arg1, 1); } @@ -9524,6 +9551,36 @@ fold_binary_loc (location_t loc, switch (code) { + case MEM_REF: + /* MEM[&MEM[p, CST1], CST2] -> MEM[p, CST1 + CST2]. */ + if (TREE_CODE (arg0) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (arg0, 0)) == MEM_REF) + { + tree iref = TREE_OPERAND (arg0, 0); + return fold_build2 (MEM_REF, type, + TREE_OPERAND (iref, 0), + int_const_binop (PLUS_EXPR, arg1, + TREE_OPERAND (iref, 1), 0)); + } + + /* MEM[&a.b, CST2] -> MEM[&a, offsetof (a, b) + CST2]. */ + if (TREE_CODE (arg0) == ADDR_EXPR + && handled_component_p (TREE_OPERAND (arg0, 0))) + { + tree base; + HOST_WIDE_INT coffset; + base = get_addr_base_and_unit_offset (TREE_OPERAND (arg0, 0), + &coffset); + if (!base) + return NULL_TREE; + return fold_build2 (MEM_REF, type, + build_fold_addr_expr (base), + int_const_binop (PLUS_EXPR, arg1, + size_int (coffset), 0)); + } + + return NULL_TREE; + case POINTER_PLUS_EXPR: /* 0 +p index -> (type)index */ if (integer_zerop (arg0)) |