mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +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:
		| @@ -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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user