diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index f722a0b57a506..05d0d5f964a83 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -396,9 +396,14 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, setOperationAction(ISD::CTLZ, MVT::i32, Expand); } - if (!RV64LegalI32 && Subtarget.is64Bit()) + if (!RV64LegalI32 && Subtarget.is64Bit() && + !Subtarget.hasShortForwardBranchOpt()) setOperationAction(ISD::ABS, MVT::i32, Custom); + // We can use PseudoCCSUB to implement ABS. + if (Subtarget.hasShortForwardBranchOpt()) + setOperationAction(ISD::ABS, XLenVT, Legal); + if (!Subtarget.hasVendorXTHeadCondMov()) setOperationAction(ISD::SELECT, XLenVT, Custom); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index af34e026bed14..0f1d1d4cb23ce 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1242,6 +1242,10 @@ def anyext_oneuse : unop_oneuse; def ext_oneuse : unop_oneuse; def fpext_oneuse : unop_oneuse; +def 33signbits_node : PatLeaf<(i64 GPR:$src), [{ + return CurDAG->ComputeNumSignBits(SDValue(N, 0)) > 32; +}]>; + /// Simple arithmetic operations def : PatGprGpr; @@ -2002,6 +2006,15 @@ def : Pat<(binop_allwusers GPR:$rs1, (AddiPair:$rs2)), (AddiPairImmSmall AddiPair:$rs2))>; } +let Predicates = [HasShortForwardBranchOpt] in +def : Pat<(XLenVT (abs GPR:$rs1)), + (PseudoCCSUB (XLenVT GPR:$rs1), (XLenVT X0), /* COND_LT */ 2, + (XLenVT GPR:$rs1), (XLenVT X0), (XLenVT GPR:$rs1))>; +let Predicates = [HasShortForwardBranchOpt, IsRV64] in +def : Pat<(sext_inreg (abs 33signbits_node:$rs1), i32), + (PseudoCCSUBW (i64 GPR:$rs1), (i64 X0), /* COND_LT */ 2, + (XLenVT GPR:$rs1), (i64 X0), (i64 GPR:$rs1))>; + //===----------------------------------------------------------------------===// // Experimental RV64 i32 legalization patterns. //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll b/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll index 553bda6ff6733..725b8fd6eeea6 100644 --- a/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll +++ b/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll @@ -1458,3 +1458,81 @@ entry: %1 = select i1 %cond, i32 %C, i32 %0 ret i32 %1 } + +define signext i32 @abs_i32(i32 signext %x) { +; NOSFB-LABEL: abs_i32: +; NOSFB: # %bb.0: +; NOSFB-NEXT: sraiw a1, a0, 31 +; NOSFB-NEXT: xor a0, a0, a1 +; NOSFB-NEXT: subw a0, a0, a1 +; NOSFB-NEXT: ret +; +; RV64SFB-LABEL: abs_i32: +; RV64SFB: # %bb.0: +; RV64SFB-NEXT: bgez a0, .LBB34_2 +; RV64SFB-NEXT: # %bb.1: +; RV64SFB-NEXT: negw a0, a0 +; RV64SFB-NEXT: .LBB34_2: +; RV64SFB-NEXT: ret +; +; ZICOND-LABEL: abs_i32: +; ZICOND: # %bb.0: +; ZICOND-NEXT: bgez a0, .LBB34_2 +; ZICOND-NEXT: # %bb.1: +; ZICOND-NEXT: negw a0, a0 +; ZICOND-NEXT: .LBB34_2: +; ZICOND-NEXT: ret +; +; RV32SFB-LABEL: abs_i32: +; RV32SFB: # %bb.0: +; RV32SFB-NEXT: bgez a0, .LBB34_2 +; RV32SFB-NEXT: # %bb.1: +; RV32SFB-NEXT: neg a0, a0 +; RV32SFB-NEXT: .LBB34_2: +; RV32SFB-NEXT: ret + %a = call i32 @llvm.abs.i32(i32 %x, i1 false) + ret i32 %a +} +declare i32 @llvm.abs.i32(i32, i1) + +define i64 @abs_i64(i64 %x) { +; NOSFB-LABEL: abs_i64: +; NOSFB: # %bb.0: +; NOSFB-NEXT: srai a1, a0, 63 +; NOSFB-NEXT: xor a0, a0, a1 +; NOSFB-NEXT: sub a0, a0, a1 +; NOSFB-NEXT: ret +; +; RV64SFB-LABEL: abs_i64: +; RV64SFB: # %bb.0: +; RV64SFB-NEXT: bgez a0, .LBB35_2 +; RV64SFB-NEXT: # %bb.1: +; RV64SFB-NEXT: neg a0, a0 +; RV64SFB-NEXT: .LBB35_2: +; RV64SFB-NEXT: ret +; +; ZICOND-LABEL: abs_i64: +; ZICOND: # %bb.0: +; ZICOND-NEXT: bgez a0, .LBB35_2 +; ZICOND-NEXT: # %bb.1: +; ZICOND-NEXT: neg a0, a0 +; ZICOND-NEXT: .LBB35_2: +; ZICOND-NEXT: ret +; +; RV32SFB-LABEL: abs_i64: +; RV32SFB: # %bb.0: +; RV32SFB-NEXT: snez a2, a0 +; RV32SFB-NEXT: add a2, a2, a1 +; RV32SFB-NEXT: bgez a1, .LBB35_2 +; RV32SFB-NEXT: # %bb.1: +; RV32SFB-NEXT: neg a0, a0 +; RV32SFB-NEXT: .LBB35_2: +; RV32SFB-NEXT: bgez a1, .LBB35_4 +; RV32SFB-NEXT: # %bb.3: +; RV32SFB-NEXT: neg a1, a2 +; RV32SFB-NEXT: .LBB35_4: +; RV32SFB-NEXT: ret + %a = call i64 @llvm.abs.i64(i64 %x, i1 false) + ret i64 %a +} +declare i64 @llvm.abs.i64(i64, i1)