Skip to content

Commit fad852e

Browse files
committed
[DAG] combineShiftAnd1ToBitTest - improve support for peeking through truncations
Allows us to handle shift amounts that exceed the original bitwidth
1 parent 56cc0bb commit fad852e

File tree

2 files changed

+21
-27
lines changed

2 files changed

+21
-27
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6446,12 +6446,6 @@ SDValue DAGCombiner::unfoldExtremeBitClearingToShifts(SDNode *N) {
64466446
static SDValue combineShiftAnd1ToBitTest(SDNode *And, SelectionDAG &DAG) {
64476447
assert(And->getOpcode() == ISD::AND && "Expected an 'and' op");
64486448

6449-
// This is probably not worthwhile without a supported type.
6450-
EVT VT = And->getValueType(0);
6451-
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
6452-
if (!TLI.isTypeLegal(VT))
6453-
return SDValue();
6454-
64556449
// Look through an optional extension.
64566450
SDValue And0 = And->getOperand(0), And1 = And->getOperand(1);
64576451
if (And0.getOpcode() == ISD::ANY_EXTEND && And0.hasOneUse())
@@ -6479,13 +6473,17 @@ static SDValue combineShiftAnd1ToBitTest(SDNode *And, SelectionDAG &DAG) {
64796473
if (Src.getOpcode() != ISD::SRL || !Src.hasOneUse())
64806474
return SDValue();
64816475

6476+
// This is probably not worthwhile without a supported type.
6477+
EVT SrcVT = Src.getValueType();
6478+
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
6479+
if (!TLI.isTypeLegal(SrcVT))
6480+
return SDValue();
6481+
64826482
// We might have looked through casts that make this transform invalid.
6483-
// TODO: If the source type is wider than the result type, do the mask and
6484-
// compare in the source type.
6485-
unsigned VTBitWidth = VT.getScalarSizeInBits();
6483+
unsigned BitWidth = SrcVT.getScalarSizeInBits();
64866484
SDValue ShiftAmt = Src.getOperand(1);
64876485
auto *ShiftAmtC = dyn_cast<ConstantSDNode>(ShiftAmt);
6488-
if (!ShiftAmtC || !ShiftAmtC->getAPIntValue().ult(VTBitWidth))
6486+
if (!ShiftAmtC || !ShiftAmtC->getAPIntValue().ult(BitWidth))
64896487
return SDValue();
64906488

64916489
// Set source to shift source.
@@ -6506,14 +6504,15 @@ static SDValue combineShiftAnd1ToBitTest(SDNode *And, SelectionDAG &DAG) {
65066504
// and (not (srl X, C)), 1 --> (and X, 1<<C) == 0
65076505
// and (srl (not X), C)), 1 --> (and X, 1<<C) == 0
65086506
SDLoc DL(And);
6509-
SDValue X = DAG.getZExtOrTrunc(Src, DL, VT);
6510-
EVT CCVT = TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
6507+
SDValue X = DAG.getZExtOrTrunc(Src, DL, SrcVT);
6508+
EVT CCVT =
6509+
TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), SrcVT);
65116510
SDValue Mask = DAG.getConstant(
6512-
APInt::getOneBitSet(VTBitWidth, ShiftAmtC->getZExtValue()), DL, VT);
6513-
SDValue NewAnd = DAG.getNode(ISD::AND, DL, VT, X, Mask);
6514-
SDValue Zero = DAG.getConstant(0, DL, VT);
6511+
APInt::getOneBitSet(BitWidth, ShiftAmtC->getZExtValue()), DL, SrcVT);
6512+
SDValue NewAnd = DAG.getNode(ISD::AND, DL, SrcVT, X, Mask);
6513+
SDValue Zero = DAG.getConstant(0, DL, SrcVT);
65156514
SDValue Setcc = DAG.getSetCC(DL, CCVT, NewAnd, Zero, ISD::SETEQ);
6516-
return DAG.getZExtOrTrunc(Setcc, DL, VT);
6515+
return DAG.getZExtOrTrunc(Setcc, DL, And->getValueType(0));
65176516
}
65186517

65196518
/// For targets that support usubsat, match a bit-hack form of that operation

llvm/test/CodeGen/X86/test-vs-bittest.ll

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -574,11 +574,9 @@ define i64 @is_upper_bit_clear_i64(i64 %x) {
574574
define i32 @is_upper_bit_clear_i64_trunc(i64 %x) {
575575
; CHECK-LABEL: is_upper_bit_clear_i64_trunc:
576576
; CHECK: # %bb.0:
577-
; CHECK-NEXT: movq %rdi, %rax
578-
; CHECK-NEXT: shrq $42, %rax
579-
; CHECK-NEXT: notl %eax
580-
; CHECK-NEXT: andl $1, %eax
581-
; CHECK-NEXT: # kill: def $eax killed $eax killed $rax
577+
; CHECK-NEXT: xorl %eax, %eax
578+
; CHECK-NEXT: btq $42, %rdi
579+
; CHECK-NEXT: setae %al
582580
; CHECK-NEXT: retq
583581
%sh = lshr i64 %x, 42
584582
%t = trunc i64 %sh to i32
@@ -704,16 +702,13 @@ define i8 @is_bit_clear_i8_not(i8 %x) {
704702
ret i8 %r
705703
}
706704

707-
; TODO: We could use bt/test on the 64-bit value.
705+
; Use bt/test on the 64-bit value and truncate result.
708706

709707
define i8 @overshift(i64 %x) {
710708
; CHECK-LABEL: overshift:
711709
; CHECK: # %bb.0:
712-
; CHECK-NEXT: movq %rdi, %rax
713-
; CHECK-NEXT: shrq $42, %rax
714-
; CHECK-NEXT: notb %al
715-
; CHECK-NEXT: andb $1, %al
716-
; CHECK-NEXT: # kill: def $al killed $al killed $rax
710+
; CHECK-NEXT: btq $42, %rdi
711+
; CHECK-NEXT: setae %al
717712
; CHECK-NEXT: retq
718713
%a = lshr i64 %x, 42
719714
%t = trunc i64 %a to i8

0 commit comments

Comments
 (0)