aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2008-06-06 00:58:26 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2008-06-06 00:58:26 +0000
commited7723d74eaf4701b47a6a8b206844ae7b97c002 (patch)
tree54235299d2c7d3f61f573bbcff9378f3d0bdc4f6 /lib
parent5bd39169641c448a43c191fd55245deeb911cfc3 (diff)
downloadexternal_llvm-ed7723d74eaf4701b47a6a8b206844ae7b97c002.zip
external_llvm-ed7723d74eaf4701b47a6a8b206844ae7b97c002.tar.gz
external_llvm-ed7723d74eaf4701b47a6a8b206844ae7b97c002.tar.bz2
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
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp46
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp95
-rw-r--r--lib/Target/Mips/MipsISelLowering.h7
-rw-r--r--lib/Target/Mips/MipsInstrFormats.td2
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td39
5 files changed, 175 insertions, 14 deletions
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index b2ad666..8043f7b 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 441f212..0e233c7 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<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
//===----------------------------------------------------------------------===//
@@ -182,6 +248,23 @@ LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG)
}
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)
{
SDOperand ResNode;
diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h
index e2b4b3f..cda36ac 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 caeabd5..e84dd26 100644
--- a/lib/Target/Mips/MipsInstrFormats.td
+++ b/lib/Target/Mips/MipsInstrFormats.td
@@ -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>;
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index 2395423..b469167 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<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)>;
///