From 3a00d68945a3ea6b7e377dcb2c9a65a524f770e0 Mon Sep 17 00:00:00 2001 From: Milica Lazarevic Date: Fri, 5 May 2023 12:34:43 +0200 Subject: [PATCH] nanoMIPS: Optimize 64bit comparisons when -Os Comparison of two 64-bit data can be realized using three nanomips conditional branch instructions. To accomplish it, we're introducing custom lowering for the BRCOND node. This situation must be recognized as valid when we're analyzing the branch and when we're printing the assembler. Therefore, additional checks have been added for the MipsInstrInfo::analyzeBranch method in the case of nanoMIPS architecture. Also, there we set a LabelMustBeEmitted flag for the If.then block. We're trying to optimize when -Os is turned on. --- llvm/lib/Target/Mips/MipsISelLowering.cpp | 52 +++++++++++++++++-- llvm/lib/Target/Mips/MipsInstrInfo.cpp | 43 ++++++++++++++- .../CodeGen/Mips/nanomips/64bit-comparison.ll | 31 +++++++++++ 3 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 llvm/test/CodeGen/Mips/nanomips/64bit-comparison.ll 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 }