summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/DataLayout.cpp
diff options
context:
space:
mode:
authorElena Demikhovsky <elena.demikhovsky@intel.com>2018-02-14 06:58:08 +0000
committerElena Demikhovsky <elena.demikhovsky@intel.com>2018-02-14 06:58:08 +0000
commit945b7e5aa639353f5660415935e58601d01cf270 (patch)
treef986734d50dea15ca61f00eb2b248af7e61c0159 /llvm/lib/IR/DataLayout.cpp
parent5ecea9fff5832d85115387189297bcde38f0a43c (diff)
downloadbcm5719-llvm-945b7e5aa639353f5660415935e58601d01cf270.tar.gz
bcm5719-llvm-945b7e5aa639353f5660415935e58601d01cf270.zip
Adding a width of the GEP index to the Data Layout.
Making a width of GEP Index, which is used for address calculation, to be one of the pointer properties in the Data Layout. p[address space]:size:memory_size:alignment:pref_alignment:index_size_in_bits. The index size parameter is optional, if not specified, it is equal to the pointer size. Till now, the InstCombiner normalized GEPs and extended the Index operand to the pointer width. It works fine if you can convert pointer to integer for address calculation and all registered targets do this. But some ISAs have very restricted instruction set for the pointer calculation. During discussions were desided to retrieve information for GEP index from the Data Layout. http://lists.llvm.org/pipermail/llvm-dev/2018-January/120416.html I added an interface to the Data Layout and I changed the InstCombiner and some other passes to take the Index width into account. This change does not affect any in-tree target. I added tests to cover data layouts with explicitly specified index size. Differential Revision: https://reviews.llvm.org/D42123 llvm-svn: 325102
Diffstat (limited to 'llvm/lib/IR/DataLayout.cpp')
-rw-r--r--llvm/lib/IR/DataLayout.cpp61
1 files changed, 51 insertions, 10 deletions
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index f4dddeb30d0..289001d2020 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -129,13 +129,15 @@ LayoutAlignElem::operator==(const LayoutAlignElem &rhs) const {
PointerAlignElem
PointerAlignElem::get(uint32_t AddressSpace, unsigned ABIAlign,
- unsigned PrefAlign, uint32_t TypeByteWidth) {
+ unsigned PrefAlign, uint32_t TypeByteWidth,
+ uint32_t IndexWidth) {
assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!");
PointerAlignElem retval;
retval.AddressSpace = AddressSpace;
retval.ABIAlign = ABIAlign;
retval.PrefAlign = PrefAlign;
retval.TypeByteWidth = TypeByteWidth;
+ retval.IndexWidth = IndexWidth;
return retval;
}
@@ -144,7 +146,8 @@ PointerAlignElem::operator==(const PointerAlignElem &rhs) const {
return (ABIAlign == rhs.ABIAlign
&& AddressSpace == rhs.AddressSpace
&& PrefAlign == rhs.PrefAlign
- && TypeByteWidth == rhs.TypeByteWidth);
+ && TypeByteWidth == rhs.TypeByteWidth
+ && IndexWidth == rhs.IndexWidth);
}
//===----------------------------------------------------------------------===//
@@ -189,7 +192,7 @@ void DataLayout::reset(StringRef Desc) {
setAlignment((AlignTypeEnum)E.AlignType, E.ABIAlign, E.PrefAlign,
E.TypeBitWidth);
}
- setPointerAlignment(0, 8, 8, 8);
+ setPointerAlignment(0, 8, 8, 8, 8);
parseSpecifier(Desc);
}
@@ -287,6 +290,10 @@ void DataLayout::parseSpecifier(StringRef Desc) {
report_fatal_error(
"Pointer ABI alignment must be a power of 2");
+ // Size of index used in GEP for address calculation.
+ // The parameter is optional. By default it is equal to size of pointer.
+ unsigned IndexSize = PointerMemSize;
+
// Preferred alignment.
unsigned PointerPrefAlign = PointerABIAlign;
if (!Rest.empty()) {
@@ -295,10 +302,17 @@ void DataLayout::parseSpecifier(StringRef Desc) {
if (!isPowerOf2_64(PointerPrefAlign))
report_fatal_error(
"Pointer preferred alignment must be a power of 2");
- }
+ // Now read the index. It is the second optional parameter here.
+ if (!Rest.empty()) {
+ Split = split(Rest, ':');
+ IndexSize = inBytes(getInt(Tok));
+ if (!IndexSize)
+ report_fatal_error("Invalid index size of 0 bytes");
+ }
+ }
setPointerAlignment(AddrSpace, PointerABIAlign, PointerPrefAlign,
- PointerMemSize);
+ PointerMemSize, IndexSize);
break;
}
case 'i':
@@ -467,8 +481,8 @@ DataLayout::findPointerLowerBound(uint32_t AddressSpace) {
}
void DataLayout::setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign,
- unsigned PrefAlign,
- uint32_t TypeByteWidth) {
+ unsigned PrefAlign, uint32_t TypeByteWidth,
+ uint32_t IndexWidth) {
if (PrefAlign < ABIAlign)
report_fatal_error(
"Preferred alignment cannot be less than the ABI alignment");
@@ -476,11 +490,12 @@ void DataLayout::setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign,
PointersTy::iterator I = findPointerLowerBound(AddrSpace);
if (I == Pointers.end() || I->AddressSpace != AddrSpace) {
Pointers.insert(I, PointerAlignElem::get(AddrSpace, ABIAlign, PrefAlign,
- TypeByteWidth));
+ TypeByteWidth, IndexWidth));
} else {
I->ABIAlign = ABIAlign;
I->PrefAlign = PrefAlign;
I->TypeByteWidth = TypeByteWidth;
+ I->IndexWidth = IndexWidth;
}
}
@@ -618,6 +633,22 @@ unsigned DataLayout::getPointerTypeSizeInBits(Type *Ty) const {
return getPointerSizeInBits(cast<PointerType>(Ty)->getAddressSpace());
}
+unsigned DataLayout::getIndexSize(unsigned AS) const {
+ PointersTy::const_iterator I = findPointerLowerBound(AS);
+ if (I == Pointers.end() || I->AddressSpace != AS) {
+ I = findPointerLowerBound(0);
+ assert(I->AddressSpace == 0);
+ }
+ return I->IndexWidth;
+}
+
+unsigned DataLayout::getIndexTypeSizeInBits(Type *Ty) const {
+ assert(Ty->isPtrOrPtrVectorTy() &&
+ "This should only be called with a pointer or pointer vector type");
+ Ty = Ty->getScalarType();
+ return getIndexSizeInBits(cast<PointerType>(Ty)->getAddressSpace());
+}
+
/*!
\param abi_or_pref Flag that determines which alignment is returned. true
returns the ABI alignment, false returns the preferred alignment.
@@ -701,13 +732,13 @@ unsigned DataLayout::getPreferredTypeAlignmentShift(Type *Ty) const {
IntegerType *DataLayout::getIntPtrType(LLVMContext &C,
unsigned AddressSpace) const {
- return IntegerType::get(C, getPointerSizeInBits(AddressSpace));
+ return IntegerType::get(C, getIndexSizeInBits(AddressSpace));
}
Type *DataLayout::getIntPtrType(Type *Ty) const {
assert(Ty->isPtrOrPtrVectorTy() &&
"Expected a pointer or pointer vector type.");
- unsigned NumBits = getPointerTypeSizeInBits(Ty);
+ unsigned NumBits = getIndexTypeSizeInBits(Ty);
IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits);
if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
return VectorType::get(IntTy, VecTy->getNumElements());
@@ -726,6 +757,16 @@ unsigned DataLayout::getLargestLegalIntTypeSizeInBits() const {
return Max != LegalIntWidths.end() ? *Max : 0;
}
+Type *DataLayout::getIndexType(Type *Ty) const {
+ assert(Ty->isPtrOrPtrVectorTy() &&
+ "Expected a pointer or pointer vector type.");
+ unsigned NumBits = getIndexTypeSizeInBits(Ty);
+ IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits);
+ if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
+ return VectorType::get(IntTy, VecTy->getNumElements());
+ return IntTy;
+}
+
int64_t DataLayout::getIndexedOffsetInType(Type *ElemTy,
ArrayRef<Value *> Indices) const {
int64_t Result = 0;
OpenPOWER on IntegriCloud