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 @@ -132,6 +132,15 @@ class AAResults; class Function; +/// Abstract Attribute helper functions. +namespace AA { +/// Try to convert \p V to type \p Ty without introducing new instructions. If +/// this is not possible return `nullptr`. Note: this function basically knows +/// how to cast various constants. +Value *getWithType(Value &V, Type &Ty); + +} // namespace AA + /// The value passed to the line option that defines the maximal initialization /// chain length. extern unsigned MaxInitializationChainLength; 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 @@ -26,6 +26,7 @@ #include "llvm/Analysis/MustExecute.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Attributes.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" @@ -159,6 +160,26 @@ } ///} +Value *AA::getWithType(Value &V, Type &Ty) { + if (V.getType() == &Ty) + return &V; + if (isa(V)) + return PoisonValue::get(&Ty); + if (isa(V)) + return UndefValue::get(&Ty); + if (auto *C = dyn_cast(&V)) { + if (C->isNullValue()) + return Constant::getNullValue(&Ty); + if (C->getType()->isPointerTy() && Ty.isPointerTy()) + return ConstantExpr::getPointerCast(C, &Ty); + if (C->getType()->isIntegerTy() && Ty.isIntegerTy()) + return ConstantExpr::getTrunc(C, &Ty, /* OnlyIfReduced */ true); + if (C->getType()->isFloatingPointTy() && Ty.isFloatingPointTy()) + return ConstantExpr::getFPTrunc(C, &Ty, /* OnlyIfReduced */ true); + } + return nullptr; +} + /// Return true if \p New is equal or worse than \p Old. static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) { if (!Old.isIntAttribute()) 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 @@ -4628,12 +4628,13 @@ auto *C = SimplifiedAssociatedValue.hasValue() ? dyn_cast(SimplifiedAssociatedValue.getValue()) : UndefValue::get(V.getType()); - if (C) { + if (C && C != &V && !V.user_empty()) { + Value *NewV = AA::getWithType(*C, *V.getType()); // We can replace the AssociatedValue with the constant. - if (!V.user_empty() && &V != C && V.getType() == C->getType()) { - LLVM_DEBUG(dbgs() << "[ValueSimplify] " << V << " -> " << *C + if (NewV && NewV != &V) { + LLVM_DEBUG(dbgs() << "[ValueSimplify] " << V << " -> " << *NewV << " :: " << *this << "\n"); - if (A.changeValueAfterManifest(V, *C)) + if (A.changeValueAfterManifest(V, *NewV)) Changed = ChangeStatus::CHANGED; } } @@ -4769,35 +4770,34 @@ if (SimplifiedAssociatedValue.hasValue() && !SimplifiedAssociatedValue.getValue()) - return Changed; + return Changed | AAValueSimplify::manifest(A); - Value &V = getAssociatedValue(); auto *C = SimplifiedAssociatedValue.hasValue() ? dyn_cast(SimplifiedAssociatedValue.getValue()) - : UndefValue::get(V.getType()); - if (C) { - auto PredForReturned = - [&](Value &V, const SmallSetVector &RetInsts) { - // We can replace the AssociatedValue with the constant. - if (&V == C || V.getType() != C->getType() || isa(V)) - return true; - - for (ReturnInst *RI : RetInsts) { - if (RI->getFunction() != getAnchorScope()) - continue; - auto *RC = C; - if (RC->getType() != RI->getReturnValue()->getType()) - RC = ConstantExpr::getPointerCast( - RC, RI->getReturnValue()->getType()); - LLVM_DEBUG(dbgs() << "[ValueSimplify] " << V << " -> " << *RC - << " in " << *RI << " :: " << *this << "\n"); - if (A.changeUseAfterManifest(RI->getOperandUse(0), *RC)) - Changed = ChangeStatus::CHANGED; - } + : UndefValue::get(getAssociatedType()); + if (!C || C == &getAssociatedValue()) + return Changed | AAValueSimplify::manifest(A); + + auto PredForReturned = + [&](Value &V, const SmallSetVector &RetInsts) { + // We can replace the AssociatedValue with the constant. + if (&V == C || isa(V)) return true; - }; - A.checkForAllReturnedValuesAndReturnInsts(PredForReturned, *this); - } + + for (ReturnInst *RI : RetInsts) { + if (RI->getFunction() != getAnchorScope()) + continue; + Value *NewV = AA::getWithType(*C, *RI->getReturnValue()->getType()); + if (!NewV) + continue; + LLVM_DEBUG(dbgs() << "[ValueSimplify] " << V << " -> " << *NewV + << " in " << *RI << " :: " << *this << "\n"); + if (A.changeUseAfterManifest(RI->getOperandUse(0), *NewV)) + Changed = ChangeStatus::CHANGED; + } + return true; + }; + A.checkForAllReturnedValuesAndReturnInsts(PredForReturned, *this); return Changed | AAValueSimplify::manifest(A); } @@ -4991,9 +4991,10 @@ Use &U = cast(&getAnchorValue()) ->getArgOperandUse(getCallSiteArgNo()); // We can replace the AssociatedValue with the constant. - if (&V != C && V.getType() == C->getType()) { - if (A.changeUseAfterManifest(U, *C)) - Changed = ChangeStatus::CHANGED; + if (&V != C) { + if (Value *NewV = AA::getWithType(*C, *V.getType())) + if (A.changeUseAfterManifest(U, *NewV)) + Changed = ChangeStatus::CHANGED; } } diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll @@ -43,9 +43,8 @@ ; IS__CGSCC____-LABEL: define {{[^@]+}}@run ; IS__CGSCC____-SAME: () #[[ATTR0:[0-9]+]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[A_CAST:%.*]] = bitcast %struct.Foo* @a to i32* -; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[A_CAST]], align 8 -; IS__CGSCC____-NEXT: [[A_0_1:%.*]] = getelementptr [[STRUCT_FOO:%.*]], %struct.Foo* @a, i32 0, i32 1 +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* getelementptr inbounds ([[STRUCT_FOO:%.*]], %struct.Foo* @a, i32 0, i32 0), align 8 +; IS__CGSCC____-NEXT: [[A_0_1:%.*]] = getelementptr [[STRUCT_FOO]], %struct.Foo* @a, i32 0, i32 1 ; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i64, i64* [[A_0_1]], align 8 ; IS__CGSCC____-NEXT: unreachable ; 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 @@ -59,11 +59,10 @@ ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 1 ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 0 -; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = load i8, i8* [[TMP2]], align 8 -; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = zext i8 [[TMP3]] to i32 -; IS__TUNIT_OPM-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], [[TMP1]] -; IS__TUNIT_OPM-NEXT: ret i32 [[TMP5]] +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = load i8, i8* getelementptr inbounds ([[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 0), align 8 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = zext i8 [[TMP2]] to i32 +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = add i32 [[TMP3]], [[TMP1]] +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP4]] ; ; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readonly willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@vfu2 @@ -76,11 +75,10 @@ ; IS__TUNIT_NPM-NEXT: store i32 [[TMP1]], i32* [[U_PRIV_0_1]], align 4 ; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 1 ; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 -; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 0 -; IS__TUNIT_NPM-NEXT: [[TMP5:%.*]] = load i8, i8* [[TMP4]], align 8 -; IS__TUNIT_NPM-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 -; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], [[TMP3]] -; IS__TUNIT_NPM-NEXT: ret i32 [[TMP7]] +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load i8, i8* getelementptr inbounds ([[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 0), align 8 +; IS__TUNIT_NPM-NEXT: [[TMP5:%.*]] = zext i8 [[TMP4]] to i32 +; IS__TUNIT_NPM-NEXT: [[TMP6:%.*]] = add i32 [[TMP5]], [[TMP3]] +; IS__TUNIT_NPM-NEXT: ret i32 [[TMP6]] ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@vfu2 @@ -88,11 +86,10 @@ ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 ; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 0 -; IS__CGSCC____-NEXT: [[TMP3:%.*]] = load i8, i8* [[TMP2]], align 8 -; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i8 [[TMP3]] to i32 -; IS__CGSCC____-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], [[TMP1]] -; IS__CGSCC____-NEXT: ret i32 [[TMP5]] +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = load i8, i8* getelementptr inbounds ([[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 0), align 8 +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i8 [[TMP2]] to i32 +; IS__CGSCC____-NEXT: [[TMP4:%.*]] = add i32 [[TMP3]], [[TMP1]] +; IS__CGSCC____-NEXT: ret i32 [[TMP4]] ; entry: %0 = getelementptr %struct.MYstr, %struct.MYstr* %u, i32 0, i32 1 ; [#uses=1] @@ -245,9 +242,8 @@ ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@unions_v2 ; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { ; IS__CGSCC_NPM-NEXT: entry: -; IS__CGSCC_NPM-NEXT: [[MYSTR_CAST1:%.*]] = bitcast %struct.MYstr* @mystr to i8* -; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST1]], align 8 -; IS__CGSCC_NPM-NEXT: [[MYSTR_0_12:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* getelementptr inbounds ([[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 0), align 8 +; IS__CGSCC_NPM-NEXT: [[MYSTR_0_12:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 1 ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_12]], align 8 ; IS__CGSCC_NPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR3:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 [[RESULT]] diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll b/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll @@ -15,19 +15,11 @@ ; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #[[ATTR0]], !range [[RNG0:![0-9]+]] ; IS__TUNIT____-NEXT: ret i64 [[CALL2]] ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@fn2 -; IS__CGSCC_OPM-SAME: () #[[ATTR0:[0-9]+]] { -; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #[[ATTR1:[0-9]+]] -; IS__CGSCC_OPM-NEXT: ret i64 [[CALL2]] -; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@fn2 -; IS__CGSCC_NPM-SAME: () #[[ATTR0:[0-9]+]] { -; IS__CGSCC_NPM-NEXT: entry: -; IS__CGSCC_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]] -; IS__CGSCC_NPM-NEXT: ret i64 [[CALL2]] +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2 +; IS__CGSCC____-SAME: () #[[ATTR0:[0-9]+]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i64 undef ; entry: %conv = sext i32 undef to i64 @@ -48,7 +40,7 @@ ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2b -; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) #[[ATTR0]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 ; IS__CGSCC____-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]] diff --git a/llvm/test/Transforms/Attributor/misc_crash.ll b/llvm/test/Transforms/Attributor/misc_crash.ll --- a/llvm/test/Transforms/Attributor/misc_crash.ll +++ b/llvm/test/Transforms/Attributor/misc_crash.ll @@ -26,21 +26,16 @@ ; CHECK: Function Attrs: nofree nosync nounwind readnone willreturn ; CHECK-LABEL: define {{[^@]+}}@func1 ; CHECK-SAME: () #[[ATTR0]] { -; CHECK-NEXT: [[PTR:%.*]] = call i32* @func1a() #[[ATTR0]] -; CHECK-NEXT: ret i32* [[PTR]] +; CHECK-NEXT: ret i32* getelementptr inbounds ([1 x i32], [1 x i32]* @var1, i32 0, i32 0) ; %ptr = call i32* @func1a([1 x i32]* @var1) ret i32* %ptr } -; UTC_ARGS: --disable -; CHECK-LABEL: define internal noundef nonnull align 4 dereferenceable(4) i32* @func1a() -; CHECK-NEXT: ret i32* getelementptr inbounds ([1 x i32], [1 x i32]* @var1, i32 0, i32 0) define internal i32* @func1a([1 x i32]* %arg) { %ptr = getelementptr inbounds [1 x i32], [1 x i32]* %arg, i64 0, i64 0 ret i32* %ptr } -; UTC_ARGS: --enable define internal void @func2a(i32* %0) { ; CHECK: Function Attrs: nofree nosync nounwind willreturn writeonly diff --git a/llvm/test/Transforms/Attributor/norecurse.ll b/llvm/test/Transforms/Attributor/norecurse.ll --- a/llvm/test/Transforms/Attributor/norecurse.ll +++ b/llvm/test/Transforms/Attributor/norecurse.ll @@ -73,7 +73,7 @@ ; CHECK: Function Attrs: argmemonly nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@intrinsic ; CHECK-SAME: (i8* nocapture nofree writeonly [[DEST:%.*]], i8* nocapture nofree readonly [[SRC:%.*]], i32 [[LEN:%.*]]) #[[ATTR5:[0-9]+]] { -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture nofree writeonly [[DEST]], i8* noalias nocapture nofree readonly [[SRC]], i32 [[LEN]], i1 noundef false) #[[ATTR10:[0-9]+]] +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture nofree writeonly [[DEST]], i8* noalias nocapture nofree readonly [[SRC]], i32 [[LEN]], i1 noundef false) #[[ATTR11:[0-9]+]] ; CHECK-NEXT: ret void ; call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false) @@ -93,7 +93,7 @@ ; ; IS__CGSCC____: Function Attrs: norecurse nosync readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@called_by_norecurse -; IS__CGSCC____-SAME: () #[[ATTR6:[0-9]+]] { +; IS__CGSCC____-SAME: () #[[ATTR7:[0-9]+]] { ; IS__CGSCC____-NEXT: [[A:%.*]] = call i32 @k() ; IS__CGSCC____-NEXT: ret i32 undef ; @@ -103,13 +103,13 @@ define void @m() norecurse { ; IS__TUNIT____: Function Attrs: norecurse nosync readnone ; IS__TUNIT____-LABEL: define {{[^@]+}}@m -; IS__TUNIT____-SAME: () #[[ATTR6:[0-9]+]] { +; IS__TUNIT____-SAME: () #[[ATTR7:[0-9]+]] { ; IS__TUNIT____-NEXT: [[A:%.*]] = call i32 @called_by_norecurse() #[[ATTR3]] ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: norecurse nosync readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@m -; IS__CGSCC____-SAME: () #[[ATTR6]] { +; IS__CGSCC____-SAME: () #[[ATTR7]] { ; IS__CGSCC____-NEXT: [[A:%.*]] = call i32 @called_by_norecurse() ; IS__CGSCC____-NEXT: ret void ; @@ -136,7 +136,7 @@ ; ; IS__CGSCC____: Function Attrs: norecurse nosync readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@o -; IS__CGSCC____-SAME: () #[[ATTR6]] { +; IS__CGSCC____-SAME: () #[[ATTR7]] { ; IS__CGSCC____-NEXT: [[A:%.*]] = call i32 @called_by_norecurse_indirectly() ; IS__CGSCC____-NEXT: ret i32 [[A]] ; @@ -146,13 +146,13 @@ define i32 @p() norecurse { ; IS__TUNIT____: Function Attrs: norecurse nosync readnone ; IS__TUNIT____-LABEL: define {{[^@]+}}@p -; IS__TUNIT____-SAME: () #[[ATTR6]] { +; IS__TUNIT____-SAME: () #[[ATTR7]] { ; IS__TUNIT____-NEXT: [[A:%.*]] = call i32 @o() #[[ATTR3]] ; IS__TUNIT____-NEXT: ret i32 [[A]] ; ; IS__CGSCC____: Function Attrs: norecurse nosync readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@p -; IS__CGSCC____-SAME: () #[[ATTR6]] { +; IS__CGSCC____-SAME: () #[[ATTR7]] { ; IS__CGSCC____-NEXT: [[A:%.*]] = call i32 @o() ; IS__CGSCC____-NEXT: ret i32 [[A]] ; @@ -163,7 +163,7 @@ define void @f(i32 %x) { ; CHECK: Function Attrs: nofree nosync nounwind readnone ; CHECK-LABEL: define {{[^@]+}}@f -; CHECK-SAME: (i32 [[X:%.*]]) #[[ATTR7:[0-9]+]] { +; CHECK-SAME: (i32 [[X:%.*]]) #[[ATTR8:[0-9]+]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 ; CHECK-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 @@ -171,7 +171,7 @@ ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0 ; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: -; CHECK-NEXT: call void @g() #[[ATTR8:[0-9]+]] +; CHECK-NEXT: call void @g() #[[ATTR9:[0-9]+]] ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: ; CHECK-NEXT: ret void @@ -194,9 +194,9 @@ define void @g() norecurse { ; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone ; CHECK-LABEL: define {{[^@]+}}@g -; CHECK-SAME: () #[[ATTR8]] { +; CHECK-SAME: () #[[ATTR9]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @f(i32 noundef 0) #[[ATTR7]] +; CHECK-NEXT: call void @f(i32 noundef 0) #[[ATTR8]] ; CHECK-NEXT: ret void ; entry: @@ -225,7 +225,7 @@ define i32 @eval_func2(i32 (i32)* , i32) local_unnamed_addr null_pointer_is_valid{ ; CHECK: Function Attrs: null_pointer_is_valid ; CHECK-LABEL: define {{[^@]+}}@eval_func2 -; CHECK-SAME: (i32 (i32)* nocapture nofree noundef [[TMP0:%.*]], i32 [[TMP1:%.*]]) local_unnamed_addr #[[ATTR9:[0-9]+]] { +; CHECK-SAME: (i32 (i32)* nocapture nofree noundef [[TMP0:%.*]], i32 [[TMP1:%.*]]) local_unnamed_addr #[[ATTR10:[0-9]+]] { ; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 [[TMP0]](i32 [[TMP1]]) ; CHECK-NEXT: ret i32 [[TMP3]] ; @@ -263,11 +263,12 @@ ; IS__TUNIT____: attributes #[[ATTR3]] = { nosync readnone } ; IS__TUNIT____: attributes #[[ATTR4:[0-9]+]] = { readnone } ; IS__TUNIT____: attributes #[[ATTR5]] = { argmemonly nofree nosync nounwind willreturn } -; IS__TUNIT____: attributes #[[ATTR6]] = { norecurse nosync readnone } -; IS__TUNIT____: attributes #[[ATTR7]] = { nofree nosync nounwind readnone } -; IS__TUNIT____: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind readnone } -; IS__TUNIT____: attributes #[[ATTR9]] = { null_pointer_is_valid } -; IS__TUNIT____: attributes #[[ATTR10]] = { willreturn } +; IS__TUNIT____: attributes #[[ATTR6:[0-9]+]] = { argmemonly nofree nounwind willreturn } +; IS__TUNIT____: attributes #[[ATTR7]] = { norecurse nosync readnone } +; IS__TUNIT____: attributes #[[ATTR8]] = { nofree nosync nounwind readnone } +; IS__TUNIT____: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind readnone } +; IS__TUNIT____: attributes #[[ATTR10]] = { null_pointer_is_valid } +; IS__TUNIT____: attributes #[[ATTR11]] = { willreturn } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse noreturn nosync nounwind readnone willreturn } @@ -275,9 +276,10 @@ ; IS__CGSCC____: attributes #[[ATTR3]] = { nosync readnone } ; IS__CGSCC____: attributes #[[ATTR4:[0-9]+]] = { readnone } ; IS__CGSCC____: attributes #[[ATTR5]] = { argmemonly nofree nosync nounwind willreturn } -; IS__CGSCC____: attributes #[[ATTR6]] = { norecurse nosync readnone } -; IS__CGSCC____: attributes #[[ATTR7]] = { nofree nosync nounwind readnone } -; IS__CGSCC____: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind readnone } -; IS__CGSCC____: attributes #[[ATTR9]] = { null_pointer_is_valid } -; IS__CGSCC____: attributes #[[ATTR10]] = { willreturn } +; IS__CGSCC____: attributes #[[ATTR6:[0-9]+]] = { argmemonly nofree nounwind willreturn } +; IS__CGSCC____: attributes #[[ATTR7]] = { norecurse nosync readnone } +; IS__CGSCC____: attributes #[[ATTR8]] = { nofree nosync nounwind readnone } +; IS__CGSCC____: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind readnone } +; IS__CGSCC____: attributes #[[ATTR10]] = { null_pointer_is_valid } +; IS__CGSCC____: attributes #[[ATTR11]] = { willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/noreturn_async.ll b/llvm/test/Transforms/Attributor/noreturn_async.ll --- a/llvm/test/Transforms/Attributor/noreturn_async.ll +++ b/llvm/test/Transforms/Attributor/noreturn_async.ll @@ -86,7 +86,7 @@ ; CHECK-NOT: nounwind ; CHECK-NEXT: define ; CHECK-NEXT: entry: -; CHECK-NEXT: %call3 = call i32 (i8*, ...) @printf(i8* noundef nonnull dereferenceable(18) getelementptr inbounds ([18 x i8], [18 x i8]* @"??_C@_0BC@NKPAGFFJ@Exception?5caught?6?$AA@", i64 0, i64 0)) +; CHECK-NEXT: %call3 = call i32 (i8*, ...) @printf(i8* noundef nonnull dereferenceable(18) getelementptr inbounds ([18 x i8], [18 x i8]* @"??_C@_0BC@NKPAGFFJ@Exception?5caught?6?$AA@", i32 0, i32 0)) ; CHECK-NEXT: call void @"?overflow@@YAXXZ_may_throw"() ; CHECK-NEXT: unreachable %call3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @"??_C@_0BC@NKPAGFFJ@Exception?5caught?6?$AA@", i64 0, i64 0)) diff --git a/llvm/test/Transforms/Attributor/noreturn_sync.ll b/llvm/test/Transforms/Attributor/noreturn_sync.ll --- a/llvm/test/Transforms/Attributor/noreturn_sync.ll +++ b/llvm/test/Transforms/Attributor/noreturn_sync.ll @@ -82,7 +82,7 @@ ; CHECK-NOT: nounwind ; CHECK-NEXT: define ; CHECK-NEXT: entry: -; CHECK-NEXT: %call3 = call i32 (i8*, ...) @printf(i8* noundef nonnull dereferenceable(18) getelementptr inbounds ([18 x i8], [18 x i8]* @"??_C@_0BC@NKPAGFFJ@Exception?5caught?6?$AA@", i64 0, i64 0)) +; CHECK-NEXT: %call3 = call i32 (i8*, ...) @printf(i8* noundef nonnull dereferenceable(18) getelementptr inbounds ([18 x i8], [18 x i8]* @"??_C@_0BC@NKPAGFFJ@Exception?5caught?6?$AA@", i32 0, i32 0)) ; CHECK-NEXT: call void @"?overflow@@YAXXZ_may_throw"() ; CHECK-NEXT: unreachable %call3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @"??_C@_0BC@NKPAGFFJ@Exception?5caught?6?$AA@", i64 0, i64 0)) 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 @@ -1051,7 +1051,7 @@ ; IS__TUNIT_OPM-NEXT: store float 0x3FF19999A0000000, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 3), align 4, !tbaa [[TBAA7]] ; IS__TUNIT_OPM-NEXT: store float 0x40019999A0000000, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 4), align 4, !tbaa [[TBAA10]] ; IS__TUNIT_OPM-NEXT: store float 0x400A666660000000, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 5), align 4, !tbaa [[TBAA11]] -; IS__TUNIT_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 0), i32 noundef 1) #[[ATTR6]] +; IS__TUNIT_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i32 0, i32 0), i32 noundef 1) #[[ATTR6]] ; IS__TUNIT_OPM-NEXT: call void @write_arg(i32* nocapture nofree writeonly align 4 dereferenceable_or_null(20) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 1), i32 noundef 2) #[[ATTR6]] ; IS__TUNIT_OPM-NEXT: call void @write_arg(i32* nocapture nofree writeonly align 4 dereferenceable_or_null(16) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 2), i32 noundef 3) #[[ATTR6]] ; IS__TUNIT_OPM-NEXT: [[I:%.*]] = load float, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 3), align 4, !tbaa [[TBAA7]] @@ -1087,7 +1087,7 @@ ; IS__TUNIT_NPM-NEXT: store float 0x3FF19999A0000000, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 3), align 4, !tbaa [[TBAA7]] ; IS__TUNIT_NPM-NEXT: store float 0x40019999A0000000, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 4), align 4, !tbaa [[TBAA10]] ; IS__TUNIT_NPM-NEXT: store float 0x400A666660000000, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 5), align 4, !tbaa [[TBAA11]] -; IS__TUNIT_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 0), i32 noundef 1) #[[ATTR5]] +; IS__TUNIT_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i32 0, i32 0), i32 noundef 1) #[[ATTR5]] ; IS__TUNIT_NPM-NEXT: call void @write_arg(i32* nocapture nofree writeonly align 4 dereferenceable_or_null(20) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 1), i32 noundef 2) #[[ATTR5]] ; IS__TUNIT_NPM-NEXT: call void @write_arg(i32* nocapture nofree writeonly align 4 dereferenceable_or_null(16) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 2), i32 noundef 3) #[[ATTR5]] ; IS__TUNIT_NPM-NEXT: [[I:%.*]] = load float, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 3), align 4, !tbaa [[TBAA7]] @@ -1123,7 +1123,7 @@ ; IS__CGSCC____-NEXT: store float 0x3FF19999A0000000, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 3), align 4, !tbaa [[TBAA7]] ; IS__CGSCC____-NEXT: store float 0x40019999A0000000, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 4), align 4, !tbaa [[TBAA10]] ; IS__CGSCC____-NEXT: store float 0x400A666660000000, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 5), align 4, !tbaa [[TBAA11]] -; IS__CGSCC____-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 0), i32 noundef 1) #[[ATTR9]] +; IS__CGSCC____-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i32 0, i32 0), i32 noundef 1) #[[ATTR9]] ; IS__CGSCC____-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 1), i32 noundef 2) #[[ATTR9]] ; IS__CGSCC____-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 2), i32 noundef 3) #[[ATTR9]] ; IS__CGSCC____-NEXT: [[I:%.*]] = load float, float* getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 3), align 4, !tbaa [[TBAA7]] 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 @@ -623,15 +623,13 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test_byval2 ; IS__TUNIT____-SAME: () #[[ATTR4:[0-9]+]] { -; IS__TUNIT____-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X:%.*]], %struct.X* @S, i32 0, i32 0 -; IS__TUNIT____-NEXT: [[L:%.*]] = load i8*, i8** [[G0]], align 8 +; IS__TUNIT____-NEXT: [[L:%.*]] = load i8*, i8** getelementptr inbounds ([[STRUCT_X:%.*]], %struct.X* @S, i32 0, i32 0), align 8 ; IS__TUNIT____-NEXT: ret i8* [[L]] ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test_byval2 ; IS__CGSCC____-SAME: () #[[ATTR3:[0-9]+]] { -; IS__CGSCC____-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X:%.*]], %struct.X* @S, i32 0, i32 0 -; IS__CGSCC____-NEXT: [[L:%.*]] = load i8*, i8** [[G0]], align 8 +; IS__CGSCC____-NEXT: [[L:%.*]] = load i8*, i8** getelementptr inbounds ([[STRUCT_X:%.*]], %struct.X* @S, i32 0, i32 0), align 8 ; IS__CGSCC____-NEXT: ret i8* [[L]] ; %g0 = getelementptr %struct.X, %struct.X* %a, i32 0, i32 0