Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
Show First 20 Lines • Show All 5,031 Lines • ▼ Show 20 Lines | if (!SDValue(Node, 1).use_empty()) { | ||||
ReplaceUses(SDValue(Node, 1), Result); | ReplaceUses(SDValue(Node, 1), Result); | ||||
LLVM_DEBUG(dbgs() << "=> "; Result.getNode()->dump(CurDAG); | LLVM_DEBUG(dbgs() << "=> "; Result.getNode()->dump(CurDAG); | ||||
dbgs() << '\n'); | dbgs() << '\n'); | ||||
} | } | ||||
CurDAG->RemoveDeadNode(Node); | CurDAG->RemoveDeadNode(Node); | ||||
return; | return; | ||||
} | } | ||||
case X86ISD::CMP: { | case X86ISD::CMP: | ||||
SDValue N0 = Node->getOperand(0); | case X86ISD::STRICT_FCMP: | ||||
SDValue N1 = Node->getOperand(1); | case X86ISD::STRICT_FCMPS: { | ||||
bool IsStrictCmp = Node->getOpcode() == X86ISD::STRICT_FCMP || | |||||
Node->getOpcode() == X86ISD::STRICT_FCMPS; | |||||
SDValue N0 = Node->getOperand(IsStrictCmp ? 1 : 0); | |||||
SDValue N1 = Node->getOperand(IsStrictCmp ? 2 : 1); | |||||
// Save the original VT of the compare. | |||||
MVT CmpVT = N0.getSimpleValueType(); | |||||
// Floating point needs special handling if we don't have FCOMI. | |||||
// FIXME: Should we have a X86ISD::FCMP to avoid mixing int and fp? | |||||
if (CmpVT.isFloatingPoint()) { | |||||
if (Subtarget->hasCMov()) | |||||
break; | |||||
bool IsSignaling = Node->getOpcode() == X86ISD::STRICT_FCMPS; | |||||
unsigned Opc; | |||||
switch (CmpVT.SimpleTy) { | |||||
default: llvm_unreachable("Unexpected type!"); | |||||
case MVT::f32: | |||||
Opc = IsSignaling ? X86::COM_Fpr32 : X86::UCOM_Fpr32; | |||||
break; | |||||
case MVT::f64: | |||||
Opc = IsSignaling ? X86::COM_Fpr64 : X86::UCOM_Fpr64; | |||||
break; | |||||
case MVT::f80: | |||||
Opc = IsSignaling ? X86::COM_Fpr80 : X86::UCOM_Fpr80; | |||||
break; | |||||
} | |||||
SDValue Cmp; | |||||
SDValue Chain = | |||||
IsStrictCmp ? Node->getOperand(0) : CurDAG->getEntryNode(); | |||||
if (IsStrictCmp) { | |||||
SDVTList VTs = CurDAG->getVTList(MVT::i16, MVT::Other); | |||||
Cmp = SDValue(CurDAG->getMachineNode(Opc, dl, VTs, {N0, N1, Chain}), 0); | |||||
Chain = Cmp.getValue(1); | |||||
} else { | |||||
Cmp = SDValue(CurDAG->getMachineNode(Opc, dl, MVT::i16, N0, N1), 0); | |||||
} | |||||
// Move FPSW to AX. | |||||
SDValue FPSW = CurDAG->getCopyToReg(Chain, dl, X86::FPSW, Cmp, SDValue()); | |||||
Chain = FPSW; | |||||
SDValue FNSTSW = | |||||
SDValue(CurDAG->getMachineNode(X86::FNSTSW16r, dl, MVT::i16, FPSW, | |||||
FPSW.getValue(1)), | |||||
0); | |||||
// Extract upper 8-bits of AX. | |||||
SDValue Extract = | |||||
CurDAG->getTargetExtractSubreg(X86::sub_8bit_hi, dl, MVT::i8, FNSTSW); | |||||
// Move AH into flags. | |||||
// Some 64-bit targets lack SAHF support, but they do support FCOMI. | |||||
assert(Subtarget->hasLAHFSAHF() && | |||||
"Target doesn't support SAHF or FCOMI?"); | |||||
SDValue AH = CurDAG->getCopyToReg(Chain, dl, X86::AH, Extract, SDValue()); | |||||
Chain = AH; | |||||
SDValue SAHF = SDValue( | |||||
CurDAG->getMachineNode(X86::SAHF, dl, MVT::i32, AH.getValue(1)), 0); | |||||
if (IsStrictCmp) | |||||
ReplaceUses(SDValue(Node, 1), Chain); | |||||
ReplaceUses(SDValue(Node, 0), SAHF); | |||||
CurDAG->RemoveDeadNode(Node); | |||||
return; | |||||
} | |||||
// Optimizations for TEST compares. | // Optimizations for TEST compares. | ||||
if (!isNullConstant(N1)) | if (!isNullConstant(N1)) | ||||
break; | break; | ||||
// Save the original VT of the compare. | |||||
MVT CmpVT = N0.getSimpleValueType(); | |||||
// If we are comparing (and (shr X, C, Mask) with 0, emit a BEXTR followed | // If we are comparing (and (shr X, C, Mask) with 0, emit a BEXTR followed | ||||
// by a test instruction. The test should be removed later by | // by a test instruction. The test should be removed later by | ||||
// analyzeCompare if we are using only the zero flag. | // analyzeCompare if we are using only the zero flag. | ||||
// TODO: Should we check the users and use the BEXTR flags directly? | // TODO: Should we check the users and use the BEXTR flags directly? | ||||
if (N0.getOpcode() == ISD::AND && N0.hasOneUse()) { | if (N0.getOpcode() == ISD::AND && N0.hasOneUse()) { | ||||
if (MachineSDNode *NewNode = matchBEXTRFromAndImm(N0.getNode())) { | if (MachineSDNode *NewNode = matchBEXTRFromAndImm(N0.getNode())) { | ||||
unsigned TestOpc = CmpVT == MVT::i64 ? X86::TEST64rr | unsigned TestOpc = CmpVT == MVT::i64 ? X86::TEST64rr | ||||
: X86::TEST32rr; | : X86::TEST32rr; | ||||
▲ Show 20 Lines • Show All 249 Lines • Show Last 20 Lines |