forked from OSchip/llvm-project
[X86] Move code that shrinks immediates for ((x << C1) op C2) into a helper function. NFCI
Preliminary step for D59909 llvm-svn: 363645
This commit is contained in:
parent
587427716c
commit
f4284f8a9d
|
@ -502,6 +502,7 @@ namespace {
|
|||
bool shrinkAndImmediate(SDNode *N);
|
||||
bool isMaskZeroExtended(SDNode *N) const;
|
||||
bool tryShiftAmountMod(SDNode *N);
|
||||
bool tryShrinkShlLogicImm(SDNode *N);
|
||||
bool tryVPTESTM(SDNode *Root, SDValue Setcc, SDValue Mask);
|
||||
|
||||
MachineSDNode *emitPCMPISTR(unsigned ROpc, unsigned MOpc, bool MayFoldLoad,
|
||||
|
@ -3567,6 +3568,119 @@ bool X86DAGToDAGISel::tryShiftAmountMod(SDNode *N) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool X86DAGToDAGISel::tryShrinkShlLogicImm(SDNode *N) {
|
||||
MVT NVT = N->getSimpleValueType(0);
|
||||
unsigned Opcode = N->getOpcode();
|
||||
SDLoc dl(N);
|
||||
|
||||
// For operations of the form (x << C1) op C2, check if we can use a smaller
|
||||
// encoding for C2 by transforming it into (x op (C2>>C1)) << C1.
|
||||
SDValue Shift = N->getOperand(0);
|
||||
SDValue N1 = N->getOperand(1);
|
||||
|
||||
ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N1);
|
||||
if (!Cst)
|
||||
return false;
|
||||
|
||||
int64_t Val = Cst->getSExtValue();
|
||||
|
||||
// If we have an any_extend feeding the AND, look through it to see if there
|
||||
// is a shift behind it. But only if the AND doesn't use the extended bits.
|
||||
// FIXME: Generalize this to other ANY_EXTEND than i32 to i64?
|
||||
bool FoundAnyExtend = false;
|
||||
if (Shift.getOpcode() == ISD::ANY_EXTEND && Shift.hasOneUse() &&
|
||||
Shift.getOperand(0).getSimpleValueType() == MVT::i32 &&
|
||||
isUInt<32>(Val)) {
|
||||
FoundAnyExtend = true;
|
||||
Shift = Shift.getOperand(0);
|
||||
}
|
||||
|
||||
if (Shift.getOpcode() != ISD::SHL || !Shift.hasOneUse())
|
||||
return false;
|
||||
|
||||
// i8 is unshrinkable, i16 should be promoted to i32.
|
||||
if (NVT != MVT::i32 && NVT != MVT::i64)
|
||||
return false;
|
||||
|
||||
ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(Shift.getOperand(1));
|
||||
if (!ShlCst)
|
||||
return false;
|
||||
|
||||
uint64_t ShAmt = ShlCst->getZExtValue();
|
||||
|
||||
// Make sure that we don't change the operation by removing bits.
|
||||
// This only matters for OR and XOR, AND is unaffected.
|
||||
uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1;
|
||||
if (Opcode != ISD::AND && (Val & RemovedBitsMask) != 0)
|
||||
return false;
|
||||
|
||||
// Check the minimum bitwidth for the new constant.
|
||||
// TODO: Using 16 and 8 bit operations is also possible for or32 & xor32.
|
||||
auto CanShrinkImmediate = [&](int64_t &ShiftedVal) {
|
||||
if (Opcode == ISD::AND) {
|
||||
// AND32ri is the same as AND64ri32 with zext imm.
|
||||
// Try this before sign extended immediates below.
|
||||
ShiftedVal = (uint64_t)Val >> ShAmt;
|
||||
if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal))
|
||||
return true;
|
||||
// Also swap order when the AND can become MOVZX.
|
||||
if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX)
|
||||
return true;
|
||||
}
|
||||
ShiftedVal = Val >> ShAmt;
|
||||
if ((!isInt<8>(Val) && isInt<8>(ShiftedVal)) ||
|
||||
(!isInt<32>(Val) && isInt<32>(ShiftedVal)))
|
||||
return true;
|
||||
if (Opcode != ISD::AND) {
|
||||
// MOV32ri+OR64r/XOR64r is cheaper than MOV64ri64+OR64rr/XOR64rr
|
||||
ShiftedVal = (uint64_t)Val >> ShAmt;
|
||||
if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
int64_t ShiftedVal;
|
||||
if (!CanShrinkImmediate(ShiftedVal))
|
||||
return false;
|
||||
|
||||
// Ok, we can reorder to get a smaller immediate.
|
||||
|
||||
// But, its possible the original immediate allowed an AND to become MOVZX.
|
||||
// Doing this late due to avoid the MakedValueIsZero call as late as
|
||||
// possible.
|
||||
if (Opcode == ISD::AND) {
|
||||
// Find the smallest zext this could possibly be.
|
||||
unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
|
||||
ZExtWidth = PowerOf2Ceil(std::max(ZExtWidth, 8U));
|
||||
|
||||
// Figure out which bits need to be zero to achieve that mask.
|
||||
APInt NeededMask = APInt::getLowBitsSet(NVT.getSizeInBits(),
|
||||
ZExtWidth);
|
||||
NeededMask &= ~Cst->getAPIntValue();
|
||||
|
||||
if (CurDAG->MaskedValueIsZero(N->getOperand(0), NeededMask))
|
||||
return false;
|
||||
}
|
||||
|
||||
SDValue X = Shift.getOperand(0);
|
||||
if (FoundAnyExtend) {
|
||||
SDValue NewX = CurDAG->getNode(ISD::ANY_EXTEND, dl, NVT, X);
|
||||
insertDAGNode(*CurDAG, SDValue(N, 0), NewX);
|
||||
X = NewX;
|
||||
}
|
||||
|
||||
SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT);
|
||||
insertDAGNode(*CurDAG, SDValue(N, 0), NewCst);
|
||||
SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst);
|
||||
insertDAGNode(*CurDAG, SDValue(N, 0), NewBinOp);
|
||||
SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp,
|
||||
Shift.getOperand(1));
|
||||
ReplaceNode(N, NewSHL.getNode());
|
||||
SelectCode(NewSHL.getNode());
|
||||
return true;
|
||||
}
|
||||
|
||||
/// If the high bits of an 'and' operand are known zero, try setting the
|
||||
/// high bits of an 'and' constant operand to produce a smaller encoding by
|
||||
/// creating a small, sign-extended negative immediate rather than a large
|
||||
|
@ -4131,115 +4245,11 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
|
|||
|
||||
LLVM_FALLTHROUGH;
|
||||
case ISD::OR:
|
||||
case ISD::XOR: {
|
||||
case ISD::XOR:
|
||||
if (tryShrinkShlLogicImm(Node))
|
||||
return;
|
||||
break;
|
||||
|
||||
// For operations of the form (x << C1) op C2, check if we can use a smaller
|
||||
// encoding for C2 by transforming it into (x op (C2>>C1)) << C1.
|
||||
SDValue Shift = Node->getOperand(0);
|
||||
SDValue N1 = Node->getOperand(1);
|
||||
|
||||
ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N1);
|
||||
if (!Cst)
|
||||
break;
|
||||
|
||||
int64_t Val = Cst->getSExtValue();
|
||||
|
||||
// If we have an any_extend feeding the AND, look through it to see if there
|
||||
// is a shift behind it. But only if the AND doesn't use the extended bits.
|
||||
// FIXME: Generalize this to other ANY_EXTEND than i32 to i64?
|
||||
bool FoundAnyExtend = false;
|
||||
if (Shift.getOpcode() == ISD::ANY_EXTEND && Shift.hasOneUse() &&
|
||||
Shift.getOperand(0).getSimpleValueType() == MVT::i32 &&
|
||||
isUInt<32>(Val)) {
|
||||
FoundAnyExtend = true;
|
||||
Shift = Shift.getOperand(0);
|
||||
}
|
||||
|
||||
if (Shift.getOpcode() != ISD::SHL || !Shift.hasOneUse())
|
||||
break;
|
||||
|
||||
// i8 is unshrinkable, i16 should be promoted to i32.
|
||||
if (NVT != MVT::i32 && NVT != MVT::i64)
|
||||
break;
|
||||
|
||||
ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(Shift.getOperand(1));
|
||||
if (!ShlCst)
|
||||
break;
|
||||
|
||||
uint64_t ShAmt = ShlCst->getZExtValue();
|
||||
|
||||
// Make sure that we don't change the operation by removing bits.
|
||||
// This only matters for OR and XOR, AND is unaffected.
|
||||
uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1;
|
||||
if (Opcode != ISD::AND && (Val & RemovedBitsMask) != 0)
|
||||
break;
|
||||
|
||||
// Check the minimum bitwidth for the new constant.
|
||||
// TODO: Using 16 and 8 bit operations is also possible for or32 & xor32.
|
||||
auto CanShrinkImmediate = [&](int64_t &ShiftedVal) {
|
||||
if (Opcode == ISD::AND) {
|
||||
// AND32ri is the same as AND64ri32 with zext imm.
|
||||
// Try this before sign extended immediates below.
|
||||
ShiftedVal = (uint64_t)Val >> ShAmt;
|
||||
if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal))
|
||||
return true;
|
||||
// Also swap order when the AND can become MOVZX.
|
||||
if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX)
|
||||
return true;
|
||||
}
|
||||
ShiftedVal = Val >> ShAmt;
|
||||
if ((!isInt<8>(Val) && isInt<8>(ShiftedVal)) ||
|
||||
(!isInt<32>(Val) && isInt<32>(ShiftedVal)))
|
||||
return true;
|
||||
if (Opcode != ISD::AND) {
|
||||
// MOV32ri+OR64r/XOR64r is cheaper than MOV64ri64+OR64rr/XOR64rr
|
||||
ShiftedVal = (uint64_t)Val >> ShAmt;
|
||||
if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
int64_t ShiftedVal;
|
||||
if (!CanShrinkImmediate(ShiftedVal))
|
||||
break;
|
||||
|
||||
// Ok, we can reorder to get a smaller immediate.
|
||||
|
||||
// But, its possible the original immediate allowed an AND to become MOVZX.
|
||||
// Doing this late due to avoid the MakedValueIsZero call as late as
|
||||
// possible.
|
||||
if (Opcode == ISD::AND) {
|
||||
// Find the smallest zext this could possibly be.
|
||||
unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
|
||||
ZExtWidth = PowerOf2Ceil(std::max(ZExtWidth, 8U));
|
||||
|
||||
// Figure out which bits need to be zero to achieve that mask.
|
||||
APInt NeededMask = APInt::getLowBitsSet(NVT.getSizeInBits(),
|
||||
ZExtWidth);
|
||||
NeededMask &= ~Cst->getAPIntValue();
|
||||
|
||||
if (CurDAG->MaskedValueIsZero(Node->getOperand(0), NeededMask))
|
||||
break;
|
||||
}
|
||||
|
||||
SDValue X = Shift.getOperand(0);
|
||||
if (FoundAnyExtend) {
|
||||
SDValue NewX = CurDAG->getNode(ISD::ANY_EXTEND, dl, NVT, X);
|
||||
insertDAGNode(*CurDAG, SDValue(Node, 0), NewX);
|
||||
X = NewX;
|
||||
}
|
||||
|
||||
SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT);
|
||||
insertDAGNode(*CurDAG, SDValue(Node, 0), NewCst);
|
||||
SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst);
|
||||
insertDAGNode(*CurDAG, SDValue(Node, 0), NewBinOp);
|
||||
SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp,
|
||||
Shift.getOperand(1));
|
||||
ReplaceNode(Node, NewSHL.getNode());
|
||||
SelectCode(NewSHL.getNode());
|
||||
return;
|
||||
}
|
||||
case X86ISD::SMUL:
|
||||
// i16/i32/i64 are handled with isel patterns.
|
||||
if (NVT != MVT::i8)
|
||||
|
|
Loading…
Reference in New Issue