Skip to content

Commit

Permalink
[RISCV][SelectionDAG] Enable TargetLowering::hasBitTest for masks tha…
Browse files Browse the repository at this point in the history
…t fit in ANDI.

Modified DAGCombiner to pass the shift the bittest input and the shift amount
to hasBitTest. This matches the other call to hasBitTest in TargetLowering.h

This is an alternative to D122454.

Reviewed By: luismarques

Differential Revision: https://reviews.llvm.org/D122458
  • Loading branch information
topperc committed Mar 28, 2022
1 parent 382de90 commit e68257f
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 159 deletions.
8 changes: 5 additions & 3 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Expand Up @@ -5927,6 +5927,9 @@ static SDValue combineShiftAnd1ToBitTest(SDNode *And, SelectionDAG &DAG) {
if (ShiftAmt.uge(VTBitWidth))
return SDValue();

if (!TLI.hasBitTest(Srl.getOperand(0), Srl.getOperand(1)))
return SDValue();

// Turn this into a bit-test pattern using mask op + setcc:
// and (not (srl X, C)), 1 --> (and X, 1<<C) == 0
SDLoc DL(And);
Expand Down Expand Up @@ -6352,9 +6355,8 @@ SDValue DAGCombiner::visitAND(SDNode *N) {
if (SDValue Shifts = unfoldExtremeBitClearingToShifts(N))
return Shifts;

if (TLI.hasBitTest(N0, N1))
if (SDValue V = combineShiftAnd1ToBitTest(N, DAG))
return V;
if (SDValue V = combineShiftAnd1ToBitTest(N, DAG))
return V;

// Recognize the following pattern:
//
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Expand Up @@ -1245,6 +1245,12 @@ bool RISCVTargetLowering::hasAndNotCompare(SDValue Y) const {
!isa<ConstantSDNode>(Y);
}

bool RISCVTargetLowering::hasBitTest(SDValue X, SDValue Y) const {
// We can use ANDI+SEQZ/SNEZ as a bit test. Y contains the bit position.
auto *C = dyn_cast<ConstantSDNode>(Y);
return C && C->getAPIntValue().ule(10);
}

/// Check if sinking \p I's operands to I's basic block is profitable, because
/// the operands can be folded into a target instruction, e.g.
/// splats of scalars can fold into vector instructions.
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.h
Expand Up @@ -346,6 +346,7 @@ class RISCVTargetLowering : public TargetLowering {
bool isCheapToSpeculateCttz() const override;
bool isCheapToSpeculateCtlz() const override;
bool hasAndNotCompare(SDValue Y) const override;
bool hasBitTest(SDValue X, SDValue Y) const override;
bool shouldSinkOperands(Instruction *I,
SmallVectorImpl<Use *> &Ops) const override;
bool isFPImmLegal(const APFloat &Imm, EVT VT,
Expand Down
189 changes: 189 additions & 0 deletions llvm/test/CodeGen/RISCV/bittest.ll
@@ -0,0 +1,189 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64I
; RUN: llc -mtriple=riscv64 -mattr=+zbs -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64ZBS

define signext i32 @bittest_7_i32(i32 signext %a) nounwind {
; RV64I-LABEL: bittest_7_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 128
; RV64I-NEXT: seqz a0, a0
; RV64I-NEXT: ret
;
; RV64ZBS-LABEL: bittest_7_i32:
; RV64ZBS: # %bb.0:
; RV64ZBS-NEXT: andi a0, a0, 128
; RV64ZBS-NEXT: seqz a0, a0
; RV64ZBS-NEXT: ret
%shr = lshr i32 %a, 7
%not = xor i32 %shr, -1
%and = and i32 %not, 1
ret i32 %and
}

define signext i32 @bittest_10_i32(i32 signext %a) nounwind {
; RV64I-LABEL: bittest_10_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 1024
; RV64I-NEXT: seqz a0, a0
; RV64I-NEXT: ret
;
; RV64ZBS-LABEL: bittest_10_i32:
; RV64ZBS: # %bb.0:
; RV64ZBS-NEXT: andi a0, a0, 1024
; RV64ZBS-NEXT: seqz a0, a0
; RV64ZBS-NEXT: ret
%shr = lshr i32 %a, 10
%not = xor i32 %shr, -1
%and = and i32 %not, 1
ret i32 %and
}

define signext i32 @bittest_11_i32(i32 signext %a) nounwind {
; RV64I-LABEL: bittest_11_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: srli a0, a0, 11
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: andi a0, a0, 1
; RV64I-NEXT: ret
;
; RV64ZBS-LABEL: bittest_11_i32:
; RV64ZBS: # %bb.0:
; RV64ZBS-NEXT: bexti a0, a0, 11
; RV64ZBS-NEXT: xori a0, a0, 1
; RV64ZBS-NEXT: ret
%shr = lshr i32 %a, 11
%not = xor i32 %shr, -1
%and = and i32 %not, 1
ret i32 %and
}

define signext i32 @bittest_31_i32(i32 signext %a) nounwind {
; RV64I-LABEL: bittest_31_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: srliw a0, a0, 31
; RV64I-NEXT: ret
;
; RV64ZBS-LABEL: bittest_31_i32:
; RV64ZBS: # %bb.0:
; RV64ZBS-NEXT: not a0, a0
; RV64ZBS-NEXT: srliw a0, a0, 31
; RV64ZBS-NEXT: ret
%shr = lshr i32 %a, 31
%not = xor i32 %shr, -1
%and = and i32 %not, 1
ret i32 %and
}

define i64 @bittest_7_i64(i64 %a) nounwind {
; RV64I-LABEL: bittest_7_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 128
; RV64I-NEXT: seqz a0, a0
; RV64I-NEXT: ret
;
; RV64ZBS-LABEL: bittest_7_i64:
; RV64ZBS: # %bb.0:
; RV64ZBS-NEXT: andi a0, a0, 128
; RV64ZBS-NEXT: seqz a0, a0
; RV64ZBS-NEXT: ret
%shr = lshr i64 %a, 7
%not = xor i64 %shr, -1
%and = and i64 %not, 1
ret i64 %and
}

define i64 @bittest_10_i64(i64 %a) nounwind {
; RV64I-LABEL: bittest_10_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 1024
; RV64I-NEXT: seqz a0, a0
; RV64I-NEXT: ret
;
; RV64ZBS-LABEL: bittest_10_i64:
; RV64ZBS: # %bb.0:
; RV64ZBS-NEXT: andi a0, a0, 1024
; RV64ZBS-NEXT: seqz a0, a0
; RV64ZBS-NEXT: ret
%shr = lshr i64 %a, 10
%not = xor i64 %shr, -1
%and = and i64 %not, 1
ret i64 %and
}

define i64 @bittest_11_i64(i64 %a) nounwind {
; RV64I-LABEL: bittest_11_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: srli a0, a0, 11
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: andi a0, a0, 1
; RV64I-NEXT: ret
;
; RV64ZBS-LABEL: bittest_11_i64:
; RV64ZBS: # %bb.0:
; RV64ZBS-NEXT: bexti a0, a0, 11
; RV64ZBS-NEXT: xori a0, a0, 1
; RV64ZBS-NEXT: ret
%shr = lshr i64 %a, 11
%not = xor i64 %shr, -1
%and = and i64 %not, 1
ret i64 %and
}

define i64 @bittest_31_i64(i64 %a) nounwind {
; RV64I-LABEL: bittest_31_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: srli a0, a0, 31
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: andi a0, a0, 1
; RV64I-NEXT: ret
;
; RV64ZBS-LABEL: bittest_31_i64:
; RV64ZBS: # %bb.0:
; RV64ZBS-NEXT: bexti a0, a0, 31
; RV64ZBS-NEXT: xori a0, a0, 1
; RV64ZBS-NEXT: ret
%shr = lshr i64 %a, 31
%not = xor i64 %shr, -1
%and = and i64 %not, 1
ret i64 %and
}

define i64 @bittest_32_i64(i64 %a) nounwind {
; RV64I-LABEL: bittest_32_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: andi a0, a0, 1
; RV64I-NEXT: ret
;
; RV64ZBS-LABEL: bittest_32_i64:
; RV64ZBS: # %bb.0:
; RV64ZBS-NEXT: bexti a0, a0, 32
; RV64ZBS-NEXT: xori a0, a0, 1
; RV64ZBS-NEXT: ret
%shr = lshr i64 %a, 32
%not = xor i64 %shr, -1
%and = and i64 %not, 1
ret i64 %and
}

define i64 @bittest_63_i64(i64 %a) nounwind {
; RV64I-LABEL: bittest_63_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: srli a0, a0, 63
; RV64I-NEXT: ret
;
; RV64ZBS-LABEL: bittest_63_i64:
; RV64ZBS: # %bb.0:
; RV64ZBS-NEXT: not a0, a0
; RV64ZBS-NEXT: srli a0, a0, 63
; RV64ZBS-NEXT: ret
%shr = lshr i64 %a, 63
%not = xor i64 %shr, -1
%and = and i64 %not, 1
ret i64 %and
}
80 changes: 0 additions & 80 deletions llvm/test/CodeGen/RISCV/rv32zbs.ll
Expand Up @@ -355,86 +355,6 @@ define i64 @bexti_i64(i64 %a) nounwind {
ret i64 %and
}

define i32 @bexti_xor_i32(i32 %a) nounwind {
; RV32I-LABEL: bexti_xor_i32:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a0, a0, 7
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: andi a0, a0, 1
; RV32I-NEXT: ret
;
; RV32ZBS-LABEL: bexti_xor_i32:
; RV32ZBS: # %bb.0:
; RV32ZBS-NEXT: bexti a0, a0, 7
; RV32ZBS-NEXT: xori a0, a0, 1
; RV32ZBS-NEXT: ret
%shr = lshr i32 %a, 7
%not = xor i32 %shr, -1
%and = and i32 %not, 1
ret i32 %and
}

define i64 @bexti_xor_i64(i64 %a) nounwind {
; RV32I-LABEL: bexti_xor_i64:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a0, a0, 7
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: andi a0, a0, 1
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: ret
;
; RV32ZBS-LABEL: bexti_xor_i64:
; RV32ZBS: # %bb.0:
; RV32ZBS-NEXT: bexti a0, a0, 7
; RV32ZBS-NEXT: xori a0, a0, 1
; RV32ZBS-NEXT: li a1, 0
; RV32ZBS-NEXT: ret
%shr = lshr i64 %a, 7
%not = xor i64 %shr, -1
%and = and i64 %not, 1
ret i64 %and
}

define i32 @bexti_xor_i32_1(i32 %a) nounwind {
; RV32I-LABEL: bexti_xor_i32_1:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a0, a0, 7
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: andi a0, a0, 1
; RV32I-NEXT: ret
;
; RV32ZBS-LABEL: bexti_xor_i32_1:
; RV32ZBS: # %bb.0:
; RV32ZBS-NEXT: bexti a0, a0, 7
; RV32ZBS-NEXT: xori a0, a0, 1
; RV32ZBS-NEXT: ret
%shr = lshr i32 %a, 7
%and = and i32 %shr, 1
%xor = xor i32 %and, 1
ret i32 %xor
}

define i64 @bexti_xor_i64_1(i64 %a) nounwind {
; RV32I-LABEL: bexti_xor_i64_1:
; RV32I: # %bb.0:
; RV32I-NEXT: srli a0, a0, 7
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: andi a0, a0, 1
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: ret
;
; RV32ZBS-LABEL: bexti_xor_i64_1:
; RV32ZBS: # %bb.0:
; RV32ZBS-NEXT: bexti a0, a0, 7
; RV32ZBS-NEXT: xori a0, a0, 1
; RV32ZBS-NEXT: li a1, 0
; RV32ZBS-NEXT: ret
%shr = lshr i64 %a, 7
%and = and i64 %shr, 1
%xor = xor i64 %and, 1
ret i64 %xor
}

define i32 @bclri_i32_10(i32 %a) nounwind {
; RV32I-LABEL: bclri_i32_10:
; RV32I: # %bb.0:
Expand Down

0 comments on commit e68257f

Please sign in to comment.