forked from OSchip/llvm-project
Added custom SELECT_CC lowering
Added special isel for ADDE,SUBE and new patterns to match SUBC,ADDC llvm-svn: 52031
This commit is contained in:
parent
1d304a99d7
commit
4eed3afda0
|
@ -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: {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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)>;
|
||||
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue