Skip to content

Commit

Permalink
[RISCV] Add a special case to lowerSELECT for select of 2 constants w…
Browse files Browse the repository at this point in the history
…ith a SETLT condition.

If the constants have a difference of 1 we can convert one to
the other by adding or subtracting the condition.

We have a DAG combine for this, but it only runs before type
legalization. If the select is introduced later during type
legalization or op legalization we will miss it.

We don't need a specific condition, but some conditions are
harder to materialize than others on RISCV. I know that SETLT
will be a single instruction and it is what is used by the
motivating pattern from signed saturating add/sub.

Differential Revision: https://reviews.llvm.org/D99021
  • Loading branch information
topperc committed Apr 7, 2021
1 parent 2da6ce6 commit 56ea2e2
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 296 deletions.
17 changes: 17 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2242,6 +2242,23 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
auto CC = cast<CondCodeSDNode>(CondV.getOperand(2));
ISD::CondCode CCVal = CC->get();

// Special case for a select of 2 constants that have a diffence of 1.
// Normally this is done by DAGCombine, but if the select is introduced by
// type legalization or op legalization, we miss it. Restricting to SETLT
// case for now because that is what signed saturating add/sub need.
// FIXME: We don't need the condition to be SETLT or even a SETCC,
// but we would probably want to swap the true/false values if the condition
// is SETGE/SETLE to avoid an XORI.
if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
CCVal == ISD::SETLT) {
const APInt &TrueVal = cast<ConstantSDNode>(TrueV)->getAPIntValue();
const APInt &FalseVal = cast<ConstantSDNode>(FalseV)->getAPIntValue();
if (TrueVal - 1 == FalseVal)
return DAG.getNode(ISD::ADD, DL, Op.getValueType(), CondV, FalseV);
if (TrueVal + 1 == FalseVal)
return DAG.getNode(ISD::SUB, DL, Op.getValueType(), FalseV, CondV);
}

translateSetCCForBranch(DL, LHS, RHS, CCVal, DAG);

