diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -1510,13 +1510,14 @@ /// there is any change. The flag \p ChangeDroppable indicates if dropppable /// uses should be changed too. bool changeValueAfterManifest(Value &V, Value &NV, - bool ChangeDroppable = true) { + bool ChangeDroppable = true, + bool AllowDuplicates = false) { auto &Entry = ToBeChangedValues[&V]; Value *&CurNV = Entry.first; if (CurNV && (CurNV->stripPointerCasts() == NV.stripPointerCasts() || isa(CurNV))) return false; - assert((!CurNV || CurNV == &NV || isa(NV)) && + assert((AllowDuplicates || !CurNV || CurNV == &NV || isa(NV)) && "Value replacement was registered twice with different values!"); CurNV = &NV; Entry.second = ChangeDroppable; @@ -4862,6 +4863,34 @@ static const char ID; }; +/// An abstract interface for address space information. +struct AAAddressSpaceInfo + : public StateWrapper, AbstractAttribute> { + AAAddressSpaceInfo(const IRPosition &IRP, Attributor &A) + : StateWrapper, AbstractAttribute>(IRP) {} + + virtual uint32_t getAddressSpace() const = 0; + + /// Create an abstract attribute view for the position \p IRP. + static AAAddressSpaceInfo &createForPosition(const IRPosition &IRP, + Attributor &A); + + /// See AbstractAttribute::getName() + const std::string getName() const override { return "AAAddressSpaceInfo"; } + + /// See AbstractAttribute::getIdAddr() + const char *getIdAddr() const override { return &ID; } + + /// This function should return true if the type of the \p AA is + /// AAAssumptionInfo + static bool classof(const AbstractAttribute *AA) { + return (AA->getIdAddr() == &ID); + } + + /// Unique ID (due to the unique address) + static const char ID; +}; + /// An abstract attribute for getting assumption information. struct AAAssumptionInfo : public StateWrapper, AbstractAttribute, diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -2890,11 +2890,16 @@ if (isa(I)) { getOrCreateAAFor( IRPosition::value(*cast(I).getPointerOperand())); + getOrCreateAAFor( + IRPosition::value(*cast(I).getPointerOperand())); if (SimplifyAllLoads) getOrCreateAAFor(IRPosition::value(I)); - } else + } else { getOrCreateAAFor( IRPosition::value(*cast(I).getPointerOperand())); + getOrCreateAAFor( + IRPosition::value(*cast(I).getPointerOperand())); + } return true; }; Success = checkForAllInstructionsImpl( diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -160,6 +160,7 @@ PIPE_OPERATOR(AAFunctionReachability) PIPE_OPERATOR(AAPointerInfo) PIPE_OPERATOR(AAAssumptionInfo) +PIPE_OPERATOR(AAAddressSpaceInfo) #undef PIPE_OPERATOR @@ -9897,6 +9898,136 @@ DenseMap InstQueries; }; +/// ------------------------ Address Space Propagation ------------------------- +struct AAAddressSpaceInfoImpl : public AAAddressSpaceInfo { + AAAddressSpaceInfoImpl(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfo(IRP, A) {} + + uint32_t getAddressSpace() const override { + if (!isValidState()) + return getWorstState(); + return getAssumed(); + } + + /// See AbstractAttribute::initialize(...). + void initialize(Attributor &A) override { + assert(getAssociatedType()->isPointerTy() && + "Cannot deduce address space of value that is not a pointer"); + + A.getAAFor(*this, getIRPosition(), DepClassTy::NONE); + } + + ChangeStatus updateImpl(Attributor &A) override { + SmallVector Objects; + bool UsedAssumedInformation = false; + if (!AA::getAssumedUnderlyingObjects(A, getAssociatedValue(), Objects, *this, + getCtxI(), UsedAssumedInformation)) + return indicatePessimisticFixpoint(); + + // We can infer the address space if each underlying object has the same + // address space or at least one that is the same on the target. + uint32_t AddressSpace = getAssumed(); + for (Value *Obj : Objects) { + if (isa(Obj)) + continue; + + uint32_t NewAddressSpace = Obj->getType()->getPointerAddressSpace(); + + if (AddressSpace == getBestState()) { + AddressSpace = NewAddressSpace; + } else if (AddressSpace != NewAddressSpace) { + AddressSpace = getWorstState(); + break; + } + } + + return takeAssumedMinimum(AddressSpace).getAssumed() == AddressSpace + ? ChangeStatus::UNCHANGED + : ChangeStatus::CHANGED; + }; + + /// See AbstractAttribute::manifest(...). + ChangeStatus manifest(Attributor &A) override { + Instruction *CtxI = getCtxI(); + Value *AssociatedValue = &getAssociatedValue(); + if (!CtxI || getKnown() == getBestState() || + getKnown() == getAssociatedType()->getPointerAddressSpace()) + return ChangeStatus::UNCHANGED; + + Type *NewPtrTy = PointerType::getWithSamePointeeType( + cast(AssociatedValue->getType()), getKnown()); + Instruction *Cast = new AddrSpaceCastInst(AssociatedValue, NewPtrTy); + Cast->insertAfter(CtxI); + + // Cast the pointer to the inferred address space and replace the uses with + // it. If the pointer is considered dead don't bother removing it. + for (User *U : AssociatedValue->users()) { + const IRPosition &InstPos = IRPosition::inst(*cast(U)); + bool UsedAssumedInformation = false; + auto &LivenessAA = + A.getAAFor(*this, InstPos, DepClassTy::REQUIRED); + if (A.isAssumedDead(InstPos, this, &LivenessAA, UsedAssumedInformation)) + continue; + + if (auto *LI = dyn_cast(U)) { + Value *NewV = new LoadInst(LI->getType(), Cast, "", + LI->isVolatile(), LI->getAlign(), + LI->getOrdering(), LI->getSyncScopeID(), LI); + A.changeValueAfterManifest(*LI, *NewV, true, true); + A.deleteAfterManifest(*LI); + } else if (auto *SI = dyn_cast(U)) { + Value *NewV = new StoreInst( + SI->getValueOperand(), Cast, SI->isVolatile(), SI->getAlign(), + SI->getOrdering(), SI->getSyncScopeID(), SI); + A.changeValueAfterManifest(*SI, *NewV, true, true); + A.deleteAfterManifest(*SI); + } + } + + return ChangeStatus::CHANGED; + } + + /// See AbstractAttribute::getAsStr(). + const std::string getAsStr() const override { + return "Address Space: " + std::to_string(getAssumed()); + } +}; + +struct AAAddressSpaceInfoFloating final : AAAddressSpaceInfoImpl { + AAAddressSpaceInfoFloating(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfoImpl(IRP, A) {} + + void trackStatistics() const override {} +}; +struct AAAddressSpaceInfoReturned final : AAAddressSpaceInfoImpl { + AAAddressSpaceInfoReturned(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfoImpl(IRP, A) {} + + void trackStatistics() const override {} +}; +struct AAAddressSpaceInfoCallSiteReturned final : AAAddressSpaceInfoImpl { + AAAddressSpaceInfoCallSiteReturned(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfoImpl(IRP, A) {} + + void trackStatistics() const override {} +}; +struct AAAddressSpaceInfoArgument final : AAAddressSpaceInfoImpl { + AAAddressSpaceInfoArgument(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfoImpl(IRP, A) {} + + void trackStatistics() const override {} +}; +struct AAAddressSpaceInfoCallSiteArgument final : AAAddressSpaceInfoImpl { + AAAddressSpaceInfoCallSiteArgument(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfoImpl(IRP, A) {} + + ChangeStatus updateImpl(Attributor &A) override { + return ChangeStatus::UNCHANGED; + }; + + void trackStatistics() const override {} +}; + /// ---------------------- Assumption Propagation ------------------------------ struct AAAssumptionInfoImpl : public AAAssumptionInfo { AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A, @@ -10066,6 +10197,7 @@ const char AAFunctionReachability::ID = 0; const char AAPointerInfo::ID = 0; const char AAAssumptionInfo::ID = 0; +const char AAAddressSpaceInfo::ID = 0; // Macro magic to create the static generator function for attributes that // follow the naming scheme. @@ -10180,6 +10312,7 @@ CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialValues) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUndef) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPointerInfo) +CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAddressSpaceInfo) CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify) CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead) diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/alloca-as.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/alloca-as.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/alloca-as.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/alloca-as.ll @@ -65,6 +65,8 @@ ; IS__CGSCC_NPM-NEXT: [[ARG_PRIV:%.*]] = alloca i32, align 4, addrspace(7) ; IS__CGSCC_NPM-NEXT: store i32 [[TMP0]], i32 addrspace(7)* [[ARG_PRIV]], align 4 ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = addrspacecast i32 addrspace(7)* [[ARG_PRIV]] to i32* +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = addrspacecast i32* [[TMP1]] to i32 addrspace(7)* +; IS__CGSCC_NPM-NEXT: [[L1:%.*]] = load i32, i32 addrspace(7)* [[TMP2]], align 4 ; IS__CGSCC_NPM-NEXT: [[L:%.*]] = load i32, i32* [[TMP1]], align 4 ; IS__CGSCC_NPM-NEXT: call void @use(i32 [[TMP0]]) ; IS__CGSCC_NPM-NEXT: ret i32 [[TMP0]] diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll @@ -147,15 +147,15 @@ ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@unions ; IS__TUNIT_NPM-SAME: () #[[ATTR0]] { ; IS__TUNIT_NPM-NEXT: entry: -; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST1:%.*]] = bitcast %struct.MYstr* @mystr to i8* -; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST1]], align 8 -; IS__TUNIT_NPM-NEXT: [[MYSTR_0_12:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i64 0, i32 1 -; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_12]], align 8 -; IS__TUNIT_NPM-NEXT: call void @vfu1(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR0]] ; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST:%.*]] = bitcast %struct.MYstr* @mystr to i8* -; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i8, i8* [[MYSTR_CAST]], align 8 -; IS__TUNIT_NPM-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i64 0, i32 1 -; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[MYSTR_0_1]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST]], align 8 +; IS__TUNIT_NPM-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i64 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_1]], align 8 +; IS__TUNIT_NPM-NEXT: call void @vfu1(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR0]] +; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST1:%.*]] = bitcast %struct.MYstr* @mystr to i8* +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i8, i8* [[MYSTR_CAST1]], align 8 +; IS__TUNIT_NPM-NEXT: [[MYSTR_0_12:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i64 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[MYSTR_0_12]], align 8 ; IS__TUNIT_NPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2(i8 [[TMP2]], i32 [[TMP3]]) #[[ATTR2:[0-9]+]] ; IS__TUNIT_NPM-NEXT: ret i32 [[RESULT]] ; @@ -228,9 +228,9 @@ ; IS__CGSCC_NPM-NEXT: [[U_PRIV_0_1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i64 0, i32 1 ; IS__CGSCC_NPM-NEXT: [[Z:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 ; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 -; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* undef, align 4 ; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 0 -; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = load i8, i8* [[TMP4]], align 8 +; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = load i8, i8* undef, align 8 ; IS__CGSCC_NPM-NEXT: [[TMP6:%.*]] = zext i8 0 to i32 ; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = add i32 0, 99 ; IS__CGSCC_NPM-NEXT: ret i32 undef @@ -260,15 +260,15 @@ ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@unions_v2 ; IS__TUNIT_NPM-SAME: () #[[ATTR0]] { ; IS__TUNIT_NPM-NEXT: entry: -; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST1:%.*]] = bitcast %struct.MYstr* @mystr to i8* -; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST1]], align 8 -; IS__TUNIT_NPM-NEXT: [[MYSTR_0_12:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i64 0, i32 1 -; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_12]], align 8 -; IS__TUNIT_NPM-NEXT: call void @vfu1(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR0]] ; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST:%.*]] = bitcast %struct.MYstr* @mystr to i8* -; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i8, i8* [[MYSTR_CAST]], align 8 -; IS__TUNIT_NPM-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i64 0, i32 1 -; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[MYSTR_0_1]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST]], align 8 +; IS__TUNIT_NPM-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i64 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_1]], align 8 +; IS__TUNIT_NPM-NEXT: call void @vfu1(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR0]] +; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST1:%.*]] = bitcast %struct.MYstr* @mystr to i8* +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i8, i8* [[MYSTR_CAST1]], align 8 +; IS__TUNIT_NPM-NEXT: [[MYSTR_0_12:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i64 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[MYSTR_0_12]], align 8 ; IS__TUNIT_NPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(i8 [[TMP2]], i32 [[TMP3]]) #[[ATTR2]] ; IS__TUNIT_NPM-NEXT: ret i32 [[RESULT]] ; diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll b/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll @@ -115,11 +115,10 @@ ; IS__TUNIT_OPM: for.cond1: ; IS__TUNIT_OPM-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]] ; IS__TUNIT_OPM: if.end: -; IS__TUNIT_OPM-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4 ; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) #[[ATTR3]] ; IS__TUNIT_OPM-NEXT: store i32 [[CALL]], i32* [[P]], align 4 -; IS__TUNIT_OPM-NEXT: br label [[FOR_COND1]] +; IS__TUNIT_OPM-NEXT: br label [[FOR_COND1:%.*]] ; IS__TUNIT_OPM: exit: ; IS__TUNIT_OPM-NEXT: ret void ; @@ -131,10 +130,9 @@ ; IS__TUNIT_NPM: for.cond1: ; IS__TUNIT_NPM-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]] ; IS__TUNIT_NPM: if.end: -; IS__TUNIT_NPM-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] ; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4 ; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[P]], align 4 -; IS__TUNIT_NPM-NEXT: br label [[FOR_COND1]] +; IS__TUNIT_NPM-NEXT: br label [[FOR_COND1:%.*]] ; IS__TUNIT_NPM: exit: ; IS__TUNIT_NPM-NEXT: ret void ; diff --git a/llvm/test/Transforms/Attributor/address_space_info.ll b/llvm/test/Transforms/Attributor/address_space_info.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Attributor/address_space_info.ll @@ -0,0 +1,307 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals --prefix-filecheck-ir-name true +; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM +; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM +; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM +; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM + +define float @load_global_from_flat(float* %generic_scalar) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; CHECK-LABEL: define {{[^@]+}}@load_global_from_flat +; CHECK-SAME: (float* nocapture nofree readonly align 4 dereferenceable_or_null(4) [[GENERIC_SCALAR:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[TRUETMP0:%.*]] = addrspacecast float* [[GENERIC_SCALAR]] to float addrspace(1)* +; CHECK-NEXT: [[TRUETMP1:%.*]] = load float, float addrspace(1)* [[TRUETMP0]], align 4 +; CHECK-NEXT: ret float [[TRUETMP1]] +; + %tmp0 = addrspacecast float* %generic_scalar to float addrspace(1)* + %tmp1 = load float, float addrspace(1)* %tmp0 + ret float %tmp1 +} + +define float @load_constant_from_flat(float* %generic_scalar) #0 { +; +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; CHECK-LABEL: define {{[^@]+}}@load_constant_from_flat +; CHECK-SAME: (float* nocapture nofree readonly align 4 dereferenceable_or_null(4) [[GENERIC_SCALAR:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[TRUETMP0:%.*]] = addrspacecast float* [[GENERIC_SCALAR]] to float addrspace(4)* +; CHECK-NEXT: [[TRUETMP1:%.*]] = load float, float addrspace(4)* [[TRUETMP0]], align 4 +; CHECK-NEXT: ret float [[TRUETMP1]] +; + %tmp0 = addrspacecast float* %generic_scalar to float addrspace(4)* + %tmp1 = load float, float addrspace(4)* %tmp0 + ret float %tmp1 +} + +define float @load_group_from_flat(float* %generic_scalar) #0 { +; +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; CHECK-LABEL: define {{[^@]+}}@load_group_from_flat +; CHECK-SAME: (float* nocapture nofree readonly align 4 dereferenceable_or_null(4) [[GENERIC_SCALAR:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[TRUETMP0:%.*]] = addrspacecast float* [[GENERIC_SCALAR]] to float addrspace(3)* +; CHECK-NEXT: [[TRUETMP1:%.*]] = load float, float addrspace(3)* [[TRUETMP0]], align 4 +; CHECK-NEXT: ret float [[TRUETMP1]] +; + %tmp0 = addrspacecast float* %generic_scalar to float addrspace(3)* + %tmp1 = load float, float addrspace(3)* %tmp0 + ret float %tmp1 +} + +define float @load_private_from_flat(float* %generic_scalar) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; CHECK-LABEL: define {{[^@]+}}@load_private_from_flat +; CHECK-SAME: (float* nocapture nofree readonly align 4 dereferenceable_or_null(4) [[GENERIC_SCALAR:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[TRUETMP0:%.*]] = addrspacecast float* [[GENERIC_SCALAR]] to float addrspace(5)* +; CHECK-NEXT: [[TRUETMP1:%.*]] = load float, float addrspace(5)* [[TRUETMP0]], align 4 +; CHECK-NEXT: ret float [[TRUETMP1]] +; + %tmp0 = addrspacecast float* %generic_scalar to float addrspace(5)* + %tmp1 = load float, float addrspace(5)* %tmp0 + ret float %tmp1 +} + +define void @store_global_from_flat(float* %generic_scalar) #0 { +; +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@store_global_from_flat +; CHECK-SAME: (float* nocapture nofree writeonly align 4 dereferenceable_or_null(4) [[GENERIC_SCALAR:%.*]]) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: [[TRUETMP0:%.*]] = addrspacecast float* [[GENERIC_SCALAR]] to float addrspace(1)* +; CHECK-NEXT: store float 0.000000e+00, float addrspace(1)* [[TRUETMP0]], align 4 +; CHECK-NEXT: ret void +; + %tmp0 = addrspacecast float* %generic_scalar to float addrspace(1)* + store float 0.0, float addrspace(1)* %tmp0 + ret void +} + +define void @store_group_from_flat(float* %generic_scalar) #0 { +; +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@store_group_from_flat +; CHECK-SAME: (float* nocapture nofree writeonly align 4 dereferenceable_or_null(4) [[GENERIC_SCALAR:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[TRUETMP0:%.*]] = addrspacecast float* [[GENERIC_SCALAR]] to float addrspace(3)* +; CHECK-NEXT: store float 0.000000e+00, float addrspace(3)* [[TRUETMP0]], align 4 +; CHECK-NEXT: ret void +; + %tmp0 = addrspacecast float* %generic_scalar to float addrspace(3)* + store float 0.0, float addrspace(3)* %tmp0 + ret void +} + +define void @store_private_from_flat(float* %generic_scalar) #0 { +; +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@store_private_from_flat +; CHECK-SAME: (float* nocapture nofree writeonly align 4 dereferenceable_or_null(4) [[GENERIC_SCALAR:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[TRUETMP0:%.*]] = addrspacecast float* [[GENERIC_SCALAR]] to float addrspace(5)* +; CHECK-NEXT: store float 0.000000e+00, float addrspace(5)* [[TRUETMP0]], align 4 +; CHECK-NEXT: ret void +; + %tmp0 = addrspacecast float* %generic_scalar to float addrspace(5)* + store float 0.0, float addrspace(5)* %tmp0 + ret void +} + +; optimized to global load/store. + +define void @load_store_global(i32 addrspace(1)* nocapture %input, i32 addrspace(1)* nocapture %output) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@load_store_global +; CHECK-SAME: (i32 addrspace(1)* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[INPUT:%.*]], i32 addrspace(1)* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[OUTPUT:%.*]]) #[[ATTR2:[0-9]+]] { +; CHECK-NEXT: [[CAST0:%.*]] = addrspacecast i32 addrspace(1)* [[INPUT]] to i32* +; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast i32* [[CAST0]] to i32 addrspace(1)* +; CHECK-NEXT: [[CAST1:%.*]] = addrspacecast i32 addrspace(1)* [[OUTPUT]] to i32* +; CHECK-NEXT: [[TMP2:%.*]] = addrspacecast i32* [[CAST1]] to i32 addrspace(1)* +; CHECK-NEXT: [[VAL1:%.*]] = load i32, i32 addrspace(1)* [[TMP1]], align 4 +; CHECK-NEXT: store i32 [[VAL1]], i32 addrspace(1)* [[TMP2]], align 4 +; CHECK-NEXT: ret void +; + %cast0 = addrspacecast i32 addrspace(1)* %input to i32* + %cast1 = addrspacecast i32 addrspace(1)* %output to i32* + %val = load i32, i32* %cast0, align 4 + store i32 %val, i32* %cast1, align 4 + ret void +} + +; Optimized to group load/store. + +define void @load_store_group(i32 addrspace(3)* nocapture %input, i32 addrspace(3)* nocapture %output) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@load_store_group +; CHECK-SAME: (i32 addrspace(3)* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[INPUT:%.*]], i32 addrspace(3)* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[OUTPUT:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[TRUETMP0:%.*]] = addrspacecast i32 addrspace(3)* [[INPUT]] to i32* +; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast i32* [[TRUETMP0]] to i32 addrspace(3)* +; CHECK-NEXT: [[TRUETMP1:%.*]] = addrspacecast i32 addrspace(3)* [[OUTPUT]] to i32* +; CHECK-NEXT: [[TMP2:%.*]] = addrspacecast i32* [[TRUETMP1]] to i32 addrspace(3)* +; CHECK-NEXT: [[VAL1:%.*]] = load i32, i32 addrspace(3)* [[TMP1]], align 4 +; CHECK-NEXT: store i32 [[VAL1]], i32 addrspace(3)* [[TMP2]], align 4 +; CHECK-NEXT: ret void +; + %tmp0 = addrspacecast i32 addrspace(3)* %input to i32* + %tmp1 = addrspacecast i32 addrspace(3)* %output to i32* + %val = load i32, i32* %tmp0, align 4 + store i32 %val, i32* %tmp1, align 4 + ret void +} + +; Optimized to private load/store. + +define void @load_store_private(i32 addrspace(5)* nocapture %input, i32 addrspace(5)* nocapture %output) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@load_store_private +; CHECK-SAME: (i32 addrspace(5)* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[INPUT:%.*]], i32 addrspace(5)* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[OUTPUT:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[TRUETMP0:%.*]] = addrspacecast i32 addrspace(5)* [[INPUT]] to i32* +; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast i32* [[TRUETMP0]] to i32 addrspace(5)* +; CHECK-NEXT: [[TRUETMP1:%.*]] = addrspacecast i32 addrspace(5)* [[OUTPUT]] to i32* +; CHECK-NEXT: [[TMP2:%.*]] = addrspacecast i32* [[TRUETMP1]] to i32 addrspace(5)* +; CHECK-NEXT: [[VAL1:%.*]] = load i32, i32 addrspace(5)* [[TMP1]], align 4 +; CHECK-NEXT: store i32 [[VAL1]], i32 addrspace(5)* [[TMP2]], align 4 +; CHECK-NEXT: ret void +; + %tmp0 = addrspacecast i32 addrspace(5)* %input to i32* + %tmp1 = addrspacecast i32 addrspace(5)* %output to i32* + %val = load i32, i32* %tmp0, align 4 + store i32 %val, i32* %tmp1, align 4 + ret void +} + +; No optimization. flat load/store. + +define void @load_store_flat(i32* nocapture %input, i32* nocapture %output) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@load_store_flat +; CHECK-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[INPUT:%.*]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[OUTPUT:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[INPUT]], align 4 +; CHECK-NEXT: store i32 [[VAL]], i32* [[OUTPUT]], align 4 +; CHECK-NEXT: ret void +; + %val = load i32, i32* %input, align 4 + store i32 %val, i32* %output, align 4 + ret void +} + +define void @store_addrspacecast_ptr_value(i32 addrspace(1)* nocapture %input, i32* addrspace(1)* nocapture %output) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@store_addrspacecast_ptr_value +; CHECK-SAME: (i32 addrspace(1)* nocapture nofree writeonly [[INPUT:%.*]], i32* addrspace(1)* nocapture nofree noundef writeonly align 4 dereferenceable_or_null(8) [[OUTPUT:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CAST:%.*]] = addrspacecast i32 addrspace(1)* [[INPUT]] to i32* +; CHECK-NEXT: store i32* [[CAST]], i32* addrspace(1)* [[OUTPUT]], align 4 +; CHECK-NEXT: ret void +; + %cast = addrspacecast i32 addrspace(1)* %input to i32* + store i32* %cast, i32* addrspace(1)* %output, align 4 + ret void +} + +define i32 @atomicrmw_add_global_to_flat(i32 addrspace(1)* %global.ptr, i32 %y) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@atomicrmw_add_global_to_flat +; CHECK-SAME: (i32 addrspace(1)* nocapture nofree nonnull dereferenceable(4) [[GLOBAL_PTR:%.*]], i32 [[Y:%.*]]) #[[ATTR3:[0-9]+]] { +; CHECK-NEXT: [[CAST:%.*]] = addrspacecast i32 addrspace(1)* [[GLOBAL_PTR]] to i32* +; CHECK-NEXT: [[RET:%.*]] = atomicrmw add i32* [[CAST]], i32 [[Y]] seq_cst, align 4 +; CHECK-NEXT: ret i32 [[RET]] +; + %cast = addrspacecast i32 addrspace(1)* %global.ptr to i32* + %ret = atomicrmw add i32* %cast, i32 %y seq_cst + ret i32 %ret +} + +define i32 @atomicrmw_add_group_to_flat(i32 addrspace(3)* %group.ptr, i32 %y) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@atomicrmw_add_group_to_flat +; CHECK-SAME: (i32 addrspace(3)* nocapture nofree nonnull dereferenceable(4) [[GROUP_PTR:%.*]], i32 [[Y:%.*]]) #[[ATTR3]] { +; CHECK-NEXT: [[CAST:%.*]] = addrspacecast i32 addrspace(3)* [[GROUP_PTR]] to i32* +; CHECK-NEXT: [[RET:%.*]] = atomicrmw add i32* [[CAST]], i32 [[Y]] seq_cst, align 4 +; CHECK-NEXT: ret i32 [[RET]] +; + %cast = addrspacecast i32 addrspace(3)* %group.ptr to i32* + %ret = atomicrmw add i32* %cast, i32 %y seq_cst + ret i32 %ret +} + +define { i32, i1 } @cmpxchg_global_to_flat(i32 addrspace(1)* %global.ptr, i32 %cmp, i32 %val) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@cmpxchg_global_to_flat +; CHECK-SAME: (i32 addrspace(1)* nocapture nofree nonnull dereferenceable(4) [[GLOBAL_PTR:%.*]], i32 [[CMP:%.*]], i32 [[VAL:%.*]]) #[[ATTR3]] { +; CHECK-NEXT: [[CAST:%.*]] = addrspacecast i32 addrspace(1)* [[GLOBAL_PTR]] to i32* +; CHECK-NEXT: [[RET:%.*]] = cmpxchg i32* [[CAST]], i32 [[CMP]], i32 [[VAL]] seq_cst monotonic, align 4 +; CHECK-NEXT: ret { i32, i1 } [[RET]] +; + %cast = addrspacecast i32 addrspace(1)* %global.ptr to i32* + %ret = cmpxchg i32* %cast, i32 %cmp, i32 %val seq_cst monotonic + ret { i32, i1 } %ret +} + +define { i32, i1 } @cmpxchg_group_to_flat(i32 addrspace(3)* %group.ptr, i32 %cmp, i32 %val) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@cmpxchg_group_to_flat +; CHECK-SAME: (i32 addrspace(3)* nocapture nofree nonnull dereferenceable(4) [[GROUP_PTR:%.*]], i32 [[CMP:%.*]], i32 [[VAL:%.*]]) #[[ATTR3]] { +; CHECK-NEXT: [[CAST:%.*]] = addrspacecast i32 addrspace(3)* [[GROUP_PTR]] to i32* +; CHECK-NEXT: [[RET:%.*]] = cmpxchg i32* [[CAST]], i32 [[CMP]], i32 [[VAL]] seq_cst monotonic, align 4 +; CHECK-NEXT: ret { i32, i1 } [[RET]] +; + %cast = addrspacecast i32 addrspace(3)* %group.ptr to i32* + %ret = cmpxchg i32* %cast, i32 %cmp, i32 %val seq_cst monotonic + ret { i32, i1 } %ret +} + +; Not pointer operand +define { i32*, i1 } @cmpxchg_group_to_flat_wrong_operand(i32* addrspace(3)* %cas.ptr, i32 addrspace(3)* %cmp.ptr, i32* %val) #0 { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@cmpxchg_group_to_flat_wrong_operand +; CHECK-SAME: (i32* addrspace(3)* nocapture nofree noundef dereferenceable_or_null(8) [[CAS_PTR:%.*]], i32 addrspace(3)* nofree [[CMP_PTR:%.*]], i32* nofree [[VAL:%.*]]) #[[ATTR3]] { +; CHECK-NEXT: [[CAST_CMP:%.*]] = addrspacecast i32 addrspace(3)* [[CMP_PTR]] to i32* +; CHECK-NEXT: [[RET:%.*]] = cmpxchg i32* addrspace(3)* [[CAS_PTR]], i32* [[CAST_CMP]], i32* [[VAL]] seq_cst monotonic, align 8 +; CHECK-NEXT: ret { i32*, i1 } [[RET]] +; + %cast.cmp = addrspacecast i32 addrspace(3)* %cmp.ptr to i32* + %ret = cmpxchg i32* addrspace(3)* %cas.ptr, i32* %cast.cmp, i32* %val seq_cst monotonic + ret { i32*, i1 } %ret +} + +; Null pointer in local addr space + +define void @local_nullptr(i32 addrspace(1)* nocapture %results, i8 addrspace(3)* %a) { +; +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@local_nullptr +; CHECK-SAME: (i32 addrspace(1)* nocapture nofree noundef writeonly align 4 dereferenceable_or_null(4) [[RESULTS:%.*]], i8 addrspace(3)* nofree writeonly [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i8 addrspace(3)* [[A]], addrspacecast (i8 addrspace(5)* null to i8 addrspace(3)*) +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TOBOOL]] to i32 +; CHECK-NEXT: store i32 [[CONV]], i32 addrspace(1)* [[RESULTS]], align 4 +; CHECK-NEXT: ret void +; +entry: + %tobool = icmp ne i8 addrspace(3)* %a, addrspacecast (i8 addrspace(5)* null to i8 addrspace(3)*) + %conv = zext i1 %tobool to i32 + store i32 %conv, i32 addrspace(1)* %results, align 4 + ret void +} + +attributes #0 = { nounwind } + + + + +;. +; CHECK: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } +; CHECK: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } +; CHECK: attributes #[[ATTR2]] = { argmemonly nofree norecurse nosync nounwind willreturn } +; CHECK: attributes #[[ATTR3]] = { argmemonly nofree norecurse nounwind willreturn } +;. diff --git a/llvm/test/Transforms/Attributor/callbacks.ll b/llvm/test/Transforms/Attributor/callbacks.ll --- a/llvm/test/Transforms/Attributor/callbacks.ll +++ b/llvm/test/Transforms/Attributor/callbacks.ll @@ -22,7 +22,6 @@ ; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__TUNIT_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__TUNIT_OPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__TUNIT_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__TUNIT_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 undef, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -34,7 +33,6 @@ ; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__TUNIT_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__TUNIT_NPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__TUNIT_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__TUNIT_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 undef, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -46,7 +44,6 @@ ; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__CGSCC_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 noundef 99, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -58,7 +55,6 @@ ; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__CGSCC_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__CGSCC_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__CGSCC_NPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__CGSCC_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__CGSCC_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 noundef 99, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -122,7 +118,6 @@ ; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__TUNIT_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__TUNIT_OPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__TUNIT_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__TUNIT_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -134,7 +129,6 @@ ; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__TUNIT_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__TUNIT_NPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__TUNIT_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__TUNIT_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -146,7 +140,6 @@ ; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__CGSCC_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -158,7 +151,6 @@ ; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__CGSCC_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__CGSCC_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__CGSCC_NPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__CGSCC_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__CGSCC_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -222,7 +214,6 @@ ; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__TUNIT_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__TUNIT_OPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__TUNIT_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__TUNIT_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -234,7 +225,6 @@ ; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__TUNIT_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__TUNIT_NPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__TUNIT_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__TUNIT_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -246,7 +236,6 @@ ; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__CGSCC_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -258,7 +247,6 @@ ; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__CGSCC_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__CGSCC_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__CGSCC_NPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__CGSCC_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__CGSCC_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -322,7 +310,6 @@ ; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__TUNIT_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__TUNIT_OPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__TUNIT_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__TUNIT_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -335,7 +322,6 @@ ; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__TUNIT_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__TUNIT_NPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__TUNIT_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__TUNIT_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -348,7 +334,6 @@ ; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__CGSCC_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) @@ -361,7 +346,6 @@ ; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 ; IS__CGSCC_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 ; IS__CGSCC_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* ; IS__CGSCC_NPM-NEXT: store i32 42, i32* [[B]], align 32 ; IS__CGSCC_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 ; IS__CGSCC_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]]) diff --git a/llvm/test/Transforms/Attributor/depgraph.ll b/llvm/test/Transforms/Attributor/depgraph.ll --- a/llvm/test/Transforms/Attributor/depgraph.ll +++ b/llvm/test/Transforms/Attributor/depgraph.ll @@ -263,6 +263,8 @@ ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANoFree] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_arg: [@0]} with state nofree ; GRAPH-EMPTY: +; GRAPH-NEXT: [AAAddressSpaceInfo] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state Address Space: 0 +; GRAPH-EMPTY: ; GRAPH-NEXT: [AADereferenceable] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state unknown-dereferenceable ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAAlign] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_ret: [@-1]} with state align<1-16> diff --git a/llvm/test/Transforms/Attributor/heap_to_stack.ll b/llvm/test/Transforms/Attributor/heap_to_stack.ll --- a/llvm/test/Transforms/Attributor/heap_to_stack.ll +++ b/llvm/test/Transforms/Attributor/heap_to_stack.ll @@ -220,12 +220,21 @@ ; leave alone a constant-but-invalid alignment define void @test3d(i8* %p) { -; CHECK-LABEL: define {{[^@]+}}@test3d -; CHECK-SAME; (i8* nocapture [[P:%.*]]) { -; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 33, i64 noundef 128) -; CHECK: tail call void @free(i8* noalias nocapture [[TMP1]]) -; CHECK-NEXT: ret void +; IS________OPM-LABEL: define {{[^@]+}}@test3d +; IS________OPM-SAME: (i8* nocapture [[P:%.*]]) { +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 33, i64 noundef 128) +; IS________OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]]) +; IS________OPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) +; IS________OPM-NEXT: ret void ; +; IS________NPM-LABEL: define {{[^@]+}}@test3d +; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) { +; IS________NPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 33, i64 noundef 128) +; IS________NPM-NEXT: tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP1]], i8* nocapture [[P]]) +; IS________NPM-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]]) +; IS________NPM-NEXT: ret void +; +; CHECK-SAME; (i8* nocapture [[P:%.*]]) { %1 = tail call noalias i8* @aligned_alloc(i64 33, i64 128) tail call void @nofree_arg_only(i8* %1, i8* %p) tail call void @free(i8* %1) @@ -635,7 +644,6 @@ ; IS________OPM: 8: ; IS________OPM-NEXT: [[TMP9:%.*]] = call noalias i8* @malloc(i64 noundef 4) ; IS________OPM-NEXT: [[TMP10:%.*]] = bitcast i8* [[TMP9]] to i32* -; IS________OPM-NEXT: store i32 1, i32* [[TMP10]], align 8 ; IS________OPM-NEXT: br label [[TMP4]] ; IS________OPM: 11: ; IS________OPM-NEXT: ret i32 5 diff --git a/llvm/test/Transforms/Attributor/heap_to_stack_gpu.ll b/llvm/test/Transforms/Attributor/heap_to_stack_gpu.ll --- a/llvm/test/Transforms/Attributor/heap_to_stack_gpu.ll +++ b/llvm/test/Transforms/Attributor/heap_to_stack_gpu.ll @@ -498,7 +498,6 @@ ; CHECK: 8: ; CHECK-NEXT: [[TMP9:%.*]] = call noalias i8* @malloc(i64 noundef 4) ; CHECK-NEXT: [[TMP10:%.*]] = bitcast i8* [[TMP9]] to i32* -; CHECK-NEXT: store i32 1, i32* [[TMP10]], align 8 ; CHECK-NEXT: br label [[TMP4]] ; CHECK: 11: ; CHECK-NEXT: ret i32 5 diff --git a/llvm/test/Transforms/Attributor/nocapture-1.ll b/llvm/test/Transforms/Attributor/nocapture-1.ll --- a/llvm/test/Transforms/Attributor/nocapture-1.ll +++ b/llvm/test/Transforms/Attributor/nocapture-1.ll @@ -234,9 +234,10 @@ ; CHECK-NEXT: [[X:%.*]] = phi i32 addrspace(1)* [ [[P]], [[E:%.*]] ] ; CHECK-NEXT: [[Y:%.*]] = phi i32* [ [[Q]], [[E]] ] ; CHECK-NEXT: [[TMP:%.*]] = addrspacecast i32 addrspace(1)* [[X]] to i32* +; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast i32* [[TMP]] to i32 addrspace(1)* ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[B]], i32* [[TMP]], i32* [[Y]] ; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[TMP2]], align 4 -; CHECK-NEXT: store i32 0, i32* [[TMP]], align 4 +; CHECK-NEXT: store i32 0, i32 addrspace(1)* [[TMP0]], align 4 ; CHECK-NEXT: store i32* [[Y]], i32** @g, align 8 ; CHECK-NEXT: ret i32 [[VAL]] ; diff --git a/llvm/test/Transforms/Attributor/nodelete.ll b/llvm/test/Transforms/Attributor/nodelete.ll --- a/llvm/test/Transforms/Attributor/nodelete.ll +++ b/llvm/test/Transforms/Attributor/nodelete.ll @@ -48,8 +48,6 @@ ; IS__CGSCC____-LABEL: define {{[^@]+}}@f3 ; IS__CGSCC____-SAME: () #[[ATTR0]] align 2 { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[THIS_ADDR:%.*]] = alloca %b*, align 8 -; IS__CGSCC____-NEXT: [[THIS1:%.*]] = load %b*, %b** [[THIS_ADDR]], align 8 ; IS__CGSCC____-NEXT: ret void ; entry: @@ -65,8 +63,6 @@ ; IS__CGSCC____-LABEL: define {{[^@]+}}@f4 ; IS__CGSCC____-SAME: () #[[ATTR0]] align 2 { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[THIS_ADDR:%.*]] = alloca %b*, align 8 -; IS__CGSCC____-NEXT: [[THIS1:%.*]] = load %b*, %b** [[THIS_ADDR]], align 8 ; IS__CGSCC____-NEXT: ret i1 undef ; entry: diff --git a/llvm/test/Transforms/Attributor/value-simplify-gpu.ll b/llvm/test/Transforms/Attributor/value-simplify-gpu.ll --- a/llvm/test/Transforms/Attributor/value-simplify-gpu.ll +++ b/llvm/test/Transforms/Attributor/value-simplify-gpu.ll @@ -337,14 +337,23 @@ } define internal void @level2b(i32* %addr) { -; IS__TUNIT____: Function Attrs: norecurse nosync nounwind -; IS__TUNIT____-LABEL: define {{[^@]+}}@level2b -; IS__TUNIT____-SAME: () #[[ATTR1]] { -; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 -; IS__TUNIT____-NEXT: [[TMP1:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 -; IS__TUNIT____-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]], i32 17) #[[ATTR6]] -; IS__TUNIT____-NEXT: ret void +; IS__TUNIT_OPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@level2b +; IS__TUNIT_OPM-SAME: () #[[ATTR1]] { +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 +; IS__TUNIT_OPM-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]], i32 noundef 17) #[[ATTR6]] +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@level2b +; IS__TUNIT_NPM-SAME: () #[[ATTR1]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 +; IS__TUNIT_NPM-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]], i32 17) #[[ATTR6]] +; IS__TUNIT_NPM-NEXT: ret void ; ; IS__CGSCC_OPM: Function Attrs: norecurse nosync nounwind ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@level2b diff --git a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll --- a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll +++ b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll @@ -2565,7 +2565,6 @@ ; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0 ; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: -; CHECK-NEXT: store i32 1, i32* @Flag1, align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: ; CHECK-NEXT: ret i32 1 diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll --- a/llvm/test/Transforms/Attributor/value-simplify.ll +++ b/llvm/test/Transforms/Attributor/value-simplify.ll @@ -785,17 +785,24 @@ ret void } define void @user() { -; NOT_CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly -; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@user -; NOT_CGSCC_OPM-SAME: () #[[ATTR3]] { -; NOT_CGSCC_OPM-NEXT: store i32 0, i32* addrspacecast (i32 addrspace(3)* @ConstAS3Ptr to i32*), align 4 -; NOT_CGSCC_OPM-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@user +; IS__TUNIT____-SAME: () #[[ATTR3]] { +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = addrspacecast i32* addrspacecast (i32 addrspace(3)* @ConstAS3Ptr to i32*) to i32 addrspace(3)* +; IS__TUNIT____-NEXT: store i32 0, i32 addrspace(3)* [[TMP1]], align 4 +; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@user ; IS__CGSCC_OPM-SAME: () #[[ATTR4]] { ; IS__CGSCC_OPM-NEXT: store i32 0, i32* addrspacecast (i32 addrspace(3)* @ConstAS3Ptr to i32*), align 4 ; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@user +; IS__CGSCC_NPM-SAME: () #[[ATTR3]] { +; IS__CGSCC_NPM-NEXT: store i32 0, i32* addrspacecast (i32 addrspace(3)* @ConstAS3Ptr to i32*), align 4 +; IS__CGSCC_NPM-NEXT: ret void ; %call = call fastcc i32* @const_ptr_return() store i32 0, i32* %call @@ -1100,24 +1107,103 @@ } define i1 @test_liveness(i1 %c) { +; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test_liveness +; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT_OPM: t: +; IS__TUNIT_OPM-NEXT: br label [[F]] +; IS__TUNIT_OPM: f: +; IS__TUNIT_OPM-NEXT: [[P:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[T]] ] +; IS__TUNIT_OPM-NEXT: [[RC1:%.*]] = call noundef i1 @ret(i1 noundef [[P]]) #[[ATTR5]] +; IS__TUNIT_OPM-NEXT: ret i1 [[RC1]] +; +; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test_liveness +; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT_NPM: t: +; IS__TUNIT_NPM-NEXT: br label [[F]] +; IS__TUNIT_NPM: f: +; IS__TUNIT_NPM-NEXT: [[P:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[T]] ] +; IS__TUNIT_NPM-NEXT: [[RC1:%.*]] = call noundef i1 @ret(i1 noundef [[P]]) #[[ATTR4]] +; IS__TUNIT_NPM-NEXT: ret i1 [[RC1]] +; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test_liveness +; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC_OPM: t: +; IS__CGSCC_OPM-NEXT: br label [[F]] +; IS__CGSCC_OPM: f: +; IS__CGSCC_OPM-NEXT: [[P:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[T]] ] +; IS__CGSCC_OPM-NEXT: [[RC1:%.*]] = call noundef i1 @ret(i1 noundef [[P]]) #[[ATTR7:[0-9]+]] +; IS__CGSCC_OPM-NEXT: ret i1 [[RC1]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test_liveness +; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC_NPM: t: +; IS__CGSCC_NPM-NEXT: br label [[F]] +; IS__CGSCC_NPM: f: +; IS__CGSCC_NPM-NEXT: ret i1 false +; entry: - br i1 %c, label %t, label %f + br i1 %c, label %t, label %f t: - br label %f + br label %f f: - %p = phi i1 [true, %entry], [false, %t] - %rc1 = call i1 @ret(i1 %p) - ret i1 %rc1 + %p = phi i1 [true, %entry], [false, %t] + %rc1 = call i1 @ret(i1 %p) + ret i1 %rc1 } define internal i1 @ret(i1 %c) { +; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS________OPM-LABEL: define {{[^@]+}}@ret +; IS________OPM-SAME: (i1 noundef [[C:%.*]]) #[[ATTR1]] { +; IS________OPM-NEXT: entry: +; IS________OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS________OPM: t: +; IS________OPM-NEXT: br label [[F]] +; IS________OPM: f: +; IS________OPM-NEXT: [[P:%.*]] = phi i1 [ [[C]], [[ENTRY:%.*]] ], [ false, [[T]] ] +; IS________OPM-NEXT: ret i1 [[P]] +; +; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@ret +; IS__TUNIT_NPM-SAME: (i1 noundef [[C:%.*]]) #[[ATTR1]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT_NPM: t: +; IS__TUNIT_NPM-NEXT: br label [[F]] +; IS__TUNIT_NPM: f: +; IS__TUNIT_NPM-NEXT: [[P:%.*]] = phi i1 [ [[C]], [[ENTRY:%.*]] ], [ false, [[T]] ] +; IS__TUNIT_NPM-NEXT: ret i1 false +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@ret +; IS__CGSCC_NPM-SAME: (i1 noundef [[C:%.*]]) #[[ATTR1]] { +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC_NPM: t: +; IS__CGSCC_NPM-NEXT: br label [[F]] +; IS__CGSCC_NPM: f: +; IS__CGSCC_NPM-NEXT: [[P:%.*]] = phi i1 [ [[C]], [[ENTRY:%.*]] ], [ false, [[T]] ] +; IS__CGSCC_NPM-NEXT: ret i1 undef +; entry: - br i1 %c, label %t, label %f + br i1 %c, label %t, label %f t: - br label %f + br label %f f: - %p = phi i1 [%c, %entry], [false, %t] - ret i1 %p + %p = phi i1 [%c, %entry], [false, %t] + ret i1 %p } ;. @@ -1145,6 +1231,7 @@ ; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR5]] = { willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR6]] = { nounwind willreturn writeonly } +; IS__CGSCC_OPM: attributes #[[ATTR7]] = { readnone willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree nosync nounwind willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }