diff options
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 184 |
1 files changed, 68 insertions, 116 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 8a3f448..ddbbd79 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -4455,7 +4455,10 @@ stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue) { tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist)); - gcc_assert (vatype != NULL_TREE); + /* The current way of determining the type of valist is completely + bogus. We should have the information on the va builtin instead. */ + if (!vatype) + vatype = targetm.fn_abi_va_list (cfun->decl); if (TREE_CODE (vatype) == ARRAY_TYPE) { @@ -4474,21 +4477,21 @@ stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue) } else { - tree pt; + tree pt = build_pointer_type (vatype); if (! needs_lvalue) { if (! TREE_SIDE_EFFECTS (valist)) return valist; - pt = build_pointer_type (vatype); valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist); TREE_SIDE_EFFECTS (valist) = 1; } if (TREE_SIDE_EFFECTS (valist)) valist = save_expr (valist); - valist = build_fold_indirect_ref_loc (loc, valist); + valist = fold_build2_loc (loc, MEM_REF, + vatype, valist, build_int_cst (pt, 0)); } return valist; @@ -8346,6 +8349,7 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, { tree srctype, desttype; int src_align, dest_align; + tree off0; if (endp == 3) { @@ -8371,37 +8375,26 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, } /* If *src and *dest can't overlap, optimize into memcpy as well. */ - srcvar = build_fold_indirect_ref_loc (loc, src); - destvar = build_fold_indirect_ref_loc (loc, dest); - if (srcvar - && !TREE_THIS_VOLATILE (srcvar) - && destvar - && !TREE_THIS_VOLATILE (destvar)) + if (TREE_CODE (src) == ADDR_EXPR + && TREE_CODE (dest) == ADDR_EXPR) { tree src_base, dest_base, fn; HOST_WIDE_INT src_offset = 0, dest_offset = 0; HOST_WIDE_INT size = -1; HOST_WIDE_INT maxsize = -1; - src_base = srcvar; - if (handled_component_p (src_base)) - src_base = get_ref_base_and_extent (src_base, &src_offset, - &size, &maxsize); - dest_base = destvar; - if (handled_component_p (dest_base)) - dest_base = get_ref_base_and_extent (dest_base, &dest_offset, - &size, &maxsize); + srcvar = TREE_OPERAND (src, 0); + src_base = get_ref_base_and_extent (srcvar, &src_offset, + &size, &maxsize); + destvar = TREE_OPERAND (dest, 0); + dest_base = get_ref_base_and_extent (destvar, &dest_offset, + &size, &maxsize); if (host_integerp (len, 1)) - { - maxsize = tree_low_cst (len, 1); - if (maxsize - > INTTYPE_MAXIMUM (HOST_WIDE_INT) / BITS_PER_UNIT) - maxsize = -1; - else - maxsize *= BITS_PER_UNIT; - } + maxsize = tree_low_cst (len, 1); else maxsize = -1; + src_offset /= BITS_PER_UNIT; + dest_offset /= BITS_PER_UNIT; if (SSA_VAR_P (src_base) && SSA_VAR_P (dest_base)) { @@ -8410,13 +8403,25 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, dest_offset, maxsize)) return NULL_TREE; } - else if (TREE_CODE (src_base) == INDIRECT_REF - && TREE_CODE (dest_base) == INDIRECT_REF) + else if (TREE_CODE (src_base) == MEM_REF + && TREE_CODE (dest_base) == MEM_REF) { + double_int off; if (! operand_equal_p (TREE_OPERAND (src_base, 0), - TREE_OPERAND (dest_base, 0), 0) - || ranges_overlap_p (src_offset, maxsize, - dest_offset, maxsize)) + TREE_OPERAND (dest_base, 0), 0)) + return NULL_TREE; + off = double_int_add (mem_ref_offset (src_base), + shwi_to_double_int (src_offset)); + if (!double_int_fits_in_shwi_p (off)) + return NULL_TREE; + src_offset = off.low; + off = double_int_add (mem_ref_offset (dest_base), + shwi_to_double_int (dest_offset)); + if (!double_int_fits_in_shwi_p (off)) + return NULL_TREE; + dest_offset = off.low; + if (ranges_overlap_p (src_offset, maxsize, + dest_offset, maxsize)) return NULL_TREE; } else @@ -8472,12 +8477,12 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest); } if (!srctype || !desttype + || TREE_ADDRESSABLE (srctype) + || TREE_ADDRESSABLE (desttype) || !TYPE_SIZE_UNIT (srctype) || !TYPE_SIZE_UNIT (desttype) || TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST - || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST - || TYPE_VOLATILE (srctype) - || TYPE_VOLATILE (desttype)) + || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST) return NULL_TREE; src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); @@ -8489,97 +8494,44 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, if (!ignore) dest = builtin_save_expr (dest); - srcvar = NULL_TREE; - if (tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)) - { - srcvar = build_fold_indirect_ref_loc (loc, src); - if (TREE_THIS_VOLATILE (srcvar)) - return NULL_TREE; - else if (!tree_int_cst_equal (tree_expr_size (srcvar), len)) - srcvar = NULL_TREE; - /* With memcpy, it is possible to bypass aliasing rules, so without - this check i.e. execute/20060930-2.c would be misoptimized, - because it use conflicting alias set to hold argument for the - memcpy call. This check is probably unnecessary with - -fno-strict-aliasing. Similarly for destvar. See also - PR29286. */ - else if (!var_decl_component_p (srcvar)) - srcvar = NULL_TREE; - } - - destvar = NULL_TREE; - if (tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len)) - { - destvar = build_fold_indirect_ref_loc (loc, dest); - if (TREE_THIS_VOLATILE (destvar)) - return NULL_TREE; - else if (!tree_int_cst_equal (tree_expr_size (destvar), len)) - destvar = NULL_TREE; - else if (!var_decl_component_p (destvar)) - destvar = NULL_TREE; - } + /* Build accesses at offset zero with a ref-all character type. */ + off0 = build_int_cst (build_pointer_type_for_mode (char_type_node, + ptr_mode, true), 0); + + destvar = dest; + STRIP_NOPS (destvar); + if (TREE_CODE (destvar) == ADDR_EXPR + && var_decl_component_p (TREE_OPERAND (destvar, 0)) + && tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len)) + destvar = fold_build2 (MEM_REF, desttype, destvar, off0); + else + destvar = NULL_TREE; + + srcvar = src; + STRIP_NOPS (srcvar); + if (TREE_CODE (srcvar) == ADDR_EXPR + && var_decl_component_p (TREE_OPERAND (srcvar, 0)) + && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)) + srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype, + srcvar, off0); + else + srcvar = NULL_TREE; if (srcvar == NULL_TREE && destvar == NULL_TREE) return NULL_TREE; if (srcvar == NULL_TREE) { - tree srcptype; - if (TREE_ADDRESSABLE (TREE_TYPE (destvar))) - return NULL_TREE; - - srctype = build_qualified_type (desttype, 0); - if (src_align < (int) TYPE_ALIGN (srctype)) - { - if (AGGREGATE_TYPE_P (srctype) - || SLOW_UNALIGNED_ACCESS (TYPE_MODE (srctype), src_align)) - return NULL_TREE; - - srctype = build_variant_type_copy (srctype); - TYPE_ALIGN (srctype) = src_align; - TYPE_USER_ALIGN (srctype) = 1; - TYPE_PACKED (srctype) = 1; - } - srcptype = build_pointer_type_for_mode (srctype, ptr_mode, true); - src = fold_convert_loc (loc, srcptype, src); - srcvar = build_fold_indirect_ref_loc (loc, src); + STRIP_NOPS (src); + srcvar = fold_build2 (MEM_REF, desttype, src, off0); } else if (destvar == NULL_TREE) { - tree destptype; - if (TREE_ADDRESSABLE (TREE_TYPE (srcvar))) - return NULL_TREE; - - desttype = build_qualified_type (srctype, 0); - if (dest_align < (int) TYPE_ALIGN (desttype)) - { - if (AGGREGATE_TYPE_P (desttype) - || SLOW_UNALIGNED_ACCESS (TYPE_MODE (desttype), dest_align)) - return NULL_TREE; + STRIP_NOPS (dest); + destvar = fold_build2 (MEM_REF, srctype, dest, off0); + } - desttype = build_variant_type_copy (desttype); - TYPE_ALIGN (desttype) = dest_align; - TYPE_USER_ALIGN (desttype) = 1; - TYPE_PACKED (desttype) = 1; - } - destptype = build_pointer_type_for_mode (desttype, ptr_mode, true); - dest = fold_convert_loc (loc, destptype, dest); - destvar = build_fold_indirect_ref_loc (loc, dest); - } - - if (srctype == desttype - || (gimple_in_ssa_p (cfun) - && useless_type_conversion_p (desttype, srctype))) - expr = srcvar; - else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar)) - || POINTER_TYPE_P (TREE_TYPE (srcvar))) - && (INTEGRAL_TYPE_P (TREE_TYPE (destvar)) - || POINTER_TYPE_P (TREE_TYPE (destvar)))) - expr = fold_convert_loc (loc, TREE_TYPE (destvar), srcvar); - else - expr = fold_build1_loc (loc, VIEW_CONVERT_EXPR, - TREE_TYPE (destvar), srcvar); - expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr); + expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar); } if (ignore) @@ -12068,7 +12020,7 @@ maybe_emit_free_warning (tree exp) return; arg = get_base_address (TREE_OPERAND (arg, 0)); - if (arg == NULL || INDIRECT_REF_P (arg)) + if (arg == NULL || INDIRECT_REF_P (arg) || TREE_CODE (arg) == MEM_REF) return; if (SSA_VAR_P (arg)) |