From: Noah Goldstein Date: Tue, 14 Feb 2023 01:40:18 +0000 (-0600) Subject: Transform `(icmp eq/ne Abs(A), Pow2)` -> `(and/or (icmp eq/ne A,Pow2), (icmp eq/ne... X-Git-Tag: upstream/17.0.6~17491 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8b5c3902475b3c23ea87e58bc87541f543782e54;p=platform%2Fupstream%2Fllvm.git Transform `(icmp eq/ne Abs(A), Pow2)` -> `(and/or (icmp eq/ne A,Pow2), (icmp eq/ne A,-Pow2))` Only if Abs(A) has one use, in which case the `(and/or (icmp eq/ne A,Pow2), (icmp eq/ne A,-Pow2))` can be optimized in `DAGCombiner::foldAndOrOfSETCC`. Alive Links: EQ: https://alive2.llvm.org/ce/z/gTxSgV NE: https://alive2.llvm.org/ce/z/MUf57Y Reviewed By: RKSimon Differential Revision: https://reviews.llvm.org/D142345 --- diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 792e7c6..db6dd99 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -53991,6 +53991,29 @@ static SDValue combineSetCC(SDNode *N, SelectionDAG &DAG, return DAG.getSetCC(DL, VT, LHS.getOperand(0), DAG.getConstant(0, DL, SrcVT), CC); } + + // With C as a power of 2 and C != 0 and C != INT_MIN: + // icmp eq Abs(X) C -> + // (icmp eq A, C) | (icmp eq A, -C) + // icmp ne Abs(X) C -> + // (icmp ne A, C) & (icmp ne A, -C) + // Both of these patterns can be better optimized in + // DAGCombiner::foldAndOrOfSETCC. Note this only applies for scalar + // integers which is checked above. + if (LHS.getOpcode() == ISD::ABS && LHS.hasOneUse()) { + if (auto *C = dyn_cast(RHS)) { + const APInt &CInt = C->getAPIntValue(); + // We can better optimize this case in DAGCombiner::foldAndOrOfSETCC. + if (CInt.isPowerOf2() && !CInt.isMinSignedValue()) { + SDValue BaseOp = LHS.getOperand(0); + SDValue SETCC0 = DAG.getSetCC(DL, VT, BaseOp, RHS, CC); + SDValue SETCC1 = DAG.getSetCC( + DL, VT, BaseOp, DAG.getConstant(-CInt, DL, OpVT), CC); + return DAG.getNode(CC == ISD::SETEQ ? ISD::OR : ISD::AND, DL, VT, + SETCC0, SETCC1); + } + } + } } } diff --git a/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll b/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll index 5a0c8e9..df1cfb8 100644 --- a/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll +++ b/llvm/test/CodeGen/X86/icmp-pow2-logic-npow2.ll @@ -154,20 +154,15 @@ define i1 @abs_eq_pow2(i32 %0) nounwind { ; X86-LABEL: abs_eq_pow2: ; 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: subl %ecx, %eax -; X86-NEXT: cmpl $4, %eax +; X86-NEXT: addl $4, %eax +; X86-NEXT: testl $-9, %eax ; X86-NEXT: sete %al ; X86-NEXT: retl ; ; X64-LABEL: abs_eq_pow2: ; X64: # %bb.0: -; X64-NEXT: movl %edi, %eax -; X64-NEXT: negl %eax -; X64-NEXT: cmovsl %edi, %eax -; X64-NEXT: cmpl $4, %eax +; X64-NEXT: addl $4, %edi +; X64-NEXT: testl $-9, %edi ; X64-NEXT: sete %al ; X64-NEXT: retq %2 = tail call i32 @llvm.abs.i32(i32 %0, i1 true) @@ -179,24 +174,18 @@ define i1 @abs_ne_pow2(i64 %0) nounwind { ; X86-LABEL: abs_ne_pow2: ; 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), %edx -; X86-NEXT: xorl %ecx, %edx -; X86-NEXT: subl %ecx, %edx -; X86-NEXT: sbbl %ecx, %eax -; X86-NEXT: xorl $2, %edx -; X86-NEXT: orl %eax, %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: addl $2, %eax +; X86-NEXT: adcl $0, %ecx +; X86-NEXT: andl $-5, %eax +; X86-NEXT: orl %ecx, %eax ; X86-NEXT: setne %al ; X86-NEXT: retl ; ; X64-LABEL: abs_ne_pow2: ; X64: # %bb.0: -; X64-NEXT: movq %rdi, %rax -; X64-NEXT: negq %rax -; X64-NEXT: cmovsq %rdi, %rax -; X64-NEXT: cmpq $2, %rax +; X64-NEXT: addq $2, %rdi +; X64-NEXT: testq $-5, %rdi ; X64-NEXT: setne %al ; X64-NEXT: retq %2 = tail call i64 @llvm.abs.i64(i64 %0, i1 true)