diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4665,6 +4665,17 @@ .getRValue(CGF) .getScalarVal(); } + + LLVM_NODISCARD llvm::AttributeList + TryEmitAsCallSiteAttribute(const llvm::AttributeList &Attrs) { + llvm::AttributeList NewAttrs = Attrs; + if (AA) + NewAttrs = + Attrs.addParamAttribute(CGF.getLLVMContext(), AA->getParamIndex().getLLVMIndex(), + llvm::Attribute::AllocAlign); + return AbstractAssumeAlignedAttrEmitter< + AllocAlignAttr>::TryEmitAsCallSiteAttribute(NewAttrs); + } }; } // namespace diff --git a/clang/test/CodeGen/alloc-align-attr.c b/clang/test/CodeGen/alloc-align-attr.c --- a/clang/test/CodeGen/alloc-align-attr.c +++ b/clang/test/CodeGen/alloc-align-attr.c @@ -9,7 +9,7 @@ // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A_ADDR]], align 4 -// CHECK-NEXT: [[CALL:%.*]] = call i32* @m1(i32 noundef [[TMP0]]) +// CHECK-NEXT: [[CALL:%.*]] = call i32* @m1(i32 allocalign noundef [[TMP0]]) // CHECK-NEXT: [[CASTED_ALIGN:%.*]] = zext i32 [[TMP0]] to i64 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[CASTED_ALIGN]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[CALL]], align 4 @@ -25,7 +25,7 @@ // CHECK-NEXT: store i64 [[A:%.*]], i64* [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[A_ADDR]], align 8 // CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[TMP0]] to i32 -// CHECK-NEXT: [[CALL:%.*]] = call i32* @m1(i32 noundef [[CONV]]) +// CHECK-NEXT: [[CALL:%.*]] = call i32* @m1(i32 allocalign noundef [[CONV]]) // CHECK-NEXT: [[CASTED_ALIGN:%.*]] = zext i32 [[CONV]] to i64 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[CASTED_ALIGN]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[CALL]], align 4 @@ -43,7 +43,7 @@ // CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A_ADDR]], align 4 // CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 -// CHECK-NEXT: [[CALL:%.*]] = call i32* @m2(i64 noundef [[CONV]]) +// CHECK-NEXT: [[CALL:%.*]] = call i32* @m2(i64 allocalign noundef [[CONV]]) // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[CONV]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[CALL]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] @@ -58,7 +58,7 @@ // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 // CHECK-NEXT: store i64 [[A:%.*]], i64* [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[A_ADDR]], align 8 -// CHECK-NEXT: [[CALL:%.*]] = call i32* @m2(i64 noundef [[TMP0]]) +// CHECK-NEXT: [[CALL:%.*]] = call i32* @m2(i64 allocalign noundef [[TMP0]]) // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[TMP0]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[CALL]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] @@ -93,7 +93,7 @@ // CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[TMP5]], align 16 // CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[TMP4]], i32 0, i32 1 // CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[TMP7]], align 8 -// CHECK-NEXT: [[CALL:%.*]] = call i32* @m3(i64 noundef [[TMP6]], i64 noundef [[TMP8]]) +// CHECK-NEXT: [[CALL:%.*]] = call i32* @m3(i64 noundef [[TMP6]], i64 allocalign noundef [[TMP8]]) // CHECK-NEXT: [[CASTED_ALIGN:%.*]] = trunc i128 [[TMP3]] to i64 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[CASTED_ALIGN]]) ] // CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[CALL]], align 4 @@ -130,7 +130,7 @@ // CHECK-NEXT: [[TMP11:%.*]] = load i64, i64* [[TMP10]], align 16 // CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[TMP9]], i32 0, i32 1 // CHECK-NEXT: [[TMP13:%.*]] = load i64, i64* [[TMP12]], align 8 -// CHECK-NEXT: [[CALL:%.*]] = call i32* @m4(i64 [[TMP6]], i64 [[TMP8]], i64 noundef [[TMP11]], i64 noundef [[TMP13]]) +// CHECK-NEXT: [[CALL:%.*]] = call i32* @m4(i64 [[TMP6]], i64 allocalign [[TMP8]], i64 noundef [[TMP11]], i64 noundef [[TMP13]]) // CHECK-NEXT: [[CASTED_ALIGN:%.*]] = trunc i128 [[TMP3]] to i64 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[CASTED_ALIGN]]) ] // CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[CALL]], align 4 diff --git a/clang/test/CodeGen/alloc-fns-alignment.c b/clang/test/CodeGen/alloc-fns-alignment.c --- a/clang/test/CodeGen/alloc-fns-alignment.c +++ b/clang/test/CodeGen/alloc-fns-alignment.c @@ -61,13 +61,13 @@ // CHECK: declare i8* @realloc // CHECK-LABEL: @aligned_alloc_variable_test -// CHECK: %[[ALLOCATED:.*]] = call i8* @aligned_alloc({{i32|i64}} noundef %[[ALIGN:.*]], {{i32|i64}} noundef %[[NBYTES:.*]]) +// CHECK: %[[ALLOCATED:.*]] = call i8* @aligned_alloc({{i32|i64}} allocalign noundef %[[ALIGN:.*]], {{i32|i64}} noundef %[[NBYTES:.*]]) // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* %[[ALLOCATED]], {{i32|i64}} %[[ALIGN]]) ] // CHECK: declare i8* @aligned_alloc // CHECK-LABEL: @memalign_variable_test -// CHECK: %[[ALLOCATED:.*]] = call i8* @memalign({{i32|i64}} noundef %[[ALIGN:.*]], {{i32|i64}} noundef %[[NBYTES:.*]]) +// CHECK: %[[ALLOCATED:.*]] = call i8* @memalign({{i32|i64}} allocalign noundef %[[ALIGN:.*]], {{i32|i64}} noundef %[[NBYTES:.*]]) // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* %[[ALLOCATED]], {{i32|i64}} %[[ALIGN]]) ] // CHECK-LABEL: @aligned_alloc_constant_test diff --git a/clang/test/CodeGen/assume-aligned-and-alloc-align-attributes.c b/clang/test/CodeGen/assume-aligned-and-alloc-align-attributes.c --- a/clang/test/CodeGen/assume-aligned-and-alloc-align-attributes.c +++ b/clang/test/CodeGen/assume-aligned-and-alloc-align-attributes.c @@ -5,7 +5,7 @@ // CHECK-LABEL: @t0_immediate0( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL:%.*]] = call align 32 i8* @my_aligned_alloc(i32 noundef 320, i32 noundef 16) +// CHECK-NEXT: [[CALL:%.*]] = call align 32 i8* @my_aligned_alloc(i32 noundef 320, i32 allocalign noundef 16) // CHECK-NEXT: ret i8* [[CALL]] // void *t0_immediate0(void) { @@ -14,7 +14,7 @@ // CHECK-LABEL: @t1_immediate1( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL:%.*]] = call align 32 i8* @my_aligned_alloc(i32 noundef 320, i32 noundef 32) +// CHECK-NEXT: [[CALL:%.*]] = call align 32 i8* @my_aligned_alloc(i32 noundef 320, i32 allocalign noundef 32) // CHECK-NEXT: ret i8* [[CALL]] // void *t1_immediate1(void) { @@ -23,7 +23,7 @@ // CHECK-LABEL: @t2_immediate2( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL:%.*]] = call align 64 i8* @my_aligned_alloc(i32 noundef 320, i32 noundef 64) +// CHECK-NEXT: [[CALL:%.*]] = call align 64 i8* @my_aligned_alloc(i32 noundef 320, i32 allocalign noundef 64) // CHECK-NEXT: ret i8* [[CALL]] // void *t2_immediate2(void) { @@ -35,7 +35,7 @@ // CHECK-NEXT: [[ALIGNMENT_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: store i32 [[ALIGNMENT:%.*]], i32* [[ALIGNMENT_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ALIGNMENT_ADDR]], align 4 -// CHECK-NEXT: [[CALL:%.*]] = call align 32 i8* @my_aligned_alloc(i32 noundef 320, i32 noundef [[TMP0]]) +// CHECK-NEXT: [[CALL:%.*]] = call align 32 i8* @my_aligned_alloc(i32 noundef 320, i32 allocalign noundef [[TMP0]]) // CHECK-NEXT: [[CASTED_ALIGN:%.*]] = zext i32 [[TMP0]] to i64 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[CALL]], i64 [[CASTED_ALIGN]]) ] // CHECK-NEXT: ret i8* [[CALL]] diff --git a/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp b/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp --- a/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp @@ -29,7 +29,7 @@ // CHECK-NEXT: store i64 %[[ALIGNMENT]], i64* %[[ALIGNMENT_ADDR]], align 8 // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8 // CHECK-NEXT: %[[ALIGNMENT_RELOADED:.*]] = load i64, i64* %[[ALIGNMENT_ADDR]], align 8 - // CHECK-NEXT: %[[X_RETURNED:.*]] = call noundef i8** @[[PASSTHROUGH]](i8** noundef %[[X_RELOADED]], i64 noundef %[[ALIGNMENT_RELOADED]]) + // CHECK-NEXT: %[[X_RETURNED:.*]] = call noundef i8** @[[PASSTHROUGH]](i8** noundef %[[X_RELOADED]], i64 allocalign noundef %[[ALIGNMENT_RELOADED]]) // CHECK-SANITIZE-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64 // CHECK-SANITIZE-NEXT: %[[MASK:.*]] = sub i64 %[[ALIGNMENT_RELOADED]], 1 // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], %[[MASK]] diff --git a/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp b/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp --- a/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp @@ -26,8 +26,8 @@ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8 // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8 // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8 - // CHECK-NOSANITIZE-NEXT: %[[X_RETURNED:.*]] = call noundef align 128 i8** @[[PASSTHROUGH]](i8** noundef %[[X_RELOADED]], i64 noundef 128) - // CHECK-SANITIZE-NEXT: %[[X_RETURNED:.*]] = call noundef i8** @[[PASSTHROUGH]](i8** noundef %[[X_RELOADED]], i64 noundef 128) + // CHECK-NOSANITIZE-NEXT: %[[X_RETURNED:.*]] = call noundef align 128 i8** @[[PASSTHROUGH]](i8** noundef %[[X_RELOADED]], i64 allocalign noundef 128) + // CHECK-SANITIZE-NEXT: %[[X_RETURNED:.*]] = call noundef i8** @[[PASSTHROUGH]](i8** noundef %[[X_RELOADED]], i64 allocalign noundef 128) // CHECK-SANITIZE-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64 // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 127 // CHECK-SANITIZE-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 diff --git a/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c b/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c --- a/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c +++ b/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c @@ -8,7 +8,7 @@ // CHECK-NEXT: [[ALIGN_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: store i32 [[ALIGN:%.*]], i32* [[ALIGN_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ALIGN_ADDR]], align 4 -// CHECK-NEXT: [[CALL:%.*]] = call i8* @alloc(i32 noundef [[TMP0]]) +// CHECK-NEXT: [[CALL:%.*]] = call i8* @alloc(i32 allocalign noundef [[TMP0]]) // CHECK-NEXT: [[CASTED_ALIGN:%.*]] = zext i32 [[TMP0]] to i64 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[CALL]], i64 [[CASTED_ALIGN]]) ] // CHECK-NEXT: ret void @@ -20,7 +20,7 @@ // CHECK-NEXT: entry: // CHECK-NEXT: [[ALIGN_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: store i32 [[ALIGN:%.*]], i32* [[ALIGN_ADDR]], align 4 -// CHECK-NEXT: [[CALL:%.*]] = call i8* @alloc(i32 noundef 7) +// CHECK-NEXT: [[CALL:%.*]] = call i8* @alloc(i32 allocalign noundef 7) // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[CALL]], i64 7) ] // CHECK-NEXT: ret void // @@ -31,7 +31,7 @@ // CHECK-NEXT: entry: // CHECK-NEXT: [[ALIGN_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: store i32 [[ALIGN:%.*]], i32* [[ALIGN_ADDR]], align 4 -// CHECK-NEXT: [[CALL:%.*]] = call align 8 i8* @alloc(i32 noundef 8) +// CHECK-NEXT: [[CALL:%.*]] = call align 8 i8* @alloc(i32 allocalign noundef 8) // CHECK-NEXT: ret void // void t2(int align) { diff --git a/clang/test/CodeGenCXX/builtin-operator-new-delete.cpp b/clang/test/CodeGenCXX/builtin-operator-new-delete.cpp --- a/clang/test/CodeGenCXX/builtin-operator-new-delete.cpp +++ b/clang/test/CodeGenCXX/builtin-operator-new-delete.cpp @@ -47,7 +47,7 @@ // CHECK-LABEL: define{{.*}} void @test_aligned_alloc( extern "C" void test_aligned_alloc() { - // CHECK: call noalias noundef nonnull align 4 i8* @_ZnwmSt11align_val_t(i64 noundef 4, i64 noundef 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] + // CHECK: call noalias noundef nonnull align 4 i8* @_ZnwmSt11align_val_t(i64 noundef 4, i64 allocalign noundef 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] // CHECK: call void @_ZdlPvSt11align_val_t({{.*}}, i64 noundef 4) [[ATTR_BUILTIN_DELETE:#[^ ]*]] __builtin_operator_delete(__builtin_operator_new(4, std::align_val_t(4)), std::align_val_t(4)); } diff --git a/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp b/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp --- a/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp +++ b/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp @@ -27,10 +27,10 @@ struct OVERALIGNED A { A(); int n[128]; }; // CHECK-LABEL: define {{.*}} @_Z2a0v() -// CHECK: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 i8* @_ZnwmSt11align_val_t(i64 noundef 512, i64 noundef 32) +// CHECK: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 i8* @_ZnwmSt11align_val_t(i64 noundef 512, i64 allocalign noundef 32) // CHECK: call void @_ZdlPvSt11align_val_t(i8* noundef %[[ALLOC]], i64 noundef 32) // CHECK-MS-LABEL: define {{.*}} @"?a0@@YAPEAXXZ"() -// CHECK-MS: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 i8* @"??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 noundef 512, i64 noundef 32) +// CHECK-MS: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 i8* @"??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 noundef 512, i64 allocalign noundef 32) // CHECK-MS: cleanuppad // CHECK-MS: call void @"??3@YAXPEAXW4align_val_t@std@@@Z"(i8* noundef %[[ALLOC]], i64 noundef 32) void *a0() { return new A; } @@ -39,13 +39,13 @@ // The size is known. // // CHECK-LABEL: define {{.*}} @_Z2a1l( -// CHECK: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 i8* @_ZnamSt11align_val_t(i64 noundef %{{.*}}, i64 noundef 32) +// CHECK: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 i8* @_ZnamSt11align_val_t(i64 noundef %{{.*}}, i64 allocalign noundef 32) // No array cookie. // CHECK-NOT: store // CHECK: invoke void @_ZN1AC1Ev( // CHECK: call void @_ZdaPvSt11align_val_t(i8* noundef %[[ALLOC]], i64 noundef 32) // CHECK-MS-LABEL: define {{.*}} @"?a1@@YAPEAXJ@Z"( -// CHECK-MS: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 i8* @"??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 noundef %{{.*}}, i64 noundef 32) +// CHECK-MS: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 i8* @"??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 noundef %{{.*}}, i64 allocalign noundef 32) // No array cookie. // CHECK-MS-NOT: store // CHECK-MS: invoke noundef %struct.A* @"??0A@@QEAA@XZ"( @@ -84,7 +84,7 @@ void *b0() { return new B; } // CHECK-LABEL: define {{.*}} @_Z2b1l( -// CHECK: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 i8* @_ZnamSt11align_val_t(i64 noundef %{{.*}}, i64 noundef 32) +// CHECK: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 i8* @_ZnamSt11align_val_t(i64 noundef %{{.*}}, i64 allocalign noundef 32) // No array cookie. // CHECK-NOT: store // CHECK: invoke void @_ZN1BC1Ev( @@ -169,7 +169,7 @@ #ifndef UNALIGNED // CHECK-LABEL: define {{.*}} @_Z2e0v( -// CHECK: %[[ALLOC:.*]] = call noalias noundef nonnull align 4 i8* @_ZnwmSt11align_val_t(i64 noundef 512, i64 noundef 4) +// CHECK: %[[ALLOC:.*]] = call noalias noundef nonnull align 4 i8* @_ZnwmSt11align_val_t(i64 noundef 512, i64 allocalign noundef 4) // CHECK: call void @_ZdlPvSt11align_val_t(i8* noundef %[[ALLOC]], i64 noundef 4) void *e0() { return new (std::align_val_t(4)) A; }