Skip to content

Commit

Permalink
[DAG] SimplifyDemandedBits - relax "xor (X >> ShiftC), XorC --> (not …
Browse files Browse the repository at this point in the history
…X) >> ShiftC" to match only demanded bits

The "xor (X >> ShiftC), XorC --> (not X) >> ShiftC" fold is currently limited to the XOR mask being a shifted all-bits mask, but we can relax this to only need to match under the demanded bits.

This helps expose more bit extraction/clearing patterns and fixes the PowerPC testCompares*.ll regressions from D127115

Alive2: https://alive2.llvm.org/ce/z/fl7T7K

Differential Revision: https://reviews.llvm.org/D129933
  • Loading branch information
RKSimon committed Jul 19, 2022
1 parent 9fa425c commit 0f6b046
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 104 deletions.
8 changes: 8 additions & 0 deletions llvm/include/llvm/CodeGen/TargetLowering.h
Expand Up @@ -3886,6 +3886,14 @@ class TargetLowering : public TargetLoweringBase {
return true;
}

/// Return true if it is profitable to combine an XOR of a logical shift
/// to create a logical shift of NOT. This transformation may not be desirable
/// if it disrupts a particularly auspicious target-specific tree (e.g.
/// BIC on ARM/AArch64). By default, it returns true.
virtual bool isDesirableToCommuteXorWithShift(const SDNode *N) const {
return true;
}

