forked from OSchip/llvm-project
[RISCV] With Zbb, fold (sext_inreg (abs X)) -> (max X, (negw X))
With Zbb, abs is expanded to (max X, neg) by default. If X has 33 or more sign bits, we can expand it a little early using negw instead of neg to save a sext_inreg. If X started as a 32 bit value, type legalization would have inserted a sext before the abs so X having 33 sign bits should always be true. Note: I've used ISD::FREEZE here since we increase the number of uses. Our default expansion for ABS doesn't do that, but I think that's a bug. We can't do this with custom type legalization because ISD::FREEZE doesn't propagate sign bits so later DAG combine won't expand be able to see optmize it. Alives2 https://alive2.llvm.org/ce/z/Gx3RNe Reviewed By: spatel Differential Revision: https://reviews.llvm.org/D120597
This commit is contained in:
parent
b4c1cbff79
commit
3d4e83f17d
|
@ -1041,7 +1041,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
|
|||
}
|
||||
setTargetDAGCombine(ISD::ANY_EXTEND);
|
||||
setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);
|
||||
if (Subtarget.hasStdExtZfh())
|
||||
if (Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZbb())
|
||||
setTargetDAGCombine(ISD::SIGN_EXTEND_INREG);
|
||||
if (Subtarget.hasStdExtF()) {
|
||||
setTargetDAGCombine(ISD::ZERO_EXTEND);
|
||||
|
@ -7617,15 +7617,43 @@ static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG) {
|
|||
return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false);
|
||||
}
|
||||
|
||||
static SDValue performSIGN_EXTEND_INREG(SDNode *N, SelectionDAG &DAG) {
|
||||
static SDValue
|
||||
performSIGN_EXTEND_INREGCombine(SDNode *N, SelectionDAG &DAG,
|
||||
const RISCVSubtarget &Subtarget) {
|
||||
SDValue Src = N->getOperand(0);
|
||||
EVT VT = N->getValueType(0);
|
||||
|
||||
// Fold (sext_inreg (fmv_x_anyexth X), i16) -> (fmv_x_signexth X)
|
||||
if (Src.getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
|
||||
cast<VTSDNode>(N->getOperand(1))->getVT().bitsGE(MVT::i16))
|
||||
return DAG.getNode(RISCVISD::FMV_X_SIGNEXTH, SDLoc(N), N->getValueType(0),
|
||||
return DAG.getNode(RISCVISD::FMV_X_SIGNEXTH, SDLoc(N), VT,
|
||||
Src.getOperand(0));
|
||||
|
||||
// Fold (i64 (sext_inreg (abs X), i32)) ->
|
||||
// (i64 (smax (sext_inreg (neg X), i32), X)) if X has more than 32 sign bits.
|
||||
// The (sext_inreg (neg X), i32) will be selected to negw by isel. This
|
||||
// pattern occurs after type legalization of (i32 (abs X)) on RV64 if the user
|
||||
// of the (i32 (abs X)) is a sext or setcc or something else that causes type
|
||||
// legalization to add a sext_inreg after the abs. The (i32 (abs X)) will have
|
||||
// been type legalized to (i64 (abs (sext_inreg X, i32))), but the sext_inreg
|
||||
// may get combined into an earlier operation so we need to use
|
||||
// ComputeNumSignBits.
|
||||
// NOTE: (i64 (sext_inreg (abs X), i32)) can also be created for
|
||||
// (i64 (ashr (shl (abs X), 32), 32)) without any type legalization so
|
||||
// we can't assume that X has 33 sign bits. We must check.
|
||||
if (Subtarget.hasStdExtZbb() && Subtarget.is64Bit() &&
|
||||
Src.getOpcode() == ISD::ABS && Src.hasOneUse() && VT == MVT::i64 &&
|
||||
cast<VTSDNode>(N->getOperand(1))->getVT() == MVT::i32 &&
|
||||
DAG.ComputeNumSignBits(Src.getOperand(0)) > 32) {
|
||||
SDLoc DL(N);
|
||||
SDValue Freeze = DAG.getFreeze(Src.getOperand(0));
|
||||
SDValue Neg =
|
||||
DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, MVT::i64), Freeze);
|
||||
Neg = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, Neg,
|
||||
DAG.getValueType(MVT::i32));
|
||||
return DAG.getNode(ISD::SMAX, DL, MVT::i64, Freeze, Neg);
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
|
@ -8244,7 +8272,7 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
|
|||
case ISD::XOR:
|
||||
return performXORCombine(N, DAG);
|
||||
case ISD::SIGN_EXTEND_INREG:
|
||||
return performSIGN_EXTEND_INREG(N, DAG);
|
||||
return performSIGN_EXTEND_INREGCombine(N, DAG, Subtarget);
|
||||
case ISD::ANY_EXTEND:
|
||||
return performANY_EXTENDCombine(N, DCI, Subtarget);
|
||||
case ISD::ZERO_EXTEND:
|
||||
|
|
|
@ -960,7 +960,6 @@ define i32 @abs_i32(i32 %x) {
|
|||
ret i32 %abs
|
||||
}
|
||||
|
||||
; FIXME: We can remove the sext.w on RV64ZBB by using negw.
|
||||
define signext i32 @abs_i32_sext(i32 signext %x) {
|
||||
; RV64I-LABEL: abs_i32_sext:
|
||||
; RV64I: # %bb.0:
|
||||
|
@ -971,9 +970,8 @@ define signext i32 @abs_i32_sext(i32 signext %x) {
|
|||
;
|
||||
; RV64ZBB-LABEL: abs_i32_sext:
|
||||
; RV64ZBB: # %bb.0:
|
||||
; RV64ZBB-NEXT: neg a1, a0
|
||||
; RV64ZBB-NEXT: negw a1, a0
|
||||
; RV64ZBB-NEXT: max a0, a0, a1
|
||||
; RV64ZBB-NEXT: sext.w a0, a0
|
||||
; RV64ZBB-NEXT: ret
|
||||
%abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
|
||||
ret i32 %abs
|
||||
|
|
Loading…
Reference in New Issue