diff options
author | Richard Guenther <rguenther@suse.de> | 2010-08-12 10:36:08 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2010-08-12 10:36:08 +0000 |
commit | 1be38ccb1b4a2208403ffe980073d6ed2bb61490 (patch) | |
tree | 9a3a2a1cd2ab3e673bfae829eadbac8146e824a5 /gcc/builtins.c | |
parent | a96ad3486e4f3a949bcfccf5aecbd1b5e35c5307 (diff) | |
download | gcc-1be38ccb1b4a2208403ffe980073d6ed2bb61490.zip gcc-1be38ccb1b4a2208403ffe980073d6ed2bb61490.tar.gz gcc-1be38ccb1b4a2208403ffe980073d6ed2bb61490.tar.bz2 |
tree-flow.h (struct ptr_info_def): Add align and misalign fields.
2010-08-12 Richard Guenther <rguenther@suse.de>
* tree-flow.h (struct ptr_info_def): Add align and misalign fields.
* tree-ssa-alias.c (get_ptr_info): Move ...
* tree-ssanames.c (get_ptr_info): ... here. Initialize
align and misalign fields conservatively.
* tree-ssa-ccp.c (ccp_finalize): From partially constant pointers
derive alignment information.
(evaluate_stmt): Derive alignment information from memory
allocation functions.
* tree.h (get_pointer_alignment): Make unsigned.
* builtins.c (get_object_alignment): Use alignment information we
have computed for pointers.
(get_pointer_alignment): Likewise. Make conservative, return
and unsigned value.
(expand_builtin_strlen): Adjust.
(expand_builtin_memcmp): Likewise.
(expand_builtin_strcmp): Likewise.
(expand_builtin_strncmp): Likewise.
(get_builtin_sync_mem): Use at least mode alignment.
(fold_builtin_memset): Adjust.
(fold_builtin_memory_op): Likewise.
* gimple-pretty-print.c (dump_gimple_phi): Alongside alias
information also dump pointer alignment knowledge.
(dump_gimple_stmt): Likewise.
From-SVN: r163189
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 140 |
1 files changed, 78 insertions, 62 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 3d5ca33..ad5d6aa 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -309,6 +309,7 @@ get_object_alignment (tree exp, unsigned int max_align) else if (TREE_CODE (exp) == MEM_REF) { tree addr = TREE_OPERAND (exp, 0); + struct ptr_info_def *pi; if (TREE_CODE (addr) == BIT_AND_EXPR && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST) { @@ -319,12 +320,53 @@ get_object_alignment (tree exp, unsigned int max_align) } else align = BITS_PER_UNIT; - if (TREE_CODE (addr) == ADDR_EXPR) + if (TREE_CODE (addr) == SSA_NAME + && (pi = SSA_NAME_PTR_INFO (addr))) + { + bitpos += (pi->misalign * BITS_PER_UNIT) & ~(align - 1); + align = MAX (pi->align * BITS_PER_UNIT, align); + } + else if (TREE_CODE (addr) == ADDR_EXPR) align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0), max_align)); bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT; } else if (TREE_CODE (exp) == TARGET_MEM_REF + && TMR_BASE (exp) + && POINTER_TYPE_P (TREE_TYPE (TMR_BASE (exp)))) + { + struct ptr_info_def *pi; + tree addr = TMR_BASE (exp); + if (TREE_CODE (addr) == BIT_AND_EXPR + && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST) + { + align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)) + & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))); + align *= BITS_PER_UNIT; + addr = TREE_OPERAND (addr, 0); + } + else + align = BITS_PER_UNIT; + if (TREE_CODE (addr) == SSA_NAME + && (pi = SSA_NAME_PTR_INFO (addr))) + { + bitpos += (pi->misalign * BITS_PER_UNIT) & ~(align - 1); + align = MAX (pi->align * BITS_PER_UNIT, align); + } + else if (TREE_CODE (addr) == ADDR_EXPR) + align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0), + max_align)); + if (TMR_OFFSET (exp)) + bitpos += TREE_INT_CST_LOW (TMR_OFFSET (exp)) * BITS_PER_UNIT; + if (TMR_INDEX (exp) && TMR_STEP (exp)) + { + unsigned HOST_WIDE_INT step = TREE_INT_CST_LOW (TMR_STEP (exp)); + align = MIN (align, (step & -step) * BITS_PER_UNIT); + } + else if (TMR_INDEX (exp)) + align = BITS_PER_UNIT; + } + else if (TREE_CODE (exp) == TARGET_MEM_REF && TMR_SYMBOL (exp)) { align = get_object_alignment (TMR_SYMBOL (exp), max_align); @@ -417,56 +459,28 @@ can_trust_pointer_alignment (void) Otherwise, look at the expression to see if we can do better, i.e., if the expression is actually pointing at an object whose alignment is tighter. */ -int +unsigned int get_pointer_alignment (tree exp, unsigned int max_align) { - unsigned int align, inner; - - if (!can_trust_pointer_alignment ()) - return 0; - - if (!POINTER_TYPE_P (TREE_TYPE (exp))) - return 0; - - align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))); - align = MIN (align, max_align); - - while (1) - { - switch (TREE_CODE (exp)) - { - CASE_CONVERT: - exp = TREE_OPERAND (exp, 0); - if (! POINTER_TYPE_P (TREE_TYPE (exp))) - return align; - - inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))); - align = MIN (inner, max_align); - break; - - case POINTER_PLUS_EXPR: - /* If sum of pointer + int, restrict our maximum alignment to that - imposed by the integer. If not, we can't do any better than - ALIGN. */ - if (! host_integerp (TREE_OPERAND (exp, 1), 1)) - return align; - - while (((tree_low_cst (TREE_OPERAND (exp, 1), 1)) - & (max_align / BITS_PER_UNIT - 1)) - != 0) - max_align >>= 1; - - exp = TREE_OPERAND (exp, 0); - break; - - case ADDR_EXPR: - /* See what we are pointing at and look at its alignment. */ - return get_object_alignment (TREE_OPERAND (exp, 0), max_align); + STRIP_NOPS (exp); - default: - return align; - } + if (TREE_CODE (exp) == ADDR_EXPR) + return get_object_alignment (TREE_OPERAND (exp, 0), max_align); + else if (TREE_CODE (exp) == SSA_NAME + && POINTER_TYPE_P (TREE_TYPE (exp))) + { + struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp); + unsigned align; + if (!pi) + return BITS_PER_UNIT; + if (pi->misalign != 0) + align = (pi->misalign & -pi->misalign); + else + align = pi->align; + return MIN (max_align, align * BITS_PER_UNIT); } + + return POINTER_TYPE_P (TREE_TYPE (exp)) ? BITS_PER_UNIT : 0; } /* Compute the length of a C string. TREE_STRING_LENGTH is not the right @@ -3293,7 +3307,7 @@ expand_builtin_strlen (tree exp, rtx target, rtx result, src_reg, char_rtx, before_strlen; enum machine_mode insn_mode = target_mode, char_mode; enum insn_code icode = CODE_FOR_nothing; - int align; + unsigned int align; /* If the length can be computed at compile-time, return it. */ len = c_strlen (src, 0); @@ -4066,9 +4080,9 @@ expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target, tree arg2 = CALL_EXPR_ARG (exp, 1); tree len = CALL_EXPR_ARG (exp, 2); - int arg1_align + unsigned int arg1_align = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; - int arg2_align + unsigned int arg2_align = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; enum machine_mode insn_mode; @@ -4168,9 +4182,9 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) tree arg1 = CALL_EXPR_ARG (exp, 0); tree arg2 = CALL_EXPR_ARG (exp, 1); - int arg1_align + unsigned int arg1_align = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; - int arg2_align + unsigned int arg2_align = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; /* If we don't have POINTER_TYPE, call the function. */ @@ -4319,9 +4333,9 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, tree arg2 = CALL_EXPR_ARG (exp, 1); tree arg3 = CALL_EXPR_ARG (exp, 2); - int arg1_align + unsigned int arg1_align = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; - int arg2_align + unsigned int arg2_align = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; enum machine_mode insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode; @@ -5505,7 +5519,9 @@ get_builtin_sync_mem (tree loc, enum machine_mode mode) satisfy the full barrier semantics of the intrinsic. */ mem = validize_mem (gen_rtx_MEM (mode, addr)); - set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT)); + /* The alignment needs to be at least according to that of the mode. */ + set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode), + get_pointer_alignment (loc, BIGGEST_ALIGNMENT))); set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER); MEM_VOLATILE_P (mem) = 1; @@ -8280,7 +8296,7 @@ fold_builtin_memset (location_t loc, tree dest, tree c, tree len, length = tree_low_cst (len, 1); if (GET_MODE_SIZE (TYPE_MODE (etype)) != length || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT - < (int) length) + < length) return NULL_TREE; if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT) @@ -8365,7 +8381,7 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, else { tree srctype, desttype; - int src_align, dest_align; + unsigned int src_align, dest_align; tree off0; if (endp == 3) @@ -8504,8 +8520,8 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); - if (dest_align < (int) TYPE_ALIGN (desttype) - || src_align < (int) TYPE_ALIGN (srctype)) + if (dest_align < TYPE_ALIGN (desttype) + || src_align < TYPE_ALIGN (srctype)) return NULL_TREE; if (!ignore) @@ -8531,7 +8547,7 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len) && (!STRICT_ALIGNMENT || !destvar - || src_align >= (int) TYPE_ALIGN (desttype))) + || src_align >= TYPE_ALIGN (desttype))) srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype, srcvar, off0); else @@ -8543,7 +8559,7 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, if (srcvar == NULL_TREE) { if (STRICT_ALIGNMENT - && src_align < (int) TYPE_ALIGN (desttype)) + && src_align < TYPE_ALIGN (desttype)) return NULL_TREE; STRIP_NOPS (src); srcvar = fold_build2 (MEM_REF, desttype, src, off0); @@ -8551,7 +8567,7 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, else if (destvar == NULL_TREE) { if (STRICT_ALIGNMENT - && dest_align < (int) TYPE_ALIGN (srctype)) + && dest_align < TYPE_ALIGN (srctype)) return NULL_TREE; STRIP_NOPS (dest); destvar = fold_build2 (MEM_REF, srctype, dest, off0); |