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