mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
implement unordered floating point compares
llvm-svn: 30928
This commit is contained in:
parent
a053c74b99
commit
bd50a4d757
@ -92,6 +92,7 @@ namespace llvm {
|
|||||||
RET_FLAG,
|
RET_FLAG,
|
||||||
|
|
||||||
CMP,
|
CMP,
|
||||||
|
CMPE,
|
||||||
|
|
||||||
SELECT,
|
SELECT,
|
||||||
|
|
||||||
@ -118,30 +119,56 @@ namespace llvm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DAGCCToARMCC - Convert a DAG integer condition code to an ARM CC
|
/// DAGFPCCToARMCC - Convert a DAG fp condition code to an ARM CC
|
||||||
//Note: ARM doesn't have condition codes corresponding to the ordered
|
static ARMCC::CondCodes DAGFPCCToARMCC(ISD::CondCode CC) {
|
||||||
//condition codes of LLVM. We use exception raising instructions so
|
|
||||||
//that we can be sure that V == 0 and test only the rest of the expression.
|
|
||||||
static ARMCC::CondCodes DAGCCToARMCC(ISD::CondCode CC) {
|
|
||||||
switch (CC) {
|
switch (CC) {
|
||||||
default:
|
default:
|
||||||
std::cerr << "CC = " << CC << "\n";
|
assert(0 && "Unknown fp condition code!");
|
||||||
assert(0 && "Unknown condition code!");
|
// For the following conditions we use a comparison that throws exceptions,
|
||||||
case ISD::SETUGT: return ARMCC::HI;
|
// so we may assume that V=0
|
||||||
case ISD::SETULE: return ARMCC::LS;
|
|
||||||
case ISD::SETLE:
|
|
||||||
case ISD::SETOLE: return ARMCC::LE;
|
|
||||||
case ISD::SETLT:
|
|
||||||
case ISD::SETOLT: return ARMCC::LT;
|
|
||||||
case ISD::SETGT:
|
|
||||||
case ISD::SETOGT: return ARMCC::GT;
|
|
||||||
case ISD::SETNE: return ARMCC::NE;
|
|
||||||
case ISD::SETEQ:
|
|
||||||
case ISD::SETOEQ: return ARMCC::EQ;
|
case ISD::SETOEQ: return ARMCC::EQ;
|
||||||
case ISD::SETGE:
|
case ISD::SETOGT: return ARMCC::GT;
|
||||||
case ISD::SETOGE: return ARMCC::GE;
|
case ISD::SETOGE: return ARMCC::GE;
|
||||||
case ISD::SETUGE: return ARMCC::CS;
|
case ISD::SETOLT: return ARMCC::LT;
|
||||||
|
case ISD::SETOLE: return ARMCC::LE;
|
||||||
|
case ISD::SETONE: return ARMCC::NE;
|
||||||
|
// For the following conditions the result is undefined in case of a nan,
|
||||||
|
// so we may assume that V=0
|
||||||
|
case ISD::SETEQ: return ARMCC::EQ;
|
||||||
|
case ISD::SETGT: return ARMCC::GT;
|
||||||
|
case ISD::SETGE: return ARMCC::GE;
|
||||||
|
case ISD::SETLT: return ARMCC::LT;
|
||||||
|
case ISD::SETLE: return ARMCC::LE;
|
||||||
|
case ISD::SETNE: return ARMCC::NE;
|
||||||
|
// For the following we may not assume anything
|
||||||
|
// SETO = N | Z | !C | !V = ???
|
||||||
|
// SETUO = (!N & !Z & C & V) = ???
|
||||||
|
// SETUEQ = (!N & !Z & C & V) | Z = ???
|
||||||
|
// SETUGT = (!N & !Z & C & V) | (!Z & !N) = ???
|
||||||
|
// SETUGE = (!N & !Z & C & V) | !N = !N = PL
|
||||||
|
case ISD::SETUGE: return ARMCC::PL;
|
||||||
|
// SETULT = (!N & !Z & C & V) | N = ???
|
||||||
|
// SETULE = (!N & !Z & C & V) | Z | N = ???
|
||||||
|
// SETUNE = (!N & !Z & C & V) | !Z = !Z = NE
|
||||||
|
case ISD::SETUNE: return ARMCC::NE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// DAGIntCCToARMCC - Convert a DAG integer condition code to an ARM CC
|
||||||
|
static ARMCC::CondCodes DAGIntCCToARMCC(ISD::CondCode CC) {
|
||||||
|
switch (CC) {
|
||||||
|
default:
|
||||||
|
assert(0 && "Unknown integer condition code!");
|
||||||
|
case ISD::SETEQ: return ARMCC::EQ;
|
||||||
|
case ISD::SETNE: return ARMCC::NE;
|
||||||
|
case ISD::SETLT: return ARMCC::LT;
|
||||||
|
case ISD::SETLE: return ARMCC::LE;
|
||||||
|
case ISD::SETGT: return ARMCC::GT;
|
||||||
|
case ISD::SETGE: return ARMCC::GE;
|
||||||
case ISD::SETULT: return ARMCC::CC;
|
case ISD::SETULT: return ARMCC::CC;
|
||||||
|
case ISD::SETULE: return ARMCC::LS;
|
||||||
|
case ISD::SETUGT: return ARMCC::HI;
|
||||||
|
case ISD::SETUGE: return ARMCC::CS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,6 +179,7 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||||||
case ARMISD::RET_FLAG: return "ARMISD::RET_FLAG";
|
case ARMISD::RET_FLAG: return "ARMISD::RET_FLAG";
|
||||||
case ARMISD::SELECT: return "ARMISD::SELECT";
|
case ARMISD::SELECT: return "ARMISD::SELECT";
|
||||||
case ARMISD::CMP: return "ARMISD::CMP";
|
case ARMISD::CMP: return "ARMISD::CMP";
|
||||||
|
case ARMISD::CMPE: return "ARMISD::CMPE";
|
||||||
case ARMISD::BR: return "ARMISD::BR";
|
case ARMISD::BR: return "ARMISD::BR";
|
||||||
case ARMISD::FSITOS: return "ARMISD::FSITOS";
|
case ARMISD::FSITOS: return "ARMISD::FSITOS";
|
||||||
case ARMISD::FTOSIS: return "ARMISD::FTOSIS";
|
case ARMISD::FTOSIS: return "ARMISD::FTOSIS";
|
||||||
@ -550,18 +578,31 @@ static SDOperand GetCMP(ISD::CondCode CC, SDOperand LHS, SDOperand RHS,
|
|||||||
SelectionDAG &DAG) {
|
SelectionDAG &DAG) {
|
||||||
MVT::ValueType vt = LHS.getValueType();
|
MVT::ValueType vt = LHS.getValueType();
|
||||||
assert(vt == MVT::i32 || vt == MVT::f32 || vt == MVT::f64);
|
assert(vt == MVT::i32 || vt == MVT::f32 || vt == MVT::f64);
|
||||||
//Note: unordered floating point compares should use a non throwing
|
|
||||||
//compare.
|
|
||||||
bool isUnorderedFloat = (vt == MVT::f32 || vt == MVT::f64) &&
|
|
||||||
(CC >= ISD::SETUO && CC <= ISD::SETUNE);
|
|
||||||
assert(!isUnorderedFloat && "Unordered float compares are not supported");
|
|
||||||
|
|
||||||
SDOperand Cmp = DAG.getNode(ARMISD::CMP, MVT::Flag, LHS, RHS);
|
bool isOrderedFloat = (vt == MVT::f32 || vt == MVT::f64) &&
|
||||||
|
(CC >= ISD::SETOEQ && CC <= ISD::SETONE);
|
||||||
|
|
||||||
|
SDOperand Cmp;
|
||||||
|
if (isOrderedFloat) {
|
||||||
|
Cmp = DAG.getNode(ARMISD::CMPE, MVT::Flag, LHS, RHS);
|
||||||
|
} else {
|
||||||
|
Cmp = DAG.getNode(ARMISD::CMP, MVT::Flag, LHS, RHS);
|
||||||
|
}
|
||||||
|
|
||||||
if (vt != MVT::i32)
|
if (vt != MVT::i32)
|
||||||
Cmp = DAG.getNode(ARMISD::FMSTAT, MVT::Flag, Cmp);
|
Cmp = DAG.getNode(ARMISD::FMSTAT, MVT::Flag, Cmp);
|
||||||
return Cmp;
|
return Cmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SDOperand GetARMCC(ISD::CondCode CC, MVT::ValueType vt,
|
||||||
|
SelectionDAG &DAG) {
|
||||||
|
assert(vt == MVT::i32 || vt == MVT::f32 || vt == MVT::f64);
|
||||||
|
if (vt == MVT::i32)
|
||||||
|
return DAG.getConstant(DAGIntCCToARMCC(CC), MVT::i32);
|
||||||
|
else
|
||||||
|
return DAG.getConstant(DAGFPCCToARMCC(CC), MVT::i32);
|
||||||
|
}
|
||||||
|
|
||||||
static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
|
static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
|
||||||
SDOperand LHS = Op.getOperand(0);
|
SDOperand LHS = Op.getOperand(0);
|
||||||
SDOperand RHS = Op.getOperand(1);
|
SDOperand RHS = Op.getOperand(1);
|
||||||
@ -569,7 +610,7 @@ static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
SDOperand TrueVal = Op.getOperand(2);
|
SDOperand TrueVal = Op.getOperand(2);
|
||||||
SDOperand FalseVal = Op.getOperand(3);
|
SDOperand FalseVal = Op.getOperand(3);
|
||||||
SDOperand Cmp = GetCMP(CC, LHS, RHS, DAG);
|
SDOperand Cmp = GetCMP(CC, LHS, RHS, DAG);
|
||||||
SDOperand ARMCC = DAG.getConstant(DAGCCToARMCC(CC), MVT::i32);
|
SDOperand ARMCC = GetARMCC(CC, LHS.getValueType(), DAG);
|
||||||
return DAG.getNode(ARMISD::SELECT, MVT::i32, TrueVal, FalseVal, ARMCC, Cmp);
|
return DAG.getNode(ARMISD::SELECT, MVT::i32, TrueVal, FalseVal, ARMCC, Cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,7 +621,7 @@ static SDOperand LowerBR_CC(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
SDOperand RHS = Op.getOperand(3);
|
SDOperand RHS = Op.getOperand(3);
|
||||||
SDOperand Dest = Op.getOperand(4);
|
SDOperand Dest = Op.getOperand(4);
|
||||||
SDOperand Cmp = GetCMP(CC, LHS, RHS, DAG);
|
SDOperand Cmp = GetCMP(CC, LHS, RHS, DAG);
|
||||||
SDOperand ARMCC = DAG.getConstant(DAGCCToARMCC(CC), MVT::i32);
|
SDOperand ARMCC = GetARMCC(CC, LHS.getValueType(), DAG);
|
||||||
return DAG.getNode(ARMISD::BR, MVT::Other, Chain, Dest, ARMCC, Cmp);
|
return DAG.getNode(ARMISD::BR, MVT::Other, Chain, Dest, ARMCC, Cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ def armbr : SDNode<"ARMISD::BR", SDTarmbr, [SDNPHasChain, SDNPInFlag]>;
|
|||||||
|
|
||||||
def SDTVoidBinOp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
|
def SDTVoidBinOp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
|
||||||
def armcmp : SDNode<"ARMISD::CMP", SDTVoidBinOp, [SDNPOutFlag]>;
|
def armcmp : SDNode<"ARMISD::CMP", SDTVoidBinOp, [SDNPOutFlag]>;
|
||||||
|
def armcmpe : SDNode<"ARMISD::CMPE", SDTVoidBinOp, [SDNPOutFlag]>;
|
||||||
|
|
||||||
def armfsitos : SDNode<"ARMISD::FSITOS", SDTUnaryOp>;
|
def armfsitos : SDNode<"ARMISD::FSITOS", SDTUnaryOp>;
|
||||||
def armftosis : SDNode<"ARMISD::FTOSIS", SDTUnaryOp>;
|
def armftosis : SDNode<"ARMISD::FTOSIS", SDTUnaryOp>;
|
||||||
@ -179,12 +180,20 @@ def cmp : InstARM<(ops IntRegs:$a, op_addr_mode1:$b),
|
|||||||
[(armcmp IntRegs:$a, addr_mode1:$b)]>;
|
[(armcmp IntRegs:$a, addr_mode1:$b)]>;
|
||||||
|
|
||||||
// Floating Point Compare
|
// Floating Point Compare
|
||||||
|
def fcmps : InstARM<(ops FPRegs:$a, FPRegs:$b),
|
||||||
|
"fcmps $a, $b",
|
||||||
|
[(armcmp FPRegs:$a, FPRegs:$b)]>;
|
||||||
|
|
||||||
def fcmpes : InstARM<(ops FPRegs:$a, FPRegs:$b),
|
def fcmpes : InstARM<(ops FPRegs:$a, FPRegs:$b),
|
||||||
"fcmpes $a, $b",
|
"fcmpes $a, $b",
|
||||||
[(armcmp FPRegs:$a, FPRegs:$b)]>;
|
[(armcmpe FPRegs:$a, FPRegs:$b)]>;
|
||||||
|
|
||||||
def fcmped : InstARM<(ops DFPRegs:$a, DFPRegs:$b),
|
def fcmped : InstARM<(ops DFPRegs:$a, DFPRegs:$b),
|
||||||
"fcmped $a, $b",
|
"fcmped $a, $b",
|
||||||
|
[(armcmpe DFPRegs:$a, DFPRegs:$b)]>;
|
||||||
|
|
||||||
|
def fcmpd : InstARM<(ops DFPRegs:$a, DFPRegs:$b),
|
||||||
|
"fcmpd $a, $b",
|
||||||
[(armcmp DFPRegs:$a, DFPRegs:$b)]>;
|
[(armcmp DFPRegs:$a, DFPRegs:$b)]>;
|
||||||
|
|
||||||
// Floating Point Conversion
|
// Floating Point Conversion
|
||||||
|
@ -5,7 +5,9 @@
|
|||||||
; RUN: llvm-as < %s | llc -march=arm | grep movge &&
|
; RUN: llvm-as < %s | llc -march=arm | grep movge &&
|
||||||
; RUN: llvm-as < %s | llc -march=arm | grep movle &&
|
; RUN: llvm-as < %s | llc -march=arm | grep movle &&
|
||||||
; RUN: llvm-as < %s | llc -march=arm | grep fcmpes &&
|
; RUN: llvm-as < %s | llc -march=arm | grep fcmpes &&
|
||||||
; RUN: llvm-as < %s | llc -march=arm | grep fcmped
|
; RUN: llvm-as < %s | llc -march=arm | grep fcmps &&
|
||||||
|
; RUN: llvm-as < %s | llc -march=arm | grep fcmped &&
|
||||||
|
; RUN: llvm-as < %s | llc -march=arm | grep fcmpd
|
||||||
|
|
||||||
int %f1(float %a) {
|
int %f1(float %a) {
|
||||||
entry:
|
entry:
|
||||||
@ -42,9 +44,23 @@ entry:
|
|||||||
ret int %tmp
|
ret int %tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int %f6(float %a) {
|
||||||
|
entry:
|
||||||
|
%tmp = setne float %a, 1.000000e+00 ; <bool> [#uses=1]
|
||||||
|
%tmp = cast bool %tmp to int ; <int> [#uses=1]
|
||||||
|
ret int %tmp
|
||||||
|
}
|
||||||
|
|
||||||
int %g1(double %a) {
|
int %g1(double %a) {
|
||||||
entry:
|
entry:
|
||||||
%tmp = setlt double %a, 1.000000e+00 ; <bool> [#uses=1]
|
%tmp = setlt double %a, 1.000000e+00 ; <bool> [#uses=1]
|
||||||
%tmp = cast bool %tmp to int ; <int> [#uses=1]
|
%tmp = cast bool %tmp to int ; <int> [#uses=1]
|
||||||
ret int %tmp
|
ret int %tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int %g2(double %a) {
|
||||||
|
entry:
|
||||||
|
%tmp = setne double %a, 1.000000e+00 ; <bool> [#uses=1]
|
||||||
|
%tmp = cast bool %tmp to int ; <int> [#uses=1]
|
||||||
|
ret int %tmp
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user