[llvm] 1e552d0 - [X86] Improve select of constants

Kazu Hirata via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 28 15:04:00 PST 2023


Author: Kazu Hirata
Date: 2023-02-28T14:58:22-08:00
New Revision: 1e552d0c5bf1627b92ac205cab07d3e09d911750

URL: https://github.com/llvm/llvm-project/commit/1e552d0c5bf1627b92ac205cab07d3e09d911750
DIFF: https://github.com/llvm/llvm-project/commit/1e552d0c5bf1627b92ac205cab07d3e09d911750.diff

LOG: [X86] Improve select of constants

Without this patch:

  %cmp = icmp eq i32 %a, %b
  %cond = select i1 %cmp, i32 1, i32 2

is compiled as:

  31 c9                      xor    %ecx,%ecx
  39 f7                      cmp    %esi,%edi
  0f 94 c1                   sete   %cl
  b8 02 00 00 00             mov    $0x2,%eax
  29 c8                      sub    %ecx,%eax

With this patch, the compiler generates:

  31 c0                      xor    %eax,%eax
  39 f7                      cmp    %esi,%edi
  0f 95 c0                   setne  %al
  ff c0                      inc    %eax

saving 5 bytes while reducing register usage.

This patch transforms C - setcc into inverted_setcc + (C-1) if C is a
nonzero constant.

This patch fixes:

https://github.com/llvm/llvm-project/issues/60854

Differential Revision: https://reviews.llvm.org/D144449

Added: 
    

Modified: 
    llvm/lib/Target/X86/X86ISelLowering.cpp
    llvm/test/CodeGen/X86/select-constant-xor.ll
    llvm/test/CodeGen/X86/select_const.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index abbc5ebb7108a..2ff62c2bba313 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -55560,6 +55560,33 @@ static SDValue combineSubABS(SDNode *N, SelectionDAG &DAG) {
   return DAG.getNode(ISD::ADD, DL, VT, N0, Cmov);
 }
 
