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
This commit is contained in:
Bruno Cardoso Lopes 2008-06-06 00:58:26 +00:00
parent 836bfcd689
commit 07cec75913
5 changed files with 175 additions and 14 deletions

View File

@ -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: {

View File

@ -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<MachineBasicBlock>::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)
{

View File

@ -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;

View File

@ -43,7 +43,7 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern,
}
// Mips Pseudo Instructions Format
class PseudoInstMips<dag outs, dag ins, string asmstr, list<dag> pattern>:
class MipsPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>:
MipsInst<outs, ins, asmstr, pattern, IIPseudo>;
//===----------------------------------------------------------------------===//

View File

@ -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<string instr_asm> :
// 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)>;
///