From 2625de35eda2aec28bdec3370a81f533f9721736 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Sat, 12 Dec 2009 18:55:37 +0000 Subject: [PATCH] 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 --- lib/Target/MSP430/MSP430ISelLowering.cpp | 140 ++++++++++++++++++++++- lib/Target/MSP430/MSP430ISelLowering.h | 12 +- lib/Target/MSP430/MSP430InstrInfo.td | 25 ++++ 3 files changed, 170 insertions(+), 7 deletions(-) diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index 4bd6006964f..5fe9b20bd36 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -592,9 +592,21 @@ SDValue MSP430TargetLowering::LowerShifts(SDValue Op, EVT VT = Op.getValueType(); DebugLoc dl = N->getDebugLoc(); - // We currently only lower shifts of constant argument. + // Expand non-constant shifts to loops: if (!isa(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(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::CMP: return "MSP430ISD::CMP"; 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 //===----------------------------------------------------------------------===// +MachineBasicBlock* +MSP430TargetLowering::EmitShiftInstr(MachineInstr *MI, + MachineBasicBlock *BB, + DenseMap *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* MSP430TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *BB, DenseMap *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(); 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"); // To "insert" a SELECT instruction, we actually have to insert the diamond diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h index b126d8e431f..4921500d392 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.h +++ b/lib/Target/MSP430/MSP430ISelLowering.h @@ -47,7 +47,7 @@ namespace llvm { /// CMP - Compare instruction. 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. SETCC, @@ -57,9 +57,12 @@ namespace llvm { /// instruction. 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. - SELECT_CC + SELECT_CC, + + /// SHL, SRA, SRL - Non-constant shifts. + SHL, SRA, SRL }; } @@ -99,6 +102,9 @@ namespace llvm { MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *BB, DenseMap *EM) const; + MachineBasicBlock* EmitShiftInstr(MachineInstr *MI, + MachineBasicBlock *BB, + DenseMap *EM) const; private: SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee, diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td index 321018e958b..d67ba90a4ca 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.td +++ b/lib/Target/MSP430/MSP430InstrInfo.td @@ -31,6 +31,7 @@ def SDT_MSP430BrCC : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i8>]>; def SDT_MSP430SelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>; +def SDT_MSP430Shift : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, SDTCisI8<2>]>; //===----------------------------------------------------------------------===// // MSP430 Specific Node Definitions. @@ -56,6 +57,9 @@ def MSP430Wrapper : SDNode<"MSP430ISD::Wrapper", SDT_MSP430Wrapper>; def MSP430cmp : SDNode<"MSP430ISD::CMP", SDT_MSP430Cmp, [SDNPOutFlag]>; def MSP430brcc : SDNode<"MSP430ISD::BR_CC", SDT_MSP430BrCC, [SDNPHasChain, 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. @@ -121,6 +125,27 @@ let usesCustomInserter = 1 in { "# Select16 PSEUDO", [(set GR16:$dst, (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