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;
|
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
|
/// Special Mul operations
|
||||||
case ISD::MULHS:
|
case ISD::MULHS:
|
||||||
case ISD::MULHU: {
|
case ISD::MULHU: {
|
||||||
|
|
|
@ -39,11 +39,12 @@ getTargetNodeName(unsigned Opcode) const
|
||||||
{
|
{
|
||||||
switch (Opcode)
|
switch (Opcode)
|
||||||
{
|
{
|
||||||
case MipsISD::JmpLink : return "MipsISD::JmpLink";
|
case MipsISD::JmpLink : return "MipsISD::JmpLink";
|
||||||
case MipsISD::Hi : return "MipsISD::Hi";
|
case MipsISD::Hi : return "MipsISD::Hi";
|
||||||
case MipsISD::Lo : return "MipsISD::Lo";
|
case MipsISD::Lo : return "MipsISD::Lo";
|
||||||
case MipsISD::Ret : return "MipsISD::Ret";
|
case MipsISD::Ret : return "MipsISD::Ret";
|
||||||
default : return NULL;
|
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::GlobalTLSAddress, MVT::i32, Custom);
|
||||||
setOperationAction(ISD::RET, MVT::Other, Custom);
|
setOperationAction(ISD::RET, MVT::Other, Custom);
|
||||||
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
|
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
|
||||||
|
setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
|
||||||
|
|
||||||
// Load extented operations for i1 types must be promoted
|
// Load extented operations for i1 types must be promoted
|
||||||
setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote);
|
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_JT, MVT::Other, Expand);
|
||||||
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
|
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
|
||||||
setOperationAction(ISD::SELECT_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::SELECT, MVT::i32, Expand);
|
||||||
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, 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::GlobalAddress: return LowerGlobalAddress(Op, DAG);
|
||||||
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
|
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
|
||||||
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
|
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
|
||||||
|
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
|
||||||
}
|
}
|
||||||
return SDOperand();
|
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
|
// Lower helper functions
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -181,6 +247,23 @@ LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG)
|
||||||
return SDOperand(); // Not reached
|
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::
|
SDOperand MipsTargetLowering::
|
||||||
LowerJumpTable(SDOperand Op, SelectionDAG &DAG)
|
LowerJumpTable(SDOperand Op, SelectionDAG &DAG)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,6 +37,9 @@ namespace llvm {
|
||||||
// No relation with Mips Lo register
|
// No relation with Mips Lo register
|
||||||
Lo,
|
Lo,
|
||||||
|
|
||||||
|
// Select CC Pseudo Instruction
|
||||||
|
SelectCC,
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
Ret
|
Ret
|
||||||
};
|
};
|
||||||
|
@ -80,6 +83,10 @@ namespace llvm {
|
||||||
SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG);
|
SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG);
|
||||||
SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG);
|
SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG);
|
||||||
SDOperand LowerJumpTable(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
|
// Inline asm support
|
||||||
ConstraintType getConstraintType(const std::string &Constraint) const;
|
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
|
// 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>;
|
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,
|
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd,
|
||||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
[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.
|
// 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
|
// As stack alignment is always done with addiu, we need a 16-bit immediate
|
||||||
let Defs = [SP], Uses = [SP] in {
|
let Defs = [SP], Uses = [SP] in {
|
||||||
def ADJCALLSTACKDOWN : PseudoInstMips<(outs), (ins uimm16:$amt),
|
def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins uimm16:$amt),
|
||||||
"!ADJCALLSTACKDOWN $amt",
|
"!ADJCALLSTACKDOWN $amt",
|
||||||
[(callseq_start imm:$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",
|
"!ADJCALLSTACKUP $amt1",
|
||||||
[(callseq_end imm:$amt1, imm:$amt2)]>;
|
[(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
|
// directives. If the real instructions corresponding these directives
|
||||||
// are used, we have the same behavior, but get also a bunch of warnings
|
// are used, we have the same behavior, but get also a bunch of warnings
|
||||||
// from the assembler.
|
// from the assembler.
|
||||||
def CPLOAD: PseudoInstMips<(outs), (ins CPURegs:$reg),
|
def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$reg),
|
||||||
".set noreorder\n\t.cpload $reg\n\t.set reorder\n", []>;
|
".set noreorder\n\t.cpload $reg\n\t.set reorder\n",
|
||||||
def CPRESTORE: PseudoInstMips<(outs), (ins uimm16:$loc),
|
[]>;
|
||||||
".cprestore $loc\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
|
// Instruction definition
|
||||||
|
@ -502,6 +519,14 @@ def : Pat<(i32 immZExt16:$in),
|
||||||
def : Pat<(i32 imm:$imm),
|
def : Pat<(i32 imm:$imm),
|
||||||
(ORi (LUi (HI16 imm:$imm)), (LO16 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
|
// Call
|
||||||
def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)),
|
def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)),
|
||||||
(JAL 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 (extloadi8 addr:$src)), (LBu addr:$src)>;
|
||||||
def : Pat<(i32 (extloadi16 addr:$src)), (LHu 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)>;
|
def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in New Issue