Lower select with custom inserted and make condjumps generic

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@70744 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anton Korobeynikov 2009-05-03 13:12:23 +00:00
parent ed1a51af37
commit 8b528e52ee
5 changed files with 168 additions and 36 deletions

View File

@ -51,6 +51,7 @@ namespace {
const char* Modifier = 0);
void printSrcMemOperand(const MachineInstr *MI, int OpNum,
const char* Modifier = 0);
void printCCOperand(const MachineInstr *MI, int OpNum);
bool printInstruction(const MachineInstr *MI); // autogenerated.
void printMachineInstruction(const MachineInstr * MI);
bool runOnMachineFunction(MachineFunction &F);
@ -182,3 +183,30 @@ void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
assert(0 && "Unsupported memory operand");
}
void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
unsigned CC = MI->getOperand(OpNum).getImm();
switch (CC) {
default:
assert(0 && "Unsupported CC code");
break;
case MSP430::COND_E:
O << 'e';
break;
case MSP430::COND_NE:
O << "ne";
break;
case MSP430::COND_HS:
O << "hs";
break;
case MSP430::COND_LO:
O << "lo";
break;
case MSP430::COND_GE:
O << "ge";
break;
case MSP430::COND_L:
O << 'l';
break;
}
}

View File

@ -72,8 +72,11 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
setOperationAction(ISD::BRCOND, MVT::Other, Custom);
setOperationAction(ISD::SETCC, MVT::i8 , Custom);
setOperationAction(ISD::SETCC, MVT::i16 , Custom);
setOperationAction(ISD::SETCC, MVT::i8, Custom);
setOperationAction(ISD::SETCC, MVT::i16, Custom);
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
setOperationAction(ISD::SELECT, MVT::i8, Custom);
setOperationAction(ISD::SELECT, MVT::i16, Custom);
}
SDValue MSP430TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
@ -85,6 +88,7 @@ SDValue MSP430TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
case ISD::SETCC: return LowerSETCC(Op, DAG);
case ISD::BRCOND: return LowerBRCOND(Op, DAG);
case ISD::SELECT: return LowerSELECT(Op, DAG);
default:
assert(0 && "unimplemented operand");
return SDValue();
@ -517,6 +521,40 @@ SDValue MSP430TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) {
Chain, Dest, CC, Cond);
}
SDValue MSP430TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) {
SDValue Cond = Op.getOperand(0);
SDValue TrueV = Op.getOperand(1);
SDValue FalseV = Op.getOperand(2);
DebugLoc dl = Op.getDebugLoc();
SDValue CC;
// Lower condition if not lowered yet
if (Cond.getOpcode() == ISD::SETCC)
Cond = LowerSETCC(Cond, DAG);
// If condition flag is set by a MSP430ISD::CMP, then use it as the condition
// setting operand in place of the MSP430ISD::SETCC.
if (Cond.getOpcode() == MSP430ISD::SETCC) {
CC = Cond.getOperand(0);
Cond = Cond.getOperand(1);
TrueV = Cond.getOperand(0);
FalseV = Cond.getOperand(1);
} else {
CC = DAG.getConstant(MSP430::COND_NE, MVT::i16);
Cond = DAG.getNode(MSP430ISD::CMP, dl, MVT::i16,
Cond, DAG.getConstant(0, MVT::i16));
}
SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
SmallVector<SDValue, 4> Ops;
Ops.push_back(TrueV);
Ops.push_back(FalseV);
Ops.push_back(CC);
Ops.push_back(Cond);
return DAG.getNode(MSP430ISD::SELECT, dl, VTs, &Ops[0], Ops.size());
}
const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
default: return NULL;
@ -527,5 +565,69 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
case MSP430ISD::BRCOND: return "MSP430ISD::BRCOND";
case MSP430ISD::CMP: return "MSP430ISD::CMP";
case MSP430ISD::SETCC: return "MSP430ISD::SETCC";
case MSP430ISD::SELECT: return "MSP430ISD::SELECT";
}
}
//===----------------------------------------------------------------------===//
// Other Lowering Code
//===----------------------------------------------------------------------===//
MachineBasicBlock*
MSP430TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const {
const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
DebugLoc dl = MI->getDebugLoc();
assert((MI->getOpcode() == MSP430::Select16) &&
"Unexpected instr type to insert");
// To "insert" a SELECT 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();
MachineFunction::iterator I = BB;
++I;
// thisMBB:
// ...
// TrueVal = ...
// cmpTY ccX, r1, r2
// jCC copy1MBB
// fallthrough --> copy0MBB
MachineBasicBlock *thisMBB = BB;
MachineFunction *F = BB->getParent();
MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *copy1MBB = F->CreateMachineBasicBlock(LLVM_BB);
BuildMI(BB, dl, TII.get(MSP430::JCC))
.addMBB(copy1MBB)
.addImm(MI->getOperand(3).getImm());
F->insert(I, copy0MBB);
F->insert(I, copy1MBB);
// Update machine-CFG edges by transferring all successors of the current
// block to the new block which will contain the Phi node for the select.
copy1MBB->transferSuccessors(BB);
// Next, add the true and fallthrough blocks as its successors.
BB->addSuccessor(copy0MBB);
BB->addSuccessor(copy1MBB);
// copy0MBB:
// %FalseValue = ...
// # fallthrough to copy1MBB
BB = copy0MBB;
// Update machine-CFG edges
BB->addSuccessor(copy1MBB);
// copy1MBB:
// %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
// ...
BB = copy1MBB;
BuildMI(BB, dl, TII.get(MSP430::PHI),
MI->getOperand(0).getReg())
.addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB)
.addReg(MI->getOperand(1).getReg()).addMBB(thisMBB);
F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
return BB;
}

