diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10092,6 +10092,21 @@ if (SDValue ABD = combineABSToABD(N, DAG, TLI)) return ABD; + // fold (abs (sign_extend_inreg x)) -> (zero_extend (abs (truncate x))) + // iff zero_extend/truncate are free. + if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG) { + EVT ExtVT = cast(N0.getOperand(1))->getVT(); + if (TLI.isTruncateFree(VT, ExtVT) && TLI.isZExtFree(ExtVT, VT) && + TLI.isTypeDesirableForOp(ISD::ABS, ExtVT) && + hasOperation(ISD::ABS, ExtVT)) { + SDLoc DL(N); + return DAG.getNode( + ISD::ZERO_EXTEND, DL, VT, + DAG.getNode(ISD::ABS, DL, ExtVT, + DAG.getNode(ISD::TRUNCATE, DL, ExtVT, N0.getOperand(0)))); + } + } + return SDValue(); } diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -3278,6 +3278,14 @@ GetExpandedInteger(N0, Lo, Hi); EVT NVT = Lo.getValueType(); + // If the upper half is all sign bits, then we can perform the ABS on the + // lower half and zero-extend. + if (DAG.ComputeNumSignBits(N0) > NVT.getScalarSizeInBits()) { + Lo = DAG.getNode(ISD::ABS, dl, NVT, Lo); + Hi = DAG.getConstant(0, dl, NVT); + return; + } + // If we have SUBCARRY, use the expanded form of the sra+xor+sub sequence we // use in LegalizeDAG. The SUB part of the expansion is based on // ExpandIntRes_ADDSUB which also uses SUBCARRY/USUBO after checking that diff --git a/llvm/test/CodeGen/X86/abs.ll b/llvm/test/CodeGen/X86/abs.ll --- a/llvm/test/CodeGen/X86/abs.ll +++ b/llvm/test/CodeGen/X86/abs.ll @@ -659,21 +659,18 @@ define i64 @test_sextinreg_i64(i64 %a) nounwind { ; X64-LABEL: test_sextinreg_i64: ; X64: # %bb.0: -; X64-NEXT: movslq %edi, %rcx -; X64-NEXT: movq %rcx, %rax -; X64-NEXT: negq %rax -; X64-NEXT: cmovsq %rcx, %rax +; X64-NEXT: movl %edi, %eax +; X64-NEXT: negl %eax +; X64-NEXT: cmovsl %edi, %eax ; X64-NEXT: retq ; ; X86-LABEL: test_sextinreg_i64: ; X86: # %bb.0: -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %eax, %ecx -; X86-NEXT: sarl $31, %ecx -; X86-NEXT: xorl %ecx, %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: negl %eax +; X86-NEXT: cmovsl %ecx, %eax ; X86-NEXT: xorl %edx, %edx -; X86-NEXT: subl %ecx, %eax -; X86-NEXT: sbbl %ecx, %edx ; X86-NEXT: retl %shl = shl i64 %a, 32 %ashr = ashr exact i64 %shl, 32 @@ -685,18 +682,13 @@ ; X64-LABEL: test_sextinreg_i128: ; X64: # %bb.0: ; X64-NEXT: movq %rdi, %rax -; X64-NEXT: movq %rdi, %rcx -; X64-NEXT: sarq $63, %rcx -; X64-NEXT: xorq %rcx, %rax +; X64-NEXT: negq %rax +; X64-NEXT: cmovsq %rdi, %rax ; X64-NEXT: xorl %edx, %edx -; X64-NEXT: subq %rcx, %rax -; X64-NEXT: sbbq %rcx, %rdx ; X64-NEXT: retq ; ; X86-LABEL: test_sextinreg_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx @@ -705,19 +697,13 @@ ; X86-NEXT: xorl %edx, %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi ; X86-NEXT: xorl %edx, %esi -; X86-NEXT: xorl %edi, %edi ; X86-NEXT: subl %edx, %esi ; X86-NEXT: sbbl %edx, %ecx -; X86-NEXT: movl $0, %ebx -; X86-NEXT: sbbl %edx, %ebx -; X86-NEXT: sbbl %edx, %edi ; X86-NEXT: movl %esi, (%eax) ; X86-NEXT: movl %ecx, 4(%eax) -; X86-NEXT: movl %ebx, 8(%eax) -; X86-NEXT: movl %edi, 12(%eax) +; X86-NEXT: movl $0, 12(%eax) +; X86-NEXT: movl $0, 8(%eax) ; X86-NEXT: popl %esi -; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx ; X86-NEXT: retl $4 %shl = shl i128 %a, 64 %ashr = ashr exact i128 %shl, 64