Skip to content

Commit

Permalink
[RISCV] Use branchless form for selects with 0 in either arm
Browse files Browse the repository at this point in the history
Continuing the theme of adding branchless lowerings for simple selects, this time handle the 0 arm case. This is very common for various umin idioms, etc..

Differential Revision: https://reviews.llvm.org/D135600
  • Loading branch information
preames committed Oct 12, 2022
1 parent b404a1b commit 1c41d0c
Show file tree
Hide file tree
Showing 101 changed files with 8,889 additions and 10,784 deletions.
15 changes: 15 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9494,6 +9494,21 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
return DAG.getNode(ISD::OR, DL, VT, Neg, TrueV);
}

// (select c, 0, y) -> -!c & y
if (isNullConstant(TrueV)) {
SDValue C = DAG.getSetCC(DL, VT, LHS, RHS,
ISD::getSetCCInverse(CCVal, VT));
SDValue Neg = DAG.getNegative(C, DL, VT);
return DAG.getNode(ISD::AND, DL, VT, Neg, FalseV);
}
// (select c, y, 0) -> -c & y
if (isNullConstant(FalseV)) {
SDValue C = DAG.getSetCC(DL, VT, LHS, RHS, CCVal);
SDValue Neg = DAG.getNegative(C, DL, VT);
return DAG.getNode(ISD::AND, DL, VT, Neg, TrueV);
}


