mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-19 04:32:19 +00:00
Implement variable-width shifts.
No testcase yet - it seems we're exposing generic codegen bugs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91221 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
04ab19cb14
commit
2625de35ed
@ -592,9 +592,21 @@ SDValue MSP430TargetLowering::LowerShifts(SDValue Op,
|
|||||||
EVT VT = Op.getValueType();
|
EVT VT = Op.getValueType();
|
||||||
DebugLoc dl = N->getDebugLoc();
|
DebugLoc dl = N->getDebugLoc();
|
||||||
|
|
||||||
// We currently only lower shifts of constant argument.
|
// Expand non-constant shifts to loops:
|
||||||
if (!isa<ConstantSDNode>(N->getOperand(1)))
|
if (!isa<ConstantSDNode>(N->getOperand(1)))
|
||||||
return SDValue();
|
switch (Opc) {
|
||||||
|
default:
|
||||||
|
assert(0 && "Invalid shift opcode!");
|
||||||
|
case ISD::SHL:
|
||||||
|
return DAG.getNode(MSP430ISD::SHL, dl,
|
||||||
|
VT, N->getOperand(0), N->getOperand(1));
|
||||||
|
case ISD::SRA:
|
||||||
|
return DAG.getNode(MSP430ISD::SRA, dl,
|
||||||
|
VT, N->getOperand(0), N->getOperand(1));
|
||||||
|
case ISD::SRL:
|
||||||
|
return DAG.getNode(MSP430ISD::SRL, dl,
|
||||||
|
VT, N->getOperand(0), N->getOperand(1));
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t ShiftAmount = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
|
uint64_t ShiftAmount = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
|
||||||
|
|
||||||
@ -916,6 +928,8 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||||||
case MSP430ISD::BR_CC: return "MSP430ISD::BR_CC";
|
case MSP430ISD::BR_CC: return "MSP430ISD::BR_CC";
|
||||||
case MSP430ISD::CMP: return "MSP430ISD::CMP";
|
case MSP430ISD::CMP: return "MSP430ISD::CMP";
|
||||||
case MSP430ISD::SELECT_CC: return "MSP430ISD::SELECT_CC";
|
case MSP430ISD::SELECT_CC: return "MSP430ISD::SELECT_CC";
|
||||||
|
case MSP430ISD::SHL: return "MSP430ISD::SHL";
|
||||||
|
case MSP430ISD::SRA: return "MSP430ISD::SRA";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -923,14 +937,132 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||||||
// Other Lowering Code
|
// Other Lowering Code
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
MachineBasicBlock*
|
||||||
|
MSP430TargetLowering::EmitShiftInstr(MachineInstr *MI,
|
||||||
|
MachineBasicBlock *BB,
|
||||||
|
DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const {
|
||||||
|
MachineFunction *F = BB->getParent();
|
||||||
|
MachineRegisterInfo &RI = F->getRegInfo();
|
||||||
|
DebugLoc dl = MI->getDebugLoc();
|
||||||
|
const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
|
||||||
|
|
||||||
|
unsigned Opc;
|
||||||
|
const TargetRegisterClass * RC;
|
||||||
|
switch (MI->getOpcode()) {
|
||||||
|
default:
|
||||||
|
assert(0 && "Invalid shift opcode!");
|
||||||
|
case MSP430::Shl8:
|
||||||
|
Opc = MSP430::SHL8r1;
|
||||||
|
RC = MSP430::GR8RegisterClass;
|
||||||
|
break;
|
||||||
|
case MSP430::Shl16:
|
||||||
|
Opc = MSP430::SHL16r1;
|
||||||
|
RC = MSP430::GR16RegisterClass;
|
||||||
|
break;
|
||||||
|
case MSP430::Sra8:
|
||||||
|
Opc = MSP430::SAR8r1;
|
||||||
|
RC = MSP430::GR8RegisterClass;
|
||||||
|
break;
|
||||||
|
case MSP430::Sra16:
|
||||||
|
Opc = MSP430::SAR16r1;
|
||||||
|
RC = MSP430::GR16RegisterClass;
|
||||||
|
break;
|
||||||
|
case MSP430::Srl8:
|
||||||
|
Opc = MSP430::SAR8r1c;
|
||||||
|
RC = MSP430::GR8RegisterClass;
|
||||||
|
break;
|
||||||
|
case MSP430::Srl16:
|
||||||
|
Opc = MSP430::SAR16r1c;
|
||||||
|
RC = MSP430::GR16RegisterClass;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BasicBlock *LLVM_BB = BB->getBasicBlock();
|
||||||
|
MachineFunction::iterator I = BB;
|
||||||
|
++I;
|
||||||
|
|
||||||
|
// Create loop block
|
||||||
|
MachineBasicBlock *LoopBB = F->CreateMachineBasicBlock(LLVM_BB);
|
||||||
|
MachineBasicBlock *RemBB = F->CreateMachineBasicBlock(LLVM_BB);
|
||||||
|
|
||||||
|
F->insert(I, LoopBB);
|
||||||
|
F->insert(I, RemBB);
|
||||||
|
|
||||||
|
// Update machine-CFG edges by transferring all successors of the current
|
||||||
|
// block to the block containing instructions after shift.
|
||||||
|
RemBB->transferSuccessors(BB);
|
||||||
|
|
||||||
|
// Inform sdisel of the edge changes.
|
||||||
|
for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(),
|
||||||
|
SE = BB->succ_end(); SI != SE; ++SI)
|
||||||
|
EM->insert(std::make_pair(*SI, RemBB));
|
||||||
|
|
||||||
|
// Add adges BB => LoopBB => RemBB, BB => RemBB, LoopBB => LoopBB
|
||||||
|
BB->addSuccessor(LoopBB);
|
||||||
|
BB->addSuccessor(RemBB);
|
||||||
|
LoopBB->addSuccessor(RemBB);
|
||||||
|
LoopBB->addSuccessor(LoopBB);
|
||||||
|
|
||||||
|
unsigned ShiftAmtReg = RI.createVirtualRegister(MSP430::GR8RegisterClass);
|
||||||
|
unsigned ShiftAmtReg2 = RI.createVirtualRegister(MSP430::GR8RegisterClass);
|
||||||
|
unsigned ShiftReg = RI.createVirtualRegister(RC);
|
||||||
|
unsigned ShiftReg2 = RI.createVirtualRegister(RC);
|
||||||
|
unsigned ShiftAmtSrcReg = MI->getOperand(2).getReg();
|
||||||
|
unsigned SrcReg = MI->getOperand(1).getReg();
|
||||||
|
unsigned DstReg = MI->getOperand(0).getReg();
|
||||||
|
|
||||||
|
// BB:
|
||||||
|
// cmp 0, N
|
||||||
|
// je RemBB
|
||||||
|
BuildMI(BB, dl, TII.get(MSP430::CMP8ir))
|
||||||
|
.addImm(0).addReg(ShiftAmtSrcReg);
|
||||||
|
BuildMI(BB, dl, TII.get(MSP430::JCC))
|
||||||
|
.addMBB(RemBB)
|
||||||
|
.addImm(MSP430CC::COND_E);
|
||||||
|
|
||||||
|
// LoopBB:
|
||||||
|
// ShiftReg = phi [%SrcReg, BB], [%ShiftReg2, LoopBB]
|
||||||
|
// ShiftAmt = phi [%N, BB], [%ShiftAmt2, LoopBB]
|
||||||
|
// ShiftReg2 = shift ShiftReg
|
||||||
|
// ShiftAmt2 = ShiftAmt - 1;
|
||||||
|
BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftReg)
|
||||||
|
.addReg(SrcReg).addMBB(BB)
|
||||||
|
.addReg(ShiftReg2).addMBB(LoopBB);
|
||||||
|
BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftAmtReg)
|
||||||
|
.addReg(ShiftAmtSrcReg).addMBB(BB)
|
||||||
|
.addReg(ShiftAmtReg2).addMBB(LoopBB);
|
||||||
|
BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2)
|
||||||
|
.addReg(ShiftReg);
|
||||||
|
BuildMI(LoopBB, dl, TII.get(MSP430::SUB8ri), ShiftAmtReg2)
|
||||||
|
.addReg(ShiftAmtReg).addImm(1);
|
||||||
|
BuildMI(LoopBB, dl, TII.get(MSP430::JCC))
|
||||||
|
.addMBB(LoopBB)
|
||||||
|
.addImm(MSP430CC::COND_NE);
|
||||||
|
|
||||||
|
// RemBB:
|
||||||
|
// DestReg = phi [%SrcReg, BB], [%ShiftReg, LoopBB]
|
||||||
|
BuildMI(RemBB, dl, TII.get(MSP430::PHI), DstReg)
|
||||||
|
.addReg(SrcReg).addMBB(BB)
|
||||||
|
.addReg(ShiftReg2).addMBB(LoopBB);
|
||||||
|
|
||||||
|
return RemBB;
|
||||||
|
}
|
||||||
|
|
||||||
MachineBasicBlock*
|
MachineBasicBlock*
|
||||||
MSP430TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
MSP430TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||||
MachineBasicBlock *BB,
|
MachineBasicBlock *BB,
|
||||||
DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const {
|
DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const {
|
||||||
|
unsigned Opc = MI->getOpcode();
|
||||||
|
|
||||||
|
if (Opc == MSP430::Shl8 || Opc == MSP430::Shl16 ||
|
||||||
|
Opc == MSP430::Sra8 || Opc == MSP430::Sra16 ||
|
||||||
|
Opc == MSP430::Srl8 || Opc == MSP430::Srl16)
|
||||||
|
return EmitShiftInstr(MI, BB, EM);
|
||||||
|
|
||||||
const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
|
const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
|
||||||
DebugLoc dl = MI->getDebugLoc();
|
DebugLoc dl = MI->getDebugLoc();
|
||||||
assert((MI->getOpcode() == MSP430::Select16 ||
|
|
||||||
MI->getOpcode() == MSP430::Select8) &&
|
assert((Opc == MSP430::Select16 || Opc == MSP430::Select8) &&
|
||||||
"Unexpected instr type to insert");
|
"Unexpected instr type to insert");
|
||||||
|
|
||||||
// To "insert" a SELECT instruction, we actually have to insert the diamond
|
// To "insert" a SELECT instruction, we actually have to insert the diamond
|
||||||
|
@ -47,7 +47,7 @@ namespace llvm {
|
|||||||
/// CMP - Compare instruction.
|
/// CMP - Compare instruction.
|
||||||
CMP,
|
CMP,
|
||||||
|
|
||||||
/// SetCC. Operand 0 is condition code, and operand 1 is the flag
|
/// SetCC - Operand 0 is condition code, and operand 1 is the flag
|
||||||
/// operand produced by a CMP instruction.
|
/// operand produced by a CMP instruction.
|
||||||
SETCC,
|
SETCC,
|
||||||
|
|
||||||
@ -57,9 +57,12 @@ namespace llvm {
|
|||||||
/// instruction.
|
/// instruction.
|
||||||
BR_CC,
|
BR_CC,
|
||||||
|
|
||||||
/// SELECT_CC. Operand 0 and operand 1 are selection variable, operand 3
|
/// SELECT_CC - Operand 0 and operand 1 are selection variable, operand 3
|
||||||
/// is condition code and operand 4 is flag operand.
|
/// is condition code and operand 4 is flag operand.
|
||||||
SELECT_CC
|
SELECT_CC,
|
||||||
|
|
||||||
|
/// SHL, SRA, SRL - Non-constant shifts.
|
||||||
|
SHL, SRA, SRL
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +102,9 @@ namespace llvm {
|
|||||||
MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI,
|
MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||||
MachineBasicBlock *BB,
|
MachineBasicBlock *BB,
|
||||||
DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const;
|
DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const;
|
||||||
|
MachineBasicBlock* EmitShiftInstr(MachineInstr *MI,
|
||||||
|
MachineBasicBlock *BB,
|
||||||
|
DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee,
|
SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee,
|
||||||
|
@ -31,6 +31,7 @@ def SDT_MSP430BrCC : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>,
|
|||||||
SDTCisVT<1, i8>]>;
|
SDTCisVT<1, i8>]>;
|
||||||
def SDT_MSP430SelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
|
def SDT_MSP430SelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
|
||||||
SDTCisVT<3, i8>]>;
|
SDTCisVT<3, i8>]>;
|
||||||
|
def SDT_MSP430Shift : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, SDTCisI8<2>]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// MSP430 Specific Node Definitions.
|
// MSP430 Specific Node Definitions.
|
||||||
@ -56,6 +57,9 @@ def MSP430Wrapper : SDNode<"MSP430ISD::Wrapper", SDT_MSP430Wrapper>;
|
|||||||
def MSP430cmp : SDNode<"MSP430ISD::CMP", SDT_MSP430Cmp, [SDNPOutFlag]>;
|
def MSP430cmp : SDNode<"MSP430ISD::CMP", SDT_MSP430Cmp, [SDNPOutFlag]>;
|
||||||
def MSP430brcc : SDNode<"MSP430ISD::BR_CC", SDT_MSP430BrCC, [SDNPHasChain, SDNPInFlag]>;
|
def MSP430brcc : SDNode<"MSP430ISD::BR_CC", SDT_MSP430BrCC, [SDNPHasChain, SDNPInFlag]>;
|
||||||
def MSP430selectcc: SDNode<"MSP430ISD::SELECT_CC", SDT_MSP430SelectCC, [SDNPInFlag]>;
|
def MSP430selectcc: SDNode<"MSP430ISD::SELECT_CC", SDT_MSP430SelectCC, [SDNPInFlag]>;
|
||||||
|
def MSP430shl : SDNode<"MSP430ISD::SHL", SDT_MSP430Shift, []>;
|
||||||
|
def MSP430sra : SDNode<"MSP430ISD::SRA", SDT_MSP430Shift, []>;
|
||||||
|
def MSP430srl : SDNode<"MSP430ISD::SRL", SDT_MSP430Shift, []>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// MSP430 Operand Definitions.
|
// MSP430 Operand Definitions.
|
||||||
@ -121,6 +125,27 @@ let usesCustomInserter = 1 in {
|
|||||||
"# Select16 PSEUDO",
|
"# Select16 PSEUDO",
|
||||||
[(set GR16:$dst,
|
[(set GR16:$dst,
|
||||||
(MSP430selectcc GR16:$src1, GR16:$src2, imm:$cc))]>;
|
(MSP430selectcc GR16:$src1, GR16:$src2, imm:$cc))]>;
|
||||||
|
let Defs = [SRW] in {
|
||||||
|
def Shl8 : Pseudo<(outs GR8:$dst), (ins GR8:$src, GR8:$cnt),
|
||||||
|
"# Shl8 PSEUDO",
|
||||||
|
[(set GR8:$dst, (MSP430shl GR8:$src, GR8:$cnt))]>;
|
||||||
|
def Shl16 : Pseudo<(outs GR16:$dst), (ins GR16:$src, GR8:$cnt),
|
||||||
|
"# Shl16 PSEUDO",
|
||||||
|
[(set GR16:$dst, (MSP430shl GR16:$src, GR8:$cnt))]>;
|
||||||
|
def Sra8 : Pseudo<(outs GR8:$dst), (ins GR8:$src, GR8:$cnt),
|
||||||
|
"# Sra8 PSEUDO",
|
||||||
|
[(set GR8:$dst, (MSP430sra GR8:$src, GR8:$cnt))]>;
|
||||||
|
def Sra16 : Pseudo<(outs GR16:$dst), (ins GR16:$src, GR8:$cnt),
|
||||||
|
"# Sra16 PSEUDO",
|
||||||
|
[(set GR16:$dst, (MSP430sra GR16:$src, GR8:$cnt))]>;
|
||||||
|
def Srl8 : Pseudo<(outs GR8:$dst), (ins GR8:$src, GR8:$cnt),
|
||||||
|
"# Srl8 PSEUDO",
|
||||||
|
[(set GR8:$dst, (MSP430srl GR8:$src, GR8:$cnt))]>;
|
||||||
|
def Srl16 : Pseudo<(outs GR16:$dst), (ins GR16:$src, GR8:$cnt),
|
||||||
|
"# Srl16 PSEUDO",
|
||||||
|
[(set GR16:$dst, (MSP430srl GR16:$src, GR8:$cnt))]>;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let neverHasSideEffects = 1 in
|
let neverHasSideEffects = 1 in
|
||||||
|
Loading…
x
Reference in New Issue
Block a user