From 07cec75913b74d04df40ff7fecf51f87175076c1 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Fri, 6 Jun 2008 00:58:26 +0000 Subject: [PATCH] Added custom SELECT_CC lowering Added special isel for ADDE,SUBE and new patterns to match SUBC,ADDC git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52031 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsISelDAGToDAG.cpp | 46 ++++++++++++++ lib/Target/Mips/MipsISelLowering.cpp | 95 ++++++++++++++++++++++++++-- lib/Target/Mips/MipsISelLowering.h | 7 ++ lib/Target/Mips/MipsInstrFormats.td | 2 +- lib/Target/Mips/MipsInstrInfo.td | 39 ++++++++++-- 5 files changed, 175 insertions(+), 14 deletions(-) diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index b2ad66670bb..8043f7b173b 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -226,6 +226,52 @@ Select(SDOperand N) default: break; + case ISD::ADDE: { + // ADDE is usally attached with a ADDC instruction, we must + // compare ADDC operands and set a register if we have a carry. + SDOperand InFlag = Node->getOperand(2); + unsigned Opc = InFlag.getOpcode(); + assert((Opc == ISD::ADDC || Opc == ISD::ADDE) && + "ADDE flag operand must come from a ADDC or ADDE"); + SDOperand Ops[] = { InFlag.getValue(0), InFlag.getOperand(1) }; + + SDOperand LHS = Node->getOperand(0); + SDOperand RHS = Node->getOperand(1); + AddToISelQueue(LHS); + AddToISelQueue(RHS); + + MVT::ValueType VT = LHS.getValueType(); + SDNode *Carry = CurDAG->getTargetNode(Mips::SLTu, VT, Ops, 2); + SDNode *AddCarry = CurDAG->getTargetNode(Mips::ADDu, VT, + SDOperand(Carry,0), RHS); + + return CurDAG->SelectNodeTo(N.Val, Mips::ADDu, VT, MVT::Flag, + LHS, SDOperand(AddCarry,0)); + } + + case ISD::SUBE: { + // SUBE is usally attached with a SUBC instruction, we must + // compare SUBC operands and set a register if we have a carry. + SDOperand InFlag = Node->getOperand(2); + unsigned Opc = InFlag.getOpcode(); + assert((Opc == ISD::SUBC || Opc == ISD::SUBE) && + "SUBE flag operand must come from a SUBC or SUBE"); + SDOperand Ops[] = { InFlag.getOperand(0), InFlag.getOperand(1) }; + + SDOperand LHS = Node->getOperand(0); + SDOperand RHS = Node->getOperand(1); + AddToISelQueue(LHS); + AddToISelQueue(RHS); + + MVT::ValueType VT = LHS.getValueType(); + SDNode *Carry = CurDAG->getTargetNode(Mips::SLTu, VT, Ops, 2); + SDNode *AddCarry = CurDAG->getTargetNode(Mips::ADDu, VT, + SDOperand(Carry,0), RHS); + + return CurDAG->SelectNodeTo(N.Val, Mips::SUBu, VT, MVT::Flag, + LHS, SDOperand(AddCarry,0)); + } + /// Special Mul operations case ISD::MULHS: case ISD::MULHU: { diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 441f2126d0c..0e233c71f07 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -39,11 +39,12 @@ getTargetNodeName(unsigned Opcode) const { switch (Opcode) { - case MipsISD::JmpLink : return "MipsISD::JmpLink"; - case MipsISD::Hi : return "MipsISD::Hi"; - case MipsISD::Lo : return "MipsISD::Lo"; - case MipsISD::Ret : return "MipsISD::Ret"; - default : return NULL; + case MipsISD::JmpLink : return "MipsISD::JmpLink"; + case MipsISD::Hi : return "MipsISD::Hi"; + case MipsISD::Lo : return "MipsISD::Lo"; + case MipsISD::Ret : return "MipsISD::Ret"; + case MipsISD::SelectCC : return "MipsISD::SelectCC"; + default : return NULL; } } @@ -65,6 +66,7 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM) setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); setOperationAction(ISD::RET, MVT::Other, Custom); setOperationAction(ISD::JumpTable, MVT::i32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); // Load extented operations for i1 types must be promoted setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote); @@ -75,7 +77,6 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM) setOperationAction(ISD::BR_JT, MVT::Other, Expand); setOperationAction(ISD::BR_CC, MVT::Other, Expand); setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); - setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); setOperationAction(ISD::SELECT, MVT::i32, Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); @@ -124,10 +125,75 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); + case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); } return SDOperand(); } +MachineBasicBlock * +MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) +{ + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + switch (MI->getOpcode()) { + default: assert(false && "Unexpected instr type to insert"); + case Mips::Select_CC: { + // 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(); + ilist::iterator It = BB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // setcc r1, r2, r3 + // bNE r1, r0, copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); + BuildMI(BB, TII->get(Mips::BNE)).addReg(MI->getOperand(1).getReg()) + .addReg(Mips::ZERO).addMBB(sinkMBB); + MachineFunction *F = BB->getParent(); + F->getBasicBlockList().insert(It, copy0MBB); + F->getBasicBlockList().insert(It, sinkMBB); + // Update machine-CFG edges by first adding all successors of the current + // block to the new block which will contain the Phi node for the select. + for(MachineBasicBlock::succ_iterator i = BB->succ_begin(), + e = BB->succ_end(); i != e; ++i) + sinkMBB->addSuccessor(*i); + // Next, remove all successors of the current block, and add the true + // and fallthrough blocks as its successors. + while(!BB->succ_empty()) + BB->removeSuccessor(BB->succ_begin()); + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + BB = sinkMBB; + BuildMI(BB, TII->get(Mips::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) + .addReg(MI->getOperand(3).getReg()).addMBB(thisMBB); + + delete MI; // The pseudo instruction is gone now. + return BB; + } + } +} + //===----------------------------------------------------------------------===// // Lower helper functions //===----------------------------------------------------------------------===// @@ -181,6 +247,23 @@ LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG) return SDOperand(); // Not reached } +SDOperand MipsTargetLowering:: +LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) +{ + SDOperand LHS = Op.getOperand(0); + SDOperand RHS = Op.getOperand(1); + SDOperand True = Op.getOperand(2); + SDOperand False = Op.getOperand(3); + SDOperand CC = Op.getOperand(4); + + const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32); + SDOperand Ops[] = { LHS, RHS, CC }; + SDOperand SetCCRes = DAG.getNode(ISD::SETCC, VTs, 1, Ops, 3); + + return DAG.getNode(MipsISD::SelectCC, True.getValueType(), + SetCCRes, True, False); +} + SDOperand MipsTargetLowering:: LowerJumpTable(SDOperand Op, SelectionDAG &DAG) { diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index e2b4b3f4a89..cda36acb372 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -37,6 +37,9 @@ namespace llvm { // No relation with Mips Lo register Lo, + // Select CC Pseudo Instruction + SelectCC, + // Return Ret }; @@ -80,6 +83,10 @@ namespace llvm { SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG); SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG); SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG); + + virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB); // Inline asm support ConstraintType getConstraintType(const std::string &Constraint) const; diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index caeabd5b5e7..e84dd268561 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -43,7 +43,7 @@ class MipsInst pattern, } // Mips Pseudo Instructions Format -class PseudoInstMips pattern>: +class MipsPseudo pattern>: MipsInst; //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 23954230998..b469167824c 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -43,6 +43,11 @@ def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart, def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd, [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; +// Select CC +def SDT_MipsSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, + SDTCisSameAs<1, 2>, SDTCisInt<3>]>; +def MipsSelectCC : SDNode<"MipsISD::SelectCC", SDT_MipsSelectCC>; + //===----------------------------------------------------------------------===// // Mips Instruction Predicate Definitions. //===----------------------------------------------------------------------===// @@ -346,10 +351,10 @@ class EffectiveAddress : // As stack alignment is always done with addiu, we need a 16-bit immediate let Defs = [SP], Uses = [SP] in { -def ADJCALLSTACKDOWN : PseudoInstMips<(outs), (ins uimm16:$amt), +def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins uimm16:$amt), "!ADJCALLSTACKDOWN $amt", [(callseq_start imm:$amt)]>; -def ADJCALLSTACKUP : PseudoInstMips<(outs), (ins uimm16:$amt1, uimm16:$amt2), +def ADJCALLSTACKUP : MipsPseudo<(outs), (ins uimm16:$amt1, uimm16:$amt2), "!ADJCALLSTACKUP $amt1", [(callseq_end imm:$amt1, imm:$amt2)]>; } @@ -358,10 +363,22 @@ def ADJCALLSTACKUP : PseudoInstMips<(outs), (ins uimm16:$amt1, uimm16:$amt2), // directives. If the real instructions corresponding these directives // are used, we have the same behavior, but get also a bunch of warnings // from the assembler. -def CPLOAD: PseudoInstMips<(outs), (ins CPURegs:$reg), - ".set noreorder\n\t.cpload $reg\n\t.set reorder\n", []>; -def CPRESTORE: PseudoInstMips<(outs), (ins uimm16:$loc), - ".cprestore $loc\n", []>; +def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$reg), + ".set noreorder\n\t.cpload $reg\n\t.set reorder\n", + []>; +def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), + ".cprestore $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 usesCustomDAGSchedInserter = 1 in { + def Select_CC : MipsPseudo<(outs CPURegs:$dst), + (ins CPURegs:$CmpRes, CPURegs:$T, CPURegs:$F), "# MipsSelect_CC", + [(set CPURegs:$dst, (MipsSelectCC CPURegs:$CmpRes, + CPURegs:$T, CPURegs:$F))]>; +} //===----------------------------------------------------------------------===// // Instruction definition @@ -502,6 +519,14 @@ def : Pat<(i32 immZExt16:$in), def : Pat<(i32 imm:$imm), (ORi (LUi (HI16 imm:$imm)), (LO16 imm:$imm))>; +// Carry patterns +def : Pat<(subc CPURegs:$lhs, CPURegs:$rhs), + (SUBu CPURegs:$lhs, CPURegs:$rhs)>; +def : Pat<(addc CPURegs:$lhs, CPURegs:$rhs), + (ADDu CPURegs:$lhs, CPURegs:$rhs)>; +def : Pat<(addc CPURegs:$src, imm:$imm), + (ADDiu CPURegs:$src, imm:$imm)>; + // Call def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)), (JAL tglobaladdr:$dst)>; @@ -529,7 +554,7 @@ def : Pat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>; def : Pat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>; def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>; -// some peepholes +// peepholes def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; /// -- 2.34.1