[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