[PATCH] D144449: [X86] Improve select of constants

Kazu Hirata via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 20 23:14:04 PST 2023


kazu created this revision.
Herald added subscribers: pengfei, hiraditya.
Herald added a project: All.
kazu requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D144449

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


Index: llvm/test/CodeGen/X86/select_const.ll
===================================================================
--- llvm/test/CodeGen/X86/select_const.ll
+++ llvm/test/CodeGen/X86/select_const.ll
@@ -584,11 +584,10 @@
 define i32 @select_eq_1_2(i32 %a, i32 %b) {
 ; CHECK-LABEL: select_eq_1_2:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    xorl %eax, %eax
 ; CHECK-NEXT:    cmpl %esi, %edi
-; CHECK-NEXT:    sete %cl
-; CHECK-NEXT:    movl $2, %eax
-; CHECK-NEXT:    subl %ecx, %eax
+; CHECK-NEXT:    setne %al
+; CHECK-NEXT:    incl %eax
 ; CHECK-NEXT:    retq
 
   %cmp = icmp eq i32 %a, %b
Index: llvm/test/CodeGen/X86/select-constant-xor.ll
===================================================================
--- llvm/test/CodeGen/X86/select-constant-xor.ll
+++ llvm/test/CodeGen/X86/select-constant-xor.ll
@@ -30,11 +30,10 @@
 define i32 @selecti64i32(i64 %a) {
 ; CHECK-LABEL: selecti64i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    xorl %eax, %eax
 ; CHECK-NEXT:    testq %rdi, %rdi
-; CHECK-NEXT:    setns %cl
-; CHECK-NEXT:    movl $-2147483648, %eax # imm = 0x80000000
-; CHECK-NEXT:    subl %ecx, %eax
+; CHECK-NEXT:    sets %al
+; CHECK-NEXT:    addl $2147483647, %eax # imm = 0x7FFFFFFF
 ; CHECK-NEXT:    retq
   %c = icmp sgt i64 %a, -1
   %s = select i1 %c, i32 2147483647, i32 -2147483648
Index: llvm/lib/Target/X86/X86ISelLowering.cpp
===================================================================
--- llvm/lib/Target/X86/X86ISelLowering.cpp
+++ llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -55480,6 +55480,33 @@
   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) {
@@ -55540,7 +55567,10 @@
   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,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D144449.499044.patch
Type: text/x-patch
Size: 3297 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230221/d655b53f/attachment.bin>


More information about the llvm-commits mailing list