mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-01 00:17:01 +00:00
X86: Don't emit conditional floating point moves on when targeting pre-pentiumpro architectures.
* Model FPSW (the FPU status word) as a register. * Add ISel patterns for the FUCOM*, FNSTSW and SAHF instructions. * During Legalize/Lowering, build a node sequence to transfer the comparison result from FPSW into EFLAGS. If you're wondering about the right-shift: That's an implicit sub-register extraction (%ax -> %ah) which is handled later on by the instruction selector. Fixes PR6679. Patch by Christoph Erhardt! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155704 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -8214,6 +8214,30 @@ SDValue X86TargetLowering::EmitCmp(SDValue Op0, SDValue Op1, unsigned X86CC,
|
||||
return DAG.getNode(X86ISD::CMP, dl, MVT::i32, Op0, Op1);
|
||||
}
|
||||
|
||||
/// Convert a comparison if required by the subtarget.
|
||||
SDValue X86TargetLowering::ConvertCmpIfNecessary(SDValue Cmp,
|
||||
SelectionDAG &DAG) const {
|
||||
// If the subtarget does not support the FUCOMI instruction, floating-point
|
||||
// comparisons have to be converted.
|
||||
if (Subtarget->hasCMov() ||
|
||||
Cmp.getOpcode() != X86ISD::CMP ||
|
||||
!Cmp.getOperand(0).getValueType().isFloatingPoint() ||
|
||||
!Cmp.getOperand(1).getValueType().isFloatingPoint())
|
||||
return Cmp;
|
||||
|
||||
// The instruction selector will select an FUCOM instruction instead of
|
||||
// FUCOMI, which writes the comparison result to FPSW instead of EFLAGS. Hence
|
||||
// build an SDNode sequence that transfers the result from FPSW into EFLAGS:
|
||||
// (X86sahf (trunc (srl (X86fp_stsw (trunc (X86cmp ...)), 8))))
|
||||
DebugLoc dl = Cmp.getDebugLoc();
|
||||
SDValue TruncFPSW = DAG.getNode(ISD::TRUNCATE, dl, MVT::i16, Cmp);
|
||||
SDValue FNStSW = DAG.getNode(X86ISD::FNSTSW16r, dl, MVT::i16, TruncFPSW);
|
||||
SDValue Srl = DAG.getNode(ISD::SRL, dl, MVT::i16, FNStSW,
|
||||
DAG.getConstant(8, MVT::i8));
|
||||
SDValue TruncSrl = DAG.getNode(ISD::TRUNCATE, dl, MVT::i8, Srl);
|
||||
return DAG.getNode(X86ISD::SAHF, dl, MVT::i32, TruncSrl);
|
||||
}
|
||||
|
||||
/// LowerToBT - Result of 'and' is compared against zero. Turn it into a BT node
|
||||
/// if it's possible.
|
||||
SDValue X86TargetLowering::LowerToBT(SDValue And, ISD::CondCode CC,
|
||||
@@ -8335,6 +8359,7 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
|
||||
return SDValue();
|
||||
|
||||
SDValue EFLAGS = EmitCmp(Op0, Op1, X86CC, DAG);
|
||||
EFLAGS = ConvertCmpIfNecessary(EFLAGS, DAG);
|
||||
return DAG.getNode(X86ISD::SETCC, dl, MVT::i8,
|
||||
DAG.getConstant(X86CC, MVT::i8), EFLAGS);
|
||||
}
|
||||
@@ -8503,7 +8528,8 @@ SDValue X86TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) const {
|
||||
// isX86LogicalCmp - Return true if opcode is a X86 logical comparison.
|
||||
static bool isX86LogicalCmp(SDValue Op) {
|
||||
unsigned Opc = Op.getNode()->getOpcode();
|
||||
if (Opc == X86ISD::CMP || Opc == X86ISD::COMI || Opc == X86ISD::UCOMI)
|
||||
if (Opc == X86ISD::CMP || Opc == X86ISD::COMI || Opc == X86ISD::UCOMI ||
|
||||
Opc == X86ISD::SAHF)
|
||||
return true;
|
||||
if (Op.getResNo() == 1 &&
|
||||
(Opc == X86ISD::ADD ||
|
||||
@@ -8567,6 +8593,7 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
|
||||
SDValue CmpOp0 = Cmp.getOperand(0);
|
||||
Cmp = DAG.getNode(X86ISD::CMP, DL, MVT::i32,
|
||||
CmpOp0, DAG.getConstant(1, CmpOp0.getValueType()));
|
||||
Cmp = ConvertCmpIfNecessary(Cmp, DAG);
|
||||
|
||||
SDValue Res = // Res = 0 or -1.
|
||||
DAG.getNode(X86ISD::SETCC_CARRY, DL, Op.getValueType(),
|
||||
@@ -8673,6 +8700,7 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
|
||||
// a >= b ? -1 : 0 -> RES = setcc_carry
|
||||
// a >= b ? 0 : -1 -> RES = ~setcc_carry
|
||||
if (Cond.getOpcode() == X86ISD::CMP) {
|
||||
Cond = ConvertCmpIfNecessary(Cond, DAG);
|
||||
unsigned CondCode = cast<ConstantSDNode>(CC)->getZExtValue();
|
||||
|
||||
if ((CondCode == X86::COND_AE || CondCode == X86::COND_B) &&
|
||||
@@ -8911,6 +8939,7 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
|
||||
|
||||
SDValue Cmp = DAG.getNode(X86ISD::CMP, dl, MVT::i32,
|
||||
Cond.getOperand(0), Cond.getOperand(1));
|
||||
Cmp = ConvertCmpIfNecessary(Cmp, DAG);
|
||||
CC = DAG.getConstant(X86::COND_NE, MVT::i8);
|
||||
Chain = DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(),
|
||||
Chain, Dest, CC, Cmp);
|
||||
@@ -8940,6 +8969,7 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
|
||||
|
||||
SDValue Cmp = DAG.getNode(X86ISD::CMP, dl, MVT::i32,
|
||||
Cond.getOperand(0), Cond.getOperand(1));
|
||||
Cmp = ConvertCmpIfNecessary(Cmp, DAG);
|
||||
CC = DAG.getConstant(X86::COND_NE, MVT::i8);
|
||||
Chain = DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(),
|
||||
Chain, Dest, CC, Cmp);
|
||||
@@ -8973,6 +9003,7 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
|
||||
CC = DAG.getConstant(X86::COND_NE, MVT::i8);
|
||||
Cond = EmitTest(Cond, X86::COND_NE, DAG);
|
||||
}
|
||||
Cond = ConvertCmpIfNecessary(Cond, DAG);
|
||||
return DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(),
|
||||
Chain, Dest, CC, Cond);
|
||||
}
|
||||
@@ -11111,6 +11142,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN";
|
||||
case X86ISD::TC_RETURN: return "X86ISD::TC_RETURN";
|
||||
case X86ISD::FNSTCW16m: return "X86ISD::FNSTCW16m";
|
||||
case X86ISD::FNSTSW16r: return "X86ISD::FNSTSW16r";
|
||||
case X86ISD::LCMPXCHG_DAG: return "X86ISD::LCMPXCHG_DAG";
|
||||
case X86ISD::LCMPXCHG8_DAG: return "X86ISD::LCMPXCHG8_DAG";
|
||||
case X86ISD::ATOMADD64_DAG: return "X86ISD::ATOMADD64_DAG";
|
||||
@@ -11179,6 +11211,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::MEMBARRIER: return "X86ISD::MEMBARRIER";
|
||||
case X86ISD::SEG_ALLOCA: return "X86ISD::SEG_ALLOCA";
|
||||
case X86ISD::WIN_FTOL: return "X86ISD::WIN_FTOL";
|
||||
case X86ISD::SAHF: return "X86ISD::SAHF";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user