diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index c92e4577eed97..afc47aec29ad8 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -2324,15 +2324,59 @@ SDValue MipsTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const { // The first operand is the chain, the second is the condition, the third is // the block to branch to if the condition is true. SDValue Chain = Op.getOperand(0); + SDValue Cond = Op.getOperand(1); SDValue Dest = Op.getOperand(2); - SDLoc DL(Op); + SDNode *Node = Op.getNode(); + SDLoc DL(Op); assert(!Subtarget.hasMips32r6() && !Subtarget.hasMips64r6()); SDValue CondRes = createFPCmp(DAG, Op.getOperand(1)); - // Return if flag is not set by a floating point comparison. - if (CondRes.getOpcode() != MipsISD::FPCmp) - return Op; + if (CondRes.getOpcode() != MipsISD::FPCmp) { + // For NanoMips we can try to optimize conditional branches. Try to + // recognize the following pattern: + // COND: CondV, TrueV, FalseV + // i32 = select t25, t22, t23 + // CondV: t25: i32 = setcc t4, t8, seteq:ch + // TrueV: t22: i32 = setcc t2, t6, setult:ch + // FalseV: t23: i32 = setcc t4, t8, setlt:ch + if (!(Subtarget.hasNanoMips() && DAG.shouldOptForSize() && + Cond.getOpcode() == ISD::SELECT && Node->hasOneUse())) + return Op; + auto BrNode = *Node->use_begin(); + if (BrNode->getOpcode() != ISD::BR) + return Op; + SDValue ThenDest = BrNode->getOperand(1); + //DAG.DeleteNode(BrNode); + SDValue CondV = Cond.getOperand(0); + SDValue TrueV = Cond.getOperand(1); + SDValue FalseV = Cond.getOperand(2); + if (CondV.getOpcode() != ISD::SETCC || TrueV.getOpcode() != ISD::SETCC || + FalseV.getOpcode() != ISD::SETCC) + return Op; + CondCodeSDNode *condCodeCV = dyn_cast(CondV.getOperand(2)); + CondCodeSDNode *condCodeTV = dyn_cast(TrueV.getOperand(2)); + CondCodeSDNode *condCodeFV = dyn_cast(FalseV.getOperand(2)); + if (!condCodeCV || !condCodeTV || !condCodeFV) + return Op; + // Form NanoMips conditional branch nodes: + SDValue BrFalse = + DAG.getNode(ISD::BRCOND, DL, MVT::Other, Chain, FalseV, Dest); + SDValue BrCond = + DAG.getNode(ISD::BRCOND, DL, MVT::Other, BrFalse, + DAG.getSetCC(DL, CondV->getValueType(0), + CondV->getOperand(0), CondV->getOperand(1), + ISD::getSetCCInverse( + condCodeCV->get(), + CondV->getOperand(0)->getValueType(0))), + ThenDest); + SDValue BrTrue = + DAG.getNode(ISD::BRCOND, DL, MVT::Other, BrCond, TrueV, Dest); + // Instruction selection will be able to match these BRCOND nodes with the + // nanoMIPS conditional branch instructions. + + return BrTrue; + } SDValue CCNode = CondRes.getOperand(2); Mips::CondCode CC = diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/llvm/lib/Target/Mips/MipsInstrInfo.cpp index 3184bb86ae632..6077339aa1452 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.cpp +++ b/llvm/lib/Target/Mips/MipsInstrInfo.cpp @@ -272,8 +272,47 @@ MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch( // If we reached here, there are two branches. // If there are three terminators, we don't know what sort of block this is. - if (++I != REnd && isUnpredicatedTerminator(*I)) - return BT_None; + if (++I != REnd && isUnpredicatedTerminator(*I)) { + if (!Subtarget.hasNanoMips() || + !MBB.getParent()->getFunction().hasOptSize()) + return BT_None; + // For nanoMIPS: When comparing two 64-bit data, there are three comparisons + // to determine whether the condition is met. Two conditional branches + // branch to the If.Else block, while the third branches to the If.then + // block. If this pattern is followed by the unconditional branch - that + // branch is redundant. + auto ThirdLastInst = &(*I); + if (!LastInst->isUnconditionalBranch() || + !SecondLastInst->isConditionalBranch() || + !ThirdLastInst->isConditionalBranch() || (++I) == REnd) + return BT_None; + + auto FourthLastInst = &(*I); + if (!FourthLastInst->isConditionalBranch()) + return BT_None; + auto IfElseSLI = SecondLastInst->getOperand(2).getMBB(); + auto IfElseFLI = FourthLastInst->getOperand(2).getMBB(); + auto IfThenLI = LastInst->getOperand(0).getMBB(); + auto IfThenTLI = ThirdLastInst->getOperand(2).getMBB(); + if (IfElseFLI != IfElseSLI || IfThenLI != IfThenTLI) + return BT_None; + auto HigherRegFLIFirst = FourthLastInst->getOperand(0).getReg(); + auto HigherRegTLIFirst = ThirdLastInst->getOperand(0).getReg(); + auto HigherRegFLISecond = FourthLastInst->getOperand(1).getReg(); + auto HigherRegTLISecond = ThirdLastInst->getOperand(1).getReg(); + if (HigherRegFLIFirst != HigherRegTLIFirst || + HigherRegFLISecond != HigherRegTLISecond) + return BT_None; + auto LowerRegSLIFirst = SecondLastInst->getOperand(0).getReg(); + auto LowerRegSLISecond = SecondLastInst->getOperand(1).getReg(); + + if (HigherRegFLIFirst.id() != (LowerRegSLIFirst.id() + 1) || + HigherRegFLISecond.id() != (LowerRegSLISecond.id() + 1)) + return BT_None; + // If the pattern matches, set the LabelMustBeEmitted flag for If.then block + // and continue with the analysis. + IfThenTLI->setLabelMustBeEmitted(); + } BranchInstrs.insert(BranchInstrs.begin(), SecondLastInst); diff --git a/llvm/test/CodeGen/Mips/nanomips/64bit-comparison.ll b/llvm/test/CodeGen/Mips/nanomips/64bit-comparison.ll new file mode 100644 index 0000000000000..4068b962ddca7 --- /dev/null +++ b/llvm/test/CodeGen/Mips/nanomips/64bit-comparison.ll @@ -0,0 +1,31 @@ +; RUN: llc -mtriple=nanomips -asm-show-inst -verify-machineinstrs < %s | FileCheck %s + +; CHECK: bltc $a1, $a3, .LBB0_2 +; CHECK: bnec $a1, $a3, .LBB0_1 +; CHECK: bltuc $a0, $a2, .LBB0_2 +; CHECK: .LBB0_1: +; CHECK: .LBB0_2: + +; Function Attrs: optsize +define void @test(i64 signext %a, i64 signext %b) #0 { +entry: + %cmp.not = icmp slt i64 %a, %b + br i1 %cmp.not, label %if.else, label %if.then + +if.then: ; preds = %entry + tail call void bitcast (void (...)* @aa to void ()*)() + br label %if.end + +if.else: ; preds = %entry + tail call void bitcast (void (...)* @bb to void ()*)() + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} + +declare void @aa(...) + +declare void @bb(...) + +attributes #0 = { optsize }