diff --git a/ctx.cpp b/ctx.cpp index 27d7f1a7..efc92921 100644 --- a/ctx.cpp +++ b/ctx.cpp @@ -799,28 +799,6 @@ FunctionEmitContext::I1VecToBoolVec(llvm::Value *b) { } -llvm::Value * -FunctionEmitContext::SizeOf(LLVM_TYPE_CONST llvm::Type *ty) { - // Emit code to compute the size of the given type using a GEP with a - // NULL base pointer, indexing one element of the given type, and - // casting the resulting 'pointer' to an int giving its size. - LLVM_TYPE_CONST llvm::Type *ptrType = llvm::PointerType::get(ty, 0); - llvm::Value *nullPtr = llvm::Constant::getNullValue(ptrType); - llvm::Value *index[1] = { LLVMInt32(1) }; -#if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn) - llvm::ArrayRef arrayRef(&index[0], &index[1]); - llvm::Value *poffset = llvm::GetElementPtrInst::Create(nullPtr, arrayRef, - "offset_ptr", bblock); -#else - llvm::Value *poffset = llvm::GetElementPtrInst::Create(nullPtr, &index[0], &index[1], - "offset_ptr", bblock); -#endif - AddDebugPos(poffset); - llvm::Value *sizeOf = PtrToIntInst(poffset, LLVMTypes::Int64Type, "offset_int"); - return sizeOf; -} - - static llvm::Value * lGetStringAsValue(llvm::BasicBlock *bblock, const char *s) { llvm::Constant *sConstant = llvm::ConstantArray::get(*g->ctx, s); @@ -2266,7 +2244,7 @@ FunctionEmitContext::LaunchInst(llvm::Value *callee, int align = 4 * RoundUpPow2(g->target.nativeVectorWidth); std::vector allocArgs; allocArgs.push_back(launchGroupHandlePtr); - allocArgs.push_back(SizeOf(argStructType)); + allocArgs.push_back(g->target.SizeOf(argStructType)); allocArgs.push_back(LLVMInt32(align)); llvm::Value *voidmem = CallInst(falloc, NULL, allocArgs, "args_ptr"); llvm::Value *argmem = BitCastInst(voidmem, pt); diff --git a/ctx.h b/ctx.h index 27d030ee..b4677acb 100644 --- a/ctx.h +++ b/ctx.h @@ -226,9 +226,6 @@ public: i32. */ llvm::Value *I1VecToBoolVec(llvm::Value *b); - /** Returns the size of the given type. */ - llvm::Value *SizeOf(LLVM_TYPE_CONST llvm::Type *ty); - /** If the user has asked to compile the program with instrumentation, this inserts a callback to the user-supplied instrumentation function at the current point in the code. */ diff --git a/ispc.cpp b/ispc.cpp index 3ff94a99..e62749e3 100644 --- a/ispc.cpp +++ b/ispc.cpp @@ -38,6 +38,7 @@ #include "ispc.h" #include "module.h" #include "util.h" +#include "llvmutil.h" #include #ifdef ISPC_IS_WINDOWS #include @@ -279,6 +280,28 @@ Target::GetISAString() const { } +llvm::Value * +Target::SizeOf(LLVM_TYPE_CONST llvm::Type *type) { + const llvm::TargetData *td = GetTargetMachine()->getTargetData(); + assert(td != NULL); + return is32bit ? LLVMInt32(td->getTypeSizeInBits(type) / 8) : + LLVMInt64(td->getTypeSizeInBits(type) / 8); +} + + +llvm::Value * +Target::StructOffset(LLVM_TYPE_CONST llvm::Type *type, int element) { + const llvm::TargetData *td = GetTargetMachine()->getTargetData(); + assert(td != NULL); + LLVM_TYPE_CONST llvm::StructType *structType = + llvm::dyn_cast(type); + assert(structType != NULL); + const llvm::StructLayout *sl = td->getStructLayout(structType); + assert(sl != NULL); + return LLVMInt32(sl->getElementOffset(element)); +} + + /////////////////////////////////////////////////////////////////////////// // Opt diff --git a/ispc.h b/ispc.h index e31a5656..26f209c1 100644 --- a/ispc.h +++ b/ispc.h @@ -160,6 +160,14 @@ struct Target { /** Returns a string like "avx" encoding the target. */ const char *GetISAString() const; + /** Returns the size of the given type */ + llvm::Value *SizeOf(LLVM_TYPE_CONST llvm::Type *type); + /** Given a structure type and an element number in the structure, + returns a value corresponding to the number of bytes from the start + of the structure where the element is located. */ + llvm::Value *StructOffset(LLVM_TYPE_CONST llvm::Type *type, + int element); + /** llvm Target object representing this target. */ const llvm::Target *target; diff --git a/opt.cpp b/opt.cpp index d4fbcba0..fb4ccdbc 100644 --- a/opt.cpp +++ b/opt.cpp @@ -759,128 +759,6 @@ lGetIntValue(llvm::Value *offset) { } -/** Returns the size of the given llvm::Type as an llvm::Value, if the size - can be easily determined at compile type. If it's not easy to figure - out the size, this just returns NULL and we handle finding its size - differently. - */ -static bool -lSizeOfIfKnown(const llvm::Type *type, uint64_t *size) { - if (type == LLVMTypes::Int8Type) { - *size = 1; - return true; - } - if (type == LLVMTypes::Int8VectorType) { - *size = g->target.vectorWidth * 1; - return true; - } - else if (type == LLVMTypes::Int16Type) { - *size = 2; - return true; - } - if (type == LLVMTypes::Int16VectorType) { - *size = g->target.vectorWidth * 2; - return true; - } - else if (type == LLVMTypes::FloatType || type == LLVMTypes::Int32Type) { - *size = 4; - return true; - } - else if (type == LLVMTypes::FloatVectorType || type == LLVMTypes::Int32VectorType) { - *size = g->target.vectorWidth * 4; - return true; - } - else if (type == LLVMTypes::DoubleType || type == LLVMTypes::Int64Type) { - *size = 8; - return true; - } - else if (type == LLVMTypes::DoubleVectorType || type == LLVMTypes::Int64VectorType) { - *size = g->target.vectorWidth * 8; - return true; - } - else if (llvm::isa(type)) { - const llvm::ArrayType *at = llvm::dyn_cast(type); - uint64_t eltSize; - if (lSizeOfIfKnown(at->getElementType(), &eltSize)) { - *size = eltSize * at->getNumElements(); - return true; - } - else - return false; - } - return false; -} - - -/** This function returns an llvm::Value giving the size of the given type. - If any instructions need to be generated to compute the size, they are - inserted before insertBefore. - */ -static llvm::Value * -lSizeOf(LLVM_TYPE_CONST llvm::Type *type, llvm::Instruction *insertBefore) { - // First try the easy case and see if we can get it as a simple - // constant.. - uint64_t size; - if (lSizeOfIfKnown(type, &size)) - return LLVMInt64(size); - - // Otherwise use the trick of doing a GEP with a NULL pointer to get - // the pointer to the second element of an array of items of this type. - // Then convert that pointer to an int and we've got the offset to the - // second element in the array, a.k.a. the size of the type. - LLVM_TYPE_CONST llvm::Type *ptrType = llvm::PointerType::get(type, 0); - llvm::Value *nullPtr = llvm::Constant::getNullValue(ptrType); - llvm::Value *index[1] = { LLVMInt32(1) }; -#if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn) - llvm::ArrayRef arrayRef(&index[0], &index[1]); - llvm::Value *poffset = llvm::GetElementPtrInst::Create(nullPtr, arrayRef, - "offset_ptr", insertBefore); -#else - llvm::Value *poffset = llvm::GetElementPtrInst::Create(nullPtr, &index[0], &index[1], - "offset_ptr", insertBefore); -#endif - lCopyMetadata(poffset, insertBefore); - LLVM_TYPE_CONST llvm::Type *intPtrType = g->target.is32bit ? - LLVMTypes::Int32Type : LLVMTypes::Int64Type; - llvm::Instruction *inst = new llvm::PtrToIntInst(poffset, intPtrType, - "offset_int", insertBefore); - lCopyMetadata(inst, insertBefore); - return inst; -} - - -/** This function returns a value that gives the offset in bytes from the - start of the given structure type to the given struct member. The - instructions that compute this value are inserted before insertBefore. - */ -static llvm::Value * -lStructOffset(LLVM_TYPE_CONST llvm::Type *type, uint64_t member, - llvm::Instruction *insertBefore) { - // Do a similar trick to the one done in lSizeOf above; compute the - // pointer to the member starting from a NULL base pointer and then - // cast that 'pointer' to an int... - assert(llvm::isa(type)); - LLVM_TYPE_CONST llvm::Type *ptrType = llvm::PointerType::get(type, 0); - llvm::Value *nullPtr = llvm::Constant::getNullValue(ptrType); - llvm::Value *index[2] = { LLVMInt32(0), LLVMInt32((int32_t)member) }; -#if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn) - llvm::ArrayRef arrayRef(&index[0], &index[2]); - llvm::Value *poffset = llvm::GetElementPtrInst::Create(nullPtr, arrayRef, - "member_ptr", insertBefore); -#else - llvm::Value *poffset = llvm::GetElementPtrInst::Create(nullPtr, &index[0], &index[2], - "member_ptr", insertBefore); -#endif - lCopyMetadata(poffset, insertBefore); - LLVM_TYPE_CONST llvm::Type *intPtrType = g->target.is32bit ? - LLVMTypes::Int32Type : LLVMTypes::Int64Type; - llvm::Instruction *inst = new llvm::PtrToIntInst(poffset, intPtrType, - "member_int", insertBefore); - lCopyMetadata(inst, insertBefore); - return inst; -} - - static llvm::Value * lGetTypeSize(LLVM_TYPE_CONST llvm::Type *type, llvm::Instruction *insertBefore) { LLVM_TYPE_CONST llvm::ArrayType *arrayType = @@ -888,11 +766,13 @@ lGetTypeSize(LLVM_TYPE_CONST llvm::Type *type, llvm::Instruction *insertBefore) if (arrayType != NULL) type = arrayType->getElementType(); - llvm::Value *scale = lSizeOf(type, insertBefore); - llvm::Instruction *inst = new llvm::TruncInst(scale, LLVMTypes::Int32Type, "sizeof32", - insertBefore); - lCopyMetadata(inst, insertBefore); - return inst; + llvm::Value *scale = g->target.SizeOf(type); + if (g->target.is32bit == false) { + scale = new llvm::TruncInst(scale, LLVMTypes::Int32Type, "sizeof32", + insertBefore); + lCopyMetadata(scale, insertBefore); + } + return scale; } @@ -919,11 +799,8 @@ lTraverseConstantExpr(llvm::Constant *value, llvm::Value **offsetPtr, LLVM_TYPE_CONST llvm::Type *targetType = targetPtrType->getElementType(); if (llvm::isa(targetType)) { - *offsetPtr = lStructOffset(targetType, lGetIntValue(ce->getOperand(2)), - insertBefore); - *offsetPtr = new llvm::TruncInst(*offsetPtr, LLVMTypes::Int32Type, "member32", - insertBefore); -//CO lCopyMetadata(*offset, insertBefore); + *offsetPtr = g->target.StructOffset(targetType, + lGetIntValue(ce->getOperand(2))); *scaleType = LLVMTypes::Int8Type; // aka char aka sizeof(1) } else { @@ -979,10 +856,7 @@ lGetOffsetForLane(int lane, llvm::Value *value, llvm::Value **offset, LLVM_TYPE_CONST llvm::Type *targetType = targetPtrType->getElementType(); if (llvm::isa(targetType)) { - *offset = lStructOffset(targetType, lGetIntValue(gep->getOperand(2)), - insertBefore); - *offset = new llvm::TruncInst(*offset, LLVMTypes::Int32Type, "member32", - insertBefore); + *offset = g->target.StructOffset(targetType, lGetIntValue(gep->getOperand(2))); lCopyMetadata(*offset, insertBefore); *scaleType = LLVMTypes::Int8Type; // aka char aka sizeof(1) } @@ -1806,15 +1680,17 @@ lScalarizeVector(llvm::Value *vec, llvm::Value **scalarizedVector, llvm::dyn_cast(ptrType->getElementType()); assert(vecType != NULL); LLVM_TYPE_CONST llvm::Type *elementType = vecType->getElementType(); - uint64_t elementSize; - bool sizeKnown = lSizeOfIfKnown(elementType, &elementSize); - assert(sizeKnown == true); + + llvm::Value *elementSize = g->target.SizeOf(elementType); LLVM_TYPE_CONST llvm::Type *eltPtrType = llvm::PointerType::get(elementType, 0); for (int i = 0; i < vectorLength; ++i) { - llvm::Value *offset = g->target.is32bit ? LLVMInt32(i * elementSize) : - LLVMInt64(i * elementSize); + llvm::Value *offset = + llvm::BinaryOperator::Create(llvm::Instruction::Mul, elementSize, + g->target.is32bit ? LLVMInt32(i) : + LLVMInt64(i), + "elt_offset", li); llvm::Value *intPtrOffset = llvm::BinaryOperator::Create(llvm::Instruction::Add, baseInt, offset, "baseoffset", li);