SDValue TargetCC = DAG.getConstant(CCVal, DL, XLenVT);
Expand Down
124 changes: 51 additions & 73 deletions llvm/test/CodeGen/RISCV/sadd_sat.ll
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,15 @@ define signext i32 @func(i32 signext %x, i32 signext %y) nounwind {
; RV32I-LABEL: func:
; RV32I: # %bb.0:
; RV32I-NEXT: mv a2, a0
; RV32I-NEXT: add a3, a0, a1
; RV32I-NEXT: lui a0, 524288
; RV32I-NEXT: bgez a3, .LBB0_2
; RV32I-NEXT: add a0, a0, a1
; RV32I-NEXT: slt a2, a0, a2
; RV32I-NEXT: slti a1, a1, 0
; RV32I-NEXT: beq a1, a2, .LBB0_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: addi a0, a0, -1
; RV32I-NEXT: slti a0, a0, 0
; RV32I-NEXT: lui a1, 524288
; RV32I-NEXT: sub a0, a1, a0
; RV32I-NEXT: .LBB0_2:
; RV32I-NEXT: slt a2, a3, a2
; RV32I-NEXT: slti a1, a1, 0
; RV32I-NEXT: bne a1, a2, .LBB0_4
; RV32I-NEXT: # %bb.3:
; RV32I-NEXT: mv a0, a3
; RV32I-NEXT: .LBB0_4:
; RV32I-NEXT: ret
;
; RV64I-LABEL: func:
Expand All @@ -50,18 +47,15 @@ define signext i32 @func(i32 signext %x, i32 signext %y) nounwind {
; RV32IZbbNOZbt-LABEL: func:
; RV32IZbbNOZbt: # %bb.0:
; RV32IZbbNOZbt-NEXT: mv a2, a0
; RV32IZbbNOZbt-NEXT: add a3, a0, a1
; RV32IZbbNOZbt-NEXT: lui a0, 524288
; RV32IZbbNOZbt-NEXT: bgez a3, .LBB0_2
; RV32IZbbNOZbt-NEXT: add a0, a0, a1
; RV32IZbbNOZbt-NEXT: slt a2, a0, a2
; RV32IZbbNOZbt-NEXT: slti a1, a1, 0
; RV32IZbbNOZbt-NEXT: beq a1, a2, .LBB0_2
; RV32IZbbNOZbt-NEXT: # %bb.1:
; RV32IZbbNOZbt-NEXT: addi a0, a0, -1
; RV32IZbbNOZbt-NEXT: slti a0, a0, 0
; RV32IZbbNOZbt-NEXT: lui a1, 524288
; RV32IZbbNOZbt-NEXT: sub a0, a1, a0
; RV32IZbbNOZbt-NEXT: .LBB0_2:
; RV32IZbbNOZbt-NEXT: slt a2, a3, a2
; RV32IZbbNOZbt-NEXT: slti a1, a1, 0
; RV32IZbbNOZbt-NEXT: bne a1, a2, .LBB0_4
; RV32IZbbNOZbt-NEXT: # %bb.3:
; RV32IZbbNOZbt-NEXT: mv a0, a3
; RV32IZbbNOZbt-NEXT: .LBB0_4:
; RV32IZbbNOZbt-NEXT: ret
;
; RV64IZbb-LABEL: func:
Expand Down Expand Up @@ -97,42 +91,34 @@ define i64 @func2(i64 %x, i64 %y) nounwind {
; RV32I-NEXT: add a5, a4, a3
; RV32I-NEXT: add a0, a0, a2
; RV32I-NEXT: sltu a1, a0, a1
; RV32I-NEXT: add a2, a5, a1
; RV32I-NEXT: lui a1, 524288
; RV32I-NEXT: bgez a2, .LBB1_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: addi a1, a1, -1
; RV32I-NEXT: .LBB1_2:
; RV32I-NEXT: xor a5, a4, a2
; RV32I-NEXT: add a1, a5, a1
; RV32I-NEXT: xor a2, a4, a1
; RV32I-NEXT: xor a3, a4, a3
; RV32I-NEXT: not a3, a3
; RV32I-NEXT: and a3, a3, a5
; RV32I-NEXT: bltz a3, .LBB1_4
; RV32I-NEXT: # %bb.3:
; RV32I-NEXT: and a2, a3, a2
; RV32I-NEXT: bgez a2, .LBB1_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: slti a0, a1, 0
; RV32I-NEXT: lui a2, 524288
; RV32I-NEXT: sub a2, a2, a0
; RV32I-NEXT: srai a0, a1, 31
; RV32I-NEXT: mv a1, a2
; RV32I-NEXT: ret
; RV32I-NEXT: .LBB1_4:
; RV32I-NEXT: srai a0, a2, 31
; RV32I-NEXT: .LBB1_2:
; RV32I-NEXT: ret
;
; RV64I-LABEL: func2:
; RV64I: # %bb.0:
; RV64I-NEXT: add a3, a0, a1
; RV64I-NEXT: addi a2, zero, -1
; RV64I-NEXT: bltz a3, .LBB1_2
; RV64I-NEXT: mv a2, a0
; RV64I-NEXT: add a0, a0, a1
; RV64I-NEXT: slt a2, a0, a2
; RV64I-NEXT: slti a1, a1, 0
; RV64I-NEXT: beq a1, a2, .LBB1_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: slli a2, a2, 63
; RV64I-NEXT: j .LBB1_3
; RV64I-NEXT: slti a0, a0, 0
; RV64I-NEXT: addi a1, zero, -1
; RV64I-NEXT: slli a1, a1, 63
; RV64I-NEXT: sub a0, a1, a0
; RV64I-NEXT: .LBB1_2:
; RV64I-NEXT: srli a2, a2, 1
; RV64I-NEXT: .LBB1_3:
; RV64I-NEXT: slt a0, a3, a0
; RV64I-NEXT: slti a1, a1, 0
; RV64I-NEXT: bne a1, a0, .LBB1_5
; RV64I-NEXT: # %bb.4:
; RV64I-NEXT: mv a2, a3
; RV64I-NEXT: .LBB1_5:
; RV64I-NEXT: mv a0, a2
; RV64I-NEXT: ret
;
; RV32IZbbNOZbt-LABEL: func2:
Expand All @@ -142,41 +128,33 @@ define i64 @func2(i64 %x, i64 %y) nounwind {
; RV32IZbbNOZbt-NEXT: add a5, a4, a3
; RV32IZbbNOZbt-NEXT: add a0, a0, a2
; RV32IZbbNOZbt-NEXT: sltu a1, a0, a1
; RV32IZbbNOZbt-NEXT: add a2, a5, a1
; RV32IZbbNOZbt-NEXT: lui a1, 524288
; RV32IZbbNOZbt-NEXT: add a1, a5, a1
; RV32IZbbNOZbt-NEXT: xor a2, a4, a1
; RV32IZbbNOZbt-NEXT: xor a3, a4, a3
; RV32IZbbNOZbt-NEXT: andn a2, a2, a3
; RV32IZbbNOZbt-NEXT: bgez a2, .LBB1_2
; RV32IZbbNOZbt-NEXT: # %bb.1:
; RV32IZbbNOZbt-NEXT: addi a1, a1, -1
; RV32IZbbNOZbt-NEXT: .LBB1_2:
; RV32IZbbNOZbt-NEXT: xor a5, a4, a2
; RV32IZbbNOZbt-NEXT: xor a3, a4, a3
; RV32IZbbNOZbt-NEXT: andn a3, a5, a3
; RV32IZbbNOZbt-NEXT: bltz a3, .LBB1_4
; RV32IZbbNOZbt-NEXT: # %bb.3:
; RV32IZbbNOZbt-NEXT: slti a0, a1, 0
; RV32IZbbNOZbt-NEXT: lui a2, 524288
; RV32IZbbNOZbt-NEXT: sub a2, a2, a0
; RV32IZbbNOZbt-NEXT: srai a0, a1, 31
; RV32IZbbNOZbt-NEXT: mv a1, a2
; RV32IZbbNOZbt-NEXT: ret
; RV32IZbbNOZbt-NEXT: .LBB1_4:
; RV32IZbbNOZbt-NEXT: srai a0, a2, 31
; RV32IZbbNOZbt-NEXT: .LBB1_2:
; RV32IZbbNOZbt-NEXT: ret
;
; RV64IZbbNOZbt-LABEL: func2:
; RV64IZbbNOZbt: # %bb.0:
; RV64IZbbNOZbt-NEXT: add a3, a0, a1
; RV64IZbbNOZbt-NEXT: addi a2, zero, -1
; RV64IZbbNOZbt-NEXT: bltz a3, .LBB1_2
; RV64IZbbNOZbt-NEXT: mv a2, a0
; RV64IZbbNOZbt-NEXT: add a0, a0, a1
; RV64IZbbNOZbt-NEXT: slt a2, a0, a2
; RV64IZbbNOZbt-NEXT: slti a1, a1, 0
; RV64IZbbNOZbt-NEXT: beq a1, a2, .LBB1_2
; RV64IZbbNOZbt-NEXT: # %bb.1:
; RV64IZbbNOZbt-NEXT: slli a2, a2, 63
; RV64IZbbNOZbt-NEXT: j .LBB1_3
; RV64IZbbNOZbt-NEXT: slti a0, a0, 0
; RV64IZbbNOZbt-NEXT: addi a1, zero, -1
; RV64IZbbNOZbt-NEXT: slli a1, a1, 63
; RV64IZbbNOZbt-NEXT: sub a0, a1, a0
; RV64IZbbNOZbt-NEXT: .LBB1_2:
; RV64IZbbNOZbt-NEXT: srli a2, a2, 1
; RV64IZbbNOZbt-NEXT: .LBB1_3:
; RV64IZbbNOZbt-NEXT: slt a0, a3, a0
; RV64IZbbNOZbt-NEXT: slti a1, a1, 0
; RV64IZbbNOZbt-NEXT: bne a1, a0, .LBB1_5
; RV64IZbbNOZbt-NEXT: # %bb.4:
; RV64IZbbNOZbt-NEXT: mv a2, a3
; RV64IZbbNOZbt-NEXT: .LBB1_5:
; RV64IZbbNOZbt-NEXT: mv a0, a2
; RV64IZbbNOZbt-NEXT: ret
;
; RV32IZbbZbt-LABEL: func2:
Expand Down
128 changes: 53 additions & 75 deletions llvm/test/CodeGen/RISCV/sadd_sat_plus.ll
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,16 @@ define i32 @func32(i32 %x, i32 %y, i32 %z) nounwind {
; RV32I-LABEL: func32:
; RV32I: # %bb.0:
; RV32I-NEXT: mv a3, a0
; RV32I-NEXT: mul a2, a1, a2
; RV32I-NEXT: add a1, a0, a2
; RV32I-NEXT: lui a0, 524288
; RV32I-NEXT: bgez a1, .LBB0_2
; RV32I-NEXT: mul a1, a1, a2
; RV32I-NEXT: add a0, a0, a1
; RV32I-NEXT: slt a2, a0, a3
; RV32I-NEXT: slti a1, a1, 0
; RV32I-NEXT: beq a1, a2, .LBB0_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: addi a0, a0, -1
; RV32I-NEXT: slti a0, a0, 0
; RV32I-NEXT: lui a1, 524288
; RV32I-NEXT: sub a0, a1, a0
; RV32I-NEXT: .LBB0_2:
; RV32I-NEXT: slt a3, a1, a3
; RV32I-NEXT: slti a2, a2, 0
; RV32I-NEXT: bne a2, a3, .LBB0_4
; RV32I-NEXT: # %bb.3:
; RV32I-NEXT: mv a0, a1
; RV32I-NEXT: .LBB0_4:
; RV32I-NEXT: ret
;
; RV64I-LABEL: func32:
Expand All @@ -53,19 +50,16 @@ define i32 @func32(i32 %x, i32 %y, i32 %z) nounwind {
; RV32IZbbNOZbt-LABEL: func32:
; RV32IZbbNOZbt: # %bb.0:
; RV32IZbbNOZbt-NEXT: mv a3, a0
; RV32IZbbNOZbt-NEXT: mul a2, a1, a2
; RV32IZbbNOZbt-NEXT: add a1, a0, a2
; RV32IZbbNOZbt-NEXT: lui a0, 524288
; RV32IZbbNOZbt-NEXT: bgez a1, .LBB0_2
; RV32IZbbNOZbt-NEXT: mul a1, a1, a2
; RV32IZbbNOZbt-NEXT: add a0, a0, a1
; RV32IZbbNOZbt-NEXT: slt a2, a0, a3
; RV32IZbbNOZbt-NEXT: slti a1, a1, 0
; RV32IZbbNOZbt-NEXT: beq a1, a2, .LBB0_2
; RV32IZbbNOZbt-NEXT: # %bb.1:
; RV32IZbbNOZbt-NEXT: addi a0, a0, -1
; RV32IZbbNOZbt-NEXT: slti a0, a0, 0
; RV32IZbbNOZbt-NEXT: lui a1, 524288
; RV32IZbbNOZbt-NEXT: sub a0, a1, a0
; RV32IZbbNOZbt-NEXT: .LBB0_2:
; RV32IZbbNOZbt-NEXT: slt a3, a1, a3
; RV32IZbbNOZbt-NEXT: slti a2, a2, 0
; RV32IZbbNOZbt-NEXT: bne a2, a3, .LBB0_4
; RV32IZbbNOZbt-NEXT: # %bb.3:
; RV32IZbbNOZbt-NEXT: mv a0, a1
; RV32IZbbNOZbt-NEXT: .LBB0_4:
; RV32IZbbNOZbt-NEXT: ret
;
; RV64IZbb-LABEL: func32:
Expand Down Expand Up @@ -105,42 +99,34 @@ define i64 @func64(i64 %x, i64 %y, i64 %z) nounwind {
; RV32I-NEXT: add a3, a2, a5
; RV32I-NEXT: add a0, a0, a4
; RV32I-NEXT: sltu a1, a0, a1
; RV32I-NEXT: add a3, a3, a1
; RV32I-NEXT: lui a1, 524288
; RV32I-NEXT: bgez a3, .LBB1_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: addi a1, a1, -1
; RV32I-NEXT: .LBB1_2:
; RV32I-NEXT: xor a4, a2, a3
; RV32I-NEXT: add a1, a3, a1
; RV32I-NEXT: xor a3, a2, a1
; RV32I-NEXT: xor a2, a2, a5
; RV32I-NEXT: not a2, a2
; RV32I-NEXT: and a2, a2, a4
; RV32I-NEXT: bltz a2, .LBB1_4
; RV32I-NEXT: # %bb.3:
; RV32I-NEXT: mv a1, a3
; RV32I-NEXT: ret
; RV32I-NEXT: .LBB1_4:
; RV32I-NEXT: srai a0, a3, 31
; RV32I-NEXT: and a2, a2, a3
; RV32I-NEXT: bgez a2, .LBB1_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: slti a0, a1, 0
; RV32I-NEXT: lui a2, 524288
; RV32I-NEXT: sub a2, a2, a0
; RV32I-NEXT: srai a0, a1, 31
; RV32I-NEXT: mv a1, a2
; RV32I-NEXT: .LBB1_2:
; RV32I-NEXT: ret
;
; RV64I-LABEL: func64:
; RV64I: # %bb.0:
; RV64I-NEXT: add a3, a0, a2
; RV64I-NEXT: addi a1, zero, -1
; RV64I-NEXT: bltz a3, .LBB1_2
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: add a0, a0, a2
; RV64I-NEXT: slt a1, a0, a1
; RV64I-NEXT: slti a2, a2, 0
; RV64I-NEXT: beq a2, a1, .LBB1_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: slti a0, a0, 0
; RV64I-NEXT: addi a1, zero, -1
; RV64I-NEXT: slli a1, a1, 63
; RV64I-NEXT: j .LBB1_3
; RV64I-NEXT: sub a0, a1, a0
; RV64I-NEXT: .LBB1_2:
; RV64I-NEXT: srli a1, a1, 1
; RV64I-NEXT: .LBB1_3:
; RV64I-NEXT: slt a0, a3, a0
; RV64I-NEXT: slti a2, a2, 0
; RV64I-NEXT: bne a2, a0, .LBB1_5
; RV64I-NEXT: # %bb.4:
; RV64I-NEXT: mv a1, a3
; RV64I-NEXT: .LBB1_5:
; RV64I-NEXT: mv a0, a1
; RV64I-NEXT: ret
;
; RV32IZbbNOZbt-LABEL: func64:
Expand All @@ -150,41 +136,33 @@ define i64 @func64(i64 %x, i64 %y, i64 %z) nounwind {
; RV32IZbbNOZbt-NEXT: add a3, a2, a5
; RV32IZbbNOZbt-NEXT: add a0, a0, a4
; RV32IZbbNOZbt-NEXT: sltu a1, a0, a1
; RV32IZbbNOZbt-NEXT: add a3, a3, a1
; RV32IZbbNOZbt-NEXT: lui a1, 524288
; RV32IZbbNOZbt-NEXT: bgez a3, .LBB1_2
; RV32IZbbNOZbt-NEXT: add a1, a3, a1
; RV32IZbbNOZbt-NEXT: xor a3, a2, a1
; RV32IZbbNOZbt-NEXT: xor a2, a2, a5
; RV32IZbbNOZbt-NEXT: andn a2, a3, a2
; RV32IZbbNOZbt-NEXT: bgez a2, .LBB1_2
; RV32IZbbNOZbt-NEXT: # %bb.1:
; RV32IZbbNOZbt-NEXT: addi a1, a1, -1
; RV32IZbbNOZbt-NEXT: slti a0, a1, 0
; RV32IZbbNOZbt-NEXT: lui a2, 524288
; RV32IZbbNOZbt-NEXT: sub a2, a2, a0
; RV32IZbbNOZbt-NEXT: srai a0, a1, 31
; RV32IZbbNOZbt-NEXT: mv a1, a2
; RV32IZbbNOZbt-NEXT: .LBB1_2:
; RV32IZbbNOZbt-NEXT: xor a4, a2, a3
; RV32IZbbNOZbt-NEXT: xor a2, a2, a5
; RV32IZbbNOZbt-NEXT: andn a2, a4, a2
; RV32IZbbNOZbt-NEXT: bltz a2, .LBB1_4
; RV32IZbbNOZbt-NEXT: # %bb.3:
; RV32IZbbNOZbt-NEXT: mv a1, a3
; RV32IZbbNOZbt-NEXT: ret
; RV32IZbbNOZbt-NEXT: .LBB1_4:
; RV32IZbbNOZbt-NEXT: srai a0, a3, 31
; RV32IZbbNOZbt-NEXT: ret
;
; RV64IZbbNOZbt-LABEL: func64:
; RV64IZbbNOZbt: # %bb.0:
; RV64IZbbNOZbt-NEXT: add a3, a0, a2
; RV64IZbbNOZbt-NEXT: addi a1, zero, -1
; RV64IZbbNOZbt-NEXT: bltz a3, .LBB1_2
; RV64IZbbNOZbt-NEXT: mv a1, a0
; RV64IZbbNOZbt-NEXT: add a0, a0, a2
; RV64IZbbNOZbt-NEXT: slt a1, a0, a1
; RV64IZbbNOZbt-NEXT: slti a2, a2, 0
; RV64IZbbNOZbt-NEXT: beq a2, a1, .LBB1_2
; RV64IZbbNOZbt-NEXT: # %bb.1:
; RV64IZbbNOZbt-NEXT: slti a0, a0, 0
; RV64IZbbNOZbt-NEXT: addi a1, zero, -1
; RV64IZbbNOZbt-NEXT: slli a1, a1, 63
; RV64IZbbNOZbt-NEXT: j .LBB1_3
; RV64IZbbNOZbt-NEXT: sub a0, a1, a0
; RV64IZbbNOZbt-NEXT: .LBB1_2:
; RV64IZbbNOZbt-NEXT: srli a1, a1, 1
; RV64IZbbNOZbt-NEXT: .LBB1_3:
; RV64IZbbNOZbt-NEXT: slt a0, a3, a0
; RV64IZbbNOZbt-NEXT: slti a2, a2, 0
; RV64IZbbNOZbt-NEXT: bne a2, a0, .LBB1_5
; RV64IZbbNOZbt-NEXT: # %bb.4:
; RV64IZbbNOZbt-NEXT: mv a1, a3
; RV64IZbbNOZbt-NEXT: .LBB1_5:
; RV64IZbbNOZbt-NEXT: mv a0, a1
; RV64IZbbNOZbt-NEXT: ret
;
; RV32IZbbZbt-LABEL: func64:
Expand Down
Loading

0 comments on commit 56ea2e2

Please sign in to comment.