return SDValue();
}
case RISCVISD::BR_CC: {
Expand Down
39 changes: 21 additions & 18 deletions llvm/test/CodeGen/RISCV/alu64.ll
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,10 @@ define i64 @sltiu(i64 %a) nounwind {
;
; RV32I-LABEL: sltiu:
; RV32I: # %bb.0:
; RV32I-NEXT: beqz a1, .LBB2_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: li a0, 0
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: ret
; RV32I-NEXT: .LBB2_2:
; RV32I-NEXT: sltiu a0, a0, 3
; RV32I-NEXT: snez a1, a1
; RV32I-NEXT: addi a1, a1, -1
; RV32I-NEXT: and a0, a1, a0
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: ret
%1 = icmp ult i64 %a, 3
Expand Down Expand Up @@ -215,15 +212,18 @@ define i64 @sll(i64 %a, i64 %b) nounwind {
; RV32I-NEXT: bltz a3, .LBB11_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: sll a1, a0, a3
; RV32I-NEXT: li a0, 0
; RV32I-NEXT: ret
; RV32I-NEXT: j .LBB11_3
; RV32I-NEXT: .LBB11_2:
; RV32I-NEXT: sll a1, a1, a2
; RV32I-NEXT: xori a3, a2, 31
; RV32I-NEXT: srli a4, a0, 1
; RV32I-NEXT: srl a3, a4, a3
; RV32I-NEXT: or a1, a1, a3
; RV32I-NEXT: xori a4, a2, 31
; RV32I-NEXT: srli a5, a0, 1
; RV32I-NEXT: srl a4, a5, a4
; RV32I-NEXT: or a1, a1, a4
; RV32I-NEXT: .LBB11_3:
; RV32I-NEXT: sll a0, a0, a2
; RV32I-NEXT: slti a2, a3, 0
; RV32I-NEXT: neg a2, a2
; RV32I-NEXT: and a0, a2, a0
; RV32I-NEXT: ret
%1 = shl i64 %a, %b
ret i64 %1
Expand Down Expand Up @@ -300,15 +300,18 @@ define i64 @srl(i64 %a, i64 %b) nounwind {
; RV32I-NEXT: bltz a3, .LBB15_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: srl a0, a1, a3
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: ret
; RV32I-NEXT: j .LBB15_3
; RV32I-NEXT: .LBB15_2:
; RV32I-NEXT: srl a0, a0, a2
; RV32I-NEXT: xori a3, a2, 31
; RV32I-NEXT: slli a4, a1, 1
; RV32I-NEXT: sll a3, a4, a3
; RV32I-NEXT: or a0, a0, a3
; RV32I-NEXT: xori a4, a2, 31
; RV32I-NEXT: slli a5, a1, 1
; RV32I-NEXT: sll a4, a5, a4
; RV32I-NEXT: or a0, a0, a4
; RV32I-NEXT: .LBB15_3:
; RV32I-NEXT: srl a1, a1, a2
; RV32I-NEXT: slti a2, a3, 0
; RV32I-NEXT: neg a2, a2
; RV32I-NEXT: and a1, a2, a1
; RV32I-NEXT: ret
%1 = lshr i64 %a, %b
ret i64 %1
Expand Down
24 changes: 10 additions & 14 deletions llvm/test/CodeGen/RISCV/bittest.ll
Original file line number Diff line number Diff line change
Expand Up @@ -296,15 +296,13 @@ define i1 @bittest_constant_by_var_shl_i32(i32 signext %b) nounwind {
define i1 @bittest_constant_by_var_shr_i64(i64 %b) nounwind {
; RV32-LABEL: bittest_constant_by_var_shr_i64:
; RV32: # %bb.0:
; RV32-NEXT: addi a1, a0, -32
; RV32-NEXT: bltz a1, .LBB12_2
; RV32-NEXT: # %bb.1:
; RV32-NEXT: andi a0, zero, 1
; RV32-NEXT: ret
; RV32-NEXT: .LBB12_2:
; RV32-NEXT: lui a1, 301408
; RV32-NEXT: addi a1, a1, 722
; RV32-NEXT: srl a0, a1, a0
; RV32-NEXT: srl a1, a1, a0
; RV32-NEXT: addi a0, a0, -32
; RV32-NEXT: slti a0, a0, 0
; RV32-NEXT: neg a0, a0
; RV32-NEXT: and a0, a0, a1
; RV32-NEXT: andi a0, a0, 1
; RV32-NEXT: ret
;
Expand Down Expand Up @@ -332,15 +330,13 @@ define i1 @bittest_constant_by_var_shr_i64(i64 %b) nounwind {
define i1 @bittest_constant_by_var_shl_i64(i64 %b) nounwind {
; RV32-LABEL: bittest_constant_by_var_shl_i64:
; RV32: # %bb.0:
; RV32-NEXT: addi a1, a0, -32
; RV32-NEXT: bltz a1, .LBB13_2
; RV32-NEXT: # %bb.1:
; RV32-NEXT: andi a0, zero, 1
; RV32-NEXT: ret
; RV32-NEXT: .LBB13_2:
; RV32-NEXT: lui a1, 301408
; RV32-NEXT: addi a1, a1, 722
; RV32-NEXT: srl a0, a1, a0
; RV32-NEXT: srl a1, a1, a0
; RV32-NEXT: addi a0, a0, -32
; RV32-NEXT: slti a0, a0, 0
; RV32-NEXT: neg a0, a0
; RV32-NEXT: and a0, a0, a1
; RV32-NEXT: andi a0, a0, 1
; RV32-NEXT: ret
;
Expand Down
24 changes: 12 additions & 12 deletions llvm/test/CodeGen/RISCV/compress-opt-select.ll
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
define i32 @f_small_pos(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, 20
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}

Expand All @@ -56,7 +56,7 @@ define i32 @f_small_pos(i32 %in0) minsize {
; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
define i32 @f_small_neg(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, -20
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}

Expand All @@ -70,7 +70,7 @@ define i32 @f_small_neg(i32 %in0) minsize {
; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
define i32 @f_small_edge_pos(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, 31
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}

Expand All @@ -84,7 +84,7 @@ define i32 @f_small_edge_pos(i32 %in0) minsize {
; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
define i32 @f_small_edge_neg(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, -32
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}

Expand All @@ -99,7 +99,7 @@ define i32 @f_small_edge_neg(i32 %in0) minsize {
; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
define i32 @f_medium_ledge_pos(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, 32
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}

Expand All @@ -114,7 +114,7 @@ define i32 @f_medium_ledge_pos(i32 %in0) minsize {
; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
define i32 @f_medium_ledge_neg(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, -33
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}

Expand All @@ -129,7 +129,7 @@ define i32 @f_medium_ledge_neg(i32 %in0) minsize {
; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
define i32 @f_medium_pos(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, 63
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}

Expand All @@ -144,7 +144,7 @@ define i32 @f_medium_pos(i32 %in0) minsize {
; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
define i32 @f_medium_neg(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, -63
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}

Expand All @@ -159,7 +159,7 @@ define i32 @f_medium_neg(i32 %in0) minsize {
; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
define i32 @f_medium_bedge_pos(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, 2047
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}

Expand All @@ -174,7 +174,7 @@ define i32 @f_medium_bedge_pos(i32 %in0) minsize {
; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]]
define i32 @f_medium_bedge_neg(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, -2047
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}

Expand All @@ -185,7 +185,7 @@ define i32 @f_medium_bedge_neg(i32 %in0) minsize {
; nothing to check.
define i32 @f_big_ledge_pos(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, 2048
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}

Expand All @@ -196,6 +196,6 @@ define i32 @f_big_ledge_pos(i32 %in0) minsize {
; nothing to check.
define i32 @f_big_ledge_neg(i32 %in0) minsize {
%cmp = icmp CMPCOND i32 %in0, -2048
%toRet = select i1 %cmp, i32 0, i32 42
%toRet = select i1 %cmp, i32 -99, i32 42
ret i32 %toRet
}
Loading

0 comments on commit 1c41d0c

Please sign in to comment.