We want to do this for 2 reasons:
- Value tracking does not recognize the ashr variant, so it would fail to match for cases like D39766.
- DAGCombiner tries to recognize the ashr variant for scalars, but not vectors. For vectors, we only have:
// Canonicalize integer abs. // vselect (setg[te] X, 0), X, -X -> // vselect (setgt X, -1), X, -X -> // vselect (setl[te] X, 0), -X, X -> // Y = sra (X, size(X)-1); xor (add (X, Y), Y)
(the comment isn't accurate - we'll produce an ISD::ABS node if it's legal or custom)
But even for scalars, it doesn't handle commuted variants (see DAGCombiner under comment):
// fold Y = sra (X, size(X)-1); xor (add (X, Y), Y) -> (abs X)
So it should work if you start with a cmp+sel pattern because we do this:
// Check to see if this is an integer abs. // select_cc setg[te] X, 0, X, -X -> // select_cc setgt X, -1, X, -X -> // select_cc setl[te] X, 0, -X, X -> // select_cc setlt X, 1, -X, X -> // Y = sra (X, size(X)-1); xor (add (X, Y), Y)
but it allows other cases to fall though the cracks:
define i32 @abs_shifty(i32 %x) {
%signbit = ashr i32 %x, 31
%add = add i32 %signbit, %x
%abs = xor i32 %signbit, %add
ret i32 %abs
}
define i32 @abs_cmpsubsel(i32 %x) {
%cmp = icmp slt i32 %x, zeroinitializer
%sub = sub i32 zeroinitializer, %x
%abs = select i1 %cmp, i32 %sub, i32 %x
ret i32 %abs
}
define <4 x i32> @abs_shifty_vec(<4 x i32> %x) {
%signbit = ashr <4 x i32> %x, <i32 31, i32 31, i32 31, i32 31>
%add = add <4 x i32> %signbit, %x
%abs = xor <4 x i32> %signbit, %add
ret <4 x i32> %abs
}
define <4 x i32> @abs_cmpsubsel_vec(<4 x i32> %x) {
%cmp = icmp slt <4 x i32> %x, zeroinitializer
%sub = sub <4 x i32> zeroinitializer, %x
%abs = select <4 x i1> %cmp, <4 x i32> %sub, <4 x i32> %x
ret <4 x i32> %abs
}$ ./llc -o - -mattr=avx abs.ll
_abs_shifty:
movl %edi, %eax
sarl $31, %eax
addl %eax, %edi
xorl %eax, %edi
movl %edi, %eax
retq
_abs_cmpsubsel:
movl %edi, %eax
negl %eax
cmovll %edi, %eax
retq
.cfi_endproc
_abs_shifty_vec:
vpsrad $31, %xmm0, %xmm1
vpaddd %xmm0, %xmm1, %xmm0
vpxor %xmm0, %xmm1, %xmm0
retq
_abs_cmpsubsel_vec:
vpabsd %xmm0, %xmm0
retq