diff --git a/compiler-rt/include/profile/InstrProfData.inc b/compiler-rt/include/profile/InstrProfData.inc --- a/compiler-rt/include/profile/InstrProfData.inc +++ b/compiler-rt/include/profile/InstrProfData.inc @@ -763,6 +763,9 @@ /* InstrProfile per-function control data alignment. */ #define INSTR_PROF_DATA_ALIGNMENT 8 +/* InstrProfile VNodes alilgnment. */ +#define INSTR_PROF_VNODE_ALIGNMENT 8 + /* The data structure that represents a tracked value by the * value profiler. */ diff --git a/compiler-rt/lib/profile/InstrProfiling.h b/compiler-rt/lib/profile/InstrProfiling.h --- a/compiler-rt/lib/profile/InstrProfiling.h +++ b/compiler-rt/lib/profile/InstrProfiling.h @@ -11,6 +11,7 @@ #include "InstrProfilingPort.h" #include +#include #define INSTR_PROF_VISIBILITY COMPILER_RT_VISIBILITY #include "profile/InstrProfData.inc" @@ -26,17 +27,22 @@ #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) Type Name; #include "profile/InstrProfData.inc" } __llvm_profile_data; +static_assert(INSTR_PROF_DATA_ALIGNMENT >= _Alignof(__llvm_profile_data), + "INSTR_PROF_DATA_ALIGNMENT is too small."); typedef struct __llvm_profile_header { #define INSTR_PROF_RAW_HEADER(Type, Name, Initializer) Type Name; #include "profile/InstrProfData.inc" } __llvm_profile_header; -typedef struct ValueProfNode * PtrToNodeT; -typedef struct ValueProfNode { +typedef struct ValueProfNode *PtrToNodeT; +typedef struct COMPILER_RT_ALIGNAS(INSTR_PROF_VNODE_ALIGNMENT) + ValueProfNode { #define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Initializer) Type Name; #include "profile/InstrProfData.inc" } ValueProfNode; +static_assert(INSTR_PROF_VNODE_ALIGNMENT >= _Alignof(ValueProfNode), + "INSTR_PROF_VNODE_ALIGNMENT is too small."); /*! * \brief Return 1 if profile counters are continuously synced to the raw diff --git a/llvm/include/llvm/ProfileData/InstrProfData.inc b/llvm/include/llvm/ProfileData/InstrProfData.inc --- a/llvm/include/llvm/ProfileData/InstrProfData.inc +++ b/llvm/include/llvm/ProfileData/InstrProfData.inc @@ -763,6 +763,9 @@ /* InstrProfile per-function control data alignment. */ #define INSTR_PROF_DATA_ALIGNMENT 8 +/* InstrProfile VNodes alilgnment. */ +#define INSTR_PROF_VNODE_ALIGNMENT 8 + /* The data structure that represents a tracked value by the * value profiler. */ diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -1180,6 +1180,7 @@ Constant::getNullValue(VNodesTy), getInstrProfVNodesVarName()); VNodesVar->setSection( getInstrProfSectionName(IPSK_vnodes, TT.getObjectFormat())); + VNodesVar->setAlignment(Align(INSTR_PROF_VNODE_ALIGNMENT)); // VNodesVar is used by runtime but not referenced via relocation by other // sections. Conservatively make it linker retained. UsedVars.push_back(VNodesVar); diff --git a/llvm/test/Instrumentation/InstrProfiling/alignment.ll b/llvm/test/Instrumentation/InstrProfiling/alignment.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/InstrProfiling/alignment.ll @@ -0,0 +1,70 @@ +; Tests that the globals inserted all have the correct alignments specified. +; RUN: opt %s -mtriple=powerpc64-unknown-linux -passes=instrprof -S | FileCheck %s +; RUN: opt %s -mtriple=powerpc-ibm-aix -passes=instrprof -S | FileCheck %s +; RUN: opt %s -mtriple=powerpc64-ibm-aix -passes=instrprof -S | FileCheck %s +; RUN: opt %s -mtriple=x86_64-unknown-linux -passes=instrprof -S | FileCheck %s + +@__llvm_profile_raw_version = weak hidden constant i64 72057594037927944 +; CHECK: @__profc_foo = private global {{.*}} section "__llvm_prf_cnts",{{.*}} align 8 +; CHECK: @__profd_foo = private global {{.*}} section "__llvm_prf_data",{{.*}} align 8 +; CHECK: @__profc_main = private global {{.*}} section "__llvm_prf_cnts",{{.*}} align 8 +; CHECK: @__profvp_main = private global {{.*}} section "__llvm_prf_vals",{{.*}} align 8 +; CHECK: @__profd_main = private global {{.*}} section "__llvm_prf_data",{{.*}} align 8 +; CHECK: @__llvm_prf_vnodes = private global {{.*}} section "__llvm_prf_vnds", align 8 +; CHECK: @__llvm_prf_nm = private constant {{.*}} section "__llvm_prf_names", align 1 +@__profn_foo = private constant [3 x i8] c"foo" +@__profn_main = private constant [4 x i8] c"main" + +; Function Attrs: noinline nounwind optnone +define i32 @foo() { +entry: + call void @llvm.instrprof.increment(ptr @__profn_foo, i64 742261418966908927, i32 1, i32 0) + ret i32 3 +} + +; Function Attrs: noinline nounwind optnone +define i32 @main() { +entry: + call void @llvm.instrprof.increment(ptr @__profn_main, i64 298789186344016796, i32 2, i32 1) + %retval = alloca i32, align 4 + %p = alloca ptr, align 4 + %i = alloca i32, align 4 + store i32 0, ptr %retval, align 4 + store i32 0, ptr %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %0 = load i32, ptr %i, align 4 + %cmp = icmp slt i32 %0, 10 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %1 = load ptr, ptr %p, align 4 + %2 = load ptr, ptr %p, align 4 + %add.ptr = getelementptr inbounds i32, ptr %2, i32 1 + %call = call i32 @foo() + %3 = zext i32 %call to i64 + call void @llvm.instrprof.value.profile(ptr @__profn_main, i64 298789186344016796, i64 %3, i32 1, i32 0) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %1, ptr align 4 %add.ptr, i32 %call, i1 false) + br label %for.inc + +for.inc: ; preds = %for.body + call void @llvm.instrprof.increment(ptr @__profn_main, i64 298789186344016796, i32 2, i32 0) + %4 = load i32, ptr %i, align 4 + %inc = add nsw i32 %4, 1 + store i32 %inc, ptr %i, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + %5 = load i32, ptr %retval, align 4 + ret i32 %5 +} + +; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite) +declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) + +; Function Attrs: nounwind +declare void @llvm.instrprof.increment(ptr, i64, i32, i32) + +; Function Attrs: nounwind +declare void @llvm.instrprof.value.profile(ptr, i64, i64, i32, i32)