Index: lib/Target/PowerPC/PPCFastISel.cpp =================================================================== --- lib/Target/PowerPC/PPCFastISel.cpp +++ lib/Target/PowerPC/PPCFastISel.cpp @@ -213,12 +213,22 @@ switch (Pred) { // These are not representable with any single compare. case CmpInst::FCMP_FALSE: + // For GT, LT and EQ, bc uses a normal form condition - LT, GT, EQ. + // The result UN doesn't trigger these predicates, which should be. + // + // On the other hand, testing !LT, !GT and !EQ against UN happens to be + // correct, since test will succeed, which should be. case CmpInst::FCMP_UEQ: case CmpInst::FCMP_UGT: - case CmpInst::FCMP_UGE: case CmpInst::FCMP_ULT: - case CmpInst::FCMP_ULE: - case CmpInst::FCMP_UNE: + // For GE, LE and NE, bc uses a negative form condition - !LT, !GT, !EQ. + // The result UN also triggers these predicates, which is wrong. + // + // On the other hand, testing GT, LT and EQ against UN happens to be + // correct, since test will fail on UN. + case CmpInst::FCMP_OGE: + case CmpInst::FCMP_OLE: + case CmpInst::FCMP_ONE: case CmpInst::FCMP_TRUE: default: return Optional(); @@ -232,7 +242,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 +252,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 +}