
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
126 lines
5.2 KiB
C++
126 lines
5.2 KiB
C++
// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
|
|
// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -fsanitize=signed-integer-overflow -o - | FileCheck --check-prefix=SIO %s
|
|
|
|
// CHECK: @[[ABC4:.*]] = {{.*}} constant [4 x i8] c"abc\00"
|
|
// CHECK: @[[ABC15:.*]] = {{.*}} constant [15 x i8] c"abc\00\00\00\00
|
|
|
|
// CHECK-LABEL: define void @_Z2fni
|
|
void fn(int n) {
|
|
// CHECK: icmp ult i{{32|64}} %{{[^ ]+}}, 3
|
|
// CHECK: store i32 1
|
|
// CHECK: store i32 2
|
|
// CHECK: store i32 3
|
|
// CHECK: sub {{.*}}, 12
|
|
// CHECK: call void @llvm.memset
|
|
new int[n] { 1, 2, 3 };
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_Z11const_exactv
|
|
void const_exact() {
|
|
// CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
|
|
// CHECK-NOT: icmp eq i32*
|
|
new int[3] { 1, 2, 3 };
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_Z16const_sufficientv
|
|
void const_sufficient() {
|
|
// CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
|
|
new int[4] { 1, 2, 3 };
|
|
// CHECK: ret void
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_Z22check_array_value_initv
|
|
void check_array_value_init() {
|
|
struct S;
|
|
new (int S::*[3][4][5]) ();
|
|
|
|
// CHECK: call i8* @_Zna{{.}}(i{{32 240|64 480}})
|
|
// CHECK: getelementptr inbounds i{{32|64}}, i{{32|64}}* {{.*}}, i{{32|64}} 60
|
|
|
|
// CHECK: phi
|
|
// CHECK: store i{{32|64}} -1,
|
|
// CHECK: getelementptr inbounds i{{32|64}}, i{{32|64}}* {{.*}}, i{{32|64}} 1
|
|
// CHECK: icmp eq
|
|
// CHECK: br i1
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_Z15string_nonconsti
|
|
void string_nonconst(int n) {
|
|
// CHECK: icmp slt i{{32|64}} %{{[^ ]+}}, 4
|
|
// FIXME: Conditionally throw an exception rather than passing -1 to alloc function
|
|
// CHECK: select
|
|
// CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}}
|
|
// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} %[[PTR]], i8* align {{[0-9]+}} getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4,
|
|
// CHECK: %[[REST:.*]] = getelementptr inbounds i8, i8* %[[PTR]], i32 4
|
|
// CHECK: %[[RESTSIZE:.*]] = sub {{.*}}, 4
|
|
// CHECK: call void @llvm.memset{{.*}}(i8* align {{[0-9]+}} %[[REST]], i8 0, i{{32|64}} %[[RESTSIZE]],
|
|
new char[n] { "abc" };
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_Z12string_exactv
|
|
void string_exact() {
|
|
// CHECK-NOT: icmp
|
|
// CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 4)
|
|
// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} %[[PTR]], i8* align {{[0-9]+}} getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4,
|
|
// CHECK-NOT: memset
|
|
new char[4] { "abc" };
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_Z17string_sufficientv
|
|
void string_sufficient() {
|
|
// CHECK-NOT: icmp
|
|
// CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 15)
|
|
// FIXME: For very large arrays, it would be preferable to emit a small copy and a memset.
|
|
// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} %[[PTR]], i8* align {{[0-9]+}} getelementptr inbounds ([15 x i8], [15 x i8]* @[[ABC15]], i32 0, i32 0), i32 15,
|
|
// CHECK-NOT: memset
|
|
new char[15] { "abc" };
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_Z10aggr_exactv
|
|
void aggr_exact() {
|
|
// CHECK-NOT: icmp
|
|
// CHECK: %[[MEM:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 16)
|
|
// CHECK: %[[PTR0:.*]] = bitcast i8* %[[MEM]] to %[[AGGR:.*]]*
|
|
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 0{{$}}
|
|
// CHECK: store i32 1, i32* %[[FIELD]]
|
|
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 1{{$}}
|
|
// CHECK: store i32 2, i32* %[[FIELD]]
|
|
// CHECK: %[[PTR1:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 1{{$}}
|
|
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 0{{$}}
|
|
// CHECK: store i32 3, i32* %[[FIELD]]
|
|
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 1{{$}}
|
|
// CHECK: store i32 0, i32* %[[FIELD]]
|
|
// CHECK-NOT: store
|
|
// CHECK-NOT: memset
|
|
struct Aggr { int a, b; };
|
|
new Aggr[2] { 1, 2, 3 };
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_Z15aggr_sufficienti
|
|
void aggr_sufficient(int n) {
|
|
// CHECK: icmp ult i32 %{{.*}}, 2
|
|
// CHECK: %[[MEM:.*]] = call i8* @_Zna{{.}}(
|
|
// CHECK: %[[PTR0:.*]] = bitcast i8* %[[MEM]] to %[[AGGR:.*]]*
|
|
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 0{{$}}
|
|
// CHECK: store i32 1, i32* %[[FIELD]]
|
|
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 1{{$}}
|
|
// CHECK: store i32 2, i32* %[[FIELD]]
|
|
// CHECK: %[[PTR1:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 1{{$}}
|
|
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 0{{$}}
|
|
// CHECK: store i32 3, i32* %[[FIELD]]
|
|
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 1{{$}}
|
|
// CHECK: store i32 0, i32* %[[FIELD]]
|
|
// CHECK: %[[PTR2:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 1{{$}}
|
|
// CHECK: %[[REMAIN:.*]] = sub i32 {{.*}}, 16
|
|
// CHECK: %[[MEM:.*]] = bitcast %[[AGGR]]* %[[PTR2]] to i8*
|
|
// CHECK: call void @llvm.memset{{.*}}(i8* align {{[0-9]+}} %[[MEM]], i8 0, i32 %[[REMAIN]],
|
|
struct Aggr { int a, b; };
|
|
new Aggr[n] { 1, 2, 3 };
|
|
}
|
|
|
|
// SIO-LABEL: define void @_Z14constexpr_testv
|
|
void constexpr_test() {
|
|
// SIO: call i8* @_Zna{{.}}(i32 4)
|
|
new int[0+1]{0};
|
|
}
|