Index: lib/Target/PowerPC/PPCFastISel.cpp =================================================================== --- lib/Target/PowerPC/PPCFastISel.cpp +++ lib/Target/PowerPC/PPCFastISel.cpp @@ -213,13 +213,29 @@ switch (Pred) { // These are not representable with any single compare. case CmpInst::FCMP_FALSE: + case CmpInst::FCMP_TRUE: + // Major concerns about the following 6 cases are NaN result. The 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 inspect the first 3, so when un is set, bc + // instruction may jump to undisired 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 + // gives false, which is 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 unexpectedly + // 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(); @@ -232,7 +248,7 @@ 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 @@ 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; Index: test/CodeGen/PowerPC/fast-isel-fcmp-nan.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/fast-isel-fcmp-nan.ll @@ -0,0 +1,187 @@ +; RUN: llc -mtriple powerpc64le-unknown-linux-gnu -fast-isel -O0 < %s | FileCheck %s + +define i1 @TestULT(double %t0) { +; CHECK-LABEL: TestULT: +; CHECK: mcrf +; CHECK: blr +entry: + %t1 = fcmp ult double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +} + +define i1 @TestULE(double %t0) { +; CHECK-LABEL: TestULE: +; CHECK: fcmpu +; CHECK-NEXT: ble +; CHECK: blr +entry: + %t1 = fcmp ule double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +} + +define i1 @TestUNE(double %t0) { +; CHECK-LABEL: TestUNE: +; CHECK: fcmpu +; CHECK-NEXT: bne +; CHECK: blr +entry: + %t1 = fcmp une double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +} + +define i1 @TestUEQ(double %t0) { +; CHECK-LABEL: TestUEQ: +; CHECK: mcrf +; CHECK: blr +entry: + %t1 = fcmp ueq double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +} + +define i1 @TestUGT(double %t0) { +; CHECK-LABEL: TestUGT: +; CHECK: mcrf +; CHECK: blr +entry: + %t1 = fcmp ugt double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +} + +define i1 @TestUGE(double %t0) { +; CHECK-LABEL: TestUGE: +; CHECK: fcmpu +; CHECK-NEXT: bge +; CHECK: blr +entry: + %t1 = fcmp uge double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +} + +define i1 @TestOLT(double %t0) { +; CHECK-LABEL: TestOLT: +; CHECK: fcmpu +; CHECK-NEXT: blt +; CHECK: blr +entry: + %t1 = fcmp olt double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +} + +define i1 @TestOLE(double %t0) { +; CHECK-LABEL: TestOLE: +; CHECK: mcrf +; CHECK: blr +entry: + %t1 = fcmp ole double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +} + +define i1 @TestONE(double %t0) { +; CHECK-LABEL: TestONE: +; CHECK: mcrf +; CHECK: blr +entry: + %t1 = fcmp one double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +} + +define i1 @TestOEQ(double %t0) { +; CHECK-LABEL: TestOEQ: +; CHECK: fcmpu +; CHECK-NEXT: beq +; CHECK: blr +entry: + %t1 = fcmp oeq double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +} + +define i1 @TestOGT(double %t0) { +; CHECK-LABEL: TestOGT: +; CHECK: fcmpu +; CHECK-NEXT: bgt +; CHECK: blr +entry: + %t1 = fcmp ogt double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +} + +define i1 @TestOGE(double %t0) { +; CHECK-LABEL: TestOGE: +; CHECK: mcrf +; CHECK: blr +entry: + %t1 = fcmp oge double %t0, 0.000000e+00 + br i1 %t1, label %good, label %bad + +bad: + ret i1 false + +good: + ret i1 true +}