Hello, The C/C++ front-ends apply type conversions to expressions using ABS with integral arguments of type smaller than int. This means that, for short x, ABS(x) becomes something like (short)ABS((int)x)). When the argument is the result of memory access, this restricts the vectorizer apparently because the alignment of the operation doesn't match the alignment of the memory access. This causes two failures in gcc.target/aarch64/vec-abs-compile.c where the expected abs instructions aren't generated.
This patch adds a case to convert_to_integer_1 to push the integer type conversions applied to an ABS expression into the argument, when it is safe to do so. This fixes the failing test cases. Tested aarch64-none-elf with cross-compiled check-gcc, Also tested aarch64-none-linux-gnu and x86_64-linux-gnu with native bootstrap and make check. Ok for trunk? Matthew gcc/ 2016-01-07 Matthew Wahab <matthew.wa...@arm.com> PR tree-optimization/64946 * convert.c (convert_to_integer_1): Push narrowing type conversions for ABS_EXPR into the argument when possible.
diff --git a/gcc/convert.c b/gcc/convert.c index 4b1e1f1..95ff1e2 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -852,6 +852,24 @@ convert_to_integer_1 (tree type, tree expr, bool dofold) } break; + case ABS_EXPR: + /* Convert (N) abs ((W)x) -> abs ((N)x) + if N, W and the type T of x are all signed integer types + and the precision of N is >= the precision of T. */ + { + tree arg0 = get_unwidened (TREE_OPERAND (expr, 0), type); + tree arg0_type = TREE_TYPE (arg0); + + if (!TYPE_UNSIGNED (type) + && !TYPE_UNSIGNED (arg0_type) + && outprec >= TYPE_PRECISION (arg0_type)) + { + return fold_build1 (ABS_EXPR, type, + convert (type, arg0)); + } + break; + } + case NEGATE_EXPR: case BIT_NOT_EXPR: /* This is not correct for ABS_EXPR,