View File

@ -49,7 +49,11 @@ namespace llvm {
/// is the block to branch if condition is true, operand 2 is the
/// condition code, and operand 3 is the flag operand produced by a CMP
/// instruction.
BRCOND
BRCOND,
/// SELECT. Operand 0 and operand 1 are selection variable, operand 3 is
/// condition code and operand 4 is flag operand.
SELECT
};
}
@ -77,6 +81,7 @@ namespace llvm {
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG);
SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG);
SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG);
SDValue LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
unsigned CC);
@ -84,6 +89,8 @@ namespace llvm {
CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG);
MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const;
private:
const MSP430Subtarget &Subtarget;

View File

@ -22,8 +22,7 @@ namespace llvm {
class MSP430TargetMachine;
namespace MSP430 {
// MSP430 specific condition code. These correspond to MSP430_*_COND in
// MSP430InstrInfo.td. They must be kept in synch.
// MSP430 specific condition code.
enum CondCode {
COND_E = 0, // aka COND_Z
COND_NE = 1, // aka COND_NZ

View File

@ -31,6 +31,8 @@ def SDT_MSP430SetCC : SDTypeProfile<1, 2, [SDTCisVT<0, i8>,
def SDT_MSP430Cmp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
def SDT_MSP430BrCond : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>,
SDTCisVT<1, i8>, SDTCisVT<2, i16>]>;
def SDT_MSP430Select : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
SDTCisVT<3, i8>, SDTCisVT<4, i16>]>;
//===----------------------------------------------------------------------===//
// MSP430 Specific Node Definitions.
@ -52,6 +54,7 @@ def MSP430Wrapper : SDNode<"MSP430ISD::Wrapper", SDT_MSP430Wrapper>;
def MSP430setcc : SDNode<"MSP430ISD::SETCC", SDT_MSP430SetCC>;
def MSP430cmp : SDNode<"MSP430ISD::CMP", SDT_MSP430Cmp>;
def MSP430brcond : SDNode<"MSP430ISD::BRCOND", SDT_MSP430BrCond, [SDNPHasChain]>;
def MSP430select : SDNode<"MSP430ISD::SELECT", SDT_MSP430Select>;
//===----------------------------------------------------------------------===//
// MSP430 Operand Definitions.
@ -71,6 +74,11 @@ def memdst : Operand<i16> {
// Branch targets have OtherVT type.
def brtarget : Operand<OtherVT>;
// Operand for printing out a condition code.
def cc : Operand<i8> {
let PrintMethod = "printCCOperand";
}
//===----------------------------------------------------------------------===//
// MSP430 Complex Pattern Definitions.
//===----------------------------------------------------------------------===//
@ -82,15 +90,6 @@ def addr : ComplexPattern<iPTR, 2, "SelectAddr", [], []>;
def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>;
def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 ( extloadi8 node:$ptr))>;
// MSP430 specific condition code. These correspond to CondCode in
// MSP430InstrInfo.h. They must be kept in synch.
def MSP430_COND_E : PatLeaf<(i8 0)>; // aka COND_Z
def MSP430_COND_NE : PatLeaf<(i8 1)>; // aka COND_NZ
def MSP430_COND_HS : PatLeaf<(i8 2)>; // aka COND_C
def MSP430_COND_LO : PatLeaf<(i8 3)>; // aka COND_NC
def MSP430_COND_GE : PatLeaf<(i8 4)>;
def MSP430_COND_L : PatLeaf<(i8 5)>;
//===----------------------------------------------------------------------===//
// Instruction list..
@ -108,6 +107,12 @@ def ADJCALLSTACKUP : Pseudo<(outs), (ins i16imm:$amt1, i16imm:$amt2),
[(MSP430callseq_end timm:$amt1, timm:$amt2)]>;
}
let usesCustomDAGSchedInserter = 1 in {
def Select16 : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2, i8imm:$cc),
"# Select16 PSEUDO",
[(set GR16:$dst,
(MSP430select GR16:$src1, GR16:$src2, imm:$cc, SRW))]>;
}
let neverHasSideEffects = 1 in
def NOP : Pseudo<(outs), (ins), "nop", []>;
@ -123,18 +128,9 @@ let isReturn = 1, isTerminator = 1 in {
// Conditional branches
let isBranch = 1, isTerminator = 1, Uses = [SRW] in {
def JE : Pseudo<(outs), (ins brtarget:$dst), "je\t$dst",
[(MSP430brcond bb:$dst, MSP430_COND_E, SRW)]>;
def JNE : Pseudo<(outs), (ins brtarget:$dst), "jne\t$dst",
[(MSP430brcond bb:$dst, MSP430_COND_NE, SRW)]>;
def JHS : Pseudo<(outs), (ins brtarget:$dst), "jhs\t$dst",
[(MSP430brcond bb:$dst, MSP430_COND_HS, SRW)]>;
def JLO : Pseudo<(outs), (ins brtarget:$dst), "jlo\t$dst",
[(MSP430brcond bb:$dst, MSP430_COND_LO, SRW)]>;
def JGE : Pseudo<(outs), (ins brtarget:$dst), "jge\t$dst",
[(MSP430brcond bb:$dst, MSP430_COND_GE, SRW)]>;
def JL : Pseudo<(outs), (ins brtarget:$dst), "jl\t$dst",
[(MSP430brcond bb:$dst, MSP430_COND_L, SRW)]>;
def JCC : Pseudo<(outs), (ins brtarget:$dst, cc:$cc),
"j$cc $dst",
[(MSP430brcond bb:$dst, imm:$cc, SRW)]>;
} // Uses = [SRW]
//===----------------------------------------------------------------------===//
@ -656,17 +652,17 @@ def OR16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
// Integer comparisons
let Defs = [SRW] in {
def CMP8rr : Pseudo<(outs), (ins GR8:$src1, GR8:$src2),
"cmp.b\t{$src2, $src1|$src1, $src2}",
"cmp.b\t{$src1, $src2}",
[(MSP430cmp GR8:$src1, GR8:$src2), (implicit SRW)]>;
def CMP16rr : Pseudo<(outs), (ins GR16:$src1, GR16:$src2),
"cmp.w\t{$src2, $src1|$src1, $src2}",
"cmp.w\t{$src1, $src2}",
[(MSP430cmp GR16:$src1, GR16:$src2), (implicit SRW)]>;
def CMP8ri : Pseudo<(outs), (ins GR8:$src1, i8imm:$src2),
"cmp.b\t{$src2, $src1|$src1, $src2}",
"cmp.b\t{$src1, $src2}",
[(MSP430cmp GR8:$src1, imm:$src2), (implicit SRW)]>;
def CMP16ri : Pseudo<(outs), (ins GR16:$src1, i16imm:$src2),
"cmp.w\t{$src2, $src1|$src1, $src2}",
"cmp.w\t{$src1, $src2}",
[(MSP430cmp GR16:$src1, imm:$src2), (implicit SRW)]>;
def CMP8rm : Pseudo<(outs), (ins GR8:$src1, memsrc:$src2),