[llvm] 0b02752 - [RISCV] Optimize (seteq (i64 (and X, 0xffffffff)), C1)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 18 10:55:16 PDT 2022
Author: Craig Topper
Date: 2022-07-18T10:54:45-07:00
New Revision: 0b0275289961dd49315bcb3b8dfcae5687f23eaa
URL: https://github.com/llvm/llvm-project/commit/0b0275289961dd49315bcb3b8dfcae5687f23eaa
DIFF: https://github.com/llvm/llvm-project/commit/0b0275289961dd49315bcb3b8dfcae5687f23eaa.diff
LOG: [RISCV] Optimize (seteq (i64 (and X, 0xffffffff)), C1)
(and X, 0xffffffff) requires 2 shifts in the base ISA. Since we
know the result is being used by a compare, we can use a sext_inreg
instead of an AND if we also modify C1 to have 33 sign bits instead
of 32 leading zeros. This can also improve the generated code for
materializing C1.
Reviewed By: reames
Differential Revision: https://reviews.llvm.org/D129980
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/test/CodeGen/RISCV/i64-icmp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 04833f594c74..3fcc8c344ac1 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -934,7 +934,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setJumpIsExpensive();
setTargetDAGCombine({ISD::INTRINSIC_WO_CHAIN, ISD::ADD, ISD::SUB, ISD::AND,
- ISD::OR, ISD::XOR});
+ ISD::OR, ISD::XOR, ISD::SETCC});
if (Subtarget.is64Bit())
setTargetDAGCombine(ISD::SRA);
@@ -8118,6 +8118,50 @@ static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG) {
return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false);
}
+// Replace (seteq (i64 (and X, 0xffffffff)), C1) with
+// (seteq (i64 (sext_inreg (X, i32)), C1')) where C1' is C1 sign extended from
+// bit 31. Same for setne. C1' may be cheaper to materialize and the sext_inreg
+// can become a sext.w instead of a shift pair.
+static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG,
+ const RISCVSubtarget &Subtarget) {
+ SDValue N0 = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+ EVT VT = N->getValueType(0);
+ EVT OpVT = N0.getValueType();
+
+ if (OpVT != MVT::i64 || !Subtarget.is64Bit())
+ return SDValue();
+
+ // RHS needs to be a constant.
+ auto *N1C = dyn_cast<ConstantSDNode>(N1);
+ if (!N1C)
+ return SDValue();
+
+ // LHS needs to be (and X, 0xffffffff).
+ if (N0.getOpcode() != ISD::AND || !N0.hasOneUse() ||
+ !isa<ConstantSDNode>(N0.getOperand(1)) ||
+ N0.getConstantOperandVal(1) != UINT64_C(0xffffffff))
+ return SDValue();
+
+ // Looking for an equality compare.
+ ISD::CondCode Cond = cast<CondCodeSDNode>(N->getOperand(2))->get();
+ if (!isIntEqualitySetCC(Cond))
+ return SDValue();
+
+ const APInt &C1 = cast<ConstantSDNode>(N1)->getAPIntValue();
+
+ SDLoc dl(N);
+ // If the constant is larger than 2^32 - 1 it is impossible for both sides
+ // to be equal.
+ if (C1.getActiveBits() > 32)
+ return DAG.getBoolConstant(Cond == ISD::SETNE, dl, VT, OpVT);
+
+ SDValue SExtOp = DAG.getNode(ISD::SIGN_EXTEND_INREG, N, OpVT,
+ N0.getOperand(0), DAG.getValueType(MVT::i32));
+ return DAG.getSetCC(dl, VT, SExtOp, DAG.getConstant(C1.trunc(32).sext(64),
+ dl, OpVT), Cond);
+}
+
static SDValue
performSIGN_EXTEND_INREGCombine(SDNode *N, SelectionDAG &DAG,
const RISCVSubtarget &Subtarget) {
@@ -8860,6 +8904,8 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
case ISD::FMAXNUM:
case ISD::FMINNUM:
return combineBinOpToReduce(N, DAG);
+ case ISD::SETCC:
+ return performSETCCCombine(N, DAG, Subtarget);
case ISD::SIGN_EXTEND_INREG:
return performSIGN_EXTEND_INREGCombine(N, DAG, Subtarget);
case ISD::ZERO_EXTEND:
diff --git a/llvm/test/CodeGen/RISCV/i64-icmp.ll b/llvm/test/CodeGen/RISCV/i64-icmp.ll
index 2e5b44e8ec94..503a4f1aff87 100644
--- a/llvm/test/CodeGen/RISCV/i64-icmp.ll
+++ b/llvm/test/CodeGen/RISCV/i64-icmp.ll
@@ -689,8 +689,7 @@ define i64 @icmp_sle_constant_neg_2050(i64 %a) nounwind {
define i64 @icmp_eq_zext_inreg_small_constant(i64 %a) nounwind {
; RV64I-LABEL: icmp_eq_zext_inreg_small_constant:
; RV64I: # %bb.0:
-; RV64I-NEXT: slli a0, a0, 32
-; RV64I-NEXT: srli a0, a0, 32
+; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: addi a0, a0, -123
; RV64I-NEXT: seqz a0, a0
; RV64I-NEXT: ret
@@ -703,12 +702,9 @@ define i64 @icmp_eq_zext_inreg_small_constant(i64 %a) nounwind {
define i64 @icmp_eq_zext_inreg_large_constant(i64 %a) nounwind {
; RV64I-LABEL: icmp_eq_zext_inreg_large_constant:
; RV64I: # %bb.0:
-; RV64I-NEXT: slli a0, a0, 32
-; RV64I-NEXT: srli a0, a0, 32
-; RV64I-NEXT: lui a1, 138
-; RV64I-NEXT: addiw a1, a1, -1347
-; RV64I-NEXT: slli a1, a1, 12
-; RV64I-NEXT: addi a1, a1, -529
+; RV64I-NEXT: sext.w a0, a0
+; RV64I-NEXT: lui a1, 563901
+; RV64I-NEXT: addiw a1, a1, -529
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: seqz a0, a0
; RV64I-NEXT: ret
@@ -721,8 +717,7 @@ define i64 @icmp_eq_zext_inreg_large_constant(i64 %a) nounwind {
define i64 @icmp_ne_zext_inreg_small_constant(i64 %a) nounwind {
; RV64I-LABEL: icmp_ne_zext_inreg_small_constant:
; RV64I: # %bb.0:
-; RV64I-NEXT: slli a0, a0, 32
-; RV64I-NEXT: srli a0, a0, 32
+; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: snez a0, a0
; RV64I-NEXT: ret
%1 = and i64 %a, 4294967295
@@ -734,12 +729,8 @@ define i64 @icmp_ne_zext_inreg_small_constant(i64 %a) nounwind {
define i64 @icmp_ne_zext_inreg_large_constant(i64 %a) nounwind {
; RV64I-LABEL: icmp_ne_zext_inreg_large_constant:
; RV64I: # %bb.0:
-; RV64I-NEXT: slli a0, a0, 32
-; RV64I-NEXT: srli a0, a0, 32
-; RV64I-NEXT: li a1, 1
-; RV64I-NEXT: slli a1, a1, 32
-; RV64I-NEXT: addi a1, a1, -2
-; RV64I-NEXT: xor a0, a0, a1
+; RV64I-NEXT: sext.w a0, a0
+; RV64I-NEXT: addi a0, a0, 2
; RV64I-NEXT: snez a0, a0
; RV64I-NEXT: ret
%1 = and i64 %a, 4294967295
More information about the llvm-commits
mailing list