+static SDValue combineSubSetcc(SDNode *N, SelectionDAG &DAG) {
+  SDValue Op0 = N->getOperand(0);
+  SDValue Op1 = N->getOperand(1);
+
+  // (sub C (zero_extend (setcc)))
+  // =>
+  // (add (zero_extend (setcc inverted) C-1))   if C is a nonzero immediate
+  // Don't disturb (sub 0 setcc), which is easily done with neg.
+  EVT VT = N->getValueType(0);
+  auto *Op0C = dyn_cast<ConstantSDNode>(Op0);
+  if (Op1.getOpcode() == ISD::ZERO_EXTEND && Op1.hasOneUse() && Op0C &&
+      !Op0C->isZero() && Op1.getOperand(0).getOpcode() == X86ISD::SETCC &&
+      Op1.getOperand(0).hasOneUse()) {
+    SDValue SetCC = Op1.getOperand(0);
+    X86::CondCode CC = (X86::CondCode)SetCC.getConstantOperandVal(0);
+    X86::CondCode NewCC = X86::GetOppositeBranchCondition(CC);
+    uint64_t NewImm = Op0C->getZExtValue() - 1;
+    SDLoc DL(Op1);
+    SDValue NewSetCC = getSETCC(NewCC, SetCC.getOperand(1), DL, DAG);
+    NewSetCC = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, NewSetCC);
+    return DAG.getNode(X86ISD::ADD, DL, DAG.getVTList(VT, VT), NewSetCC,
+                       DAG.getConstant(NewImm, DL, VT));
+  }
+
+  return SDValue();
+}
+
 static SDValue combineSub(SDNode *N, SelectionDAG &DAG,
                           TargetLowering::DAGCombinerInfo &DCI,
                           const X86Subtarget &Subtarget) {
@@ -55620,7 +55647,10 @@ static SDValue combineSub(SDNode *N, SelectionDAG &DAG,
   if (SDValue V = combineXorSubCTLZ(N, DAG, Subtarget))
     return V;
 
-  return combineAddOrSubToADCOrSBB(N, DAG);
+  if (SDValue V = combineAddOrSubToADCOrSBB(N, DAG))
+    return V;
+
+  return combineSubSetcc(N, DAG);
 }
 
 static SDValue combineVectorCompare(SDNode *N, SelectionDAG &DAG,

diff  --git a/llvm/test/CodeGen/X86/select-constant-xor.ll b/llvm/test/CodeGen/X86/select-constant-xor.ll
index 622e0ced843a4..efc367d204cf1 100644
--- a/llvm/test/CodeGen/X86/select-constant-xor.ll
+++ b/llvm/test/CodeGen/X86/select-constant-xor.ll
@@ -47,20 +47,18 @@ define i64 @selecti64i64(i64 %a) {
 define i32 @selecti64i32(i64 %a) {
 ; X86-LABEL: selecti64i32:
 ; X86:       # %bb.0:
-; X86-NEXT:    xorl %ecx, %ecx
+; X86-NEXT:    xorl %eax, %eax
 ; X86-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
-; X86-NEXT:    setns %cl
-; X86-NEXT:    movl $-2147483648, %eax # imm = 0x80000000
-; X86-NEXT:    subl %ecx, %eax
+; X86-NEXT:    sets %al
+; X86-NEXT:    addl $2147483647, %eax # imm = 0x7FFFFFFF
 ; X86-NEXT:    retl
 ;
 ; X64-LABEL: selecti64i32:
 ; X64:       # %bb.0:
-; X64-NEXT:    xorl %ecx, %ecx
+; X64-NEXT:    xorl %eax, %eax
 ; X64-NEXT:    testq %rdi, %rdi
-; X64-NEXT:    setns %cl
-; X64-NEXT:    movl $-2147483648, %eax # imm = 0x80000000
-; X64-NEXT:    subl %ecx, %eax
+; X64-NEXT:    sets %al
+; X64-NEXT:    addl $2147483647, %eax # imm = 0x7FFFFFFF
 ; X64-NEXT:    retq
   %c = icmp sgt i64 %a, -1
   %s = select i1 %c, i32 2147483647, i32 -2147483648

diff  --git a/llvm/test/CodeGen/X86/select_const.ll b/llvm/test/CodeGen/X86/select_const.ll
index 900dcd38951cf..dd054348ac014 100644
--- a/llvm/test/CodeGen/X86/select_const.ll
+++ b/llvm/test/CodeGen/X86/select_const.ll
@@ -1062,27 +1062,30 @@ define i32 @select_ugt3_3_2(i32 %X) {
 define i32 @select_eq_1_2(i32 %a, i32 %b) {
 ; X86-LABEL: select_eq_1_2:
 ; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    xorl %ecx, %ecx
-; X86-NEXT:    cmpl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    sete %cl
-; X86-NEXT:    movl $2, %eax
-; X86-NEXT:    subl %ecx, %eax
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    cmpl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    setne %al
+; X86-NEXT:    incl %eax
 ; X86-NEXT:    retl
 ;
-; X64-LABEL: select_eq_1_2:
-; X64:       # %bb.0:
-; X64-NEXT:    xorl %ecx, %ecx
-; X64-NEXT:    cmpl %esi, %edi
-; X64-NEXT:    sete %cl
-; X64-NEXT:    movl $2, %eax
-; X64-NEXT:    subl %ecx, %eax
-; X64-NEXT:    retq
+; X64-FASTINC-LABEL: select_eq_1_2:
+; X64-FASTINC:       # %bb.0:
+; X64-FASTINC-NEXT:    xorl %eax, %eax
+; X64-FASTINC-NEXT:    cmpl %esi, %edi
+; X64-FASTINC-NEXT:    setne %al
+; X64-FASTINC-NEXT:    incl %eax
+; X64-FASTINC-NEXT:    retq
+;
+; X64-SLOWINC-LABEL: select_eq_1_2:
+; X64-SLOWINC:       # %bb.0:
+; X64-SLOWINC-NEXT:    xorl %eax, %eax
+; X64-SLOWINC-NEXT:    cmpl %esi, %edi
+; X64-SLOWINC-NEXT:    setne %al
+; X64-SLOWINC-NEXT:    addl $1, %eax
+; X64-SLOWINC-NEXT:    retq
 
   %cmp = icmp eq i32 %a, %b
   %cond = select i1 %cmp, i32 1, i32 2
   ret i32 %cond
 }
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; X64-FASTINC: {{.*}}
-; X64-SLOWINC: {{.*}}


        


More information about the llvm-commits mailing list