Skip to content

Commit

Permalink
[RISCV] Use short forward branch for ISD::ABS.
Browse files Browse the repository at this point in the history
We can use short forward branch to conditionally negate if the
value is negative.
  • Loading branch information
topperc committed Nov 21, 2023
1 parent ce61274 commit 7a6fd49
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 1 deletion.
7 changes: 6 additions & 1 deletion llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,10 @@ def anyext_oneuse : unop_oneuse<anyext>;
def ext_oneuse : unop_oneuse<ext>;
def fpext_oneuse : unop_oneuse<any_fpextend>;

def 33signbits_node : PatLeaf<(i64 GPR:$src), [{
return CurDAG->ComputeNumSignBits(SDValue(N, 0)) > 32;
}]>;

/// Simple arithmetic operations

def : PatGprGpr<add, ADD>;
Expand Down Expand Up @@ -2002,6 +2006,15 @@ def : Pat<(binop_allwusers<add> 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.
//===----------------------------------------------------------------------===//
Expand Down
78 changes: 78 additions & 0 deletions llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit 7a6fd49

Please sign in to comment.