/// Return true if the target has native support for the specified value type
/// and it is 'desirable' to use the type for the given node type. e.g. On x86
/// i16 is legal, but undesirable since i16 instruction encodings are longer
Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
Expand Up @@ -1533,8 +1533,10 @@ bool TargetLowering::SimplifyDemandedBits(
APInt Ones = APInt::getAllOnes(BitWidth);
Ones = Op0Opcode == ISD::SHL ? Ones.shl(ShiftAmt)
: Ones.lshr(ShiftAmt);
if (C->getAPIntValue() == Ones) {
// If the xor constant is a shifted -1, do a 'not' before the
const TargetLowering &TLI = TLO.DAG.getTargetLoweringInfo();
if ((DemandedBits & C->getAPIntValue()) == (DemandedBits & Ones) &&
TLI.isDesirableToCommuteXorWithShift(Op.getNode())) {
// If the xor constant is a demanded mask, do a 'not' before the
// shift:
// xor (X << ShiftC), XorC --> (not X) << ShiftC
// xor (X >> ShiftC), XorC --> (not X) >> ShiftC
Expand Down
24 changes: 24 additions & 0 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Expand Up @@ -13613,6 +13613,30 @@ AArch64TargetLowering::isDesirableToCommuteWithShift(const SDNode *N,
return true;
}

bool AArch64TargetLowering::isDesirableToCommuteXorWithShift(
const SDNode *N) const {
assert(N->getOpcode() == ISD::XOR &&
(N->getOperand(0).getOpcode() == ISD::SHL ||
N->getOperand(0).getOpcode() == ISD::SRL) &&
"Expected XOR(SHIFT) pattern");

// Only commute if the entire NOT mask is a hidden shifted mask.
auto *XorC = dyn_cast<ConstantSDNode>(N->getOperand(1));
auto *ShiftC = dyn_cast<ConstantSDNode>(N->getOperand(0).getOperand(1));
if (XorC && ShiftC) {
unsigned MaskIdx, MaskLen;
if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
unsigned ShiftAmt = ShiftC->getZExtValue();
unsigned BitWidth = N->getValueType(0).getScalarSizeInBits();
if (N->getOperand(0).getOpcode() == ISD::SHL)
return MaskIdx == ShiftAmt && MaskLen == (BitWidth - ShiftAmt);
return MaskIdx == 0 && MaskLen == (BitWidth - ShiftAmt);
}
}

return false;
}

bool AArch64TargetLowering::shouldFoldConstantShiftPairToMask(
const SDNode *N, CombineLevel Level) const {
assert(((N->getOpcode() == ISD::SHL &&
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.h
Expand Up @@ -657,6 +657,9 @@ class AArch64TargetLowering : public TargetLowering {
bool isDesirableToCommuteWithShift(const SDNode *N,
CombineLevel Level) const override;

/// Returns false if N is a bit extraction pattern of (X >> C) & Mask.
bool isDesirableToCommuteXorWithShift(const SDNode *N) const override;

/// Return true if it is profitable to fold a pair of shifts into a mask.
bool shouldFoldConstantShiftPairToMask(const SDNode *N,
CombineLevel Level) const override;
Expand Down
24 changes: 24 additions & 0 deletions llvm/lib/Target/ARM/ARMISelLowering.cpp
Expand Up @@ -13609,6 +13609,30 @@ ARMTargetLowering::isDesirableToCommuteWithShift(const SDNode *N,
return false;
}

bool ARMTargetLowering::isDesirableToCommuteXorWithShift(
const SDNode *N) const {
assert(N->getOpcode() == ISD::XOR &&
(N->getOperand(0).getOpcode() == ISD::SHL ||
N->getOperand(0).getOpcode() == ISD::SRL) &&
"Expected XOR(SHIFT) pattern");

// Only commute if the entire NOT mask is a hidden shifted mask.
auto *XorC = dyn_cast<ConstantSDNode>(N->getOperand(1));
auto *ShiftC = dyn_cast<ConstantSDNode>(N->getOperand(0).getOperand(1));
if (XorC && ShiftC) {
unsigned MaskIdx, MaskLen;
if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
unsigned ShiftAmt = ShiftC->getZExtValue();
unsigned BitWidth = N->getValueType(0).getScalarSizeInBits();
if (N->getOperand(0).getOpcode() == ISD::SHL)
return MaskIdx == ShiftAmt && MaskLen == (BitWidth - ShiftAmt);
return MaskIdx == 0 && MaskLen == (BitWidth - ShiftAmt);
}
}

return false;
}

bool ARMTargetLowering::shouldFoldConstantShiftPairToMask(
const SDNode *N, CombineLevel Level) const {
assert(((N->getOpcode() == ISD::SHL &&
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/ARM/ARMISelLowering.h
Expand Up @@ -733,6 +733,8 @@ class VectorType;
bool isDesirableToCommuteWithShift(const SDNode *N,
CombineLevel Level) const override;

bool isDesirableToCommuteXorWithShift(const SDNode *N) const override;

bool shouldFoldConstantShiftPairToMask(const SDNode *N,
CombineLevel Level) const override;

Expand Down
124 changes: 54 additions & 70 deletions llvm/test/CodeGen/Mips/bittest.ll
Expand Up @@ -149,62 +149,56 @@ define signext i32 @bittest_15_i32(i32 signext %a) nounwind {
define signext i32 @bittest_16_i32(i32 signext %a) nounwind {
; MIPS-LABEL: bittest_16_i32:
; MIPS: # %bb.0:
; MIPS-NEXT: srl $1, $4, 16
; MIPS-NEXT: not $1, $1
; MIPS-NEXT: not $1, $4
; MIPS-NEXT: srl $1, $1, 16
; MIPS-NEXT: jr $ra
; MIPS-NEXT: andi $2, $1, 1
;
; MIPS32R2-LABEL: bittest_16_i32:
; MIPS32R2: # %bb.0:
; MIPS32R2-NEXT: srl $1, $4, 16
; MIPS32R2-NEXT: not $1, $1
; MIPS32R2-NEXT: not $1, $4
; MIPS32R2-NEXT: jr $ra
; MIPS32R2-NEXT: andi $2, $1, 1
; MIPS32R2-NEXT: ext $2, $1, 16, 1
;
; MIPS32R6-LABEL: bittest_16_i32:
; MIPS32R6: # %bb.0:
; MIPS32R6-NEXT: srl $1, $4, 16
; MIPS32R6-NEXT: not $1, $1
; MIPS32R6-NEXT: not $1, $4
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: andi $2, $1, 1
; MIPS32R6-NEXT: ext $2, $1, 16, 1
;
; MIPS64-LABEL: bittest_16_i32:
; MIPS64: # %bb.0:
; MIPS64-NEXT: srl $1, $4, 16
; MIPS64-NEXT: not $1, $1
; MIPS64-NEXT: not $1, $4
; MIPS64-NEXT: srl $1, $1, 16
; MIPS64-NEXT: andi $1, $1, 1
; MIPS64-NEXT: dsll $1, $1, 32
; MIPS64-NEXT: jr $ra
; MIPS64-NEXT: dsrl $2, $1, 32
;
; MIPS64R2-LABEL: bittest_16_i32:
; MIPS64R2: # %bb.0:
; MIPS64R2-NEXT: srl $1, $4, 16
; MIPS64R2-NEXT: not $1, $1
; MIPS64R2-NEXT: andi $1, $1, 1
; MIPS64R2-NEXT: not $1, $4
; MIPS64R2-NEXT: ext $1, $1, 16, 1
; MIPS64R2-NEXT: jr $ra
; MIPS64R2-NEXT: dext $2, $1, 0, 32
;
; MIPS64R6-LABEL: bittest_16_i32:
; MIPS64R6: # %bb.0:
; MIPS64R6-NEXT: srl $1, $4, 16
; MIPS64R6-NEXT: not $1, $1
; MIPS64R6-NEXT: andi $1, $1, 1
; MIPS64R6-NEXT: not $1, $4
; MIPS64R6-NEXT: ext $1, $1, 16, 1
; MIPS64R6-NEXT: jr $ra
; MIPS64R6-NEXT: dext $2, $1, 0, 32
;
; MM32R3-LABEL: bittest_16_i32:
; MM32R3: # %bb.0:
; MM32R3-NEXT: srl $2, $4, 16
; MM32R3-NEXT: not16 $2, $2
; MM32R3-NEXT: andi16 $2, $2, 1
; MM32R3-NEXT: jrc $ra
; MM32R3-NEXT: not16 $2, $4
; MM32R3-NEXT: jr $ra
; MM32R3-NEXT: ext $2, $2, 16, 1
;
; MM32R6-LABEL: bittest_16_i32:
; MM32R6: # %bb.0:
; MM32R6-NEXT: srl $2, $4, 16
; MM32R6-NEXT: not16 $2, $2
; MM32R6-NEXT: andi16 $2, $2, 1
; MM32R6-NEXT: not16 $2, $4
; MM32R6-NEXT: ext $2, $2, 16, 1
; MM32R6-NEXT: jrc $ra
%shr = lshr i32 %a, 16
%not = xor i32 %shr, -1
Expand Down Expand Up @@ -399,65 +393,59 @@ define i64 @bittest_15_i64(i64 %a) nounwind {
define i64 @bittest_16_i64(i64 %a) nounwind {
; MIPS-LABEL: bittest_16_i64:
; MIPS: # %bb.0:
; MIPS-NEXT: srl $1, $5, 16
; MIPS-NEXT: not $1, $1
; MIPS-NEXT: not $1, $5
; MIPS-NEXT: srl $1, $1, 16
; MIPS-NEXT: andi $3, $1, 1
; MIPS-NEXT: jr $ra
; MIPS-NEXT: addiu $2, $zero, 0
;
; MIPS32R2-LABEL: bittest_16_i64:
; MIPS32R2: # %bb.0:
; MIPS32R2-NEXT: srl $1, $5, 16
; MIPS32R2-NEXT: not $1, $1
; MIPS32R2-NEXT: andi $3, $1, 1
; MIPS32R2-NEXT: not $1, $5
; MIPS32R2-NEXT: ext $3, $1, 16, 1
; MIPS32R2-NEXT: jr $ra
; MIPS32R2-NEXT: addiu $2, $zero, 0
;
; MIPS32R6-LABEL: bittest_16_i64:
; MIPS32R6: # %bb.0:
; MIPS32R6-NEXT: srl $1, $5, 16
; MIPS32R6-NEXT: not $1, $1
; MIPS32R6-NEXT: andi $3, $1, 1
; MIPS32R6-NEXT: not $1, $5
; MIPS32R6-NEXT: ext $3, $1, 16, 1
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: addiu $2, $zero, 0
;
; MIPS64-LABEL: bittest_16_i64:
; MIPS64: # %bb.0:
; MIPS64-NEXT: dsrl $1, $4, 16
; MIPS64-NEXT: daddiu $2, $zero, -1
; MIPS64-NEXT: xor $1, $1, $2
; MIPS64-NEXT: daddiu $1, $zero, -1
; MIPS64-NEXT: xor $1, $4, $1
; MIPS64-NEXT: dsrl $1, $1, 16
; MIPS64-NEXT: jr $ra
; MIPS64-NEXT: andi $2, $1, 1
;
; MIPS64R2-LABEL: bittest_16_i64:
; MIPS64R2: # %bb.0:
; MIPS64R2-NEXT: dsrl $1, $4, 16
; MIPS64R2-NEXT: daddiu $2, $zero, -1
; MIPS64R2-NEXT: xor $1, $1, $2
; MIPS64R2-NEXT: daddiu $1, $zero, -1
; MIPS64R2-NEXT: xor $1, $4, $1
; MIPS64R2-NEXT: jr $ra
; MIPS64R2-NEXT: andi $2, $1, 1
; MIPS64R2-NEXT: dext $2, $1, 16, 1
;
; MIPS64R6-LABEL: bittest_16_i64:
; MIPS64R6: # %bb.0:
; MIPS64R6-NEXT: dsrl $1, $4, 16
; MIPS64R6-NEXT: daddiu $2, $zero, -1
; MIPS64R6-NEXT: xor $1, $1, $2
; MIPS64R6-NEXT: daddiu $1, $zero, -1
; MIPS64R6-NEXT: xor $1, $4, $1
; MIPS64R6-NEXT: jr $ra
; MIPS64R6-NEXT: andi $2, $1, 1
; MIPS64R6-NEXT: dext $2, $1, 16, 1
;
; MM32R3-LABEL: bittest_16_i64:
; MM32R3: # %bb.0:
; MM32R3-NEXT: srl $2, $5, 16
; MM32R3-NEXT: not16 $2, $2
; MM32R3-NEXT: andi16 $3, $2, 1
; MM32R3-NEXT: not16 $2, $5
; MM32R3-NEXT: ext $3, $2, 16, 1
; MM32R3-NEXT: li16 $2, 0
; MM32R3-NEXT: jrc $ra
;
; MM32R6-LABEL: bittest_16_i64:
; MM32R6: # %bb.0:
; MM32R6-NEXT: srl $2, $5, 16
; MM32R6-NEXT: not16 $2, $2
; MM32R6-NEXT: andi16 $3, $2, 1
; MM32R6-NEXT: not16 $2, $5
; MM32R6-NEXT: ext $3, $2, 16, 1
; MM32R6-NEXT: li16 $2, 0
; MM32R6-NEXT: jrc $ra
%shr = lshr i64 %a, 16
Expand Down Expand Up @@ -490,27 +478,25 @@ define i64 @bittest_31_i64(i64 %a) nounwind {
;
; MIPS64-LABEL: bittest_31_i64:
; MIPS64: # %bb.0:
; MIPS64-NEXT: dsrl $1, $4, 31
; MIPS64-NEXT: daddiu $2, $zero, -1
; MIPS64-NEXT: xor $1, $1, $2
; MIPS64-NEXT: daddiu $1, $zero, -1
; MIPS64-NEXT: xor $1, $4, $1
; MIPS64-NEXT: dsrl $1, $1, 31
; MIPS64-NEXT: jr $ra
; MIPS64-NEXT: andi $2, $1, 1
;
; MIPS64R2-LABEL: bittest_31_i64:
; MIPS64R2: # %bb.0:
; MIPS64R2-NEXT: dsrl $1, $4, 31
; MIPS64R2-NEXT: daddiu $2, $zero, -1
; MIPS64R2-NEXT: xor $1, $1, $2
; MIPS64R2-NEXT: daddiu $1, $zero, -1
; MIPS64R2-NEXT: xor $1, $4, $1
; MIPS64R2-NEXT: jr $ra
; MIPS64R2-NEXT: andi $2, $1, 1
; MIPS64R2-NEXT: dext $2, $1, 31, 1
;
; MIPS64R6-LABEL: bittest_31_i64:
; MIPS64R6: # %bb.0:
; MIPS64R6-NEXT: dsrl $1, $4, 31
; MIPS64R6-NEXT: daddiu $2, $zero, -1
; MIPS64R6-NEXT: xor $1, $1, $2
; MIPS64R6-NEXT: daddiu $1, $zero, -1
; MIPS64R6-NEXT: xor $1, $4, $1
; MIPS64R6-NEXT: jr $ra
; MIPS64R6-NEXT: andi $2, $1, 1
; MIPS64R6-NEXT: dext $2, $1, 31, 1
;
; MM32R3-LABEL: bittest_31_i64:
; MM32R3: # %bb.0:
Expand Down Expand Up @@ -555,27 +541,25 @@ define i64 @bittest_32_i64(i64 %a) nounwind {
;
; MIPS64-LABEL: bittest_32_i64:
; MIPS64: # %bb.0:
; MIPS64-NEXT: dsrl $1, $4, 32
; MIPS64-NEXT: daddiu $2, $zero, -1
; MIPS64-NEXT: xor $1, $1, $2
; MIPS64-NEXT: daddiu $1, $zero, -1
; MIPS64-NEXT: xor $1, $4, $1
; MIPS64-NEXT: dsrl $1, $1, 32
; MIPS64-NEXT: jr $ra
; MIPS64-NEXT: andi $2, $1, 1
;
; MIPS64R2-LABEL: bittest_32_i64:
; MIPS64R2: # %bb.0:
; MIPS64R2-NEXT: dsrl $1, $4, 32
; MIPS64R2-NEXT: daddiu $2, $zero, -1
; MIPS64R2-NEXT: xor $1, $1, $2
; MIPS64R2-NEXT: daddiu $1, $zero, -1
; MIPS64R2-NEXT: xor $1, $4, $1
; MIPS64R2-NEXT: jr $ra
; MIPS64R2-NEXT: andi $2, $1, 1
; MIPS64R2-NEXT: dextu $2, $1, 32, 1
;
; MIPS64R6-LABEL: bittest_32_i64:
; MIPS64R6: # %bb.0:
; MIPS64R6-NEXT: dsrl $1, $4, 32
; MIPS64R6-NEXT: daddiu $2, $zero, -1
; MIPS64R6-NEXT: xor $1, $1, $2
; MIPS64R6-NEXT: daddiu $1, $zero, -1
; MIPS64R6-NEXT: xor $1, $4, $1
; MIPS64R6-NEXT: jr $ra
; MIPS64R6-NEXT: andi $2, $1, 1
; MIPS64R6-NEXT: dextu $2, $1, 32, 1
;
; MM32R3-LABEL: bittest_32_i64:
; MM32R3: # %bb.0:
Expand Down

0 comments on commit 0f6b046

Please sign in to comment.