Skip to content

Commit 067632e

Browse files
authored
Revert "[DAGCombiner] Transform (icmp eq/ne (and X,C0),(shift X,C1)) to use rotate or to getter constants." due to a miscompile (llvm#71598)
- Revert "[DAGCombiner] Transform `(icmp eq/ne (and X,C0),(shift X,C1))` to use rotate or to getter constants." - causes a miscompile, see llvm@112e49b#commitcomment-131943923 - Revert "[X86] Fix gcc warning about mix of enumeral and non-enumeral types. NFC", which fixes a compiler warning in the commit above
1 parent d79fff0 commit 067632e

File tree

5 files changed

+86
-280
lines changed

5 files changed

+86
-280
lines changed

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -832,24 +832,6 @@ class TargetLoweringBase {
832832
return N->getOpcode() == ISD::FDIV;
833833
}
834834

835-
// Given:
836-
// (icmp eq/ne (and X, C0), (shift X, C1))
837-
// or
838-
// (icmp eq/ne X, (rotate X, CPow2))
839-
840-
// If C0 is a mask or shifted mask and the shift amt (C1) isolates the
841-
// remaining bits (i.e something like `(x64 & UINT32_MAX) == (x64 >> 32)`)
842-
// Do we prefer the shift to be shift-right, shift-left, or rotate.
843-
// Note: Its only valid to convert the rotate version to the shift version iff
844-
// the shift-amt (`C1`) is a power of 2 (including 0).
845-
// If ShiftOpc (current Opcode) is returned, do nothing.
846-
virtual unsigned preferedOpcodeForCmpEqPiecesOfOperand(
847-
EVT VT, unsigned ShiftOpc, bool MayTransformRotate,
848-
const APInt &ShiftOrRotateAmt,
849-
const std::optional<APInt> &AndMask) const {
850-
return ShiftOpc;
851-
}
852-
853835
/// These two forms are equivalent:
854836
/// sub %y, (xor %x, -1)
855837
/// add (add %x, 1), %y

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 15 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -12456,127 +12456,27 @@ SDValue DAGCombiner::visitSETCC(SDNode *N) {
1245612456

1245712457
ISD::CondCode Cond = cast<CondCodeSDNode>(N->getOperand(2))->get();
1245812458
EVT VT = N->getValueType(0);
12459-
SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
12460-
12461-
SDValue Combined = SimplifySetCC(VT, N0, N1, Cond, SDLoc(N), !PreferSetCC);
1246212459

12463-
if (Combined) {
12464-
// If we prefer to have a setcc, and we don't, we'll try our best to
12465-
// recreate one using rebuildSetCC.
12466-
if (PreferSetCC && Combined.getOpcode() != ISD::SETCC) {
12467-
SDValue NewSetCC = rebuildSetCC(Combined);
12460+
SDValue Combined = SimplifySetCC(VT, N->getOperand(0), N->getOperand(1), Cond,
12461+
SDLoc(N), !PreferSetCC);
1246812462

12469-
// We don't have anything interesting to combine to.
12470-
if (NewSetCC.getNode() == N)
12471-
return SDValue();
12463+
if (!Combined)
12464+
return SDValue();
1247212465

12473-
if (NewSetCC)
12474-
return NewSetCC;
12475-
}
12476-
return Combined;
12477-
}
12466+
// If we prefer to have a setcc, and we don't, we'll try our best to
12467+
// recreate one using rebuildSetCC.
12468+
if (PreferSetCC && Combined.getOpcode() != ISD::SETCC) {
12469+
SDValue NewSetCC = rebuildSetCC(Combined);
1247812470

12479-
// Optimize
12480-
// 1) (icmp eq/ne (and X, C0), (shift X, C1))
12481-
// or
12482-
// 2) (icmp eq/ne X, (rotate X, C1))
12483-
// If C0 is a mask or shifted mask and the shift amt (C1) isolates the
12484-
// remaining bits (i.e something like `(x64 & UINT32_MAX) == (x64 >> 32)`)
12485-
// Then:
12486-
// If C1 is a power of 2, then the rotate and shift+and versions are
12487-
// equivilent, so we can interchange them depending on target preference.
12488-
// Otherwise, if we have the shift+and version we can interchange srl/shl
12489-
// which inturn affects the constant C0. We can use this to get better
12490-
// constants again determined by target preference.
12491-
if (Cond == ISD::SETNE || Cond == ISD::SETEQ) {
12492-
auto IsAndWithShift = [](SDValue A, SDValue B) {
12493-
return A.getOpcode() == ISD::AND &&
12494-
(B.getOpcode() == ISD::SRL || B.getOpcode() == ISD::SHL) &&
12495-
A.getOperand(0) == B.getOperand(0);
12496-
};
12497-
auto IsRotateWithOp = [](SDValue A, SDValue B) {
12498-
return (B.getOpcode() == ISD::ROTL || B.getOpcode() == ISD::ROTR) &&
12499-
B.getOperand(0) == A;
12500-
};
12501-
SDValue AndOrOp = SDValue(), ShiftOrRotate = SDValue();
12502-
bool IsRotate = false;
12503-
12504-
// Find either shift+and or rotate pattern.
12505-
if (IsAndWithShift(N0, N1)) {
12506-
AndOrOp = N0;
12507-
ShiftOrRotate = N1;
12508-
} else if (IsAndWithShift(N1, N0)) {
12509-
AndOrOp = N1;
12510-
ShiftOrRotate = N0;
12511-
} else if (IsRotateWithOp(N0, N1)) {
12512-
IsRotate = true;
12513-
AndOrOp = N0;
12514-
ShiftOrRotate = N1;
12515-
} else if (IsRotateWithOp(N1, N0)) {
12516-
IsRotate = true;
12517-
AndOrOp = N1;
12518-
ShiftOrRotate = N0;
12519-
}
12520-
12521-
if (AndOrOp && ShiftOrRotate && ShiftOrRotate.hasOneUse() &&
12522-
(IsRotate || AndOrOp.hasOneUse())) {
12523-
EVT OpVT = N0.getValueType();
12524-
// Get constant shift/rotate amount and possibly mask (if its shift+and
12525-
// variant).
12526-
auto GetAPIntValue = [](SDValue Op) -> std::optional<APInt> {
12527-
ConstantSDNode *CNode = isConstOrConstSplat(Op, /*AllowUndefs*/ false,
12528-
/*AllowTrunc*/ false);
12529-
if (CNode == nullptr)
12530-
return std::nullopt;
12531-
return CNode->getAPIntValue();
12532-
};
12533-
std::optional<APInt> AndCMask =
12534-
IsRotate ? std::nullopt : GetAPIntValue(AndOrOp.getOperand(1));
12535-
std::optional<APInt> ShiftCAmt =
12536-
GetAPIntValue(ShiftOrRotate.getOperand(1));
12537-
unsigned NumBits = OpVT.getScalarSizeInBits();
12538-
12539-
// We found constants.
12540-
if (ShiftCAmt && (IsRotate || AndCMask) && ShiftCAmt->ult(NumBits)) {
12541-
unsigned ShiftOpc = ShiftOrRotate.getOpcode();
12542-
// Check that the constants meet the constraints.
12543-
bool CanTransform =
12544-
IsRotate ||
12545-
(*ShiftCAmt == (~*AndCMask).popcount() && ShiftOpc == ISD::SHL
12546-
? (~*AndCMask).isMask()
12547-
: AndCMask->isMask());
12548-
12549-
// See if target prefers another shift/rotate opcode.
12550-
unsigned NewShiftOpc = TLI.preferedOpcodeForCmpEqPiecesOfOperand(
12551-
OpVT, ShiftOpc, ShiftCAmt->isPowerOf2(), *ShiftCAmt, AndCMask);
12552-
// Transform is valid and we have a new preference.
12553-
if (CanTransform && NewShiftOpc != ShiftOpc) {
12554-
SDLoc DL(N);
12555-
SDValue NewShiftOrRotate =
12556-
DAG.getNode(NewShiftOpc, DL, OpVT, ShiftOrRotate.getOperand(0),
12557-
ShiftOrRotate.getOperand(1));
12558-
SDValue NewAndOrOp = SDValue();
12559-
12560-
if (NewShiftOpc == ISD::SHL || NewShiftOpc == ISD::SRL) {
12561-
APInt NewMask =
12562-
NewShiftOpc == ISD::SHL
12563-
? APInt::getHighBitsSet(NumBits,
12564-
NumBits - ShiftCAmt->getZExtValue())
12565-
: APInt::getLowBitsSet(NumBits,
12566-
NumBits - ShiftCAmt->getZExtValue());
12567-
NewAndOrOp =
12568-
DAG.getNode(ISD::AND, DL, OpVT, ShiftOrRotate.getOperand(0),
12569-
DAG.getConstant(NewMask, DL, OpVT));
12570-
} else {
12571-
NewAndOrOp = ShiftOrRotate.getOperand(0);
12572-
}
12471+
// We don't have anything interesting to combine to.
12472+
if (NewSetCC.getNode() == N)
12473+
return SDValue();
1257312474

12574-
return DAG.getSetCC(DL, VT, NewAndOrOp, NewShiftOrRotate, Cond);
12575-
}
12576-
}
12577-
}
12475+
if (NewSetCC)
12476+
return NewSetCC;
1257812477
}
12579-
return SDValue();
12478+
12479+
return Combined;
1258012480
}
1258112481

1258212482
SDValue DAGCombiner::visitSETCCCARRY(SDNode *N) {

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3257,73 +3257,6 @@ bool X86TargetLowering::
32573257
return NewShiftOpcode == ISD::SHL;
32583258
}
32593259

3260-
unsigned X86TargetLowering::preferedOpcodeForCmpEqPiecesOfOperand(
3261-
EVT VT, unsigned ShiftOpc, bool MayTransformRotate,
3262-
const APInt &ShiftOrRotateAmt, const std::optional<APInt> &AndMask) const {
3263-
if (!VT.isInteger())
3264-
return ShiftOpc;
3265-
3266-
bool PreferRotate = false;
3267-
if (VT.isVector()) {
3268-
// For vectors, if we have rotate instruction support, then its definetly
3269-
// best. Otherwise its not clear what the best so just don't make changed.
3270-
PreferRotate = Subtarget.hasAVX512() && (VT.getScalarType() == MVT::i32 ||
3271-
VT.getScalarType() == MVT::i64);
3272-
} else {
3273-
// For scalar, if we have bmi prefer rotate for rorx. Otherwise prefer
3274-
// rotate unless we have a zext mask+shr.
3275-
PreferRotate = Subtarget.hasBMI2();
3276-
if (!PreferRotate) {
3277-
unsigned MaskBits =
3278-
VT.getScalarSizeInBits() - ShiftOrRotateAmt.getZExtValue();
3279-
PreferRotate = (MaskBits != 8) && (MaskBits != 16) && (MaskBits != 32);
3280-
}
3281-
}
3282-
3283-
if (ShiftOpc == ISD::SHL || ShiftOpc == ISD::SRL) {
3284-
assert(AndMask.has_value() && "Null andmask when querying about shift+and");
3285-
3286-
if (PreferRotate && MayTransformRotate)
3287-
return ISD::ROTL;
3288-
3289-
// If vector we don't really get much benefit swapping around constants.
3290-
// Maybe we could check if the DAG has the flipped node already in the
3291-
// future.
3292-
if (VT.isVector())
3293-
return ShiftOpc;
3294-
3295-
// See if the beneficial to swap shift type.
3296-
if (ShiftOpc == ISD::SHL) {
3297-
// If the current setup has imm64 mask, then inverse will have
3298-
// at least imm32 mask (or be zext i32 -> i64).
3299-
if (VT == MVT::i64)
3300-
return AndMask->getSignificantBits() > 32 ? (unsigned)ISD::SRL
3301-
: ShiftOpc;
3302-
3303-
// We can only benefit if req at least 7-bit for the mask. We
3304-
// don't want to replace shl of 1,2,3 as they can be implemented
3305-
// with lea/add.
3306-
return ShiftOrRotateAmt.uge(7) ? (unsigned)ISD::SRL : ShiftOpc;
3307-
}
3308-
3309-
if (VT == MVT::i64)
3310-
// Keep exactly 32-bit imm64, this is zext i32 -> i64 which is
3311-
// extremely efficient.
3312-
return AndMask->getSignificantBits() > 33 ? (unsigned)ISD::SHL : ShiftOpc;
3313-
3314-
// Keep small shifts as shl so we can generate add/lea.
3315-
return ShiftOrRotateAmt.ult(7) ? (unsigned)ISD::SHL : ShiftOpc;
3316-
}
3317-
3318-
// We prefer rotate for vectors of if we won't get a zext mask with SRL
3319-
// (PreferRotate will be set in the latter case).
3320-
if (PreferRotate || VT.isVector())
3321-
return ShiftOpc;
3322-
3323-
// Non-vector type and we have a zext mask with SRL.
3324-
return ISD::SRL;
3325-
}
3326-
33273260
bool X86TargetLowering::preferScalarizeSplat(SDNode *N) const {
33283261
return N->getOpcode() != ISD::FP_EXTEND;
33293262
}

llvm/lib/Target/X86/X86ISelLowering.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,11 +1138,6 @@ namespace llvm {
11381138
unsigned OldShiftOpcode, unsigned NewShiftOpcode,
11391139
SelectionDAG &DAG) const override;
11401140

1141-
unsigned preferedOpcodeForCmpEqPiecesOfOperand(
1142-
EVT VT, unsigned ShiftOpc, bool MayTransformRotate,
1143-
const APInt &ShiftOrRotateAmt,
1144-
const std::optional<APInt> &AndMask) const override;
1145-
11461141
bool preferScalarizeSplat(SDNode *N) const override;
11471142

11481143
bool shouldFoldConstantShiftPairToMask(const SDNode *N,

0 commit comments

Comments
 (0)