builtins.c (get_pointer_alignment_1): Handle POINTER_PLUS_EXPR.

2015-07-02  Richard Biener  <rguenther@suse.de>

	* builtins.c (get_pointer_alignment_1): Handle POINTER_PLUS_EXPR.
	* fold-const.c (get_pointer_modulus_and_residue): Remove.
	(fold_binary_loc): Implement (T)ptr & CST in terms of
	get_pointer_alignment_1.
	* tree-vect-loop-manip.c (vect_gen_niters_for_prolog_loop):
	Make sure to build the alignment test on a SSA name without
	final alignment info valid only after the prologue.

From-SVN: r225310
This commit is contained in:
Richard Biener 2015-07-02 11:33:16 +00:00 committed by Richard Biener
parent cc2af70593
commit 5fa79de857
4 changed files with 41 additions and 85 deletions

View File

@ -1,3 +1,13 @@
2015-07-02 Richard Biener <rguenther@suse.de>
* builtins.c (get_pointer_alignment_1): Handle POINTER_PLUS_EXPR.
* fold-const.c (get_pointer_modulus_and_residue): Remove.
(fold_binary_loc): Implement (T)ptr & CST in terms of
get_pointer_alignment_1.
* tree-vect-loop-manip.c (vect_gen_niters_for_prolog_loop):
Make sure to build the alignment test on a SSA name without
final alignment info valid only after the prologue.
2015-07-02 Hans-Peter Nilsson <hp@axis.com> 2015-07-02 Hans-Peter Nilsson <hp@axis.com>
* config/cris/cris.md ("epilogue"): Remove condition. * config/cris/cris.md ("epilogue"): Remove condition.

View File

