Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
lib/Target/X86/X86ISelLowering.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 33,122 Lines • ▼ Show 20 Lines | static SDValue combineOrCmpEqZeroToCtlzSrl(SDNode *N, SelectionDAG &DAG, | ||||
} | } | ||||
if (Ret) | if (Ret) | ||||
Ret = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), N->getValueType(0), Ret); | Ret = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), N->getValueType(0), Ret); | ||||
return Ret; | return Ret; | ||||
} | } | ||||
static SDValue getShiftDoubleNode(SDNode *N, SelectionDAG &DAG, unsigned Opc, | |||||
EVT VT, EVT OpVT, const SDValue &Op0, | |||||
const SDValue &Op1, const SDValue &ShAmt) { | |||||
SDLoc DL(N); | |||||
unsigned Bits = OpVT.getScalarSizeInBits(); | |||||
SDValue ShAmtI8 = DAG.getNode(ISD::TRUNCATE, DL, MVT::i8, ShAmt); | |||||
if ((VT == MVT::i64 || VT == MVT::i32) && VT == OpVT) { | |||||
return DAG.getNode(Opc, DL, VT, Op0, Op1, ShAmtI8); | |||||
} else if (OpVT == MVT::i16) { | |||||
SDValue Op0I16 = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Op0); | |||||
SDValue Op1I16 = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Op1); | |||||
SDValue ShDbl = DAG.getNode(Opc, DL, OpVT, Op0I16, Op1I16, ShAmtI8); | |||||
return DAG.getNode(ISD::ZERO_EXTEND, DL, VT, ShDbl); | |||||
} else if (OpVT == MVT::i8) { | |||||
if (Opc == X86ISD::SHLD) { | |||||
SDValue Op1ShAmt = | |||||
DAG.getConstant(VT.getSizeInBits() - Bits, DL, MVT::i8); | |||||
SDValue Op1Shl = DAG.getNode(ISD::SHL, DL, VT, Op1, Op1ShAmt); | |||||
return DAG.getNode(Opc, DL, VT, Op0, Op1Shl, ShAmtI8); | |||||
} else if (Opc == X86ISD::SHRD) { | |||||
SDValue Op0ShAmt = | |||||
DAG.getConstant(VT.getSizeInBits() - Bits, DL, MVT::i8); | |||||
SDValue Op0Shl = DAG.getNode(ISD::SHL, DL, VT, Op0, Op0ShAmt); | |||||
SDValue Op0Shrd = DAG.getNode(Opc, DL, VT, Op0Shl, Op1, ShAmtI8); | |||||
return DAG.getNode(ISD::SRL, DL, VT, Op0Shrd, Op0ShAmt); | |||||
} | |||||
} | |||||
return SDValue(); | |||||
} | |||||
static SDValue combineOr(SDNode *N, SelectionDAG &DAG, | static SDValue combineOr(SDNode *N, SelectionDAG &DAG, | ||||
TargetLowering::DAGCombinerInfo &DCI, | TargetLowering::DAGCombinerInfo &DCI, | ||||
const X86Subtarget &Subtarget) { | const X86Subtarget &Subtarget) { | ||||
if (DCI.isBeforeLegalizeOps()) | if (DCI.isBeforeLegalizeOps()) | ||||
return SDValue(); | return SDValue(); | ||||
if (SDValue R = combineCompareEqual(N, DAG, DCI, Subtarget)) | if (SDValue R = combineCompareEqual(N, DAG, DCI, Subtarget)) | ||||
return R; | return R; | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | static SDValue combineOr(SDNode *N, SelectionDAG &DAG, | ||||
// OR( SRL( X, C ), SHL( Y, 32 - C ) ) -> SHRD( X, Y, C ) | // OR( SRL( X, C ), SHL( Y, 32 - C ) ) -> SHRD( X, Y, C ) | ||||
// OR( SHL( X, C ), SRL( SRL( Y, 1 ), XOR( C, 31 ) ) ) -> SHLD( X, Y, C ) | // OR( SHL( X, C ), SRL( SRL( Y, 1 ), XOR( C, 31 ) ) ) -> SHLD( X, Y, C ) | ||||
// OR( SRL( X, C ), SHL( SHL( Y, 1 ), XOR( C, 31 ) ) ) -> SHRD( X, Y, C ) | // OR( SRL( X, C ), SHL( SHL( Y, 1 ), XOR( C, 31 ) ) ) -> SHRD( X, Y, C ) | ||||
unsigned Bits = VT.getSizeInBits(); | unsigned Bits = VT.getSizeInBits(); | ||||
if (ShAmt1.getOpcode() == ISD::SUB) { | if (ShAmt1.getOpcode() == ISD::SUB) { | ||||
SDValue Sum = ShAmt1.getOperand(0); | SDValue Sum = ShAmt1.getOperand(0); | ||||
if (ConstantSDNode *SumC = dyn_cast<ConstantSDNode>(Sum)) { | if (ConstantSDNode *SumC = dyn_cast<ConstantSDNode>(Sum)) { | ||||
SDValue ShAmt1Op1 = ShAmt1.getOperand(1); | SDValue ShAmt1Op1 = ShAmt1.getOperand(1); | ||||
if (ShAmt1Op1.getOpcode() == ISD::TRUNCATE) | if ((ShAmt1Op1.getOpcode() == ISD::TRUNCATE) || | ||||
(ShAmt1Op1.getOpcode() == ISD::ANY_EXTEND)) | |||||
ShAmt1Op1 = ShAmt1Op1.getOperand(0); | ShAmt1Op1 = ShAmt1Op1.getOperand(0); | ||||
if (SumC->getSExtValue() == Bits && ShAmt1Op1 == ShAmt0) | if (SumC->getSExtValue() == Bits && ShAmt1Op1 == ShAmt0) { | ||||
return DAG.getNode(Opc, DL, VT, | return DAG.getNode(Opc, DL, VT, Op0, Op1, | ||||
Op0, Op1, | DAG.getNode(ISD::TRUNCATE, DL, MVT::i8, ShAmt0)); | ||||
DAG.getNode(ISD::TRUNCATE, DL, | } | ||||
MVT::i8, ShAmt0)); | if ((Op0.getOpcode() == ISD::AssertZext && | ||||
Op1.getOpcode() == ISD::AssertZext) && | |||||
ShAmt1Op1 == ShAmt0) { | |||||
// Op0 is ZEXT(Y, i16) | |||||
SDValue Op0Zext = Op0.getOperand(1); | |||||
VTSDNode *Op0VT = cast<VTSDNode>(Op0Zext); | |||||
// Op1 is ZEXT(X, i16) | |||||
SDValue Op1Zext = Op1.getOperand(1); | |||||
VTSDNode *Op1VT = cast<VTSDNode>(Op1Zext); | |||||
if (Op0VT && Op1VT && (Op0VT->getVT() == Op1VT->getVT()) && | |||||
(Op0VT->getVT() == MVT::i16 || Op0VT->getVT() == MVT::i8)) { | |||||
return getShiftDoubleNode(N, DAG, Opc, VT, Op0VT->getVT(), Op0, Op1, | |||||
ShAmt0); | |||||
} | |||||
} | |||||
if ((Op0.getOpcode() == ISD::LOAD && Op1.getOpcode() == ISD::LOAD) && | |||||
ShAmt1Op1 == ShAmt0) { | |||||
LoadSDNode *Op0Ld = cast<LoadSDNode>(Op0); | |||||
LoadSDNode *Op1Ld = cast<LoadSDNode>(Op1); | |||||
EVT Op0LdVT = Op0Ld->getMemoryVT(); | |||||
EVT Op1LdVT = Op1Ld->getMemoryVT(); | |||||
// If this is a ZEXTLoad. | |||||
if (Op0Ld && Op1Ld && ((Op0LdVT == MVT::i8) || (Op0LdVT == MVT::i16)) && | |||||
(Op0LdVT == Op1LdVT) && | |||||
(ISD::LoadExtType::ZEXTLOAD == Op0Ld->getExtensionType()) && | |||||
(ISD::LoadExtType::ZEXTLOAD == Op1Ld->getExtensionType())) | |||||
{ | |||||
return getShiftDoubleNode(N, DAG, Opc, VT, Op0LdVT, Op0, Op1, ShAmt0); | |||||
} | |||||
} | |||||
//----------------------------------------- | |||||
} | } | ||||
} else if (ConstantSDNode *ShAmt1C = dyn_cast<ConstantSDNode>(ShAmt1)) { | } else if (ConstantSDNode *ShAmt1C = dyn_cast<ConstantSDNode>(ShAmt1)) { | ||||
ConstantSDNode *ShAmt0C = dyn_cast<ConstantSDNode>(ShAmt0); | ConstantSDNode *ShAmt0C = dyn_cast<ConstantSDNode>(ShAmt0); | ||||
if (ShAmt0C && (ShAmt0C->getSExtValue() + ShAmt1C->getSExtValue()) == Bits) | if (ShAmt0C && (ShAmt0C->getSExtValue() + ShAmt1C->getSExtValue()) == Bits) | ||||
return DAG.getNode(Opc, DL, VT, | return DAG.getNode(Opc, DL, VT, N0.getOperand(0), N1.getOperand(0), | ||||
N0.getOperand(0), N1.getOperand(0), | DAG.getNode(ISD::TRUNCATE, DL, MVT::i8, ShAmt0)); | ||||
DAG.getNode(ISD::TRUNCATE, DL, | |||||
MVT::i8, ShAmt0)); | |||||
} else if (ShAmt1.getOpcode() == ISD::XOR) { | } else if (ShAmt1.getOpcode() == ISD::XOR) { | ||||
SDValue Mask = ShAmt1.getOperand(1); | SDValue Mask = ShAmt1.getOperand(1); | ||||
if (ConstantSDNode *MaskC = dyn_cast<ConstantSDNode>(Mask)) { | if (ConstantSDNode *MaskC = dyn_cast<ConstantSDNode>(Mask)) { | ||||
unsigned InnerShift = (X86ISD::SHLD == Opc ? ISD::SRL : ISD::SHL); | unsigned InnerShift = (X86ISD::SHLD == Opc ? ISD::SRL : ISD::SHL); | ||||
SDValue ShAmt1Op0 = ShAmt1.getOperand(0); | SDValue ShAmt1Op0 = ShAmt1.getOperand(0); | ||||
if (ShAmt1Op0.getOpcode() == ISD::TRUNCATE) | if (ShAmt1Op0.getOpcode() == ISD::TRUNCATE) | ||||
ShAmt1Op0 = ShAmt1Op0.getOperand(0); | ShAmt1Op0 = ShAmt1Op0.getOperand(0); | ||||
if (MaskC->getSExtValue() == (Bits - 1) && ShAmt1Op0 == ShAmt0) { | if (MaskC->getSExtValue() == (Bits - 1) && ShAmt1Op0 == ShAmt0) { | ||||
if (Op1.getOpcode() == InnerShift && | if (Op1.getOpcode() == InnerShift && | ||||
isa<ConstantSDNode>(Op1.getOperand(1)) && | isa<ConstantSDNode>(Op1.getOperand(1)) && | ||||
Op1.getConstantOperandVal(1) == 1) { | Op1.getConstantOperandVal(1) == 1) { | ||||
return DAG.getNode(Opc, DL, VT, Op0, Op1.getOperand(0), | return DAG.getNode(Opc, DL, VT, Op0, Op1.getOperand(0), | ||||
DAG.getNode(ISD::TRUNCATE, DL, MVT::i8, ShAmt0)); | DAG.getNode(ISD::TRUNCATE, DL, MVT::i8, ShAmt0)); | ||||
} | } | ||||
// Test for ADD( Y, Y ) as an equivalent to SHL( Y, 1 ). | // Test for ADD( Y, Y ) as an equivalent to SHL( Y, 1 ). | ||||
if (InnerShift == ISD::SHL && Op1.getOpcode() == ISD::ADD && | if (InnerShift == ISD::SHL && Op1.getOpcode() == ISD::ADD && | ||||
Op1.getOperand(0) == Op1.getOperand(1)) { | Op1.getOperand(0) == Op1.getOperand(1)) { | ||||
return DAG.getNode(Opc, DL, VT, Op0, Op1.getOperand(0), | return DAG.getNode(Opc, DL, VT, Op0, Op1.getOperand(0), | ||||
DAG.getNode(ISD::TRUNCATE, DL, MVT::i8, ShAmt0)); | DAG.getNode(ISD::TRUNCATE, DL, MVT::i8, ShAmt0)); | ||||
} | } | ||||
} | } | ||||
// ShAmpt1 node can be: XOR( ZEXT(C, i16), MASK) or it can be: XOR( C, | |||||
// MASK) | |||||
SDValue ShAmt1Zext = ShAmt1.getOperand(0); | |||||
if (ShAmt1Zext.getOpcode() == ISD::TRUNCATE) | |||||
ShAmt1Zext = ShAmt1Zext.getOperand(0); | |||||
SDValue ShAmt1Const = ShAmt1.getOperand(1); | |||||
ConstantSDNode *XorMaskConst = dyn_cast<ConstantSDNode>(ShAmt1Const); | |||||
// Op1 node is either SHL( ZEXT(Y, i16), 1) or SRL( ZEXT(Y, i16), 1) or | |||||
// SHL( LOAD(Y, i16), 1) | |||||
SDValue Op1Zext = Op1.getOperand(0); | |||||
SDValue Op1Const = Op1.getOperand(1); | |||||
ConstantSDNode *OneConst = dyn_cast<ConstantSDNode>(Op1Const); | |||||
// Check for operands that were promoted to integer | |||||
if ((Op0.getOpcode() == ISD::AssertZext) && | |||||
(Op1.getOpcode() == ISD::SHL || Op1.getOpcode() == ISD::SRL) && | |||||
XorMaskConst && OneConst && (OneConst->getSExtValue() == 1) && | |||||
(Op1Zext.getOpcode() == ISD::AssertZext)) { | |||||
// Op0 node is ZEXT( X, i16) | |||||
// SDValue OpX = Op0.getOperand(0); // X (bits to shift) operand | |||||
SDValue Op0Prom = | |||||
Op0.getOperand(1); // X operand type before integer promotion | |||||
VTSDNode *Op0PromVT = cast<VTSDNode>(Op0Prom); | |||||
// ShAmt0 node can be: ZEXT( C, i16) or it can be CopyFromReg(C) | |||||
EVT ShAmt0VT; | |||||
SDValue ShAmt0Prom; // C (shift amount) operand | |||||
if (ShAmt0.getOpcode() == ISD::AssertZext) { | |||||
ShAmt0Prom = ShAmt0.getOperand(0); // C (shift amount) operand | |||||
SDValue ShAmt0PromType = | |||||
ShAmt0.getOperand(1); // C operand type before integer promotion | |||||
VTSDNode *ShAmt0PromVT = cast<VTSDNode>(ShAmt0PromType); | |||||
ShAmt0VT = ShAmt0PromVT->getVT(); | |||||
} else { | |||||
ShAmt0Prom = ShAmt0; | |||||
ShAmt0VT = ShAmt0.getValueType(); | |||||
} | |||||
// Op1Zext is ZEXT(Y, i16) | |||||
// SDValue OpY = Op1Zext.getOperand(0); // Y (bits source) operand | |||||
SDValue Op1Prom = | |||||
Op1Zext.getOperand(1); // Y operand type before integer promotion | |||||
VTSDNode *Op1PromVT = cast<VTSDNode>(Op1Prom); | |||||
// ShAmt1Zext node is ZEXT( C, i16) or it can be CopyFromReg(C) | |||||
EVT ShAmt1VT; | |||||
SDValue ShAmt1Prom; // C (shift amount) operand | |||||
if (ShAmt1Zext.getOpcode() == ISD::AssertZext) { | |||||
ShAmt1Prom = ShAmt1Zext.getOperand(0); // C (shift amount) operand | |||||
SDValue ShAmt1PromType = ShAmt1Zext.getOperand( | |||||
1); // C operand type before integer promotion | |||||
VTSDNode *ShAmt1PromVT = cast<VTSDNode>(ShAmt1PromType); | |||||
ShAmt1VT = ShAmt1PromVT->getVT(); | |||||
} else { | |||||
ShAmt1Prom = ShAmt1Zext; // C (shift amount) operand | |||||
ShAmt1VT = ShAmt1Zext.getValueType(); | |||||
} | |||||
if (Op0PromVT && Op1PromVT && | |||||
(Op0PromVT->getVT() == Op1PromVT->getVT()) && | |||||
(ShAmt0VT == ShAmt1VT) && (ShAmt0Prom == ShAmt1Prom) && | |||||
(Op0PromVT->getVT() == MVT::i16 || Op0PromVT->getVT() == MVT::i8)) { | |||||
unsigned OpXBits = Op0PromVT->getVT().getSizeInBits(); | |||||
if (XorMaskConst->getSExtValue() == (OpXBits - 1)) { | |||||
return getShiftDoubleNode(N, DAG, Opc, VT, Op0PromVT->getVT(), Op0, | |||||
Op1Zext, ShAmt0); | |||||
} | |||||
} | |||||
} | |||||
// Op1 node is either SHL( LOAD(Y, i16), 1) or SRL( LOAD(Y, i16), 1) | |||||
SDValue Op1Load = Op1.getOperand(0); | |||||
// ShAmpt1 node can be: XOR( LOAD(C, i16), MASK) or it can be: XOR( C, | |||||
// MASK) | |||||
SDValue ShAmt1Load = ShAmt1.getOperand(0); | |||||
if (ShAmt1Load.getOpcode() == ISD::TRUNCATE) | |||||
ShAmt1Load = ShAmt1Load.getOperand(0); | |||||
// Check for operands that were loaded from memory and promoted to integer | |||||
if ((Op0.getOpcode() == ISD::LOAD && | |||||
(Op1.getOpcode() == ISD::SHL || Op1.getOpcode() == ISD::SRL) && | |||||
XorMaskConst && OneConst && (OneConst->getSExtValue() == 1) && | |||||
(Op1Load.getOpcode() == ISD::LOAD))) { | |||||
// Op0 node is LOAD( X, i16) | |||||
LoadSDNode *Op0Ld = cast<LoadSDNode>(Op0); | |||||
EVT Op0VT = Op0Ld->getMemoryVT(); | |||||
// ShAmt0 node can be: LOAD(C, zext i16) or it can be CopyFromReg(C) | |||||
EVT ShAmt0VT; | |||||
if (ShAmt0.getOpcode() == ISD::LOAD) { | |||||
LoadSDNode *ShAmt0Ld = cast<LoadSDNode>(ShAmt0); | |||||
ShAmt0VT = ShAmt0Ld->getMemoryVT(); | |||||
} else { | |||||
ShAmt0VT = ShAmt0.getValueType(); | |||||
} | |||||
// Op1Load is LOAD(Y, i16) | |||||
LoadSDNode *Op1Ld = cast<LoadSDNode>(Op1Load); | |||||
EVT Op1VT = Op1Ld->getMemoryVT(); | |||||
// ShAmt1Load node is LOAD(C, zext i16) or it can be CopyFromReg(C) | |||||
EVT ShAmt1VT; | |||||
if (ShAmt1Load.getOpcode() == ISD::LOAD) { | |||||
LoadSDNode *ShAmt1Ld = cast<LoadSDNode>(ShAmt1Load); | |||||
ShAmt1VT = ShAmt1Ld->getMemoryVT(); | |||||
} else { | |||||
ShAmt1VT = ShAmt1Load.getValueType(); | |||||
} | |||||
if ((Op0VT == Op1VT) && (ShAmt0VT == ShAmt1VT) && | |||||
(ShAmt0 == ShAmt1Load) && (Op0VT == MVT::i16 || Op0VT == MVT::i8)) { | |||||
unsigned Op0Bits = Op0VT.getSizeInBits(); | |||||
if (XorMaskConst->getSExtValue() == (Op0Bits - 1)) { | |||||
return getShiftDoubleNode(N, DAG, Opc, VT, Op0VT, Op0, Op1Load, | |||||
ShAmt0); | |||||
} | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
return SDValue(); | return SDValue(); | ||||
} | } | ||||
/// Try to turn tests against the signbit in the form of: | /// Try to turn tests against the signbit in the form of: | ||||
/// XOR(TRUNCATE(SRL(X, size(X)-1)), 1) | /// XOR(TRUNCATE(SRL(X, size(X)-1)), 1) | ||||
▲ Show 20 Lines • Show All 4,677 Lines • Show Last 20 Lines |