mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-10-30 00:16:48 +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