Skip to content

Commit 5bc99fb

Browse files
authored
[RISCV] Select (and (sra x, c2), c1) as (srli (srai x, c2-c3), c3). (#101868)
If c1 is a mask with c3 leading zeros and c3 is larger than c2. Fixes regression reported in #101751.
1 parent 35b4f83 commit 5bc99fb

File tree

4 files changed

+69
-24
lines changed

4 files changed

+69
-24
lines changed

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,31 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
14501450
}
14511451
}
14521452

1453+
// Turn (and (sra x, c2), c1) -> (srli (srai x, c2-c3), c3) if c1 is a mask
1454+
// with c3 leading zeros and c2 is larger than c3.
1455+
if (N0.getOpcode() == ISD::SRA && isa<ConstantSDNode>(N0.getOperand(1)) &&
1456+
N0.hasOneUse()) {
1457+
unsigned C2 = N0.getConstantOperandVal(1);
1458+
unsigned XLen = Subtarget->getXLen();
1459+
assert((C2 > 0 && C2 < XLen) && "Unexpected shift amount!");
1460+
1461+
SDValue X = N0.getOperand(0);
1462+
1463+
if (isMask_64(C1)) {
1464+
unsigned Leading = XLen - llvm::bit_width(C1);
1465+
if (C2 > Leading) {
1466+
SDNode *SRAI = CurDAG->getMachineNode(
1467+
RISCV::SRAI, DL, VT, X,
1468+
CurDAG->getTargetConstant(C2 - Leading, DL, VT));
1469+
SDNode *SRLI = CurDAG->getMachineNode(
1470+
RISCV::SRLI, DL, VT, SDValue(SRAI, 0),
1471+
CurDAG->getTargetConstant(Leading, DL, VT));
1472+
ReplaceNode(Node, SRLI);
1473+
return;
1474+
}
1475+
}
1476+
}
1477+
14531478
// If C1 masks off the upper bits only (but can't be formed as an
14541479
// ANDI), use an unsigned bitfield extract (e.g., th.extu), if
14551480
// available.

llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,23 @@
2424
define i1 @shifts_necmp_i16_i8(i16 %x) nounwind {
2525
; RV32I-LABEL: shifts_necmp_i16_i8:
2626
; RV32I: # %bb.0:
27-
; RV32I-NEXT: lui a1, 16
28-
; RV32I-NEXT: addi a1, a1, -1
29-
; RV32I-NEXT: and a2, a0, a1
27+
; RV32I-NEXT: slli a1, a0, 16
28+
; RV32I-NEXT: srli a1, a1, 16
3029
; RV32I-NEXT: slli a0, a0, 24
31-
; RV32I-NEXT: srai a0, a0, 24
32-
; RV32I-NEXT: and a0, a0, a1
33-
; RV32I-NEXT: xor a0, a0, a2
30+
; RV32I-NEXT: srai a0, a0, 8
31+
; RV32I-NEXT: srli a0, a0, 16
32+
; RV32I-NEXT: xor a0, a0, a1
3433
; RV32I-NEXT: snez a0, a0
3534
; RV32I-NEXT: ret
3635
;
3736
; RV64I-LABEL: shifts_necmp_i16_i8:
3837
; RV64I: # %bb.0:
39-
; RV64I-NEXT: lui a1, 16
40-
; RV64I-NEXT: addiw a1, a1, -1
41-
; RV64I-NEXT: and a2, a0, a1
38+
; RV64I-NEXT: slli a1, a0, 48
39+
; RV64I-NEXT: srli a1, a1, 48
4240
; RV64I-NEXT: slli a0, a0, 56
43-
; RV64I-NEXT: srai a0, a0, 56
44-
; RV64I-NEXT: and a0, a0, a1
45-
; RV64I-NEXT: xor a0, a0, a2
41+
; RV64I-NEXT: srai a0, a0, 8
42+
; RV64I-NEXT: srli a0, a0, 48
43+
; RV64I-NEXT: xor a0, a0, a1
4644
; RV64I-NEXT: snez a0, a0
4745
; RV64I-NEXT: ret
4846
;

llvm/test/CodeGen/RISCV/selectcc-to-shiftand.ll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,27 @@ define i64 @sel_shift_bool_i64(i1 %t) {
262262
%shl = select i1 %t, i64 65536, i64 0
263263
ret i64 %shl
264264
}
265+
266+
; FIXME: This should use sraiw+and
267+
define i64 @sraiw_andi(i32 signext %0, i32 signext %1) nounwind {
268+
; RV32-LABEL: sraiw_andi:
269+
; RV32: # %bb.0: # %entry
270+
; RV32-NEXT: add a0, a0, a1
271+
; RV32-NEXT: srai a0, a0, 2
272+
; RV32-NEXT: srli a0, a0, 29
273+
; RV32-NEXT: li a1, 0
274+
; RV32-NEXT: ret
275+
;
276+
; RV64-LABEL: sraiw_andi:
277+
; RV64: # %bb.0: # %entry
278+
; RV64-NEXT: add a0, a0, a1
279+
; RV64-NEXT: slli a0, a0, 32
280+
; RV64-NEXT: srai a0, a0, 2
281+
; RV64-NEXT: srli a0, a0, 61
282+
; RV64-NEXT: ret
283+
entry:
284+
%3 = add i32 %0, %1
285+
%4 = icmp sgt i32 %3, -1
286+
%5 = select i1 %4, i64 0, i64 7
287+
ret i64 %5
288+
}

llvm/test/CodeGen/RISCV/signed-truncation-check.ll

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,23 @@
2424
define i1 @shifts_eqcmp_i16_i8(i16 %x) nounwind {
2525
; RV32I-LABEL: shifts_eqcmp_i16_i8:
2626
; RV32I: # %bb.0:
27-
; RV32I-NEXT: lui a1, 16
28-
; RV32I-NEXT: addi a1, a1, -1
29-
; RV32I-NEXT: and a2, a0, a1
27+
; RV32I-NEXT: slli a1, a0, 16
28+
; RV32I-NEXT: srli a1, a1, 16
3029
; RV32I-NEXT: slli a0, a0, 24
31-
; RV32I-NEXT: srai a0, a0, 24
32-
; RV32I-NEXT: and a0, a0, a1
33-
; RV32I-NEXT: xor a0, a0, a2
30+
; RV32I-NEXT: srai a0, a0, 8
31+
; RV32I-NEXT: srli a0, a0, 16
32+
; RV32I-NEXT: xor a0, a0, a1
3433
; RV32I-NEXT: seqz a0, a0
3534
; RV32I-NEXT: ret
3635
;
3736
; RV64I-LABEL: shifts_eqcmp_i16_i8:
3837
; RV64I: # %bb.0:
39-
; RV64I-NEXT: lui a1, 16
40-
; RV64I-NEXT: addiw a1, a1, -1
41-
; RV64I-NEXT: and a2, a0, a1
38+
; RV64I-NEXT: slli a1, a0, 48
39+
; RV64I-NEXT: srli a1, a1, 48
4240
; RV64I-NEXT: slli a0, a0, 56
43-
; RV64I-NEXT: srai a0, a0, 56
44-
; RV64I-NEXT: and a0, a0, a1
45-
; RV64I-NEXT: xor a0, a0, a2
41+
; RV64I-NEXT: srai a0, a0, 8
42+
; RV64I-NEXT: srli a0, a0, 48
43+
; RV64I-NEXT: xor a0, a0, a1
4644
; RV64I-NEXT: seqz a0, a0
4745
; RV64I-NEXT: ret
4846
;

0 commit comments

Comments
 (0)