llvm-project/clang/test/CodeGen/packed-structure.c
Daniel Neilson 6e938effaa Change memcpy/memove/memset to have dest and source alignment attributes (Step 1).
Summary:
  Upstream LLVM is changing the the prototypes of the @llvm.memcpy/memmove/memset
intrinsics. This change updates the Clang tests for this change.

  The @llvm.memcpy/memmove/memset intrinsics currently have an explicit argument
which is required to be a constant integer. It represents the alignment of the
dest (and source), and so must be the minimum of the actual alignment of the
two.

 This change removes the alignment argument in favour of placing the alignment
attribute on the source and destination pointers of the memory intrinsic call.

 For example, code which used to read:
   call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 100, i32 4, i1 false)
will now read
   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %dest, i8* align 4 %src, i32 100, i1 false)

 At this time the source and destination alignments must be the same (Step 1).
Step 2 of the change, to be landed shortly, will relax that contraint and allow
the source and destination to have different alignments.

llvm-svn: 322964
2018-01-19 17:12:54 +00:00

101 lines
3.6 KiB
C

// RUN: %clang_cc1 -triple x86_64 -emit-llvm -o - %s | opt -S -strip -o %t
// RUN: FileCheck --check-prefix=CHECK-GLOBAL < %t %s
// RUN: FileCheck --check-prefix=CHECK-FUNCTIONS < %t %s
struct s0 {
int x;
int y __attribute__((packed));
};
// CHECK-GLOBAL: @s0_align_x = global i32 4
// CHECK-GLOBAL: @s0_align_y = global i32 1
// CHECK-GLOBAL: @s0_align = global i32 4
int s0_align_x = __alignof(((struct s0*)0)->x);
int s0_align_y = __alignof(((struct s0*)0)->y);
int s0_align = __alignof(struct s0);
// CHECK-FUNCTIONS-LABEL: define i32 @s0_load_x
// CHECK-FUNCTIONS: [[s0_load_x:%.*]] = load i32, i32* {{.*}}, align 4
// CHECK-FUNCTIONS: ret i32 [[s0_load_x]]
int s0_load_x(struct s0 *a) { return a->x; }
// FIXME: This seems like it should be align 1. This is actually something which
// has changed in llvm-gcc recently, previously both x and y would be loaded
// with align 1 (in 2363.1 at least).
//
// CHECK-FUNCTIONS-LABEL: define i32 @s0_load_y
// CHECK-FUNCTIONS: [[s0_load_y:%.*]] = load i32, i32* {{.*}}, align 4
// CHECK-FUNCTIONS: ret i32 [[s0_load_y]]
int s0_load_y(struct s0 *a) { return a->y; }
// CHECK-FUNCTIONS-LABEL: define void @s0_copy
// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 {{.*}}, i8* align 4 {{.*}}, i64 8, i1 false)
void s0_copy(struct s0 *a, struct s0 *b) { *b = *a; }
//
struct s1 {
int x;
int y;
} __attribute__((packed));
// CHECK-GLOBAL: @s1_align_x = global i32 1
// CHECK-GLOBAL: @s1_align_y = global i32 1
// CHECK-GLOBAL: @s1_align = global i32 1
int s1_align_x = __alignof(((struct s1*)0)->x);
int s1_align_y = __alignof(((struct s1*)0)->y);
int s1_align = __alignof(struct s1);
// CHECK-FUNCTIONS-LABEL: define i32 @s1_load_x
// CHECK-FUNCTIONS: [[s1_load_x:%.*]] = load i32, i32* {{.*}}, align 1
// CHECK-FUNCTIONS: ret i32 [[s1_load_x]]
int s1_load_x(struct s1 *a) { return a->x; }
// CHECK-FUNCTIONS-LABEL: define i32 @s1_load_y
// CHECK-FUNCTIONS: [[s1_load_y:%.*]] = load i32, i32* {{.*}}, align 1
// CHECK-FUNCTIONS: ret i32 [[s1_load_y]]
int s1_load_y(struct s1 *a) { return a->y; }
// CHECK-FUNCTIONS-LABEL: define void @s1_copy
// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i1 false)
void s1_copy(struct s1 *a, struct s1 *b) { *b = *a; }
//
#pragma pack(push,2)
struct s2 {
int x;
int y;
};
#pragma pack(pop)
// CHECK-GLOBAL: @s2_align_x = global i32 2
// CHECK-GLOBAL: @s2_align_y = global i32 2
// CHECK-GLOBAL: @s2_align = global i32 2
int s2_align_x = __alignof(((struct s2*)0)->x);
int s2_align_y = __alignof(((struct s2*)0)->y);
int s2_align = __alignof(struct s2);
// CHECK-FUNCTIONS-LABEL: define i32 @s2_load_x
// CHECK-FUNCTIONS: [[s2_load_y:%.*]] = load i32, i32* {{.*}}, align 2
// CHECK-FUNCTIONS: ret i32 [[s2_load_y]]
int s2_load_x(struct s2 *a) { return a->x; }
// CHECK-FUNCTIONS-LABEL: define i32 @s2_load_y
// CHECK-FUNCTIONS: [[s2_load_y:%.*]] = load i32, i32* {{.*}}, align 2
// CHECK-FUNCTIONS: ret i32 [[s2_load_y]]
int s2_load_y(struct s2 *a) { return a->y; }
// CHECK-FUNCTIONS-LABEL: define void @s2_copy
// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 {{.*}}, i8* align 2 {{.*}}, i64 8, i1 false)
void s2_copy(struct s2 *a, struct s2 *b) { *b = *a; }
struct __attribute__((packed, aligned)) s3 {
short aShort;
int anInt;
};
// CHECK-GLOBAL: @s3_1 = global i32 1
int s3_1 = __alignof(((struct s3*) 0)->anInt);
// CHECK-FUNCTIONS-LABEL: define i32 @test3(
int test3(struct s3 *ptr) {
// CHECK-FUNCTIONS: [[PTR:%.*]] = getelementptr inbounds {{%.*}}, {{%.*}}* {{%.*}}, i32 0, i32 1
// CHECK-FUNCTIONS-NEXT: load i32, i32* [[PTR]], align 2
return ptr->anInt;
}