From d6282b7238775141a8670583ad04e92ff343cbfa Mon Sep 17 00:00:00 2001 From: Chen Steenvoorden Date: Mon, 5 Aug 2024 15:15:42 +0200 Subject: [PATCH 01/14] Fix access to aggregate load/store not using wrapper array --- llvm/lib/CheerpWriter/CheerpWriter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/CheerpWriter/CheerpWriter.cpp b/llvm/lib/CheerpWriter/CheerpWriter.cpp index ba6c3ab4225a..015204abfcab 100644 --- a/llvm/lib/CheerpWriter/CheerpWriter.cpp +++ b/llvm/lib/CheerpWriter/CheerpWriter.cpp @@ -4671,7 +4671,7 @@ void CheerpWriter::compileLoadElem(const LoadInst& li, Type* Ty, StructType* STy compileCompleteObject(ptrOp); if(STy) { - compileAccessToElement(STy, {ConstantInt::get(IntegerType::get(Ty->getContext(), 32), structElemIdx)}, false); + compileAccessToElement(STy, {ConstantInt::get(IntegerType::get(Ty->getContext(), 32), structElemIdx)}, true); } if(isOffset) stream << 'o'; @@ -4821,7 +4821,7 @@ void CheerpWriter::compileStoreElem(const StoreInst& si, Type* Ty, StructType* S compileCompleteObject(ptrOp); if(STy) { - compileAccessToElement(STy, {ConstantInt::get(IntegerType::get(Ty->getContext(), 32), structElemIdx)}, false); + compileAccessToElement(STy, {ConstantInt::get(IntegerType::get(Ty->getContext(), 32), structElemIdx)}, true); } if(isOffset) stream << 'o'; From 5a57b62637175bb68119389d9671eb18609b7307 Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Wed, 15 May 2024 12:09:16 +0200 Subject: [PATCH 02/14] Writer: remove some uses of getPointerElementType --- llvm/lib/CheerpWriter/CheerpWriter.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/llvm/lib/CheerpWriter/CheerpWriter.cpp b/llvm/lib/CheerpWriter/CheerpWriter.cpp index 015204abfcab..516956e68e82 100644 --- a/llvm/lib/CheerpWriter/CheerpWriter.cpp +++ b/llvm/lib/CheerpWriter/CheerpWriter.cpp @@ -2033,9 +2033,8 @@ void CheerpWriter::compilePointerBaseTyped(const Value* p, Type* elementType, bo if(kind == RAW) { assert(isa(p->getType())); - Type* ty = llvm::cast(p->getType())->getPointerElementType(); if (isWasmTarget) - compileHeapForType(ty); + compileHeapForType(elementType); else stream << "nullArray"; return; @@ -3424,7 +3423,7 @@ void CheerpWriter::compileGEPBase(const llvm::User* gep_inst, bool forEscapingPo return; } compileCompleteObject(gep_inst->getOperand(0), indices.front()); - Type* basePointedType = basePointerType->getPointerElementType(); + Type* basePointedType = cast(gep_inst)->getSourceElementType(); if (useDownCastArray) { compileAccessToElement(basePointedType, makeArrayRef(std::next(indices.begin()),indices.end()), /*compileLastWrapperArray*/true); @@ -3573,7 +3572,7 @@ void CheerpWriter::compileGEPOffset(const llvm::User* gep_inst, PARENT_PRIORITY { if (useDownCastArray) { - Type* basePointedType = basePointerType->getPointerElementType(); + Type* basePointedType = cast(gep_inst)->getSourceElementType(); compileCompleteObject(gep_inst->getOperand(0), indices.front()); compileAccessToElement(basePointedType, makeArrayRef(std::next(indices.begin()), indices.end()), /*compileLastWrapperArray*/true); stream << ".o"; From a15c4b621ab38a2d2d047d4e121d531878ff9ab5 Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Mon, 25 Sep 2023 17:50:30 +0200 Subject: [PATCH 03/14] Include AddrSpaceCastInst in cheerp::isBitCast --- llvm/include/llvm/Cheerp/Utility.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/include/llvm/Cheerp/Utility.h b/llvm/include/llvm/Cheerp/Utility.h index a91d2c9f7250..d135194bd600 100644 --- a/llvm/include/llvm/Cheerp/Utility.h +++ b/llvm/include/llvm/Cheerp/Utility.h @@ -251,6 +251,8 @@ inline bool isBitCast(const llvm::Value* v) { if( llvm::isa< llvm::BitCastInst>(v) ) return true; + if( llvm::isa< llvm::AddrSpaceCastInst>(v) ) + return true; if(const llvm::ConstantExpr * ce = llvm::dyn_cast(v) ) return ce->getOpcode() == llvm::Instruction::BitCast; if(const llvm::IntrinsicInst* II=llvm::dyn_cast(v)) From c411433e76e24a43d66f00102c7c5e1bef904c1f Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Mon, 19 Feb 2024 12:50:08 +0100 Subject: [PATCH 04/14] propagate the AS when building library calls in BuildLibCalls The changes in this commit are not complete. More getInt8PtrTy() calls need to be changed --- llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 36 ++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp index 5fb4ee1cac52..a8be3050492c 100644 --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -1460,7 +1460,7 @@ Value *llvm::emitStrDup(Value *Ptr, IRBuilderBase &B, Value *llvm::emitStrChr(Value *Ptr, char C, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Ptr->getType()->getPointerAddressSpace()); Type *IntTy = getIntTy(B, TLI); return emitLibCall(LibFunc_strchr, I8Ptr, {I8Ptr, IntTy}, {castToCStr(Ptr, B), ConstantInt::get(IntTy, C)}, B, TLI); @@ -1485,14 +1485,14 @@ Value *llvm::emitStrCpy(Value *Dst, Value *Src, IRBuilderBase &B, Value *llvm::emitStpCpy(Value *Dst, Value *Src, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dst->getType()->getPointerAddressSpace()); return emitLibCall(LibFunc_stpcpy, I8Ptr, {I8Ptr, I8Ptr}, {castToCStr(Dst, B), castToCStr(Src, B)}, B, TLI); } Value *llvm::emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dst->getType()->getPointerAddressSpace()); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall(LibFunc_strncpy, I8Ptr, {I8Ptr, I8Ptr, SizeTTy}, {castToCStr(Dst, B), castToCStr(Src, B), Len}, B, TLI); @@ -1500,7 +1500,7 @@ Value *llvm::emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilderBase &B, Value *llvm::emitStpNCpy(Value *Dst, Value *Src, Value *Len, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dst->getType()->getPointerAddressSpace()); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall(LibFunc_stpncpy, I8Ptr, {I8Ptr, I8Ptr, SizeTTy}, {castToCStr(Dst, B), castToCStr(Src, B), Len}, B, TLI); @@ -1516,7 +1516,7 @@ Value *llvm::emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, AttributeList AS; AS = AttributeList::get(M->getContext(), AttributeList::FunctionIndex, Attribute::NoUnwind); - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dst->getType()->getPointerAddressSpace()); Type *SizeTTy = getSizeTTy(B, TLI); FunctionCallee MemCpy = getOrInsertLibFunc(M, *TLI, LibFunc_memcpy_chk, AttributeList::get(M->getContext(), AS), I8Ptr, @@ -1532,7 +1532,7 @@ Value *llvm::emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, Value *llvm::emitMemPCpy(Value *Dst, Value *Src, Value *Len, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dst->getType()->getPointerAddressSpace()); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall(LibFunc_mempcpy, I8Ptr, {I8Ptr, I8Ptr, SizeTTy}, @@ -1541,7 +1541,7 @@ Value *llvm::emitMemPCpy(Value *Dst, Value *Src, Value *Len, IRBuilderBase &B, Value *llvm::emitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Ptr->getType()->getPointerAddressSpace()); Type *IntTy = getIntTy(B, TLI); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall(LibFunc_memchr, I8Ptr, @@ -1551,7 +1551,7 @@ Value *llvm::emitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilderBase &B, Value *llvm::emitMemRChr(Value *Ptr, Value *Val, Value *Len, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Ptr->getType()->getPointerAddressSpace()); Type *IntTy = getIntTy(B, TLI); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall(LibFunc_memrchr, I8Ptr, @@ -1561,7 +1561,7 @@ Value *llvm::emitMemRChr(Value *Ptr, Value *Val, Value *Len, IRBuilderBase &B, Value *llvm::emitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Ptr1->getType()->getPointerAddressSpace()); Type *IntTy = getIntTy(B, TLI); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall(LibFunc_memcmp, IntTy, @@ -1571,7 +1571,7 @@ Value *llvm::emitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilderBase &B, Value *llvm::emitBCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Ptr1->getType()->getPointerAddressSpace()); Type *IntTy = getIntTy(B, TLI); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall(LibFunc_bcmp, IntTy, @@ -1581,7 +1581,7 @@ Value *llvm::emitBCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilderBase &B, Value *llvm::emitMemCCpy(Value *Ptr1, Value *Ptr2, Value *Val, Value *Len, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Ptr1->getType()->getPointerAddressSpace()); Type *IntTy = getIntTy(B, TLI); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall(LibFunc_memccpy, I8Ptr, @@ -1592,7 +1592,7 @@ Value *llvm::emitMemCCpy(Value *Ptr1, Value *Ptr2, Value *Val, Value *Len, Value *llvm::emitSNPrintf(Value *Dest, Value *Size, Value *Fmt, ArrayRef VariadicArgs, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dest->getType()->getPointerAddressSpace()); Type *IntTy = getIntTy(B, TLI); Type *SizeTTy = getSizeTTy(B, TLI); SmallVector Args{castToCStr(Dest, B), Size, castToCStr(Fmt, B)}; @@ -1605,7 +1605,7 @@ Value *llvm::emitSNPrintf(Value *Dest, Value *Size, Value *Fmt, Value *llvm::emitSPrintf(Value *Dest, Value *Fmt, ArrayRef VariadicArgs, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dest->getType()->getPointerAddressSpace()); Type *IntTy = getIntTy(B, TLI); SmallVector Args{castToCStr(Dest, B), castToCStr(Fmt, B)}; llvm::append_range(Args, VariadicArgs); @@ -1623,7 +1623,7 @@ Value *llvm::emitStrCat(Value *Dest, Value *Src, IRBuilderBase &B, Value *llvm::emitStrLCpy(Value *Dest, Value *Src, Value *Size, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dest->getType()->getPointerAddressSpace()); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall(LibFunc_strlcpy, SizeTTy, {I8Ptr, I8Ptr, SizeTTy}, @@ -1632,7 +1632,7 @@ Value *llvm::emitStrLCpy(Value *Dest, Value *Src, Value *Size, IRBuilderBase &B, Value *llvm::emitStrLCat(Value *Dest, Value *Src, Value *Size, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dest->getType()->getPointerAddressSpace()); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall(LibFunc_strlcat, SizeTTy, {I8Ptr, I8Ptr, SizeTTy}, @@ -1641,7 +1641,7 @@ Value *llvm::emitStrLCat(Value *Dest, Value *Src, Value *Size, IRBuilderBase &B, Value *llvm::emitStrNCat(Value *Dest, Value *Src, Value *Size, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dest->getType()->getPointerAddressSpace()); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall(LibFunc_strncat, I8Ptr, {I8Ptr, I8Ptr, SizeTTy}, @@ -1650,7 +1650,7 @@ Value *llvm::emitStrNCat(Value *Dest, Value *Src, Value *Size, IRBuilderBase &B, Value *llvm::emitVSNPrintf(Value *Dest, Value *Size, Value *Fmt, Value *VAList, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dest->getType()->getPointerAddressSpace()); Type *IntTy = getIntTy(B, TLI); Type *SizeTTy = getSizeTTy(B, TLI); return emitLibCall( @@ -1661,7 +1661,7 @@ Value *llvm::emitVSNPrintf(Value *Dest, Value *Size, Value *Fmt, Value *VAList, Value *llvm::emitVSPrintf(Value *Dest, Value *Fmt, Value *VAList, IRBuilderBase &B, const TargetLibraryInfo *TLI) { - Type *I8Ptr = B.getInt8PtrTy(); + Type *I8Ptr = B.getInt8PtrTy(Dest->getType()->getPointerAddressSpace()); Type *IntTy = getIntTy(B, TLI); return emitLibCall(LibFunc_vsprintf, IntTy, {I8Ptr, I8Ptr, VAList->getType()}, From a258693f68b64281148c20c0bd401d0a830e67f8 Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Mon, 19 Feb 2024 17:07:49 +0100 Subject: [PATCH 05/14] llvm: make SimplifyLibCalls more AS-aware --- llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 7cec5300058f..44eb98484a16 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1480,12 +1480,12 @@ static Value *optimizeMemCmpConstantSize(CallInst *CI, Value *LHS, Value *RHS, // First, see if we can fold either argument to a constant. Value *LHSV = nullptr; if (auto *LHSC = dyn_cast(LHS)) { - LHSC = ConstantExpr::getBitCast(LHSC, IntType->getPointerTo()); + LHSC = ConstantExpr::getBitCast(LHSC, IntType->getPointerTo(LHSC->getType()->getPointerAddressSpace())); LHSV = ConstantFoldLoadFromConstPtr(LHSC, IntType, DL); } Value *RHSV = nullptr; if (auto *RHSC = dyn_cast(RHS)) { - RHSC = ConstantExpr::getBitCast(RHSC, IntType->getPointerTo()); + RHSC = ConstantExpr::getBitCast(RHSC, IntType->getPointerTo(RHSC->getType()->getPointerAddressSpace())); RHSV = ConstantFoldLoadFromConstPtr(RHSC, IntType, DL); } From 4cf27dfca8fe3558fd68e8e4067dd70cb81fdfcd Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Tue, 23 Apr 2024 13:09:35 +0200 Subject: [PATCH 06/14] Fix assertions to take the address space into account --- llvm/include/llvm/Cheerp/Utility.h | 4 ++-- llvm/lib/CheerpWriter/PreExecute.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/Cheerp/Utility.h b/llvm/include/llvm/Cheerp/Utility.h index d135194bd600..81576f4787a6 100644 --- a/llvm/include/llvm/Cheerp/Utility.h +++ b/llvm/include/llvm/Cheerp/Utility.h @@ -115,9 +115,9 @@ inline bool isValidVoidPtrSource(const llvm::Value* val) inline llvm::Type* getElementType(llvm::Type* t, llvm::Type* candidate) { - if(llvm::isa(t)) + if(auto* pt = llvm::dyn_cast(t)) { - assert(candidate && candidate->getPointerTo() == t); + assert(candidate && candidate->getPointerTo(pt->getAddressSpace()) == pt); return candidate; } else if (t->isVectorTy()) diff --git a/llvm/lib/CheerpWriter/PreExecute.cpp b/llvm/lib/CheerpWriter/PreExecute.cpp index 08e2eb474ac6..47239ba4eab3 100644 --- a/llvm/lib/CheerpWriter/PreExecute.cpp +++ b/llvm/lib/CheerpWriter/PreExecute.cpp @@ -664,7 +664,7 @@ Constant* PreExecute::findPointerFromGlobal(const DataLayout* DL, if (!typeFound) return NULL; Constant* GEP = ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Indices); - assert(GEP->getType() == typeFound->getPointerTo()); + assert(GEP->getType() == typeFound->getPointerTo(GEP->getType()->getPointerAddressSpace())); if(GEP->getType() != memType) return ConstantExpr::getBitCast(GEP, memType); return GEP; From bd45383c8ca85982975745c6701a854872824c58 Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Wed, 24 Apr 2024 17:23:48 +0200 Subject: [PATCH 07/14] TypeOptimizer: support pointers with non-default address spaces --- llvm/lib/CheerpUtils/TypeOptimizer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/lib/CheerpUtils/TypeOptimizer.cpp b/llvm/lib/CheerpUtils/TypeOptimizer.cpp index 44ff3f723fe7..df9c6668485d 100644 --- a/llvm/lib/CheerpUtils/TypeOptimizer.cpp +++ b/llvm/lib/CheerpUtils/TypeOptimizer.cpp @@ -749,12 +749,12 @@ TypeOptimizer::TypeMappingInfo TypeOptimizer::rewriteType(Type* t) if(newType->isArrayTy()) { // It's never a good idea to use pointers to array, we may end up creating wrapper arrays for arrays - return CacheAndReturn(PointerType::get(newType->getArrayElementType(), 0), TypeMappingInfo::POINTER_FROM_ARRAY); + return CacheAndReturn(PointerType::get(newType->getArrayElementType(), pt->getAddressSpace()), TypeMappingInfo::POINTER_FROM_ARRAY); } else if(newType == elementType) return CacheAndReturn(pt, TypeMappingInfo::IDENTICAL); else - return CacheAndReturn(PointerType::get(newType, 0), TypeMappingInfo::IDENTICAL); + return CacheAndReturn(PointerType::get(newType, pt->getPointerAddressSpace()), TypeMappingInfo::IDENTICAL); } if(ArrayType* at=dyn_cast(t)) { @@ -2070,7 +2070,7 @@ void TypeOptimizer::rewriteFunction(Function* F) { // In this case we need to rewrite the allocated type and use that directly // Moreover, we need to generate a GEP that will be used instead of this alloca - Type* newPtrType = PointerType::get(newAllocatedType, 0); + Type* newPtrType = PointerType::get(newAllocatedType, AI->getAddressSpace()); I.mutateType(newPtrType); Type* Int32 = IntegerType::get(I.getType()->getContext(), 32); Value* Zero = ConstantInt::get(Int32, 0); @@ -2192,7 +2192,7 @@ Constant* TypeOptimizer::rewriteGlobal(GlobalVariable* GV) if(newInfo.elementMappingKind == TypeMappingInfo::POINTER_FROM_ARRAY) { Type* newAllocatedType = rewriteType(GV->getValueType()); - Type* newPtrType = PointerType::get(newAllocatedType, 0); + Type* newPtrType = PointerType::get(newAllocatedType, GV->getAddressSpace()); GV->mutateType(newPtrType); Type* Int32 = IntegerType::get(GV->getType()->getContext(), 32); Value* Zero = ConstantInt::get(Int32, 0); From 9005632e6bb6be5cedf104fac2bffd65eb59bf1d Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Wed, 24 Apr 2024 17:24:22 +0200 Subject: [PATCH 08/14] Utility: support AddrSpaceCast in replaceCallOfBitCastWithBitCastOfCall --- llvm/lib/CheerpUtils/Utility.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/llvm/lib/CheerpUtils/Utility.cpp b/llvm/lib/CheerpUtils/Utility.cpp index c42195e13501..ee990616456c 100644 --- a/llvm/lib/CheerpUtils/Utility.cpp +++ b/llvm/lib/CheerpUtils/Utility.cpp @@ -1224,6 +1224,12 @@ bool replaceCallOfBitCastWithBitCastOfCall(CallBase& callInst, bool mayFail, boo assert(performPtrIntConversions); return new PtrToIntInst(src, newType, "", insertPoint); } else if(oldType->isPointerTy() && newType->isPointerTy()) { + if (oldType->getPointerAddressSpace() != newType->getPointerAddressSpace()) { + oldType = PointerType::getWithSamePointeeType(cast(oldType), newType->getPointerAddressSpace()); + src = new AddrSpaceCastInst(src, oldType, "", insertPoint); + if (oldType == newType) + return src; + } return new BitCastInst(src, newType, "", insertPoint); } else if(oldType->isIntegerTy() && newType->isIntegerTy()) { if(oldType->getIntegerBitWidth() < newType->getIntegerBitWidth()) @@ -1248,7 +1254,7 @@ bool replaceCallOfBitCastWithBitCastOfCall(CallBase& callInst, bool mayFail, boo return false; } - if (bitCast->getOpcode() != Instruction::BitCast) + if (bitCast->getOpcode() != Instruction::BitCast && bitCast->getOpcode() != Instruction::AddrSpaceCast) { assert(mayFail && "ConstantExpr BitCast expected"); return false; From 78bc3902c2ba67c05cd19a5126b32f54f6c4a111 Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Thu, 25 Apr 2024 14:27:33 +0200 Subject: [PATCH 09/14] StructMemFuncLowering: support address spaces --- .../lib/CheerpUtils/StructMemFuncLowering.cpp | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/llvm/lib/CheerpUtils/StructMemFuncLowering.cpp b/llvm/lib/CheerpUtils/StructMemFuncLowering.cpp index 511bf43d4ba7..34260dea768d 100644 --- a/llvm/lib/CheerpUtils/StructMemFuncLowering.cpp +++ b/llvm/lib/CheerpUtils/StructMemFuncLowering.cpp @@ -48,7 +48,7 @@ void StructMemFuncLowering::recursiveCopy(IRBuilder<>* IRB, Value* baseDst, Valu // For aggregates we push a new index and overwrite it for each element if(StructType* ST=dyn_cast(curType)) { - assert(baseDst->getType() == containingType->getPointerTo()); + assert(baseDst->getType() == containingType->getPointerTo(baseDst->getType()->getPointerAddressSpace())); if (ST->hasByteLayout()) return createMemFunc(IRB, baseDst, baseSrc, containingType, DL->getTypeAllocSize(curType), indexes); indexes.push_back(NULL); @@ -100,13 +100,13 @@ void StructMemFuncLowering::recursiveCopy(IRBuilder<>* IRB, Value* baseDst, Valu Value* elementSrc = baseSrc; Value* elementDst = baseDst; - assert(baseSrc->getType() == containingType->getPointerTo()); + assert(baseSrc->getType() == containingType->getPointerTo(baseSrc->getType()->getPointerAddressSpace())); assert(baseSrc->getType() == baseDst->getType()); elementSrc = IRB->CreateGEP(containingType, baseSrc, indexes); elementDst = IRB->CreateGEP(containingType, baseDst, indexes); Type* loadType = GetElementPtrInst::getIndexedType(containingType, indexes); - assert(loadType->getPointerTo() == elementSrc->getType()); + assert(loadType->getPointerTo(elementSrc->getType()->getPointerAddressSpace()) == elementSrc->getType()); Instruction* element = IRB->CreateAlignedLoad(loadType, elementSrc, MaybeAlign(baseAlign)); MDNode* newAliasScope = NULL; @@ -187,7 +187,7 @@ void StructMemFuncLowering::recursiveReset(IRBuilder<>* IRB, Value* baseDst, Val computedResetVal=IRB->CreateShl(computedResetVal, 8); computedResetVal=IRB->CreateOr(computedResetVal, expandedResetVal); } - assert(containingType->getPointerTo() == baseDst->getType()); + assert(containingType->getPointerTo(baseDst->getType()->getPointerAddressSpace()) == baseDst->getType()); Value* elementDst = IRB->CreateGEP(containingType, baseDst, indexes); IRB->CreateAlignedStore(computedResetVal, elementDst, MaybeAlign(baseAlign)); } @@ -208,7 +208,7 @@ void StructMemFuncLowering::recursiveReset(IRBuilder<>* IRB, Value* baseDst, Val Function* splatIntrinsic = Intrinsic::getDeclaration(BB->getModule(), Intrinsic::cheerp_wasm_splat, argTypes); computedResetVal = IRB->CreateCall(splatIntrinsic, { resetVal }); } - assert(containingType->getPointerTo() == baseDst->getType()); + assert(containingType->getPointerTo(baseDst->getType()->getPointerAddressSpace()) == baseDst->getType()); Value* elementDst = IRB->CreateGEP(containingType, baseDst, indexes); IRB->CreateAlignedStore(computedResetVal, elementDst, MaybeAlign(baseAlign)); } @@ -229,7 +229,7 @@ void StructMemFuncLowering::recursiveReset(IRBuilder<>* IRB, Value* baseDst, Val floatResetVal = ConstantFP::get(curType->getContext(), APFloat(APFloat::IEEEsingle(), floatConstant)); else floatResetVal = ConstantFP::get(curType->getContext(), APFloat(APFloat::IEEEdouble(), floatConstant)); - assert(containingType->getPointerTo() == baseDst->getType()); + assert(containingType->getPointerTo(baseDst->getType()->getPointerAddressSpace()) == baseDst->getType()); Value* elementDst = IRB->CreateGEP(containingType, baseDst, indexes); IRB->CreateAlignedStore(floatResetVal, elementDst, MaybeAlign(baseAlign)); } @@ -238,7 +238,7 @@ void StructMemFuncLowering::recursiveReset(IRBuilder<>* IRB, Value* baseDst, Val // Only constant NULL is supported // TODO: Stop non constant in the frontend assert(cast( resetVal )->getZExtValue() == 0); - assert(containingType->getPointerTo() == baseDst->getType()); + assert(containingType->getPointerTo(baseDst->getType()->getPointerAddressSpace()) == baseDst->getType()); Value* elementDst = IRB->CreateGEP(containingType, baseDst, indexes); IRB->CreateAlignedStore(ConstantPointerNull::get(PT), elementDst, MaybeAlign(baseAlign)); } @@ -277,16 +277,17 @@ void StructMemFuncLowering::createGenericLoop(IRBuilder<>* IRB, BasicBlock* prev PHINode* dstPHI = NULL; Value* srcVal = src; Value* dstVal = dst; + unsigned AS = dst->getType()->getPointerAddressSpace(); if(needsLoop) { if(mode != MEMSET) { - srcPHI = IRB->CreatePHI(pointedType->getPointerTo(), 2); + srcPHI = IRB->CreatePHI(pointedType->getPointerTo(AS), 2); srcPHI->addIncoming(src, previousBlock); srcVal = srcPHI; } - dstPHI = IRB->CreatePHI(pointedType->getPointerTo(), 2); + dstPHI = IRB->CreatePHI(pointedType->getPointerTo(AS), 2); dstPHI->addIncoming(dst, previousBlock); dstVal = dstPHI; baseAlign = DL->getABITypeAlignment(pointedType); @@ -439,6 +440,7 @@ bool StructMemFuncLowering::runOnBlock(BasicBlock& BB, bool asmjs) //In MEMSET mode src is the value to be written Value* src=CI->getOperand(1); Value* size=CI->getOperand(2); + unsigned AS = dst->getType()->getPointerAddressSpace(); Type* int32Type = IntegerType::get(BB.getContext(), 32); assert(alignInt != 0); // Do not inline memory intrinsics with a large or non-constant size @@ -497,10 +499,10 @@ bool StructMemFuncLowering::runOnBlock(BasicBlock& BB, bool asmjs) elemSize = sizeInt - (sizeInt % elemSize); } IRBuilder<> IRB(CI); - dst = IRB.CreateBitCast(dst, pointedType->getPointerTo()); + dst = IRB.CreateBitCast(dst, pointedType->getPointerTo(AS)); // In MEMSET mode src is the i8 value to write if(mode != MEMSET) - src = IRB.CreateBitCast(src, pointedType->getPointerTo()); + src = IRB.CreateBitCast(src, pointedType->getPointerTo(AS)); // We have found a good alignment above, check if we need to split the intrinsic to deal with an unaligned tail if(uint32_t tailSize = sizeInt % elemSize) { IRBuilder<> IRB(CI->getNextNode()); From 52039fd385072510c91ef86fda27fa34a7cf2320 Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Wed, 15 May 2024 12:07:22 +0200 Subject: [PATCH 10/14] AllocaArrays: forward the original AS to the new alloca --- llvm/lib/CheerpUtils/PointerPasses.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/CheerpUtils/PointerPasses.cpp b/llvm/lib/CheerpUtils/PointerPasses.cpp index 82dbf4eb9a26..95753df7a2d7 100644 --- a/llvm/lib/CheerpUtils/PointerPasses.cpp +++ b/llvm/lib/CheerpUtils/PointerPasses.cpp @@ -90,7 +90,7 @@ bool AllocaArrays::replaceAlloca(AllocaInst* ai, cheerp::GlobalDepsAnalyzer& gda } llvm::Type * at = llvm::ArrayType::get( ai->getAllocatedType(), ci->getZExtValue() ); - AllocaInst * newAi = new AllocaInst( at, 0, nullptr, ai->getAlign() ); + AllocaInst * newAi = new AllocaInst( at, ai->getAddressSpace(), nullptr, ai->getAlign() ); newAi->insertAfter( ai ); ai->removeFromParent(); newAi->takeName(ai); From 3ee04bccc863004fe85ad3cdca0af336e8813a4a Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Fri, 14 Jun 2024 11:26:32 +0200 Subject: [PATCH 11/14] fix(AllocaMerging): put the new alloca in the original AS --- llvm/lib/CheerpUtils/AllocaMerging.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/llvm/lib/CheerpUtils/AllocaMerging.cpp b/llvm/lib/CheerpUtils/AllocaMerging.cpp index f4830ac561a4..e868c4217c51 100644 --- a/llvm/lib/CheerpUtils/AllocaMerging.cpp +++ b/llvm/lib/CheerpUtils/AllocaMerging.cpp @@ -529,7 +529,9 @@ bool AllocaArraysMerging::runOnFunction(Function& F, cheerp::PointerAnalyzer& PA Instruction* insertionPoint = nullptr; for(auto it: arraysToMerge) insertionPoint = cheerp::findCommonInsertionPoint(nullptr, DT, insertionPoint, it.first); - AllocaInst* newAlloca = new AllocaInst(newAllocaType, 0, "mergedArray", insertionPoint); + // TODO: make sure that all the arrays to merge have the same AS + unsigned AS = arraysToMerge.begin()->first->getAddressSpace(); + AllocaInst* newAlloca = new AllocaInst(newAllocaType, AS, "mergedArray", insertionPoint); Type* indexType = IntegerType::get(newAllocaType->getContext(), 32); // Change every use of every merged array with an appropiate GEP for(auto it: arraysToMerge) From 7acc5a37168bf2032b4ebc0c634a9e83d858a881 Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Mon, 22 Jul 2024 09:13:37 +0200 Subject: [PATCH 12/14] fix(TypeOptimizer): propagate function AS when recreating one --- llvm/lib/CheerpUtils/TypeOptimizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/CheerpUtils/TypeOptimizer.cpp b/llvm/lib/CheerpUtils/TypeOptimizer.cpp index df9c6668485d..2ff096461569 100644 --- a/llvm/lib/CheerpUtils/TypeOptimizer.cpp +++ b/llvm/lib/CheerpUtils/TypeOptimizer.cpp @@ -1478,7 +1478,7 @@ Function* TypeOptimizer::rewriteFunctionSignature(Function* F) F->setAttributes(PAL); // Create the new function body and insert it into the module. - Function *NF = Function::Create(newFuncType, F->getLinkage(), F->getName()); + Function *NF = Function::Create(newFuncType, F->getLinkage(), F->getAddressSpace(), F->getName()); NF->copyAttributesFrom(F); NF->copyMetadata(F, 0); From 2937e99bc4655cf3f7556260e61b8c8a39c48635 Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Mon, 29 Jul 2024 16:25:50 +0200 Subject: [PATCH 13/14] fix(CallConstructors): strip AS casts when retrieving the constructors --- llvm/lib/CheerpUtils/CallConstructors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/CheerpUtils/CallConstructors.cpp b/llvm/lib/CheerpUtils/CallConstructors.cpp index 230f0cc82c70..6df67ab1c618 100644 --- a/llvm/lib/CheerpUtils/CallConstructors.cpp +++ b/llvm/lib/CheerpUtils/CallConstructors.cpp @@ -57,7 +57,7 @@ PreservedAnalyses CallConstructorsPass::run(llvm::Module &M, llvm::ModuleAnalysi for (Constant* C: cheerp::getGlobalConstructors(M)) { - Builder.CreateCall(Ty, cast(C->getAggregateElement(1))); + Builder.CreateCall(Ty, cast(C->getAggregateElement(1)->stripPointerCastsSafe())); } Function* Main = getMainFunction(M); bool Wasi = Triple(M.getTargetTriple()).getOS() == Triple::WASI; From 15279c115baeb2b07756df07e574a6ca4af625eb Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Tue, 20 Aug 2024 13:01:51 +0200 Subject: [PATCH 14/14] fix(Writer): treat ascast as bitcast for inlining --- llvm/lib/CheerpUtils/Utility.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/CheerpUtils/Utility.cpp b/llvm/lib/CheerpUtils/Utility.cpp index ee990616456c..163d2a84256b 100644 --- a/llvm/lib/CheerpUtils/Utility.cpp +++ b/llvm/lib/CheerpUtils/Utility.cpp @@ -289,7 +289,7 @@ bool InlineableCache::isInlineableImpl(const Instruction& I) // Split regular, regular, and byte layout are always inlined. return true; } - else if(I.getOpcode()==Instruction::BitCast) + else if(I.getOpcode()==Instruction::BitCast || I.getOpcode()==Instruction::AddrSpaceCast) { if (!I.getType()->isPointerTy()) { @@ -388,6 +388,7 @@ bool InlineableCache::isInlineableImpl(const Instruction& I) // Reached the direct user if(!nextInst->hasOneUse() && (nextInst->getOpcode() == Instruction::BitCast || + nextInst->getOpcode() == Instruction::AddrSpaceCast || nextInst->getOpcode() == Instruction::Trunc)) { // Avoid interacting with the bitcast/trunc logic for now