mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
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:
parent
ed1a51af37
commit
8b528e52ee
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user