[llvm] fad852e - [DAG] combineShiftAnd1ToBitTest - improve support for peeking through truncations
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Sat Mar 11 08:37:59 PST 2023
Author: Simon Pilgrim
Date: 2023-03-11T16:37:47Z
New Revision: fad852efe4d6a65293f30825b5ff60b4f0fcd429
URL: https://github.com/llvm/llvm-project/commit/fad852efe4d6a65293f30825b5ff60b4f0fcd429
DIFF: https://github.com/llvm/llvm-project/commit/fad852efe4d6a65293f30825b5ff60b4f0fcd429.diff
LOG: [DAG] combineShiftAnd1ToBitTest - improve support for peeking through truncations
Allows us to handle shift amounts that exceed the original bitwidth
Added:
Modified:
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/test/CodeGen/X86/test-vs-bittest.ll
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index b19e881e4c851..2b4d854a08e9c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6446,12 +6446,6 @@ SDValue DAGCombiner::unfoldExtremeBitClearingToShifts(SDNode *N) {
static SDValue combineShiftAnd1ToBitTest(SDNode *And, SelectionDAG &DAG) {
assert(And->getOpcode() == ISD::AND && "Expected an 'and' op");
- // This is probably not worthwhile without a supported type.
- EVT VT = And->getValueType(0);
- const TargetLowering &TLI = DAG.getTargetLoweringInfo();
- if (!TLI.isTypeLegal(VT))
- return SDValue();
-
// Look through an optional extension.
SDValue And0 = And->getOperand(0), And1 = And->getOperand(1);
if (And0.getOpcode() == ISD::ANY_EXTEND && And0.hasOneUse())
@@ -6479,13 +6473,17 @@ static SDValue combineShiftAnd1ToBitTest(SDNode *And, SelectionDAG &DAG) {
if (Src.getOpcode() != ISD::SRL || !Src.hasOneUse())
return SDValue();
+ // This is probably not worthwhile without a supported type.
+ EVT SrcVT = Src.getValueType();
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ if (!TLI.isTypeLegal(SrcVT))
+ return SDValue();
+
// We might have looked through casts that make this transform invalid.
- // TODO: If the source type is wider than the result type, do the mask and
- // compare in the source type.
- unsigned VTBitWidth = VT.getScalarSizeInBits();
+ unsigned BitWidth = SrcVT.getScalarSizeInBits();
SDValue ShiftAmt = Src.getOperand(1);
auto *ShiftAmtC = dyn_cast<ConstantSDNode>(ShiftAmt);
- if (!ShiftAmtC || !ShiftAmtC->getAPIntValue().ult(VTBitWidth))
+ if (!ShiftAmtC || !ShiftAmtC->getAPIntValue().ult(BitWidth))
return SDValue();
// Set source to shift source.
@@ -6506,14 +6504,15 @@ static SDValue combineShiftAnd1ToBitTest(SDNode *And, SelectionDAG &DAG) {
// and (not (srl X, C)), 1 --> (and X, 1<<C) == 0
// and (srl (not X), C)), 1 --> (and X, 1<<C) == 0
SDLoc DL(And);
- SDValue X = DAG.getZExtOrTrunc(Src, DL, VT);
- EVT CCVT = TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
+ SDValue X = DAG.getZExtOrTrunc(Src, DL, SrcVT);
+ EVT CCVT =
+ TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), SrcVT);
SDValue Mask = DAG.getConstant(
- APInt::getOneBitSet(VTBitWidth, ShiftAmtC->getZExtValue()), DL, VT);
- SDValue NewAnd = DAG.getNode(ISD::AND, DL, VT, X, Mask);
- SDValue Zero = DAG.getConstant(0, DL, VT);
+ APInt::getOneBitSet(BitWidth, ShiftAmtC->getZExtValue()), DL, SrcVT);
+ SDValue NewAnd = DAG.getNode(ISD::AND, DL, SrcVT, X, Mask);
+ SDValue Zero = DAG.getConstant(0, DL, SrcVT);
SDValue Setcc = DAG.getSetCC(DL, CCVT, NewAnd, Zero, ISD::SETEQ);
- return DAG.getZExtOrTrunc(Setcc, DL, VT);
+ return DAG.getZExtOrTrunc(Setcc, DL, And->getValueType(0));
}
/// For targets that support usubsat, match a bit-hack form of that operation
diff --git a/llvm/test/CodeGen/X86/test-vs-bittest.ll b/llvm/test/CodeGen/X86/test-vs-bittest.ll
index f936e5f7e95c5..0998a0f1d6ba9 100644
--- a/llvm/test/CodeGen/X86/test-vs-bittest.ll
+++ b/llvm/test/CodeGen/X86/test-vs-bittest.ll
@@ -574,11 +574,9 @@ define i64 @is_upper_bit_clear_i64(i64 %x) {
define i32 @is_upper_bit_clear_i64_trunc(i64 %x) {
; CHECK-LABEL: is_upper_bit_clear_i64_trunc:
; CHECK: # %bb.0:
-; CHECK-NEXT: movq %rdi, %rax
-; CHECK-NEXT: shrq $42, %rax
-; CHECK-NEXT: notl %eax
-; CHECK-NEXT: andl $1, %eax
-; CHECK-NEXT: # kill: def $eax killed $eax killed $rax
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: btq $42, %rdi
+; CHECK-NEXT: setae %al
; CHECK-NEXT: retq
%sh = lshr i64 %x, 42
%t = trunc i64 %sh to i32
@@ -704,16 +702,13 @@ define i8 @is_bit_clear_i8_not(i8 %x) {
ret i8 %r
}
-; TODO: We could use bt/test on the 64-bit value.
+; Use bt/test on the 64-bit value and truncate result.
define i8 @overshift(i64 %x) {
; CHECK-LABEL: overshift:
; CHECK: # %bb.0:
-; CHECK-NEXT: movq %rdi, %rax
-; CHECK-NEXT: shrq $42, %rax
-; CHECK-NEXT: notb %al
-; CHECK-NEXT: andb $1, %al
-; CHECK-NEXT: # kill: def $al killed $al killed $rax
+; CHECK-NEXT: btq $42, %rdi
+; CHECK-NEXT: setae %al
; CHECK-NEXT: retq
%a = lshr i64 %x, 42
%t = trunc i64 %a to i8
More information about the llvm-commits
mailing list