diff options
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCFastISel.cpp')
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCFastISel.cpp | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCFastISel.cpp b/llvm/lib/Target/PowerPC/PPCFastISel.cpp index 1de26790651..360fbb61bc5 100644 --- a/llvm/lib/Target/PowerPC/PPCFastISel.cpp +++ b/llvm/lib/Target/PowerPC/PPCFastISel.cpp @@ -213,13 +213,29 @@ static Optional<PPC::Predicate> getComparePred(CmpInst::Predicate Pred) { switch (Pred) { // These are not representable with any single compare. case CmpInst::FCMP_FALSE: + case CmpInst::FCMP_TRUE: + // Major concern about the following 6 cases is NaN result. The comparison + // result consists of 4 bits, indicating lt, eq, gt and un (unordered), + // only one of which will be set. The result is generated by fcmpu + // instruction. However, bc instruction only inspects one of the first 3 + // bits, so when un is set, bc instruction may jump to to an undesired + // place. + // + // More specifically, if we expect an unordered comparison and un is set, we + // expect to always go to true branch; in such case UEQ, UGT and ULT still + // give false, which are undesired; but UNE, UGE, ULE happen to give true, + // since they are tested by inspecting !eq, !lt, !gt, respectively. + // + // Similarly, for ordered comparison, when un is set, we always expect the + // result to be false. In such case OGT, OLT and OEQ is good, since they are + // actually testing GT, LT, and EQ respectively, which are false. OGE, OLE + // and ONE are tested through !lt, !gt and !eq, and these are true. case CmpInst::FCMP_UEQ: case CmpInst::FCMP_UGT: - case CmpInst::FCMP_UGE: case CmpInst::FCMP_ULT: - case CmpInst::FCMP_ULE: - case CmpInst::FCMP_UNE: - case CmpInst::FCMP_TRUE: + case CmpInst::FCMP_OGE: + case CmpInst::FCMP_OLE: + case CmpInst::FCMP_ONE: default: return Optional<PPC::Predicate>(); @@ -232,7 +248,7 @@ static Optional<PPC::Predicate> getComparePred(CmpInst::Predicate Pred) { case CmpInst::ICMP_SGT: return PPC::PRED_GT; - case CmpInst::FCMP_OGE: + case CmpInst::FCMP_UGE: case CmpInst::ICMP_UGE: case CmpInst::ICMP_SGE: return PPC::PRED_GE; @@ -242,12 +258,12 @@ static Optional<PPC::Predicate> getComparePred(CmpInst::Predicate Pred) { case CmpInst::ICMP_SLT: return PPC::PRED_LT; - case CmpInst::FCMP_OLE: + case CmpInst::FCMP_ULE: case CmpInst::ICMP_ULE: case CmpInst::ICMP_SLE: return PPC::PRED_LE; - case CmpInst::FCMP_ONE: + case CmpInst::FCMP_UNE: case CmpInst::ICMP_NE: return PPC::PRED_NE; |