summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2006-12-31 18:52:39 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2006-12-31 18:52:39 +0000
commit9985f9f61e1dcffcd28caa2b6a42a1347624158d (patch)
tree963073ffac4a0ddb21b36725873e03ab63170e06
parent1fd79b8c42fcdde3b102febb893e6b3919266031 (diff)
downloadllvm-9985f9f61e1dcffcd28caa2b6a42a1347624158d.tar.gz
llvm-9985f9f61e1dcffcd28caa2b6a42a1347624158d.tar.bz2
llvm-9985f9f61e1dcffcd28caa2b6a42a1347624158d.tar.xz
implement missing compares
patch by Lauro bug fixed by me git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32795 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp103
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td2
-rw-r--r--test/CodeGen/ARM/fpcmp_ueq.ll11
3 files changed, 78 insertions, 38 deletions
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index 3a8bfdb500..cf8386ce51 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -151,59 +151,62 @@ namespace llvm {
/// DAGFPCCToARMCC - Convert a DAG fp condition code to an ARM CC
// Unordered = !N & !Z & C & V = V
// Ordered = N | Z | !C | !V = N | Z | !V
-static ARMCC::CondCodes DAGFPCCToARMCC(ISD::CondCode CC) {
+static std::vector<unsigned> DAGFPCCToARMCC(ISD::CondCode CC) {
switch (CC) {
default:
assert(0 && "Unknown fp condition code!");
// SETOEQ = (N | Z | !V) & Z = Z = EQ
case ISD::SETEQ:
- case ISD::SETOEQ: return ARMCC::EQ;
+ case ISD::SETOEQ: return make_vector<unsigned>(ARMCC::EQ, 0);
// SETOGT = (N | Z | !V) & !N & !Z = !V &!N &!Z = (N = V) & !Z = GT
case ISD::SETGT:
- case ISD::SETOGT: return ARMCC::GT;
+ case ISD::SETOGT: return make_vector<unsigned>(ARMCC::GT, 0);
// SETOGE = (N | Z | !V) & !N = (Z | !V) & !N = !V & !N = GE
case ISD::SETGE:
- case ISD::SETOGE: return ARMCC::GE;
+ case ISD::SETOGE: return make_vector<unsigned>(ARMCC::GE, 0);
// SETOLT = (N | Z | !V) & N = N = MI
case ISD::SETLT:
- case ISD::SETOLT: return ARMCC::MI;
+ case ISD::SETOLT: return make_vector<unsigned>(ARMCC::MI, 0);
// SETOLE = (N | Z | !V) & (N | Z) = N | Z = !C | Z = LS
case ISD::SETLE:
- case ISD::SETOLE: return ARMCC::LS;
-// SETONE = (N | Z | !V) & !Z = (N | !V) & !Z = !V & !Z = !Z = NE
- case ISD::SETNE:
- case ISD::SETONE: return ARMCC::NE;
+ case ISD::SETOLE: return make_vector<unsigned>(ARMCC::LS, 0);
+// SETONE = OGT | OLT
+ case ISD::SETONE: return make_vector<unsigned>(ARMCC::GT, ARMCC::MI, 0);
// SETO = N | Z | !V = Z | !V = !V = VC
- case ISD::SETO: return ARMCC::VC;
+ case ISD::SETO: return make_vector<unsigned>(ARMCC::VC, 0);
// SETUO = V = VS
- case ISD::SETUO: return ARMCC::VS;
-// SETUEQ = V | Z = ??
+ case ISD::SETUO: return make_vector<unsigned>(ARMCC::VS, 0);
+// SETUEQ = V | Z (need two instructions) = EQ/VS
+ case ISD::SETUEQ: return make_vector<unsigned>(ARMCC::EQ, ARMCC::VS, 0);
// SETUGT = V | (!Z & !N) = !Z & !N = !Z & C = HI
- case ISD::SETUGT: return ARMCC::HI;
+ case ISD::SETUGT: return make_vector<unsigned>(ARMCC::HI, 0);
// SETUGE = V | !N = !N = PL
- case ISD::SETUGE: return ARMCC::PL;
-// SETULT = V | N = ??
-// SETULE = V | Z | N = ??
+ case ISD::SETUGE: return make_vector<unsigned>(ARMCC::PL, 0);
+// SETULT = V | N = LT
+ case ISD::SETULT: return make_vector<unsigned>(ARMCC::LT, 0);
+// SETULE = V | Z | N = LE
+ case ISD::SETULE: return make_vector<unsigned>(ARMCC::LE, 0);
// SETUNE = V | !Z = !Z = NE
- case ISD::SETUNE: return ARMCC::NE;
+ case ISD::SETNE:
+ case ISD::SETUNE: return make_vector<unsigned>(ARMCC::NE, 0);
}
}
/// DAGIntCCToARMCC - Convert a DAG integer condition code to an ARM CC
-static ARMCC::CondCodes DAGIntCCToARMCC(ISD::CondCode CC) {
+static std::vector<unsigned> 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::SETULE: return ARMCC::LS;
- case ISD::SETUGT: return ARMCC::HI;
- case ISD::SETUGE: return ARMCC::CS;
+ case ISD::SETEQ: return make_vector<unsigned>(ARMCC::EQ, 0);
+ case ISD::SETNE: return make_vector<unsigned>(ARMCC::NE, 0);
+ case ISD::SETLT: return make_vector<unsigned>(ARMCC::LT, 0);
+ case ISD::SETLE: return make_vector<unsigned>(ARMCC::LE, 0);
+ case ISD::SETGT: return make_vector<unsigned>(ARMCC::GT, 0);
+ case ISD::SETGE: return make_vector<unsigned>(ARMCC::GE, 0);
+ case ISD::SETULT: return make_vector<unsigned>(ARMCC::CC, 0);
+ case ISD::SETULE: return make_vector<unsigned>(ARMCC::LS, 0);
+ case ISD::SETUGT: return make_vector<unsigned>(ARMCC::HI, 0);
+ case ISD::SETUGE: return make_vector<unsigned>(ARMCC::CS, 0);
}
}
@@ -653,13 +656,20 @@ static SDOperand GetCMP(ISD::CondCode CC, SDOperand LHS, SDOperand RHS,
return Cmp;
}
-static SDOperand GetARMCC(ISD::CondCode CC, MVT::ValueType vt,
+static std::vector<SDOperand> GetARMCC(ISD::CondCode CC, MVT::ValueType vt,
SelectionDAG &DAG) {
assert(vt == MVT::i32 || vt == MVT::f32 || vt == MVT::f64);
+ std::vector<unsigned> vcc;
if (vt == MVT::i32)
- return DAG.getConstant(DAGIntCCToARMCC(CC), MVT::i32);
+ vcc = DAGIntCCToARMCC(CC);
else
- return DAG.getConstant(DAGFPCCToARMCC(CC), MVT::i32);
+ vcc = DAGFPCCToARMCC(CC);
+
+ std::vector<unsigned>::iterator it;
+ std::vector<SDOperand> result;
+ for( it = vcc.begin(); it != vcc.end(); it++ )
+ result.push_back(DAG.getConstant(*it,MVT::i32));
+ return result;
}
static bool isUInt8Immediate(uint32_t x) {
@@ -682,8 +692,9 @@ static bool isRotInt8Immediate(uint32_t x) {
return false;
}
-static void LowerCMP(SDOperand &Cmp, SDOperand &ARMCC, SDOperand LHS,
- SDOperand RHS, ISD::CondCode CC, SelectionDAG &DAG) {
+static void LowerCMP(SDOperand &Cmp, std::vector<SDOperand> &ARMCC,
+ SDOperand LHS, SDOperand RHS, ISD::CondCode CC,
+ SelectionDAG &DAG) {
MVT::ValueType vt = LHS.getValueType();
if (vt == MVT::i32) {
assert(!isa<ConstantSDNode>(LHS));
@@ -745,9 +756,18 @@ static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
SDOperand TrueVal = Op.getOperand(2);
SDOperand FalseVal = Op.getOperand(3);
SDOperand Cmp;
- SDOperand ARMCC;
+ std::vector<SDOperand> ARMCC;
LowerCMP(Cmp, ARMCC, LHS, RHS, CC, DAG);
- return DAG.getNode(ARMISD::SELECT, Op.getValueType(), TrueVal, FalseVal, ARMCC, Cmp);
+
+ SDOperand Aux = FalseVal;
+ SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
+ std::vector<SDOperand>::iterator it;
+ for (it = ARMCC.begin(); it != ARMCC.end(); ++it){
+ SDOperand Flag = it == ARMCC.begin() ? Cmp : Aux.getValue(1);
+ SDOperand Ops[] = {TrueVal, Aux, *it, Flag};
+ Aux = DAG.getNode(ARMISD::SELECT, VTs, Ops, 4);
+ }
+ return Aux;
}
static SDOperand LowerBR_CC(SDOperand Op, SelectionDAG &DAG) {
@@ -757,9 +777,18 @@ static SDOperand LowerBR_CC(SDOperand Op, SelectionDAG &DAG) {
SDOperand RHS = Op.getOperand(3);
SDOperand Dest = Op.getOperand(4);
SDOperand Cmp;
- SDOperand ARMCC;
+ std::vector<SDOperand> ARMCC;
LowerCMP(Cmp, ARMCC, LHS, RHS, CC, DAG);
- return DAG.getNode(ARMISD::BR, MVT::Other, Chain, Dest, ARMCC, Cmp);
+
+ SDOperand Aux = Chain;
+ SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Flag);
+ std::vector<SDOperand>::iterator it;
+ for (it = ARMCC.begin(); it != ARMCC.end(); it++){
+ SDOperand Flag = it == ARMCC.begin() ? Cmp : Aux.getValue(1);
+ SDOperand Ops[] = {Aux, Dest, *it, Flag};
+ Aux = DAG.getNode(ARMISD::BR, VTs, Ops, 4);
+ }
+ return Aux;
}
static SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index b13a265344..beed8abef9 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -109,7 +109,7 @@ def SDTarmfmstat : SDTypeProfile<0, 0, []>;
def armfmstat : SDNode<"ARMISD::FMSTAT", SDTarmfmstat, [SDNPInFlag, SDNPOutFlag]>;
def SDTarmbr : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>]>;
-def armbr : SDNode<"ARMISD::BR", SDTarmbr, [SDNPHasChain, SDNPInFlag]>;
+def armbr : SDNode<"ARMISD::BR", SDTarmbr, [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
def SDTVoidBinOp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
def armcmp : SDNode<"ARMISD::CMP", SDTVoidBinOp, [SDNPOutFlag]>;
diff --git a/test/CodeGen/ARM/fpcmp_ueq.ll b/test/CodeGen/ARM/fpcmp_ueq.ll
new file mode 100644
index 0000000000..2bbaa5c34b
--- /dev/null
+++ b/test/CodeGen/ARM/fpcmp_ueq.ll
@@ -0,0 +1,11 @@
+; RUN: llvm-as < %s | llc -march=arm &&
+; RUN: llvm-as < %s | llc -march=arm | grep moveq &&
+; RUN: llvm-as < %s | llc -march=arm | grep movvs
+
+define i32 %f7(float %a, float %b) {
+entry:
+ %tmp = fcmp ueq float %a,%b
+ %retval = select bool %tmp, i32 666, i32 42
+ ret i32 %retval
+}
+