mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	Completely rewrite how getelementptr instructions are expanded. This has two
(minor) benefits right now: 1. An extra dummy MOVrr32 is gone. This move would often be coallesced by both allocators anyway. 2. The code now uses the gep_type_iterator to walk the gep, which should future proof it a bit. It still assumes that array indexes are Longs though. These don't really justify rewriting the code. The big benefit will come later though. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11710 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		| @@ -27,6 +27,7 @@ | |||||||
| #include "llvm/CodeGen/SSARegMap.h" | #include "llvm/CodeGen/SSARegMap.h" | ||||||
| #include "llvm/Target/MRegisterInfo.h" | #include "llvm/Target/MRegisterInfo.h" | ||||||
| #include "llvm/Target/TargetMachine.h" | #include "llvm/Target/TargetMachine.h" | ||||||
|  | #include "llvm/Support/GetElementPtrTypeIterator.h" | ||||||
| #include "llvm/Support/InstVisitor.h" | #include "llvm/Support/InstVisitor.h" | ||||||
| #include "llvm/Support/CFG.h" | #include "llvm/Support/CFG.h" | ||||||
| using namespace llvm; | using namespace llvm; | ||||||
| @@ -2211,38 +2212,54 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB, | |||||||
|                             Value *Src, User::op_iterator IdxBegin, |                             Value *Src, User::op_iterator IdxBegin, | ||||||
|                             User::op_iterator IdxEnd, unsigned TargetReg) { |                             User::op_iterator IdxEnd, unsigned TargetReg) { | ||||||
|   const TargetData &TD = TM.getTargetData(); |   const TargetData &TD = TM.getTargetData(); | ||||||
|   const Type *Ty = Src->getType(); |  | ||||||
|   unsigned BaseReg = getReg(Src, MBB, IP); |  | ||||||
|  |  | ||||||
|   // GEPs have zero or more indices; we must perform a struct access |   std::vector<Value*> GEPOps; | ||||||
|   // or array access for each one. |   GEPOps.resize(IdxEnd-IdxBegin+1); | ||||||
|   for (GetElementPtrInst::op_iterator oi = IdxBegin, |   GEPOps[0] = Src; | ||||||
|          oe = IdxEnd; oi != oe; ++oi) { |   std::copy(IdxBegin, IdxEnd, GEPOps.begin()+1); | ||||||
|     Value *idx = *oi; |    | ||||||
|     unsigned NextReg = BaseReg; |   std::vector<const Type*> GEPTypes; | ||||||
|     if (const StructType *StTy = dyn_cast<StructType>(Ty)) { |   GEPTypes.assign(gep_type_begin(Src->getType(), IdxBegin, IdxEnd), | ||||||
|       // It's a struct access.  idx is the index into the structure, |                   gep_type_end(Src->getType(), IdxBegin, IdxEnd)); | ||||||
|       // which names the field. This index must have ubyte type. |  | ||||||
|       const ConstantUInt *CUI = cast<ConstantUInt>(idx); |   // Keep emitting instructions until we consume the entire GEP instruction. | ||||||
|       assert(CUI->getType() == Type::UByteTy |   while (!GEPOps.empty()) { | ||||||
|               && "Funny-looking structure index in GEP"); |     unsigned OldSize = GEPOps.size(); | ||||||
|       // Use the TargetData structure to pick out what the layout of |      | ||||||
|       // the structure is in memory.  Since the structure index must |     if (GEPTypes.empty()) { | ||||||
|       // be constant, we can get its value and use it to find the |       // The getGEPIndex operation didn't want to build an LEA.  Check to see if | ||||||
|       // right byte offset from the StructLayout class's list of |       // all operands are consumed but the base pointer.  If so, just load it | ||||||
|       // structure member offsets. |       // into the register. | ||||||
|  |       unsigned BaseReg = getReg(GEPOps[0], MBB, IP); | ||||||
|  |       BMI(MBB, IP, X86::MOVrr32, 1, TargetReg).addReg(BaseReg); | ||||||
|  |       return;                // we are now done | ||||||
|  |     } else if (const StructType *StTy = dyn_cast<StructType>(GEPTypes.back())) { | ||||||
|  |       // It's a struct access.  CUI is the index into the structure, | ||||||
|  |       // which names the field. This index must have unsigned type. | ||||||
|  |       const ConstantUInt *CUI = cast<ConstantUInt>(GEPOps.back()); | ||||||
|  |       GEPOps.pop_back();        // Consume a GEP operand | ||||||
|  |       GEPTypes.pop_back(); | ||||||
|  |  | ||||||
|  |       // Use the TargetData structure to pick out what the layout of the | ||||||
|  |       // structure is in memory.  Since the structure index must be constant, we | ||||||
|  |       // can get its value and use it to find the right byte offset from the | ||||||
|  |       // StructLayout class's list of structure member offsets. | ||||||
|       unsigned idxValue = CUI->getValue(); |       unsigned idxValue = CUI->getValue(); | ||||||
|       unsigned FieldOff = TD.getStructLayout(StTy)->MemberOffsets[idxValue]; |       unsigned FieldOff = TD.getStructLayout(StTy)->MemberOffsets[idxValue]; | ||||||
|       if (FieldOff) { |       if (FieldOff) { | ||||||
|         NextReg = makeAnotherReg(Type::UIntTy); |         unsigned Reg = makeAnotherReg(Type::UIntTy); | ||||||
|         // Emit an ADD to add FieldOff to the basePtr. |         // Emit an ADD to add FieldOff to the basePtr. | ||||||
|         BMI(MBB, IP, X86::ADDri32, 2,NextReg).addReg(BaseReg).addZImm(FieldOff); |         BMI(MBB, IP, X86::ADDri32, 2, TargetReg).addReg(Reg).addZImm(FieldOff); | ||||||
|  |         --IP;            // Insert the next instruction before this one. | ||||||
|  |         TargetReg = Reg; // Codegen the rest of the GEP into this | ||||||
|       } |       } | ||||||
|       // The next type is the member of the structure selected by the |        | ||||||
|       // index. |     } else { | ||||||
|       Ty = StTy->getElementType(idxValue); |  | ||||||
|     } else if (const SequentialType *SqTy = cast<SequentialType>(Ty)) { |  | ||||||
|       // It's an array or pointer access: [ArraySize x ElementType]. |       // It's an array or pointer access: [ArraySize x ElementType]. | ||||||
|  |       const SequentialType *SqTy = cast<SequentialType>(GEPTypes.back()); | ||||||
|  |       Value *idx = GEPOps.back(); | ||||||
|  |       GEPOps.pop_back();        // Consume a GEP operand | ||||||
|  |       GEPTypes.pop_back(); | ||||||
|  |  | ||||||
|       // idx is the index into the array.  Unlike with structure |       // idx is the index into the array.  Unlike with structure | ||||||
|       // indices, we may not know its actual value at code-generation |       // indices, we may not know its actual value at code-generation | ||||||
| @@ -2259,41 +2276,52 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB, | |||||||
|       // We want to add BaseReg to(idxReg * sizeof ElementType). First, we |       // We want to add BaseReg to(idxReg * sizeof ElementType). First, we | ||||||
|       // must find the size of the pointed-to type (Not coincidentally, the next |       // must find the size of the pointed-to type (Not coincidentally, the next | ||||||
|       // type is the type of the elements in the array). |       // type is the type of the elements in the array). | ||||||
|       Ty = SqTy->getElementType(); |       const Type *ElTy = SqTy->getElementType(); | ||||||
|       unsigned elementSize = TD.getTypeSize(Ty); |       unsigned elementSize = TD.getTypeSize(ElTy); | ||||||
|  |  | ||||||
|       // If idxReg is a constant, we don't need to perform the multiply! |       // If idxReg is a constant, we don't need to perform the multiply! | ||||||
|       if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) { |       if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) { | ||||||
|         if (!CSI->isNullValue()) { |         if (!CSI->isNullValue()) { | ||||||
|           unsigned Offset = elementSize*CSI->getValue(); |           unsigned Offset = elementSize*CSI->getValue(); | ||||||
|           NextReg = makeAnotherReg(Type::UIntTy); |           unsigned Reg = makeAnotherReg(Type::UIntTy); | ||||||
|           BMI(MBB, IP, X86::ADDri32, 2,NextReg).addReg(BaseReg).addZImm(Offset); |           BMI(MBB, IP, X86::ADDri32, 2, TargetReg).addReg(Reg).addZImm(Offset); | ||||||
|  |           --IP;            // Insert the next instruction before this one. | ||||||
|  |           TargetReg = Reg; // Codegen the rest of the GEP into this | ||||||
|         } |         } | ||||||
|       } else if (elementSize == 1) { |       } else if (elementSize == 1) { | ||||||
|         // If the element size is 1, we don't have to multiply, just add |         // If the element size is 1, we don't have to multiply, just add | ||||||
|         unsigned idxReg = getReg(idx, MBB, IP); |         unsigned idxReg = getReg(idx, MBB, IP); | ||||||
|         NextReg = makeAnotherReg(Type::UIntTy); |         unsigned Reg = makeAnotherReg(Type::UIntTy); | ||||||
|         BMI(MBB, IP, X86::ADDrr32, 2, NextReg).addReg(BaseReg).addReg(idxReg); |         BMI(MBB, IP, X86::ADDrr32, 2, TargetReg).addReg(Reg).addReg(idxReg); | ||||||
|  |         --IP;            // Insert the next instruction before this one. | ||||||
|  |         TargetReg = Reg; // Codegen the rest of the GEP into this | ||||||
|       } else { |       } else { | ||||||
|         unsigned idxReg = getReg(idx, MBB, IP); |         unsigned idxReg = getReg(idx, MBB, IP); | ||||||
|         unsigned OffsetReg = makeAnotherReg(Type::UIntTy); |         unsigned OffsetReg = makeAnotherReg(Type::UIntTy); | ||||||
|  |  | ||||||
|  |         // Make sure we can back the iterator up to point to the first | ||||||
|  |         // instruction emitted. | ||||||
|  |         MachineBasicBlock::iterator BeforeIt = IP; | ||||||
|  |         if (IP == MBB->begin()) | ||||||
|  |           BeforeIt = MBB->end(); | ||||||
|  |         else | ||||||
|  |           --BeforeIt; | ||||||
|         doMultiplyConst(MBB, IP, OffsetReg, Type::IntTy, idxReg, elementSize); |         doMultiplyConst(MBB, IP, OffsetReg, Type::IntTy, idxReg, elementSize); | ||||||
|  |  | ||||||
|         // Emit an ADD to add OffsetReg to the basePtr. |         // Emit an ADD to add OffsetReg to the basePtr. | ||||||
|         NextReg = makeAnotherReg(Type::UIntTy); |         unsigned Reg = makeAnotherReg(Type::UIntTy); | ||||||
|         BMI(MBB, IP, X86::ADDrr32, 2,NextReg).addReg(BaseReg).addReg(OffsetReg); |         BMI(MBB, IP, X86::ADDrr32, 2, TargetReg).addReg(Reg).addReg(OffsetReg); | ||||||
|  |  | ||||||
|  |         // Step to the first instruction of the multiply. | ||||||
|  |         if (BeforeIt == MBB->end()) | ||||||
|  |           IP = MBB->begin(); | ||||||
|  |         else | ||||||
|  |           IP = ++BeforeIt; | ||||||
|  |  | ||||||
|  |         TargetReg = Reg; // Codegen the rest of the GEP into this | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     // Now that we are here, further indices refer to subtypes of this |  | ||||||
|     // one, so we don't need to worry about BaseReg itself, anymore. |  | ||||||
|     BaseReg = NextReg; |  | ||||||
|   } |   } | ||||||
|   // After we have processed all the indices, the result is left in |  | ||||||
|   // BaseReg.  Move it to the register where we were expected to |  | ||||||
|   // put the answer.  A 32-bit move should do it, because we are in |  | ||||||
|   // ILP32 land. |  | ||||||
|   BMI(MBB, IP, X86::MOVrr32, 1, TargetReg).addReg(BaseReg); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -27,6 +27,7 @@ | |||||||
| #include "llvm/CodeGen/SSARegMap.h" | #include "llvm/CodeGen/SSARegMap.h" | ||||||
| #include "llvm/Target/MRegisterInfo.h" | #include "llvm/Target/MRegisterInfo.h" | ||||||
| #include "llvm/Target/TargetMachine.h" | #include "llvm/Target/TargetMachine.h" | ||||||
|  | #include "llvm/Support/GetElementPtrTypeIterator.h" | ||||||
| #include "llvm/Support/InstVisitor.h" | #include "llvm/Support/InstVisitor.h" | ||||||
| #include "llvm/Support/CFG.h" | #include "llvm/Support/CFG.h" | ||||||
| using namespace llvm; | using namespace llvm; | ||||||
| @@ -2211,38 +2212,54 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB, | |||||||
|                             Value *Src, User::op_iterator IdxBegin, |                             Value *Src, User::op_iterator IdxBegin, | ||||||
|                             User::op_iterator IdxEnd, unsigned TargetReg) { |                             User::op_iterator IdxEnd, unsigned TargetReg) { | ||||||
|   const TargetData &TD = TM.getTargetData(); |   const TargetData &TD = TM.getTargetData(); | ||||||
|   const Type *Ty = Src->getType(); |  | ||||||
|   unsigned BaseReg = getReg(Src, MBB, IP); |  | ||||||
|  |  | ||||||
|   // GEPs have zero or more indices; we must perform a struct access |   std::vector<Value*> GEPOps; | ||||||
|   // or array access for each one. |   GEPOps.resize(IdxEnd-IdxBegin+1); | ||||||
|   for (GetElementPtrInst::op_iterator oi = IdxBegin, |   GEPOps[0] = Src; | ||||||
|          oe = IdxEnd; oi != oe; ++oi) { |   std::copy(IdxBegin, IdxEnd, GEPOps.begin()+1); | ||||||
|     Value *idx = *oi; |    | ||||||
|     unsigned NextReg = BaseReg; |   std::vector<const Type*> GEPTypes; | ||||||
|     if (const StructType *StTy = dyn_cast<StructType>(Ty)) { |   GEPTypes.assign(gep_type_begin(Src->getType(), IdxBegin, IdxEnd), | ||||||
|       // It's a struct access.  idx is the index into the structure, |                   gep_type_end(Src->getType(), IdxBegin, IdxEnd)); | ||||||
|       // which names the field. This index must have ubyte type. |  | ||||||
|       const ConstantUInt *CUI = cast<ConstantUInt>(idx); |   // Keep emitting instructions until we consume the entire GEP instruction. | ||||||
|       assert(CUI->getType() == Type::UByteTy |   while (!GEPOps.empty()) { | ||||||
|               && "Funny-looking structure index in GEP"); |     unsigned OldSize = GEPOps.size(); | ||||||
|       // Use the TargetData structure to pick out what the layout of |      | ||||||
|       // the structure is in memory.  Since the structure index must |     if (GEPTypes.empty()) { | ||||||
|       // be constant, we can get its value and use it to find the |       // The getGEPIndex operation didn't want to build an LEA.  Check to see if | ||||||
|       // right byte offset from the StructLayout class's list of |       // all operands are consumed but the base pointer.  If so, just load it | ||||||
|       // structure member offsets. |       // into the register. | ||||||
|  |       unsigned BaseReg = getReg(GEPOps[0], MBB, IP); | ||||||
|  |       BMI(MBB, IP, X86::MOVrr32, 1, TargetReg).addReg(BaseReg); | ||||||
|  |       return;                // we are now done | ||||||
|  |     } else if (const StructType *StTy = dyn_cast<StructType>(GEPTypes.back())) { | ||||||
|  |       // It's a struct access.  CUI is the index into the structure, | ||||||
|  |       // which names the field. This index must have unsigned type. | ||||||
|  |       const ConstantUInt *CUI = cast<ConstantUInt>(GEPOps.back()); | ||||||
|  |       GEPOps.pop_back();        // Consume a GEP operand | ||||||
|  |       GEPTypes.pop_back(); | ||||||
|  |  | ||||||
|  |       // Use the TargetData structure to pick out what the layout of the | ||||||
|  |       // structure is in memory.  Since the structure index must be constant, we | ||||||
|  |       // can get its value and use it to find the right byte offset from the | ||||||
|  |       // StructLayout class's list of structure member offsets. | ||||||
|       unsigned idxValue = CUI->getValue(); |       unsigned idxValue = CUI->getValue(); | ||||||
|       unsigned FieldOff = TD.getStructLayout(StTy)->MemberOffsets[idxValue]; |       unsigned FieldOff = TD.getStructLayout(StTy)->MemberOffsets[idxValue]; | ||||||
|       if (FieldOff) { |       if (FieldOff) { | ||||||
|         NextReg = makeAnotherReg(Type::UIntTy); |         unsigned Reg = makeAnotherReg(Type::UIntTy); | ||||||
|         // Emit an ADD to add FieldOff to the basePtr. |         // Emit an ADD to add FieldOff to the basePtr. | ||||||
|         BMI(MBB, IP, X86::ADDri32, 2,NextReg).addReg(BaseReg).addZImm(FieldOff); |         BMI(MBB, IP, X86::ADDri32, 2, TargetReg).addReg(Reg).addZImm(FieldOff); | ||||||
|  |         --IP;            // Insert the next instruction before this one. | ||||||
|  |         TargetReg = Reg; // Codegen the rest of the GEP into this | ||||||
|       } |       } | ||||||
|       // The next type is the member of the structure selected by the |        | ||||||
|       // index. |     } else { | ||||||
|       Ty = StTy->getElementType(idxValue); |  | ||||||
|     } else if (const SequentialType *SqTy = cast<SequentialType>(Ty)) { |  | ||||||
|       // It's an array or pointer access: [ArraySize x ElementType]. |       // It's an array or pointer access: [ArraySize x ElementType]. | ||||||
|  |       const SequentialType *SqTy = cast<SequentialType>(GEPTypes.back()); | ||||||
|  |       Value *idx = GEPOps.back(); | ||||||
|  |       GEPOps.pop_back();        // Consume a GEP operand | ||||||
|  |       GEPTypes.pop_back(); | ||||||
|  |  | ||||||
|       // idx is the index into the array.  Unlike with structure |       // idx is the index into the array.  Unlike with structure | ||||||
|       // indices, we may not know its actual value at code-generation |       // indices, we may not know its actual value at code-generation | ||||||
| @@ -2259,41 +2276,52 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB, | |||||||
|       // We want to add BaseReg to(idxReg * sizeof ElementType). First, we |       // We want to add BaseReg to(idxReg * sizeof ElementType). First, we | ||||||
|       // must find the size of the pointed-to type (Not coincidentally, the next |       // must find the size of the pointed-to type (Not coincidentally, the next | ||||||
|       // type is the type of the elements in the array). |       // type is the type of the elements in the array). | ||||||
|       Ty = SqTy->getElementType(); |       const Type *ElTy = SqTy->getElementType(); | ||||||
|       unsigned elementSize = TD.getTypeSize(Ty); |       unsigned elementSize = TD.getTypeSize(ElTy); | ||||||
|  |  | ||||||
|       // If idxReg is a constant, we don't need to perform the multiply! |       // If idxReg is a constant, we don't need to perform the multiply! | ||||||
|       if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) { |       if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) { | ||||||
|         if (!CSI->isNullValue()) { |         if (!CSI->isNullValue()) { | ||||||
|           unsigned Offset = elementSize*CSI->getValue(); |           unsigned Offset = elementSize*CSI->getValue(); | ||||||
|           NextReg = makeAnotherReg(Type::UIntTy); |           unsigned Reg = makeAnotherReg(Type::UIntTy); | ||||||
|           BMI(MBB, IP, X86::ADDri32, 2,NextReg).addReg(BaseReg).addZImm(Offset); |           BMI(MBB, IP, X86::ADDri32, 2, TargetReg).addReg(Reg).addZImm(Offset); | ||||||
|  |           --IP;            // Insert the next instruction before this one. | ||||||
|  |           TargetReg = Reg; // Codegen the rest of the GEP into this | ||||||
|         } |         } | ||||||
|       } else if (elementSize == 1) { |       } else if (elementSize == 1) { | ||||||
|         // If the element size is 1, we don't have to multiply, just add |         // If the element size is 1, we don't have to multiply, just add | ||||||
|         unsigned idxReg = getReg(idx, MBB, IP); |         unsigned idxReg = getReg(idx, MBB, IP); | ||||||
|         NextReg = makeAnotherReg(Type::UIntTy); |         unsigned Reg = makeAnotherReg(Type::UIntTy); | ||||||
|         BMI(MBB, IP, X86::ADDrr32, 2, NextReg).addReg(BaseReg).addReg(idxReg); |         BMI(MBB, IP, X86::ADDrr32, 2, TargetReg).addReg(Reg).addReg(idxReg); | ||||||
|  |         --IP;            // Insert the next instruction before this one. | ||||||
|  |         TargetReg = Reg; // Codegen the rest of the GEP into this | ||||||
|       } else { |       } else { | ||||||
|         unsigned idxReg = getReg(idx, MBB, IP); |         unsigned idxReg = getReg(idx, MBB, IP); | ||||||
|         unsigned OffsetReg = makeAnotherReg(Type::UIntTy); |         unsigned OffsetReg = makeAnotherReg(Type::UIntTy); | ||||||
|  |  | ||||||
|  |         // Make sure we can back the iterator up to point to the first | ||||||
|  |         // instruction emitted. | ||||||
|  |         MachineBasicBlock::iterator BeforeIt = IP; | ||||||
|  |         if (IP == MBB->begin()) | ||||||
|  |           BeforeIt = MBB->end(); | ||||||
|  |         else | ||||||
|  |           --BeforeIt; | ||||||
|         doMultiplyConst(MBB, IP, OffsetReg, Type::IntTy, idxReg, elementSize); |         doMultiplyConst(MBB, IP, OffsetReg, Type::IntTy, idxReg, elementSize); | ||||||
|  |  | ||||||
|         // Emit an ADD to add OffsetReg to the basePtr. |         // Emit an ADD to add OffsetReg to the basePtr. | ||||||
|         NextReg = makeAnotherReg(Type::UIntTy); |         unsigned Reg = makeAnotherReg(Type::UIntTy); | ||||||
|         BMI(MBB, IP, X86::ADDrr32, 2,NextReg).addReg(BaseReg).addReg(OffsetReg); |         BMI(MBB, IP, X86::ADDrr32, 2, TargetReg).addReg(Reg).addReg(OffsetReg); | ||||||
|  |  | ||||||
|  |         // Step to the first instruction of the multiply. | ||||||
|  |         if (BeforeIt == MBB->end()) | ||||||
|  |           IP = MBB->begin(); | ||||||
|  |         else | ||||||
|  |           IP = ++BeforeIt; | ||||||
|  |  | ||||||
|  |         TargetReg = Reg; // Codegen the rest of the GEP into this | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     // Now that we are here, further indices refer to subtypes of this |  | ||||||
|     // one, so we don't need to worry about BaseReg itself, anymore. |  | ||||||
|     BaseReg = NextReg; |  | ||||||
|   } |   } | ||||||
|   // After we have processed all the indices, the result is left in |  | ||||||
|   // BaseReg.  Move it to the register where we were expected to |  | ||||||
|   // put the answer.  A 32-bit move should do it, because we are in |  | ||||||
|   // ILP32 land. |  | ||||||
|   BMI(MBB, IP, X86::MOVrr32, 1, TargetReg).addReg(BaseReg); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user