diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -3860,6 +3860,35 @@ } } +// For SPE instructions, the result is in GT bit of the CR +// Return the corresponding GT or LE code for this +// Prior to this, the Compare must have been modified to EF?CMP?? in SelectCC +static PPC::Predicate getPredicateForSetCCForSPE(ISD::CondCode CC) { + PPC::Predicate Opc = PPC::PRED_SPE; + switch (CC) { + case ISD::SETOEQ: + case ISD::SETEQ: + case ISD::SETOLT: + case ISD::SETLT: + case ISD::SETOGT: + case ISD::SETGT: + Opc = PPC::PRED_GT; + break; + case ISD::SETUNE: + case ISD::SETNE: + case ISD::SETULE: + case ISD::SETLE: + case ISD::SETUGE: + case ISD::SETGE: + Opc = PPC::PRED_LE; + break; + default: + llvm_unreachable("Undefined SPE Predicate for CC\n"); + break; + } + return Opc; +} + /// getCRIdxForSetCC - Return the index of the condition register field /// associated with the SetCC condition, and whether or not the field is /// treated as inverted. That is, lt = 0; ge = 0 inverted. @@ -4890,6 +4919,13 @@ } unsigned BROpc = getPredicateForSetCC(CC); + // Override BROpc if SPE with f64/f32 operation + // Watch out: N->getOperand(0).getValueType is not the same as + // N->getValueType(0) + if (PPCSubTarget->hasSPE() && + (N->getOperand(0).getValueType() == MVT::f64 || + N->getOperand(0).getValueType() == MVT::f32)) + BROpc = getPredicateForSetCCForSPE(CC); unsigned SelectCCOp; if (N->getValueType(0) == MVT::i32) @@ -5048,6 +5084,13 @@ PCC |= getBranchHint(PCC, FuncInfo, N->getOperand(4)); SDValue CondCode = SelectCC(N->getOperand(2), N->getOperand(3), CC, dl); + + if (PPCSubTarget->hasSPE() && + N->getOperand(2).getValueType().isFloatingPoint()) { + // For SPE instructions the result is in GT bit of the CR + PCC = getPredicateForSetCCForSPE(CC); + } + SDValue Ops[] = { getI32Imm(PCC, dl), CondCode, N->getOperand(4), N->getOperand(0) }; CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops); diff --git a/llvm/test/CodeGen/PowerPC/spe.ll b/llvm/test/CodeGen/PowerPC/spe.ll --- a/llvm/test/CodeGen/PowerPC/spe.ll +++ b/llvm/test/CodeGen/PowerPC/spe.ll @@ -77,12 +77,28 @@ ; CHECK: blr } -define i1 @test_fcmpgt(float %a, float %b) { - entry: - %r = fcmp ogt float %a, %b - ret i1 %r +define i32 @test_fcmpgt(float %a, float %b) { + entry: + %r = alloca i32, align 4 + %c = fcmp ogt float %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_fcmpgt ; CHECK: efscmpgt +; CHECK: ble 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] ; CHECK: blr } @@ -104,21 +120,54 @@ ; CHECK: blr } -define i1 @test_fcmpule(float %a, float %b) { +define i32 @test_fcmpule(float %a, float %b) { entry: - %r = fcmp ule float %a, %b - ret i1 %r + %r = alloca i32, align 4 + %c = fcmp ule float %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_fcmpule ; CHECK: efscmpgt -; CHECK: blr -} - -define i1 @test_fcmpeq(float %a, float %b) { - entry: - %r = fcmp oeq float %a, %b - ret i1 %r +; CHECK: bgt 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] +; CHECK: blr +} + +; The type of comparison found in C's if (x == y) +define i32 @test_fcmpeq(float %a, float %b) { + entry: + %r = alloca i32, align 4 + %c = fcmp oeq float %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_fcmpeq ; CHECK: efscmpeq +; CHECK: ble 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] ; CHECK: blr } @@ -163,21 +212,53 @@ ; CHECK: blr } -define i1 @test_fcmpune(float %a, float %b) { +define i32 @test_fcmpune(float %a, float %b) { entry: - %r = fcmp une float %a, %b - ret i1 %r + %r = alloca i32, align 4 + %c = fcmp une float %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_fcmpune ; CHECK: efscmpeq -; CHECK: blr -} - -define i1 @test_fcmplt(float %a, float %b) { - entry: - %r = fcmp olt float %a, %b - ret i1 %r +; CHECK: bgt 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] +; CHECK: blr +} + +define i32 @test_fcmplt(float %a, float %b) { + entry: + %r = alloca i32, align 4 + %c = fcmp olt float %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_fcmplt ; CHECK: efscmplt +; CHECK: ble 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] ; CHECK: blr } @@ -199,15 +280,32 @@ ; CHECK: blr } -define i1 @test_fcmpuge(float %a, float %b) { +define i32 @test_fcmpuge(float %a, float %b) { entry: - %r = fcmp uge float %a, %b - ret i1 %r + %r = alloca i32, align 4 + %c = fcmp uge float %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_fcmpuge ; CHECK: efscmplt +; CHECK: bgt 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] ; CHECK: blr } + define i32 @test_ftoui(float %a) { %v = fptoui float %a to i32 ret i32 %v @@ -357,12 +455,28 @@ ; CHECK: blr } -define i1 @test_dcmpgt(double %a, double %b) { +define i32 @test_dcmpgt(double %a, double %b) { entry: - %r = fcmp ogt double %a, %b - ret i1 %r + %r = alloca i32, align 4 + %c = fcmp ogt double %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_dcmpgt ; CHECK: efdcmpgt +; CHECK: ble 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] ; CHECK: blr } @@ -384,21 +498,54 @@ ; CHECK: blr } -define i1 @test_dcmpule(double %a, double %b) { +define i32 @test_dcmpule(double %a, double %b) { entry: - %r = fcmp ule double %a, %b - ret i1 %r + %r = alloca i32, align 4 + %c = fcmp ule double %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_dcmpule ; CHECK: efdcmpgt -; CHECK: blr -} - -define i1 @test_dcmpeq(double %a, double %b) { - entry: - %r = fcmp oeq double %a, %b - ret i1 %r +; CHECK: bgt 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] +; CHECK: blr +} + +; The type of comparison found in C's if (x == y) +define i32 @test_dcmpeq(double %a, double %b) { + entry: + %r = alloca i32, align 4 + %c = fcmp oeq double %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_dcmpeq ; CHECK: efdcmpeq +; CHECK: ble 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] ; CHECK: blr } @@ -420,21 +567,53 @@ ; CHECK: blr } -define i1 @test_dcmpune(double %a, double %b) { +define i32 @test_dcmpune(double %a, double %b) { entry: - %r = fcmp une double %a, %b - ret i1 %r + %r = alloca i32, align 4 + %c = fcmp une double %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_dcmpune ; CHECK: efdcmpeq -; CHECK: blr -} - -define i1 @test_dcmplt(double %a, double %b) { - entry: - %r = fcmp olt double %a, %b - ret i1 %r +; CHECK: bgt 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] +; CHECK: blr +} + +define i32 @test_dcmplt(double %a, double %b) { + entry: + %r = alloca i32, align 4 + %c = fcmp olt double %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_dcmplt ; CHECK: efdcmplt +; CHECK: ble 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] ; CHECK: blr } @@ -456,12 +635,28 @@ ; CHECK: blr } -define i1 @test_dcmpuge(double %a, double %b) { +define i32 @test_dcmpuge(double %a, double %b) { entry: - %r = fcmp uge double %a, %b - ret i1 %r + %r = alloca i32, align 4 + %c = fcmp uge double %a, %b + br i1 %c, label %tr, label %fa +tr: + store i32 1, i32* %r, align 4 + br label %ret +fa: + store i32 0, i32* %r, align 4 + br label %ret +ret: + %0 = load i32, i32* %r, align 4 + ret i32 %0 ; CHECK-LABEL: test_dcmpuge ; CHECK: efdcmplt +; CHECK: bgt 0, [[LABEL:.*]] +; CHECK: li 3, 1 +; CHECK: b [[RETLABEL:.*]] +; CHECK: [[LABEL]] +; CHECK-NEXT: li 3, 0 +; CHECK: [[RETLABEL]] ; CHECK: blr }