@ -473,6 +473,28 @@ get_pointer_alignment_1 (tree exp, unsigned int *alignp,
if (TREE_CODE (exp) == ADDR_EXPR) if (TREE_CODE (exp) == ADDR_EXPR)
return get_object_alignment_2 (TREE_OPERAND (exp, 0), return get_object_alignment_2 (TREE_OPERAND (exp, 0),
alignp, bitposp, true); alignp, bitposp, true);
else if (TREE_CODE (exp) == POINTER_PLUS_EXPR)
{
unsigned int align;
unsigned HOST_WIDE_INT bitpos;
bool res = get_pointer_alignment_1 (TREE_OPERAND (exp, 0),
&align, &bitpos);
if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
bitpos += TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT;
else
{
unsigned int trailing_zeros = tree_ctz (TREE_OPERAND (exp, 1));
if (trailing_zeros < HOST_BITS_PER_INT)
{
unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
if (inner)
align = MIN (align, inner);
}
}
*alignp = align;
*bitposp = bitpos & (align - 1);
return res;
}
else if (TREE_CODE (exp) == SSA_NAME else if (TREE_CODE (exp) == SSA_NAME
&& POINTER_TYPE_P (TREE_TYPE (exp))) && POINTER_TYPE_P (TREE_TYPE (exp)))
{ {

View File

@ -9350,83 +9350,6 @@ fold_mult_zconjz (location_t loc, tree type, tree expr)
} }
/* Subroutine of fold_binary. If P is the value of EXPR, computes
power-of-two M and (arbitrary) N such that M divides (P-N). This condition
guarantees that P and N have the same least significant log2(M) bits.
N is not otherwise constrained. In particular, N is not normalized to
0 <= N < M as is common. In general, the precise value of P is unknown.
M is chosen as large as possible such that constant N can be determined.
Returns M and sets *RESIDUE to N.
If ALLOW_FUNC_ALIGN is true, do take functions' DECL_ALIGN_UNIT into
account. This is not always possible due to PR 35705.
*/
static unsigned HOST_WIDE_INT
get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue,
bool allow_func_align)
{
enum tree_code code;
*residue = 0;
code = TREE_CODE (expr);
if (code == ADDR_EXPR)
{
unsigned int bitalign;
get_object_alignment_1 (TREE_OPERAND (expr, 0), &bitalign, residue);
*residue /= BITS_PER_UNIT;
return bitalign / BITS_PER_UNIT;
}
else if (code == POINTER_PLUS_EXPR)
{
tree op0, op1;
unsigned HOST_WIDE_INT modulus;
enum tree_code inner_code;
op0 = TREE_OPERAND (expr, 0);
STRIP_NOPS (op0);
modulus = get_pointer_modulus_and_residue (op0, residue,
allow_func_align);
op1 = TREE_OPERAND (expr, 1);
STRIP_NOPS (op1);
inner_code = TREE_CODE (op1);
if (inner_code == INTEGER_CST)
{
*residue += TREE_INT_CST_LOW (op1);
return modulus;
}
else if (inner_code == MULT_EXPR)
{
op1 = TREE_OPERAND (op1, 1);
if (TREE_CODE (op1) == INTEGER_CST)
{
unsigned HOST_WIDE_INT align;
/* Compute the greatest power-of-2 divisor of op1. */
align = TREE_INT_CST_LOW (op1);
align &= -align;
/* If align is non-zero and less than *modulus, replace
*modulus with align., If align is 0, then either op1 is 0
or the greatest power-of-2 divisor of op1 doesn't fit in an
unsigned HOST_WIDE_INT. In either case, no additional
constraint is imposed. */
if (align)
modulus = MIN (modulus, align);
return modulus;
}
}
}
/* If we get here, we were unable to determine anything useful about the
expression. */
return 1;
}
/* Helper function for fold_vec_perm. Store elements of VECTOR_CST or /* Helper function for fold_vec_perm. Store elements of VECTOR_CST or
CONSTRUCTOR ARG into array ELTS and return true if successful. */ CONSTRUCTOR ARG into array ELTS and return true if successful. */
@ -11149,19 +11072,20 @@ fold_binary_loc (location_t loc,
/* If arg0 is derived from the address of an object or function, we may /* If arg0 is derived from the address of an object or function, we may
be able to fold this expression using the object or function's be able to fold this expression using the object or function's
alignment. */ alignment. */
if (POINTER_TYPE_P (TREE_TYPE (arg0)) && tree_fits_uhwi_p (arg1)) if (POINTER_TYPE_P (TREE_TYPE (arg0)) && TREE_CODE (arg1) == INTEGER_CST)
{ {
unsigned HOST_WIDE_INT modulus, residue; unsigned int align;
unsigned HOST_WIDE_INT low = tree_to_uhwi (arg1); unsigned HOST_WIDE_INT bitpos;
modulus = get_pointer_modulus_and_residue (arg0, &residue, get_pointer_alignment_1 (arg0, &align, &bitpos);
integer_onep (arg1));
/* This works because modulus is a power of 2. If this weren't the /* This works because modulus is a power of 2. If this weren't the
case, we'd have to replace it by its greatest power-of-2 case, we'd have to replace it by its greatest power-of-2
divisor: modulus & -modulus. */ divisor: modulus & -modulus. */
if (low < modulus) if (wi::ltu_p (arg1, align / BITS_PER_UNIT))
return build_int_cst (type, residue & low); return wide_int_to_tree (type,
wi::bit_and (arg1,
bitpos / BITS_PER_UNIT));
} }
goto associate; goto associate;

View File

@ -1877,7 +1877,7 @@ vect_gen_niters_for_prolog_loop (loop_vec_info loop_vinfo, tree loop_niters, int
gimple_seq new_stmts = NULL; gimple_seq new_stmts = NULL;
bool negative = tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0; bool negative = tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0;
tree offset = negative tree offset = negative
? size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1) : NULL_TREE; ? size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1) : size_zero_node;
tree start_addr = vect_create_addr_base_for_vector_ref (dr_stmt, tree start_addr = vect_create_addr_base_for_vector_ref (dr_stmt,
&new_stmts, offset, loop); &new_stmts, offset, loop);
tree type = unsigned_type_for (TREE_TYPE (start_addr)); tree type = unsigned_type_for (TREE_TYPE (start_addr));