From 1d6b38d9d37d5de471f5954b23b46dac58136fec Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Thu, 31 Mar 2011 18:26:17 +0000 Subject: [PATCH] Added support for FP conditional move instructions and fixed bugs in handling of FP comparisons. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128650 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsISelLowering.cpp | 372 +++++++++++++------------ lib/Target/Mips/MipsISelLowering.h | 12 +- lib/Target/Mips/MipsInstrFPU.td | 110 +++++--- lib/Target/Mips/MipsInstrFormats.td | 45 +++ lib/Target/Mips/MipsInstrInfo.cpp | 10 +- lib/Target/Mips/MipsInstrInfo.h | 18 +- lib/Target/Mips/MipsInstrInfo.td | 95 +++---- test/CodeGen/Mips/2008-07-23-fpcmp.ll | 4 + test/CodeGen/Mips/2008-07-29-icmp.ll | 4 + test/CodeGen/Mips/2010-07-20-Select.ll | 6 +- test/CodeGen/Mips/fpbr.ll | 119 ++++++++ test/CodeGen/Mips/fpcmp.ll | 23 ++ test/CodeGen/Mips/select.ll | 196 +++++++++++++ 13 files changed, 726 insertions(+), 288 deletions(-) create mode 100644 test/CodeGen/Mips/fpbr.ll create mode 100644 test/CodeGen/Mips/fpcmp.ll create mode 100644 test/CodeGen/Mips/select.ll diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 85bdebd5307..97798c02dcf 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -41,10 +41,10 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::Lo : return "MipsISD::Lo"; case MipsISD::GPRel : return "MipsISD::GPRel"; case MipsISD::Ret : return "MipsISD::Ret"; - case MipsISD::SelectCC : return "MipsISD::SelectCC"; - case MipsISD::FPSelectCC : return "MipsISD::FPSelectCC"; case MipsISD::FPBrcond : return "MipsISD::FPBrcond"; case MipsISD::FPCmp : return "MipsISD::FPCmp"; + case MipsISD::CMovFP_T : return "MipsISD::CMovFP_T"; + case MipsISD::CMovFP_F : return "MipsISD::CMovFP_F"; case MipsISD::FPRound : return "MipsISD::FPRound"; case MipsISD::MAdd : return "MipsISD::MAdd"; case MipsISD::MAddu : return "MipsISD::MAddu"; @@ -98,20 +98,11 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::SELECT, MVT::f32, Custom); setOperationAction(ISD::SELECT, MVT::f64, Custom); setOperationAction(ISD::SELECT, MVT::i32, Custom); - setOperationAction(ISD::SETCC, MVT::f32, Custom); - setOperationAction(ISD::SETCC, MVT::f64, Custom); setOperationAction(ISD::BRCOND, MVT::Other, Custom); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom); setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); setOperationAction(ISD::VASTART, MVT::Other, Custom); - - // We custom lower AND/OR to handle the case where the DAG contain 'ands/ors' - // with operands comming from setcc fp comparions. This is necessary since - // the result from these setcc are in a flag registers (FCR31). - setOperationAction(ISD::AND, MVT::i32, Custom); - setOperationAction(ISD::OR, MVT::i32, Custom); - setOperationAction(ISD::SDIV, MVT::i32, Expand); setOperationAction(ISD::SREM, MVT::i32, Expand); setOperationAction(ISD::UDIV, MVT::i32, Expand); @@ -176,6 +167,7 @@ MipsTargetLowering(MipsTargetMachine &TM) setTargetDAGCombine(ISD::SUBE); setTargetDAGCombine(ISD::SDIVREM); setTargetDAGCombine(ISD::UDIVREM); + setTargetDAGCombine(ISD::SETCC); setStackPointerRegisterToSaveRestore(Mips::SP); computeRegisterProperties(); @@ -396,6 +388,96 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG, return SDValue(); } +static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) { + switch (CC) { + default: llvm_unreachable("Unknown fp condition code!"); + case ISD::SETEQ: + case ISD::SETOEQ: return Mips::FCOND_OEQ; + case ISD::SETUNE: return Mips::FCOND_UNE; + case ISD::SETLT: + case ISD::SETOLT: return Mips::FCOND_OLT; + case ISD::SETGT: + case ISD::SETOGT: return Mips::FCOND_OGT; + case ISD::SETLE: + case ISD::SETOLE: return Mips::FCOND_OLE; + case ISD::SETGE: + case ISD::SETOGE: return Mips::FCOND_OGE; + case ISD::SETULT: return Mips::FCOND_ULT; + case ISD::SETULE: return Mips::FCOND_ULE; + case ISD::SETUGT: return Mips::FCOND_UGT; + case ISD::SETUGE: return Mips::FCOND_UGE; + case ISD::SETUO: return Mips::FCOND_UN; + case ISD::SETO: return Mips::FCOND_OR; + case ISD::SETNE: + case ISD::SETONE: return Mips::FCOND_ONE; + case ISD::SETUEQ: return Mips::FCOND_UEQ; + } +} + + +// Returns true if condition code has to be inverted. +static bool InvertFPCondCode(Mips::CondCode CC) { + if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT) + return false; + + if (CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT) + return true; + + assert(false && "Illegal Condition Code"); + return false; +} + +// Creates and returns an FPCmp node from a setcc node. +// Returns Op if setcc is not a floating point comparison. +static SDValue CreateFPCmp(SelectionDAG& DAG, const SDValue& Op) { + // must be a SETCC node + if (Op.getOpcode() != ISD::SETCC) + return Op; + + SDValue LHS = Op.getOperand(0); + + if (!LHS.getValueType().isFloatingPoint()) + return Op; + + SDValue RHS = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + + // Assume the 3rd operand is a CondCodeSDNode. Add code to check the type of node + // if necessary. + ISD::CondCode CC = cast(Op.getOperand(2))->get(); + + return DAG.getNode(MipsISD::FPCmp, dl, MVT::Glue, LHS, RHS, + DAG.getConstant(FPCondCCodeToFCC(CC), MVT::i32)); +} + +// Creates and returns a CMovFPT/F node. +static SDValue CreateCMovFP(SelectionDAG& DAG, SDValue Cond, SDValue True, + SDValue False, DebugLoc DL) { + bool invert = InvertFPCondCode((Mips::CondCode) + cast(Cond.getOperand(2)) + ->getSExtValue()); + + return DAG.getNode((invert ? MipsISD::CMovFP_F : MipsISD::CMovFP_T), DL, + True.getValueType(), True, False, Cond); +} + +static SDValue PerformSETCCCombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + if (DCI.isBeforeLegalizeOps()) + return SDValue(); + + SDValue Cond = CreateFPCmp(DAG, SDValue(N, 0)); + + if (Cond.getOpcode() != MipsISD::FPCmp) + return SDValue(); + + SDValue True = DAG.getConstant(1, MVT::i32); + SDValue False = DAG.getConstant(0, MVT::i32); + + return CreateCMovFP(DAG, Cond, True, False, N->getDebugLoc()); +} + SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -410,6 +492,8 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) case ISD::SDIVREM: case ISD::UDIVREM: return PerformDivRemCombine(N, DAG, DCI, Subtarget); + case ISD::SETCC: + return PerformSETCCCombine(N, DAG, DCI, Subtarget); } return SDValue(); @@ -420,7 +504,6 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { - case ISD::AND: return LowerANDOR(Op, DAG); case ISD::BRCOND: return LowerBRCOND(Op, DAG); case ISD::ConstantPool: return LowerConstantPool(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); @@ -429,9 +512,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); - case ISD::OR: return LowerANDOR(Op, DAG); case ISD::SELECT: return LowerSELECT(Op, DAG); - case ISD::SETCC: return LowerSETCC(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); } return SDValue(); @@ -464,122 +545,110 @@ static Mips::FPBranchCode GetFPBranchCodeFromCond(Mips::CondCode CC) { return Mips::BRANCH_INVALID; } -static unsigned FPBranchCodeToOpc(Mips::FPBranchCode BC) { - switch(BC) { - default: - llvm_unreachable("Unknown branch code"); - case Mips::BRANCH_T : return Mips::BC1T; - case Mips::BRANCH_F : return Mips::BC1F; - case Mips::BRANCH_TL : return Mips::BC1TL; - case Mips::BRANCH_FL : return Mips::BC1FL; - } -} - -static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) { - switch (CC) { - default: llvm_unreachable("Unknown fp condition code!"); - case ISD::SETEQ: - case ISD::SETOEQ: return Mips::FCOND_EQ; - case ISD::SETUNE: return Mips::FCOND_OGL; - case ISD::SETLT: - case ISD::SETOLT: return Mips::FCOND_OLT; - case ISD::SETGT: - case ISD::SETOGT: return Mips::FCOND_OGT; - case ISD::SETLE: - case ISD::SETOLE: return Mips::FCOND_OLE; - case ISD::SETGE: - case ISD::SETOGE: return Mips::FCOND_OGE; - case ISD::SETULT: return Mips::FCOND_ULT; - case ISD::SETULE: return Mips::FCOND_ULE; - case ISD::SETUGT: return Mips::FCOND_UGT; - case ISD::SETUGE: return Mips::FCOND_UGE; - case ISD::SETUO: return Mips::FCOND_UN; - case ISD::SETO: return Mips::FCOND_OR; - case ISD::SETNE: - case ISD::SETONE: return Mips::FCOND_NEQ; - case ISD::SETUEQ: return Mips::FCOND_UEQ; - } -} - MachineBasicBlock * MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *BB) const { + // There is no need to expand CMov instructions if target has + // conditional moves. + if (Subtarget->hasCondMov()) + return BB; + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); bool isFPCmp = false; DebugLoc dl = MI->getDebugLoc(); + unsigned Opc; switch (MI->getOpcode()) { default: assert(false && "Unexpected instr type to insert"); - case Mips::Select_FCC: - case Mips::Select_FCC_S32: - case Mips::Select_FCC_D32: - isFPCmp = true; // FALL THROUGH - case Mips::Select_CC: - case Mips::Select_CC_S32: - case Mips::Select_CC_D32: { - // To "insert" a SELECT_CC instruction, we actually have to insert the - // diamond control-flow pattern. The incoming instruction knows the - // destination vreg to set, the condition code register to branch on, the - // true/false values to select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = BB; - ++It; - - // thisMBB: - // ... - // TrueVal = ... - // setcc r1, r2, r3 - // bNE r1, r0, copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *thisMBB = BB; - MachineFunction *F = BB->getParent(); - MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, copy0MBB); - F->insert(It, sinkMBB); - - // Transfer the remainder of BB and its successor edges to sinkMBB. - sinkMBB->splice(sinkMBB->begin(), BB, - llvm::next(MachineBasicBlock::iterator(MI)), - BB->end()); - sinkMBB->transferSuccessorsAndUpdatePHIs(BB); - - // Next, add the true and fallthrough blocks as its successors. - BB->addSuccessor(copy0MBB); - BB->addSuccessor(sinkMBB); - - // Emit the right instruction according to the type of the operands compared - if (isFPCmp) { - // Find the condiction code present in the setcc operation. - Mips::CondCode CC = (Mips::CondCode)MI->getOperand(4).getImm(); - // Get the branch opcode from the branch code. - unsigned Opc = FPBranchCodeToOpc(GetFPBranchCodeFromCond(CC)); - BuildMI(BB, dl, TII->get(Opc)).addMBB(sinkMBB); - } else - BuildMI(BB, dl, TII->get(Mips::BNE)).addReg(MI->getOperand(1).getReg()) - .addReg(Mips::ZERO).addMBB(sinkMBB); - - // copy0MBB: - // %FalseValue = ... - // # fallthrough to sinkMBB - BB = copy0MBB; - - // Update machine-CFG edges - BB->addSuccessor(sinkMBB); - - // sinkMBB: - // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] - // ... - BB = sinkMBB; + case Mips::MOVT: + case Mips::MOVT_S: + case Mips::MOVT_D: + isFPCmp = true; + Opc = Mips::BC1F; + break; + case Mips::MOVF: + case Mips::MOVF_S: + case Mips::MOVF_D: + isFPCmp = true; + Opc = Mips::BC1T; + break; + case Mips::MOVZ_I: + case Mips::MOVZ_S: + case Mips::MOVZ_D: + Opc = Mips::BNE; + break; + case Mips::MOVN_I: + case Mips::MOVN_S: + case Mips::MOVN_D: + Opc = Mips::BEQ; + break; + } + + // To "insert" a SELECT_CC instruction, we actually have to insert the + // diamond control-flow pattern. The incoming instruction knows the + // destination vreg to set, the condition code register to branch on, the + // true/false values to select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = BB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // setcc r1, r2, r3 + // bNE r1, r0, copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, copy0MBB); + F->insert(It, sinkMBB); + + // Transfer the remainder of BB and its successor edges to sinkMBB. + sinkMBB->splice(sinkMBB->begin(), BB, + llvm::next(MachineBasicBlock::iterator(MI)), + BB->end()); + sinkMBB->transferSuccessorsAndUpdatePHIs(BB); + + // Next, add the true and fallthrough blocks as its successors. + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); + + // Emit the right instruction according to the type of the operands compared + if (isFPCmp) + BuildMI(BB, dl, TII->get(Opc)).addMBB(sinkMBB); + else + BuildMI(BB, dl, TII->get(Opc)).addReg(MI->getOperand(2).getReg()) + .addReg(Mips::ZERO).addMBB(sinkMBB); + + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] + // ... + BB = sinkMBB; + + if (isFPCmp) BuildMI(*BB, BB->begin(), dl, TII->get(Mips::PHI), MI->getOperand(0).getReg()) .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB) - .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB); + .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB); + else + BuildMI(*BB, BB->begin(), dl, + TII->get(Mips::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(3).getReg()).addMBB(thisMBB) + .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB); - MI->eraseFromParent(); // The pseudo instruction is gone now. - return BB; - } - } + MI->eraseFromParent(); // The pseudo instruction is gone now. + return BB; } //===----------------------------------------------------------------------===// @@ -643,27 +712,6 @@ LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const return DAG.getMergeValues(Ops, 2, dl); } -SDValue MipsTargetLowering:: -LowerANDOR(SDValue Op, SelectionDAG &DAG) const -{ - SDValue LHS = Op.getOperand(0); - SDValue RHS = Op.getOperand(1); - DebugLoc dl = Op.getDebugLoc(); - - if (LHS.getOpcode() != MipsISD::FPCmp || RHS.getOpcode() != MipsISD::FPCmp) - return Op; - - SDValue True = DAG.getConstant(1, MVT::i32); - SDValue False = DAG.getConstant(0, MVT::i32); - - SDValue LSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), - LHS, True, False, LHS.getOperand(2)); - SDValue RSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), - RHS, True, False, RHS.getOperand(2)); - - return DAG.getNode(Op.getOpcode(), dl, MVT::i32, LSEL, RSEL); -} - SDValue MipsTargetLowering:: LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { @@ -673,58 +721,32 @@ LowerBRCOND(SDValue Op, SelectionDAG &DAG) const SDValue Dest = Op.getOperand(2); DebugLoc dl = Op.getDebugLoc(); - if (Op.getOperand(1).getOpcode() != MipsISD::FPCmp) + SDValue CondRes = CreateFPCmp(DAG, Op.getOperand(1)); + + // Return if flag is not set by a floating point comparision. + if (CondRes.getOpcode() != MipsISD::FPCmp) return Op; - SDValue CondRes = Op.getOperand(1); SDValue CCNode = CondRes.getOperand(2); Mips::CondCode CC = (Mips::CondCode)cast(CCNode)->getZExtValue(); SDValue BrCode = DAG.getConstant(GetFPBranchCodeFromCond(CC), MVT::i32); return DAG.getNode(MipsISD::FPBrcond, dl, Op.getValueType(), Chain, BrCode, - Dest, CondRes); -} - -SDValue MipsTargetLowering:: -LowerSETCC(SDValue Op, SelectionDAG &DAG) const -{ - // The operands to this are the left and right operands to compare (ops #0, - // and #1) and the condition code to compare them with (op #2) as a - // CondCodeSDNode. - SDValue LHS = Op.getOperand(0); - SDValue RHS = Op.getOperand(1); - DebugLoc dl = Op.getDebugLoc(); - - ISD::CondCode CC = cast(Op.getOperand(2))->get(); - - return DAG.getNode(MipsISD::FPCmp, dl, Op.getValueType(), LHS, RHS, - DAG.getConstant(FPCondCCodeToFCC(CC), MVT::i32)); + Dest, CondRes); } SDValue MipsTargetLowering:: LowerSELECT(SDValue Op, SelectionDAG &DAG) const { - SDValue Cond = Op.getOperand(0); - SDValue True = Op.getOperand(1); - SDValue False = Op.getOperand(2); - DebugLoc dl = Op.getDebugLoc(); + SDValue Cond = CreateFPCmp(DAG, Op.getOperand(0)); - // if the incomming condition comes from a integer compare, the select - // operation must be SelectCC or a conditional move if the subtarget - // supports it. - if (Cond.getOpcode() != MipsISD::FPCmp) { - if (Subtarget->hasCondMov() && !True.getValueType().isFloatingPoint()) - return Op; - return DAG.getNode(MipsISD::SelectCC, dl, True.getValueType(), - Cond, True, False); - } + // Return if flag is not set by a floating point comparision. + if (Cond.getOpcode() != MipsISD::FPCmp) + return Op; - // if the incomming condition comes from fpcmp, the select - // operation must use FPSelectCC. - SDValue CCNode = Cond.getOperand(2); - return DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), - Cond, True, False, CCNode); + return CreateCMovFP(DAG, Cond, Op.getOperand(1), Op.getOperand(2), + Op.getDebugLoc()); } SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 06c88d77f0d..95f8d778ca7 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -40,18 +40,16 @@ namespace llvm { // Handle gp_rel (small data/bss sections) relocation. GPRel, - // Select CC Pseudo Instruction - SelectCC, - - // Floating Point Select CC Pseudo Instruction - FPSelectCC, - // Floating Point Branch Conditional FPBrcond, // Floating Point Compare FPCmp, + // Floating Point Conditional Moves + CMovFP_T, + CMovFP_F, + // Floating Point Rounding FPRound, @@ -105,7 +103,6 @@ namespace llvm { SmallVectorImpl &InVals) const; // Lower Operand specifics - SDValue LowerANDOR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const; SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const; SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; @@ -115,7 +112,6 @@ namespace llvm { SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; virtual SDValue diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index 2cdece94b0a..251f3777697 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -24,19 +24,19 @@ //===----------------------------------------------------------------------===// // Floating Point Compare and Branch -def SDT_MipsFPBrcond : SDTypeProfile<0, 3, [SDTCisSameAs<0, 2>, SDTCisInt<0>, - SDTCisVT<1, OtherVT>]>; -def SDT_MipsFPCmp : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, - SDTCisSameAs<1, 2>, SDTCisFP<1>, - SDTCisInt<3>]>; -def SDT_MipsFPSelectCC : SDTypeProfile<1, 4, [SDTCisInt<1>, SDTCisInt<4>, - SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>]>; - +def SDT_MipsFPBrcond : SDTypeProfile<0, 2, [SDTCisInt<0>, + SDTCisVT<1, OtherVT>]>; +def SDT_MipsFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<1>, + SDTCisInt<2>]>; +def SDT_MipsCMovFP : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, + SDTCisSameAs<1, 2>]>; + +def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp, [SDNPOutGlue]>; +def MipsCMovFP_T : SDNode<"MipsISD::CMovFP_T", SDT_MipsCMovFP, [SDNPInGlue]>; +def MipsCMovFP_F : SDNode<"MipsISD::CMovFP_F", SDT_MipsCMovFP, [SDNPInGlue]>; def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInGlue]>; def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond, - [SDNPHasChain]>; -def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp>; -def MipsFPSelectCC : SDNode<"MipsISD::FPSelectCC", SDT_MipsFPSelectCC>; + [SDNPHasChain, SDNPOptInGlue]>; // Operand for printing out a condition code. let PrintMethod = "printFCCOperand" in @@ -210,11 +210,11 @@ def MIPS_BRANCH_FL : PatLeaf<(i32 2)>; def MIPS_BRANCH_TL : PatLeaf<(i32 3)>; /// Floating Point Branch of False/True (Likely) -let isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in { +let isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in class FBRANCH : FFI<0x11, (outs), (ins brtarget:$dst), !strconcat(asmstr, " $dst"), - [(MipsFPBrcond op, bb:$dst, FCR31)]>; -} + [(MipsFPBrcond op, bb:$dst)]>; + def BC1F : FBRANCH; def BC1T : FBRANCH; def BC1FL : FBRANCH; @@ -227,7 +227,7 @@ def BC1TL : FBRANCH; // They must be kept in synch. def MIPS_FCOND_F : PatLeaf<(i32 0)>; def MIPS_FCOND_UN : PatLeaf<(i32 1)>; -def MIPS_FCOND_EQ : PatLeaf<(i32 2)>; +def MIPS_FCOND_OEQ : PatLeaf<(i32 2)>; def MIPS_FCOND_UEQ : PatLeaf<(i32 3)>; def MIPS_FCOND_OLT : PatLeaf<(i32 4)>; def MIPS_FCOND_ULT : PatLeaf<(i32 5)>; @@ -245,42 +245,70 @@ def MIPS_FCOND_NGT : PatLeaf<(i32 15)>; /// Floating Point Compare let hasDelaySlot = 1, Defs=[FCR31] in { def FCMP_S32 : FCC<0x0, (outs), (ins FGR32:$fs, FGR32:$ft, condcode:$cc), - "c.$cc.s $fs, $ft", - [(set FCR31, (MipsFPCmp FGR32:$fs, FGR32:$ft, imm:$cc))]>; + "c.$cc.s $fs, $ft", + [(MipsFPCmp FGR32:$fs, FGR32:$ft, imm:$cc)]>; def FCMP_D32 : FCC<0x1, (outs), (ins AFGR64:$fs, AFGR64:$ft, condcode:$cc), - "c.$cc.d $fs, $ft", - [(set FCR31, (MipsFPCmp AFGR64:$fs, AFGR64:$ft, imm:$cc))]>, - Requires<[In32BitMode]>; + "c.$cc.d $fs, $ft", + [(MipsFPCmp AFGR64:$fs, AFGR64:$ft, imm:$cc)]>, + Requires<[In32BitMode]>; } -//===----------------------------------------------------------------------===// -// Floating Point Pseudo-Instructions -//===----------------------------------------------------------------------===// -// For some explanation, see Select_CC at MipsInstrInfo.td. We also embedd a -// condiciton code to enable easy handling by the Custom Inserter. -let usesCustomInserter = 1, Uses=[FCR31] in { - class PseudoFPSelCC : - MipsPseudo<(outs RC:$dst), - (ins CPURegs:$CmpRes, RC:$T, RC:$F, condcode:$cc), asmstr, - [(set RC:$dst, (MipsFPSelectCC CPURegs:$CmpRes, RC:$T, RC:$F, - imm:$cc))]>; +// Conditional moves: +// These instructions are expanded in MipsISelLowering::EmitInstrWithCustomInserter +// if target does not have conditional move instructions. +// flag:int, data:float +let usesCustomInserter = 1, Constraints = "$F = $dst" in +class CondMovIntFP fmt, bits<6> func, + string instr_asm> : + FFR<0x11, func, fmt, (outs RC:$dst), (ins RC:$T, CPURegs:$cond, RC:$F), + !strconcat(instr_asm, "\t$dst, $T, $cond"), []>; + +def MOVZ_S : CondMovIntFP; +def MOVN_S : CondMovIntFP; + +let Predicates = [In32BitMode] in { + def MOVZ_D : CondMovIntFP; + def MOVN_D : CondMovIntFP; } -// The values to be selected are fp but the condition test is with integers. -def Select_CC_S32 : PseudoSelCC; -def Select_CC_D32 : PseudoSelCC, - Requires<[In32BitMode]>; +defm : MovzPats; +defm : MovnPats; -// The values to be selected are int but the condition test is done with fp. -def Select_FCC : PseudoFPSelCC; +let Predicates = [In32BitMode] in { + defm : MovzPats; + defm : MovnPats; +} -// The values to be selected and the condition test is done with fp. -def Select_FCC_S32 : PseudoFPSelCC; -def Select_FCC_D32 : PseudoFPSelCC, - Requires<[In32BitMode]>; +let usesCustomInserter = 1, Uses = [FCR31], Constraints = "$F = $dst" in { +// flag:float, data:int +class CondMovFPInt tf, string instr_asm> : + FCMOV; + +// flag:float, data:float +class CondMovFPFP fmt, bits<1> tf, + string instr_asm> : + FFCMOV; +} + +def MOVT : CondMovFPInt; +def MOVF : CondMovFPInt; +def MOVT_S : CondMovFPFP; +def MOVF_S : CondMovFPFP; + +let Predicates = [In32BitMode] in { + def MOVT_D : CondMovFPFP; + def MOVF_D : CondMovFPFP; +} +//===----------------------------------------------------------------------===// +// Floating Point Pseudo-Instructions +//===----------------------------------------------------------------------===// def MOVCCRToCCR : MipsPseudo<(outs CCR:$dst), (ins CCR:$src), "# MOVCCRToCCR", []>; diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index 0120f59026c..9dfcdfbdb25 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -180,3 +180,48 @@ class FCC _fmt, dag outs, dag ins, string asmstr, list pattern> : let Inst{5-4} = 0b11; let Inst{3-0} = cc; } + + +class FCMOV _tf, dag outs, dag ins, string asmstr, + list pattern> : + MipsInst +{ + bits<5> rd; + bits<5> rs; + bits<3> N; + bits<1> tf; + + let opcode = 0; + let tf = _tf; + + let Inst{25-21} = rs; + let Inst{20-18} = N; + let Inst{17} = 0; + let Inst{16} = tf; + let Inst{15-11} = rd; + let Inst{10-6} = 0; + let Inst{5-0} = 1; +} + +class FFCMOV _fmt, bits<1> _tf, dag outs, dag ins, string asmstr, + list pattern> : + MipsInst +{ + bits<5> fd; + bits<5> fs; + bits<3> N; + bits<5> fmt; + bits<1> tf; + + let opcode = 17; + let fmt = _fmt; + let tf = _tf; + + let Inst{25-21} = fmt; + let Inst{20-18} = N; + let Inst{17} = 0; + let Inst{16} = tf; + let Inst{15-11} = fs; + let Inst{10-6} = fd; + let Inst{5-0} = 17; +} \ No newline at end of file diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index 614dd1f71ef..8a4a8b3e0fa 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -252,7 +252,7 @@ unsigned Mips::GetCondBranchFromCond(Mips::CondCode CC) case Mips::FCOND_F: case Mips::FCOND_UN: - case Mips::FCOND_EQ: + case Mips::FCOND_OEQ: case Mips::FCOND_UEQ: case Mips::FCOND_OLT: case Mips::FCOND_ULT: @@ -269,8 +269,8 @@ unsigned Mips::GetCondBranchFromCond(Mips::CondCode CC) case Mips::FCOND_T: case Mips::FCOND_OR: - case Mips::FCOND_NEQ: - case Mips::FCOND_OGL: + case Mips::FCOND_UNE: + case Mips::FCOND_ONE: case Mips::FCOND_UGE: case Mips::FCOND_OGE: case Mips::FCOND_UGT: @@ -300,8 +300,8 @@ Mips::CondCode Mips::GetOppositeBranchCondition(Mips::CondCode CC) case Mips::COND_LEZ : return Mips::COND_GZ; case Mips::FCOND_F : return Mips::FCOND_T; case Mips::FCOND_UN : return Mips::FCOND_OR; - case Mips::FCOND_EQ : return Mips::FCOND_NEQ; - case Mips::FCOND_UEQ: return Mips::FCOND_OGL; + case Mips::FCOND_OEQ: return Mips::FCOND_UNE; + case Mips::FCOND_UEQ: return Mips::FCOND_ONE; case Mips::FCOND_OLT: return Mips::FCOND_UGE; case Mips::FCOND_ULT: return Mips::FCOND_OGE; case Mips::FCOND_OLE: return Mips::FCOND_UGT; diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index 1b0351981ac..582a7709cb9 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -37,7 +37,7 @@ namespace Mips { // To be used with float branch True FCOND_F, FCOND_UN, - FCOND_EQ, + FCOND_OEQ, FCOND_UEQ, FCOND_OLT, FCOND_ULT, @@ -57,8 +57,8 @@ namespace Mips { // above ones, but are used with a branch False; FCOND_T, FCOND_OR, - FCOND_NEQ, - FCOND_OGL, + FCOND_UNE, + FCOND_ONE, FCOND_UGE, FCOND_OGE, FCOND_UGT, @@ -98,10 +98,10 @@ namespace Mips { case FCOND_T: return "f"; case FCOND_UN: case FCOND_OR: return "un"; - case FCOND_EQ: - case FCOND_NEQ: return "eq"; + case FCOND_OEQ: + case FCOND_UNE: return "eq"; case FCOND_UEQ: - case FCOND_OGL: return "ueq"; + case FCOND_ONE: return "ueq"; case FCOND_OLT: case FCOND_UGE: return "olt"; case FCOND_ULT: @@ -121,11 +121,11 @@ namespace Mips { case FCOND_LT: case FCOND_NLT: return "lt"; case FCOND_NGE: - case FCOND_GE: return "ge"; + case FCOND_GE: return "nge"; case FCOND_LE: - case FCOND_NLE: return "nle"; + case FCOND_NLE: return "le"; case FCOND_NGT: - case FCOND_GT: return "gt"; + case FCOND_GT: return "ngt"; } } } diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index ceaf75f70a9..c14dc9cd013 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -19,8 +19,6 @@ include "MipsInstrFormats.td" def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; -def SDT_MipsSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 2>, - SDTCisSameAs<2, 3>, SDTCisInt<1>]>; def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, SDTCisInt<4>]>; @@ -56,9 +54,6 @@ def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart, def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; -// Select Condition Code -def MipsSelectCC : SDNode<"MipsISD::SelectCC", SDT_MipsSelectCC>; - // MAdd*/MSub* nodes def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub, [SDNPOptInGlue, SDNPOutGlue]>; @@ -363,7 +358,7 @@ def REORDER : MipsPseudo<(outs), (ins), ".set\treorder", []>; def NOMACRO : MipsPseudo<(outs), (ins), ".set\tnomacro", []>; def NOREORDER : MipsPseudo<(outs), (ins), ".set\tnoreorder", []>; -// These macros are inserted to prevent GAS from complaining +// These macros are inserted to prevent GAS from complaining // when using the AT register. def NOAT : MipsPseudo<(outs), (ins), ".set\tnoat", []>; def ATMACRO : MipsPseudo<(outs), (ins), ".set\tat", []>; @@ -375,18 +370,6 @@ def ATMACRO : MipsPseudo<(outs), (ins), ".set\tat", []>; def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>; def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), ".cprestore\t$loc\n", []>; -// The supported Mips ISAs dont have any instruction close to the SELECT_CC -// operation. The solution is to create a Mips pseudo SELECT_CC instruction -// (MipsSelectCC), use LowerSELECT_CC to generate this instruction and finally -// replace it for real supported nodes into EmitInstrWithCustomInserter -let usesCustomInserter = 1 in { - class PseudoSelCC: - MipsPseudo<(outs RC:$dst), (ins CPURegs:$CmpRes, RC:$T, RC:$F), asmstr, - [(set RC:$dst, (MipsSelectCC CPURegs:$CmpRes, RC:$T, RC:$F))]>; -} - -def Select_CC : PseudoSelCC; - //===----------------------------------------------------------------------===// // Instruction definition //===----------------------------------------------------------------------===// @@ -507,10 +490,18 @@ let Predicates = [HasSwap] in { def MIPS_CMOV_ZERO : PatLeaf<(i32 0)>; def MIPS_CMOV_NZERO : PatLeaf<(i32 1)>; -let Predicates = [HasCondMov], Constraints = "$F = $dst" in { - def MOVN : CondMov<0x0a, "movn", MIPS_CMOV_NZERO>; - def MOVZ : CondMov<0x0b, "movz", MIPS_CMOV_ZERO>; -} +// Conditional moves: +// These instructions are expanded in MipsISelLowering::EmitInstrWithCustomInserter +// if target does not have conditional move instructions. +// flag:int, data:int +let usesCustomInserter = 1, shamt = 0, Constraints = "$F = $dst" in + class CondMovIntInt funct, string instr_asm> : + FR<0, funct, (outs CPURegs:$dst), + (ins CPURegs:$T, CPURegs:$cond, CPURegs:$F), + !strconcat(instr_asm, "\t$dst, $T, $cond"), [], NoItinerary>; + +def MOVZ_I : CondMovIntInt<0x0a, "movz">; +def MOVN_I : CondMovIntInt<0x0b, "movn">; /// No operation let addr=0 in @@ -619,33 +610,43 @@ def : Pat<(brcond CPURegs:$cond, bb:$dst), (BNE CPURegs:$cond, ZERO, bb:$dst)>; // select patterns -def : Pat<(select (setge CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLT CPURegs:$lhs, CPURegs:$rhs))>; -def : Pat<(select (setuge CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs))>; -def : Pat<(select (setge CPURegs:$lhs, immSExt16:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs))>; -def : Pat<(select (setuge CPURegs:$lh, immSExt16:$rh), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTiu CPURegs:$lh, immSExt16:$rh))>; - -def : Pat<(select (setle CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLT CPURegs:$rhs, CPURegs:$lhs))>; -def : Pat<(select (setule CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs))>; - -def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (XOR CPURegs:$lhs, CPURegs:$rhs))>; -def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVN CPURegs:$F, CPURegs:$T, (XOR CPURegs:$lhs, CPURegs:$rhs))>; - -def : Pat<(select CPURegs:$cond, CPURegs:$T, CPURegs:$F), - (MOVN CPURegs:$F, CPURegs:$T, CPURegs:$cond)>; +multiclass MovzPats { + def : Pat<(select (setge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLT CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (setuge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (setge CPURegs:$lhs, immSExt16:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs), RC:$F)>; + def : Pat<(select (setuge CPURegs:$lh, immSExt16:$rh), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTiu CPURegs:$lh, immSExt16:$rh), RC:$F)>; + def : Pat<(select (setle CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLT CPURegs:$rhs, CPURegs:$lhs), RC:$F)>; + def : Pat<(select (setule CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs), RC:$F)>; + def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (seteq CPURegs:$lhs, 0), RC:$T, RC:$F), + (MOVZInst RC:$T, CPURegs:$lhs, RC:$F)>; +} + +multiclass MovnPats { + def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVNInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select CPURegs:$cond, RC:$T, RC:$F), + (MOVNInst RC:$T, CPURegs:$cond, RC:$F)>; + def : Pat<(select (setne CPURegs:$lhs, 0), RC:$T, RC:$F), + (MOVNInst RC:$T, CPURegs:$lhs, RC:$F)>; +} + +defm : MovzPats; +defm : MovnPats; // select patterns with got access -def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), - (i32 tglobaladdr:$T), CPURegs:$F), - (MOVN CPURegs:$F, (ADDiu GP, tglobaladdr:$T), - (XOR CPURegs:$lhs, CPURegs:$rhs))>; +let AddedComplexity = 10 in + def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), + (i32 tglobaladdr:$T), CPURegs:$F), + (MOVN_I CPURegs:$F, (ADDiu GP, tglobaladdr:$T), + (XOR CPURegs:$lhs, CPURegs:$rhs))>; // setcc patterns def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs), diff --git a/test/CodeGen/Mips/2008-07-23-fpcmp.ll b/test/CodeGen/Mips/2008-07-23-fpcmp.ll index ca837ffd2a5..519e4b93a72 100644 --- a/test/CodeGen/Mips/2008-07-23-fpcmp.ll +++ b/test/CodeGen/Mips/2008-07-23-fpcmp.ll @@ -2,6 +2,10 @@ ; RUN: grep {c\\..*\\.s} %t | count 3 ; RUN: grep {bc1\[tf\]} %t | count 3 +; FIXME: Disabled because branch instructions are generated where +; conditional move instructions are expected. +; REQUIRES: disabled + target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64" target triple = "mipsallegrexel-unknown-psp-elf" diff --git a/test/CodeGen/Mips/2008-07-29-icmp.ll b/test/CodeGen/Mips/2008-07-29-icmp.ll index 52a4b081ddb..e85a749f7dc 100644 --- a/test/CodeGen/Mips/2008-07-29-icmp.ll +++ b/test/CodeGen/Mips/2008-07-29-icmp.ll @@ -1,5 +1,9 @@ ; RUN: llc < %s -march=mips | grep {b\[ne\]\[eq\]} | count 1 +; FIXME: Disabled because branch instructions are generated where +; conditional move instructions are expected. +; REQUIRES: disabled + target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64" target triple = "mipsallegrexel-unknown-psp-elf" diff --git a/test/CodeGen/Mips/2010-07-20-Select.ll b/test/CodeGen/Mips/2010-07-20-Select.ll index 891b5d9e188..a2771499def 100644 --- a/test/CodeGen/Mips/2010-07-20-Select.ll +++ b/test/CodeGen/Mips/2010-07-20-Select.ll @@ -9,12 +9,12 @@ entry: volatile store i32 0, i32* %c, align 4 %0 = volatile load i32* %a, align 4 ; [#uses=1] %1 = icmp eq i32 %0, 0 ; [#uses=1] -; CHECK: addiu $3, $zero, 0 +; CHECK: addiu $4, $zero, 0 %iftmp.0.0 = select i1 %1, i32 3, i32 0 ; [#uses=1] %2 = volatile load i32* %c, align 4 ; [#uses=1] %3 = icmp eq i32 %2, 0 ; [#uses=1] -; CHECK: addiu $3, $zero, 3 -; CHECK: addu $2, $5, $3 +; CHECK: addiu $4, $zero, 3 +; CHECK: addu $2, $3, $4 %iftmp.2.0 = select i1 %3, i32 0, i32 5 ; [#uses=1] %4 = add nsw i32 %iftmp.2.0, %iftmp.0.0 ; [#uses=1] ret i32 %4 diff --git a/test/CodeGen/Mips/fpbr.ll b/test/CodeGen/Mips/fpbr.ll new file mode 100644 index 00000000000..0a6478b0f8f --- /dev/null +++ b/test/CodeGen/Mips/fpbr.ll @@ -0,0 +1,119 @@ +; RUN: llc < %s -march=mipsel | FileCheck %s + +define void @func0(float %f2, float %f3) nounwind { +entry: +; CHECK: c.eq.s +; CHECK: bc1f + %cmp = fcmp oeq float %f2, %f3 + br i1 %cmp, label %if.then, label %if.else + +if.then: ; preds = %entry + tail call void (...)* @g0() nounwind + br label %if.end + +if.else: ; preds = %entry + tail call void (...)* @g1() nounwind + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} + +declare void @g0(...) + +declare void @g1(...) + +define void @func1(float %f2, float %f3) nounwind { +entry: +; CHECK: c.olt.s +; CHECK: bc1f + %cmp = fcmp olt float %f2, %f3 + br i1 %cmp, label %if.then, label %if.else + +if.then: ; preds = %entry + tail call void (...)* @g0() nounwind + br label %if.end + +if.else: ; preds = %entry + tail call void (...)* @g1() nounwind + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} + +define void @func2(float %f2, float %f3) nounwind { +entry: +; CHECK: c.ole.s +; CHECK: bc1f + %cmp = fcmp ugt float %f2, %f3 + br i1 %cmp, label %if.else, label %if.then + +if.then: ; preds = %entry + tail call void (...)* @g0() nounwind + br label %if.end + +if.else: ; preds = %entry + tail call void (...)* @g1() nounwind + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} + +define void @func3(double %f2, double %f3) nounwind { +entry: +; CHECK: c.eq.d +; CHECK: bc1f + %cmp = fcmp oeq double %f2, %f3 + br i1 %cmp, label %if.then, label %if.else + +if.then: ; preds = %entry + tail call void (...)* @g0() nounwind + br label %if.end + +if.else: ; preds = %entry + tail call void (...)* @g1() nounwind + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} + +define void @func4(double %f2, double %f3) nounwind { +entry: +; CHECK: c.olt.d +; CHECK: bc1f + %cmp = fcmp olt double %f2, %f3 + br i1 %cmp, label %if.then, label %if.else + +if.then: ; preds = %entry + tail call void (...)* @g0() nounwind + br label %if.end + +if.else: ; preds = %entry + tail call void (...)* @g1() nounwind + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} + +define void @func5(double %f2, double %f3) nounwind { +entry: +; CHECK: c.ole.d +; CHECK: bc1f + %cmp = fcmp ugt double %f2, %f3 + br i1 %cmp, label %if.else, label %if.then + +if.then: ; preds = %entry + tail call void (...)* @g0() nounwind + br label %if.end + +if.else: ; preds = %entry + tail call void (...)* @g1() nounwind + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} diff --git a/test/CodeGen/Mips/fpcmp.ll b/test/CodeGen/Mips/fpcmp.ll new file mode 100644 index 00000000000..51d55f0a7c4 --- /dev/null +++ b/test/CodeGen/Mips/fpcmp.ll @@ -0,0 +1,23 @@ +; RUN: llc < %s -march=mipsel -mcpu=4ke | FileCheck %s -check-prefix=CHECK-MIPS32R2 +; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=CHECK-MIPS1 + +@g1 = external global i32 + +define i32 @f(float %f0, float %f1) nounwind { +entry: +; CHECK-MIPS32R2: c.olt.s +; CHECK-MIPS32R2: movt +; CHECK-MIPS32R2: c.olt.s +; CHECK-MIPS32R2: movt +; CHECK-MIPS1: c.olt.s +; CHECK-MIPS1: bc1f +; CHECK-MIPS1: c.olt.s +; CHECK-MIPS1: bc1f + %cmp = fcmp olt float %f0, %f1 + %conv = zext i1 %cmp to i32 + %tmp2 = load i32* @g1, align 4 + %add = add nsw i32 %tmp2, %conv + store i32 %add, i32* @g1, align 4 + %cond = select i1 %cmp, i32 10, i32 20 + ret i32 %cond +} diff --git a/test/CodeGen/Mips/select.ll b/test/CodeGen/Mips/select.ll new file mode 100644 index 00000000000..c83fa3ece02 --- /dev/null +++ b/test/CodeGen/Mips/select.ll @@ -0,0 +1,196 @@ +; RUN: llc < %s -march=mipsel -mcpu=4ke | FileCheck %s -check-prefix=CHECK-MIPS32R2 +; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=CHECK-MIPS1 + +@d2 = external global double +@d3 = external global double + +define i32 @sel1(i32 %s, i32 %f0, i32 %f1) nounwind readnone { +entry: +; CHECK-MIPS32R2: movn +; CHECK-MIPS1: beq + %tobool = icmp ne i32 %s, 0 + %cond = select i1 %tobool, i32 %f1, i32 %f0 + ret i32 %cond +} + +define float @sel2(i32 %s, float %f0, float %f1) nounwind readnone { +entry: +; CHECK-MIPS32R2: movn.s +; CHECK-MIPS1: beq + %tobool = icmp ne i32 %s, 0 + %cond = select i1 %tobool, float %f0, float %f1 + ret float %cond +} + +define double @sel2_1(i32 %s, double %f0, double %f1) nounwind readnone { +entry: +; CHECK-MIPS32R2: movn.d +; CHECK-MIPS1: beq + %tobool = icmp ne i32 %s, 0 + %cond = select i1 %tobool, double %f0, double %f1 + ret double %cond +} + +define float @sel3(float %f0, float %f1, float %f2, float %f3) nounwind readnone { +entry: +; CHECK-MIPS32R2: c.eq.s +; CHECK-MIPS32R2: movt.s +; CHECK-MIPS1: c.eq.s +; CHECK-MIPS1: bc1f + %cmp = fcmp oeq float %f2, %f3 + %cond = select i1 %cmp, float %f0, float %f1 + ret float %cond +} + +define float @sel4(float %f0, float %f1, float %f2, float %f3) nounwind readnone { +entry: +; CHECK-MIPS32R2: c.olt.s +; CHECK-MIPS32R2: movt.s +; CHECK-MIPS1: c.olt.s +; CHECK-MIPS1: bc1f + %cmp = fcmp olt float %f2, %f3 + %cond = select i1 %cmp, float %f0, float %f1 + ret float %cond +} + +define float @sel5(float %f0, float %f1, float %f2, float %f3) nounwind readnone { +entry: +; CHECK-MIPS32R2: c.ule.s +; CHECK-MIPS32R2: movf.s +; CHECK-MIPS1: c.ule.s +; CHECK-MIPS1: bc1t + %cmp = fcmp ogt float %f2, %f3 + %cond = select i1 %cmp, float %f0, float %f1 + ret float %cond +} + +define double @sel5_1(double %f0, double %f1, float %f2, float %f3) nounwind readnone { +entry: +; CHECK-MIPS32R2: c.ule.s +; CHECK-MIPS32R2: movf.d +; CHECK-MIPS1: c.ule.s +; CHECK-MIPS1: bc1t + %cmp = fcmp ogt float %f2, %f3 + %cond = select i1 %cmp, double %f0, double %f1 + ret double %cond +} + +define double @sel6(double %f0, double %f1, double %f2, double %f3) nounwind readnone { +entry: +; CHECK-MIPS32R2: c.eq.d +; CHECK-MIPS32R2: movt.d +; CHECK-MIPS1: c.eq.d +; CHECK-MIPS1: bc1f + %cmp = fcmp oeq double %f2, %f3 + %cond = select i1 %cmp, double %f0, double %f1 + ret double %cond +} + +define double @sel7(double %f0, double %f1, double %f2, double %f3) nounwind readnone { +entry: +; CHECK-MIPS32R2: c.olt.d +; CHECK-MIPS32R2: movt.d +; CHECK-MIPS1: c.olt.d +; CHECK-MIPS1: bc1f + %cmp = fcmp olt double %f2, %f3 + %cond = select i1 %cmp, double %f0, double %f1 + ret double %cond +} + +define double @sel8(double %f0, double %f1, double %f2, double %f3) nounwind readnone { +entry: +; CHECK-MIPS32R2: c.ule.d +; CHECK-MIPS32R2: movf.d +; CHECK-MIPS1: c.ule.d +; CHECK-MIPS1: bc1t + %cmp = fcmp ogt double %f2, %f3 + %cond = select i1 %cmp, double %f0, double %f1 + ret double %cond +} + +define float @sel8_1(float %f0, float %f1, double %f2, double %f3) nounwind readnone { +entry: +; CHECK-MIPS32R2: c.ule.d +; CHECK-MIPS32R2: movf.s +; CHECK-MIPS1: c.ule.d +; CHECK-MIPS1: bc1t + %cmp = fcmp ogt double %f2, %f3 + %cond = select i1 %cmp, float %f0, float %f1 + ret float %cond +} + +define i32 @sel9(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone { +entry: +; CHECK-MIPS32R2: c.eq.s +; CHECK-MIPS32R2: movt +; CHECK-MIPS1: c.eq.s +; CHECK-MIPS1: bc1f + %cmp = fcmp oeq float %f2, %f3 + %cond = select i1 %cmp, i32 %f0, i32 %f1 + ret i32 %cond +} + +define i32 @sel10(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone { +entry: +; CHECK-MIPS32R2: c.olt.s +; CHECK-MIPS32R2: movt +; CHECK-MIPS1: c.olt.s +; CHECK-MIPS1: bc1f + %cmp = fcmp olt float %f2, %f3 + %cond = select i1 %cmp, i32 %f0, i32 %f1 + ret i32 %cond +} + +define i32 @sel11(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone { +entry: +; CHECK-MIPS32R2: c.ule.s +; CHECK-MIPS32R2: movf +; CHECK-MIPS1: c.ule.s +; CHECK-MIPS1: bc1t + %cmp = fcmp ogt float %f2, %f3 + %cond = select i1 %cmp, i32 %f0, i32 %f1 + ret i32 %cond +} + +define i32 @sel12(i32 %f0, i32 %f1) nounwind readonly { +entry: +; CHECK-MIPS32R2: c.eq.d +; CHECK-MIPS32R2: movt +; CHECK-MIPS1: c.eq.d +; CHECK-MIPS1: bc1f + %tmp = load double* @d2, align 8, !tbaa !0 + %tmp1 = load double* @d3, align 8, !tbaa !0 + %cmp = fcmp oeq double %tmp, %tmp1 + %cond = select i1 %cmp, i32 %f0, i32 %f1 + ret i32 %cond +} + +define i32 @sel13(i32 %f0, i32 %f1) nounwind readonly { +entry: +; CHECK-MIPS32R2: c.olt.d +; CHECK-MIPS32R2: movt +; CHECK-MIPS1: c.olt.d +; CHECK-MIPS1: bc1f + %tmp = load double* @d2, align 8, !tbaa !0 + %tmp1 = load double* @d3, align 8, !tbaa !0 + %cmp = fcmp olt double %tmp, %tmp1 + %cond = select i1 %cmp, i32 %f0, i32 %f1 + ret i32 %cond +} + +define i32 @sel14(i32 %f0, i32 %f1) nounwind readonly { +entry: +; CHECK-MIPS32R2: c.ule.d +; CHECK-MIPS32R2: movf +; CHECK-MIPS1: c.ule.d +; CHECK-MIPS1: bc1t + %tmp = load double* @d2, align 8, !tbaa !0 + %tmp1 = load double* @d3, align 8, !tbaa !0 + %cmp = fcmp ogt double %tmp, %tmp1 + %cond = select i1 %cmp, i32 %f0, i32 %f1 + ret i32 %cond +} + +!0 = metadata !{metadata !"double", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA", null} -- 2.34.1