Skip to content

Commit 7e15ea1

Browse files
committed
[RISCV] Add a DAG combine to pre-promote (i1 (truncate (i32 (srl X, Y)))) with Zbs on RV64.
Type legalization will want to turn (srl X, Y) into RISCVISD::SRLW, which will prevent us from using a BEXT instruction. This is similar to what we do for (i32 (and (srl X, Y), 1)).
1 parent 083d949 commit 7e15ea1

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
997997
if (Subtarget.hasStdExtZbb())
998998
setTargetDAGCombine({ISD::UMAX, ISD::UMIN, ISD::SMAX, ISD::SMIN});
999999

1000+
if (Subtarget.hasStdExtZbs() && Subtarget.is64Bit())
1001+
setTargetDAGCombine(ISD::TRUNCATE);
1002+
10001003
if (Subtarget.hasStdExtZbkb())
10011004
setTargetDAGCombine(ISD::BITREVERSE);
10021005
if (Subtarget.hasStdExtZfh())
@@ -8259,6 +8262,29 @@ static SDValue combineDeMorganOfBoolean(SDNode *N, SelectionDAG &DAG) {
82598262
return DAG.getNode(ISD::XOR, DL, VT, Logic, DAG.getConstant(1, DL, VT));
82608263
}
82618264

8265+
static SDValue performTRUNCATECombine(SDNode *N, SelectionDAG &DAG,
8266+
const RISCVSubtarget &Subtarget) {
8267+
SDValue N0 = N->getOperand(0);
8268+
EVT VT = N->getValueType(0);
8269+
8270+
// Pre-promote (i1 (truncate (srl X, Y))) on RV64 with Zbs without zero
8271+
// extending X. This is safe since we only need the LSB after the shift and
8272+
// shift amounts larger than 31 would produce poison. If we wait until
8273+
// type legalization, we'll create RISCVISD::SRLW and we can't recover it
8274+
// to use a BEXT instruction.
8275+
if (Subtarget.is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
8276+
N0.getValueType() == MVT::i32 && N0.getOpcode() == ISD::SRL &&
8277+
!isa<ConstantSDNode>(N0.getOperand(1)) && N0.hasOneUse()) {
8278+
SDLoc DL(N0);
8279+
SDValue Op0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N0.getOperand(0));
8280+
SDValue Op1 = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, N0.getOperand(1));
8281+
SDValue Srl = DAG.getNode(ISD::SRL, DL, MVT::i64, Op0, Op1);
8282+
return DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, Srl);
8283+
}
8284+
8285+
return SDValue();
8286+
}
8287+
82628288
static SDValue performANDCombine(SDNode *N,
82638289
TargetLowering::DAGCombinerInfo &DCI,
82648290
const RISCVSubtarget &Subtarget) {
@@ -9573,6 +9599,8 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
95739599
}
95749600
}
95759601
return SDValue();
9602+
case ISD::TRUNCATE:
9603+
return performTRUNCATECombine(N, DAG, Subtarget);
95769604
case RISCVISD::SELECT_CC: {
95779605
// Transform
95789606
SDValue LHS = N->getOperand(0);

llvm/test/CodeGen/RISCV/rv64zbs.ll

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,42 @@ define signext i32 @bext_i32_no_mask(i32 signext %a, i32 signext %b) nounwind {
363363
ret i32 %and1
364364
}
365365

366+
; This gets previous converted to (i1 (truncate (srl X, Y)). Make sure we are
367+
; able to use bext.
368+
define void @bext_i32_trunc(i32 signext %0, i32 signext %1) {
369+
; RV64I-LABEL: bext_i32_trunc:
370+
; RV64I: # %bb.0:
371+
; RV64I-NEXT: srlw a0, a0, a1
372+
; RV64I-NEXT: andi a0, a0, 1
373+
; RV64I-NEXT: beqz a0, .LBB19_2
374+
; RV64I-NEXT: # %bb.1:
375+
; RV64I-NEXT: ret
376+
; RV64I-NEXT: .LBB19_2:
377+
; RV64I-NEXT: tail bar@plt
378+
;
379+
; RV64ZBS-LABEL: bext_i32_trunc:
380+
; RV64ZBS: # %bb.0:
381+
; RV64ZBS-NEXT: bext a0, a0, a1
382+
; RV64ZBS-NEXT: beqz a0, .LBB19_2
383+
; RV64ZBS-NEXT: # %bb.1:
384+
; RV64ZBS-NEXT: ret
385+
; RV64ZBS-NEXT: .LBB19_2:
386+
; RV64ZBS-NEXT: tail bar@plt
387+
%3 = shl i32 1, %1
388+
%4 = and i32 %3, %0
389+
%5 = icmp eq i32 %4, 0
390+
br i1 %5, label %6, label %7
391+
392+
6: ; preds = %2
393+
tail call void @bar()
394+
br label %7
395+
396+
7: ; preds = %6, %2
397+
ret void
398+
}
399+
400+
declare void @bar()
401+
366402
define i64 @bext_i64(i64 %a, i64 %b) nounwind {
367403
; RV64I-LABEL: bext_i64:
368404
; RV64I: # %bb.0:

0 commit comments

Comments
 (0)