[Clang] Convert some tests to opaque pointers (NFC)

This commit is contained in:
Nikita Popov 2023-02-16 17:06:50 +01:00
parent 58dada5f0a
commit 55a18bfe9b
8 changed files with 420 additions and 511 deletions

View File

@ -1,6 +1,6 @@
// RUN: %clang_cc1 -no-opaque-pointers -triple aarch64-none-eabi -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-AAPCS
// RUN: %clang_cc1 -no-opaque-pointers -triple arm64-apple-ios7.0 -target-abi darwinpcs -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DARWIN
// RUN: %clang_cc1 -no-opaque-pointers -triple aarch64-linux-gnu -emit-llvm -o - -x c %s | FileCheck %s --check-prefixes=CHECK,CHECK-AAPCS
// RUN: %clang_cc1 -triple aarch64-none-eabi -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-AAPCS
// RUN: %clang_cc1 -triple arm64-apple-ios7.0 -target-abi darwinpcs -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DARWIN
// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - -x c %s | FileCheck %s --check-prefixes=CHECK,CHECK-AAPCS
typedef struct {
float v[2];
@ -12,7 +12,7 @@ float f0(S0 h) {
}
// CHECK: define{{.*}} float @f0_call()
// CHECK: %call = call float @f0([2 x float] %1)
// CHECK: %call = call float @f0([2 x float] %0)
float f0_call(void) {
S0 h = {1.0f, 2.0f};
return f0(h);
@ -27,7 +27,7 @@ double f1(S1 h) {
}
// CHECK: define{{.*}} double @f1_call()
// CHECK: %call = call double @f1([2 x double] %1
// CHECK: %call = call double @f1([2 x double] %0
double f1_call(void) {
S1 h = {1.0, 2.0};
return f1(h);
@ -43,8 +43,8 @@ double f2(S2 h) {
}
// CHECK: define{{.*}} double @f2_call()
// CHECK-AAPCS: %call = call double @f2([2 x double] alignstack(16) %1)
// CHECK-DARWIN: %call = call double @f2([2 x double] %1
// CHECK-AAPCS: %call = call double @f2([2 x double] alignstack(16) %0)
// CHECK-DARWIN: %call = call double @f2([2 x double] %0
double f2_call(void) {
S2 h = {1.0, 2.0};
return f2(h);
@ -61,8 +61,8 @@ double f3(S3 h) {
}
// CHECK: define{{.*}} double @f3_call()
// CHECK-AAPCS: %call = call double @f3([4 x double] alignstack(16) %1)
// CHECK-DARWIN: %call = call double @f3([4 x double] %1
// CHECK-AAPCS: %call = call double @f3([4 x double] alignstack(16) %0)
// CHECK-DARWIN: %call = call double @f3([4 x double] %0
double f3_call(void) {
S3 h = {1.0, 2.0};
return f3(h);

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
// RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -enable-var-scope -check-prefixes=CHECK,X86 %s
// RUN: %clang_cc1 -no-opaque-pointers -triple amdgcn -emit-llvm < %s | FileCheck -enable-var-scope -check-prefixes=CHECK,AMDGCN %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -enable-var-scope -check-prefixes=CHECK,X86 %s
// RUN: %clang_cc1 -triple amdgcn -emit-llvm < %s | FileCheck -enable-var-scope -check-prefixes=CHECK,AMDGCN %s
// CHECK: @foo ={{.*}} addrspace(1) global
int foo __attribute__((address_space(1)));
@ -11,11 +11,11 @@ int ban[10] __attribute__((address_space(1)));
int a __attribute__((address_space(0)));
// CHECK-LABEL: define{{.*}} i32 @test1()
// CHECK: load i32, i32 addrspace(1)* @foo
// CHECK: load i32, ptr addrspace(1) @foo
int test1(void) { return foo; }
// CHECK-LABEL: define{{.*}} i32 @test2(i32 noundef %i)
// CHECK: load i32, i32 addrspace(1)*
// CHECK: load i32, ptr addrspace(1)
// CHECK-NEXT: ret i32
int test2(int i) { return ban[i]; }
@ -23,12 +23,12 @@ int test2(int i) { return ban[i]; }
__attribute__((address_space(2))) int *A, *B;
// CHECK-LABEL: define{{.*}} void @test3()
// X86: load i32 addrspace(2)*, i32 addrspace(2)** @B
// AMDGCN: load i32 addrspace(2)*, i32 addrspace(2)** addrspacecast (i32 addrspace(2)* addrspace(1)* @B to i32 addrspace(2)**)
// CHECK: load i32, i32 addrspace(2)*
// X86: load i32 addrspace(2)*, i32 addrspace(2)** @A
// AMDGCN: load i32 addrspace(2)*, i32 addrspace(2)** addrspacecast (i32 addrspace(2)* addrspace(1)* @A to i32 addrspace(2)**)
// CHECK: store i32 {{.*}}, i32 addrspace(2)*
// X86: load ptr addrspace(2), ptr @B
// AMDGCN: load ptr addrspace(2), ptr addrspacecast (ptr addrspace(1) @B to ptr)
// CHECK: load i32, ptr addrspace(2)
// X86: load ptr addrspace(2), ptr @A
// AMDGCN: load ptr addrspace(2), ptr addrspacecast (ptr addrspace(1) @A to ptr)
// CHECK: store i32 {{.*}}, ptr addrspace(2)
void test3(void) {
*A = *B;
}
@ -39,8 +39,8 @@ typedef struct {
} MyStruct;
// CHECK-LABEL: define{{.*}} void @test4(
// CHECK: call void @llvm.memcpy.p0i8.p2i8
// CHECK: call void @llvm.memcpy.p2i8.p0i8
// CHECK: call void @llvm.memcpy.p0.p2
// CHECK: call void @llvm.memcpy.p2.p0
void test4(MyStruct __attribute__((address_space(2))) *pPtr) {
MyStruct s = pPtr[0];
pPtr[0] = s;
@ -50,21 +50,22 @@ void test4(MyStruct __attribute__((address_space(2))) *pPtr) {
// pointer. Make sure no invalid bitcast is introduced.
// CHECK-LABEL: @void_ptr_arithmetic_test(
// X86: [[ALLOCA:%.*]] = alloca i8 addrspace(1)*
// X86-NEXT: store i8 addrspace(1)* %arg, i8 addrspace(1)** [[ALLOCA]]
// X86-NEXT: load i8 addrspace(1)*, i8 addrspace(1)** [[ALLOCA]]
// X86-NEXT: getelementptr i8, i8 addrspace(1)*
// X86-NEXT: ret i8 addrspace(1)*
// X86: [[ALLOCA:%.*]] = alloca ptr addrspace(1)
// X86-NEXT: store ptr addrspace(1) %arg, ptr [[ALLOCA]]
// X86-NEXT: load ptr addrspace(1), ptr [[ALLOCA]]
// X86-NEXT: getelementptr i8, ptr addrspace(1)
// X86-NEXT: ret ptr addrspace(1)
void __attribute__((address_space(1)))*
void_ptr_arithmetic_test(void __attribute__((address_space(1))) *arg) {
return arg + 4;
}
// CHECK-LABEL: define{{.*}} i32* @test5(
// CHECK-LABEL: define{{.*}} ptr @test5(
const unsigned *test5(void) {
// Intentionally leave a part of an array uninitialized. This triggers a
// different code path contrary to a fully initialized array.
// CHECK: ret i32* getelementptr inbounds ([256 x i32]
// X86: ret ptr @test5.bars
// AMDGCN: ret ptr addrspacecast (ptr addrspace(4) @test5.bars to ptr)
static const unsigned bars[256] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20};

View File

@ -1,5 +1,5 @@
// RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-unknown-linux-gnu -O1 -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=O1
// RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-unknown-linux-gnu -O0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=O0
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=O1
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=O0
//
// Ensure that we place appropriate lifetime markers around indirectly returned
// temporaries, and that the lifetime.ends appear in a timely manner.
@ -24,29 +24,23 @@ struct S bar(void) {
// O1: %[[TMP2_ALLOCA:[^ ]+]] = alloca %struct.S
// O1: %[[TMP3_ALLOCA:[^ ]+]] = alloca %struct.S
// O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
// O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
// O1: call void @llvm.lifetime.start.p0({{[^,]*}}, ptr %[[TMP1_ALLOCA]])
// O1: call void @foo
r = foo();
// O1: memcpy
// O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
// O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
// O1: call void @llvm.lifetime.end.p0({{[^,]*}}, ptr %[[TMP1_ALLOCA]])
// O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
// O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
// O1: call void @llvm.lifetime.start.p0({{[^,]*}}, ptr %[[TMP2_ALLOCA]])
// O1: call void @foo
r = foo();
// O1: memcpy
// O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
// O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
// O1: call void @llvm.lifetime.end.p0({{[^,]*}}, ptr %[[TMP2_ALLOCA]])
// O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP3_ALLOCA]] to i8*
// O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
// O1: call void @llvm.lifetime.start.p0({{[^,]*}}, ptr %[[TMP3_ALLOCA]])
// O1: call void @foo
r = foo();
// O1: memcpy
// O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP3_ALLOCA]] to i8*
// O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
// O1: call void @llvm.lifetime.end.p0({{[^,]*}}, ptr %[[TMP3_ALLOCA]])
return r;
}
@ -65,22 +59,17 @@ struct S baz(int i, volatile int *j) {
// O1: %[[TMP2_ALLOCA:[^ ]+]] = alloca %struct.S
do {
// O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
// O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
// O1: call void @llvm.lifetime.start.p0({{[^,]*}}, ptr %[[TMP1_ALLOCA]])
//
// O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
// O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
// O1: call void @llvm.lifetime.end.p0({{[^,]*}}, ptr %[[TMP1_ALLOCA]])
//
// O1: call void @foo_int(%struct.S* sret(%struct.S) align 4 %[[TMP1_ALLOCA]],
// O1: call void @foo_int(ptr sret(%struct.S) align 4 %[[TMP1_ALLOCA]],
// O1: call void @llvm.memcpy
// O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
// O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
// O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
// O1: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
// O1: call void @foo_int(%struct.S* sret(%struct.S) align 4 %[[TMP2_ALLOCA]],
// O1: call void @llvm.lifetime.end.p0({{[^,]*}}, ptr %[[TMP1_ALLOCA]])
// O1: call void @llvm.lifetime.start.p0({{[^,]*}}, ptr %[[TMP2_ALLOCA]])
// O1: call void @foo_int(ptr sret(%struct.S) align 4 %[[TMP2_ALLOCA]],
// O1: call void @llvm.memcpy
// O1: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
// O1: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
// O1: call void @llvm.lifetime.end.p0({{[^,]*}}, ptr %[[TMP2_ALLOCA]])
r = foo_int(({
if (*j)
break;

View File

@ -1,6 +1,6 @@
// RUN: %clang_cc1 -no-opaque-pointers -fms-extensions -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=X64
// RUN: %clang_cc1 -no-opaque-pointers -fms-extensions -triple thumbv7-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=ARM
// RUN: %clang_cc1 -no-opaque-pointers -fms-extensions -triple aarch64-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=ARM
// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=X64
// RUN: %clang_cc1 -fms-extensions -triple thumbv7-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=ARM
// RUN: %clang_cc1 -fms-extensions -triple aarch64-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=ARM
volatile unsigned char sink = 0;
void test32(long *base, long idx) {
@ -33,103 +33,97 @@ void test_arm(long *base, long idx) {
}
#endif
// X64-LABEL: define dso_local void @test32(i32* noundef %base, i32 noundef %idx)
// X64: call i8 asm sideeffect "btl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32 {{.*}})
// X64: call i8 asm sideeffect "btcl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32 {{.*}})
// X64: call i8 asm sideeffect "btrl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32 {{.*}})
// X64: call i8 asm sideeffect "btsl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32 {{.*}})
// X64: call i8 asm sideeffect "lock btrl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32 {{.*}})
// X64: call i8 asm sideeffect "lock btsl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32 {{.*}})
// X64-LABEL: define dso_local void @test32(ptr noundef %base, i32 noundef %idx)
// X64: call i8 asm sideeffect "btl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i32 {{.*}})
// X64: call i8 asm sideeffect "btcl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i32 {{.*}})
// X64: call i8 asm sideeffect "btrl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i32 {{.*}})
// X64: call i8 asm sideeffect "btsl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i32 {{.*}})
// X64: call i8 asm sideeffect "lock btrl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i32 {{.*}})
// X64: call i8 asm sideeffect "lock btsl $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i32 {{.*}})
// X64-LABEL: define dso_local void @test64(i64* noundef %base, i64 noundef %idx)
// X64: call i8 asm sideeffect "btq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %{{.*}}, i64 {{.*}})
// X64: call i8 asm sideeffect "btcq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %{{.*}}, i64 {{.*}})
// X64: call i8 asm sideeffect "btrq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %{{.*}}, i64 {{.*}})
// X64: call i8 asm sideeffect "btsq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %{{.*}}, i64 {{.*}})
// X64: call i8 asm sideeffect "lock btrq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %{{.*}}, i64 {{.*}})
// X64: call i8 asm sideeffect "lock btsq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %{{.*}}, i64 {{.*}})
// X64-LABEL: define dso_local void @test64(ptr noundef %base, i64 noundef %idx)
// X64: call i8 asm sideeffect "btq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i64 {{.*}})
// X64: call i8 asm sideeffect "btcq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i64 {{.*}})
// X64: call i8 asm sideeffect "btrq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i64 {{.*}})
// X64: call i8 asm sideeffect "btsq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i64 {{.*}})
// X64: call i8 asm sideeffect "lock btrq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i64 {{.*}})
// X64: call i8 asm sideeffect "lock btsq $2, ($1)", "={@ccc},r,r,~{cc},~{memory},~{dirflag},~{fpsr},~{flags}"(ptr %{{.*}}, i64 {{.*}})
// ARM-LABEL: define dso_local {{.*}}void @test32(i32* noundef %base, i32 noundef %idx)
// ARM-LABEL: define dso_local {{.*}}void @test32(ptr noundef %base, i32 noundef %idx)
// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 %[[IDXHI]]
// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
// ARM: %[[BYTE:[^ ]*]] = load i8, ptr %[[BYTEADDR]], align 1
// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
// ARM: store volatile i8 %[[RES]], ptr @sink, align 1
// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 %[[IDXHI]]
// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
// ARM: %[[BYTE:[^ ]*]] = load i8, ptr %[[BYTEADDR]], align 1
// ARM: %[[NEWBYTE:[^ ]*]] = xor i8 %[[BYTE]], %[[MASK]]
// ARM: store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1
// ARM: store i8 %[[NEWBYTE]], ptr %[[BYTEADDR]], align 1
// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
// ARM: store volatile i8 %[[RES]], ptr @sink, align 1
// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 %[[IDXHI]]
// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
// ARM: %[[BYTE:[^ ]*]] = load i8, ptr %[[BYTEADDR]], align 1
// ARM: %[[NOTMASK:[^ ]*]] = xor i8 %[[MASK]], -1
// ARM: %[[NEWBYTE:[^ ]*]] = and i8 %[[BYTE]], %[[NOTMASK]]
// ARM: store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1
// ARM: store i8 %[[NEWBYTE]], ptr %[[BYTEADDR]], align 1
// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
// ARM: store volatile i8 %[[RES]], ptr @sink, align 1
// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 %[[IDXHI]]
// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
// ARM: %[[BYTE:[^ ]*]] = load i8, ptr %[[BYTEADDR]], align 1
// ARM: %[[NEWBYTE:[^ ]*]] = or i8 %[[BYTE]], %[[MASK]]
// ARM: store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1
// ARM: store i8 %[[NEWBYTE]], ptr %[[BYTEADDR]], align 1
// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
// ARM: store volatile i8 %[[RES]], ptr @sink, align 1
// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 %[[IDXHI]]
// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
// ARM: %[[NOTMASK:[^ ]*]] = xor i8 %[[MASK]], -1
// ARM: %[[BYTE:[^ ]*]] = atomicrmw and i8* %[[BYTEADDR]], i8 %[[NOTMASK]] seq_cst, align 1
// ARM: %[[BYTE:[^ ]*]] = atomicrmw and ptr %[[BYTEADDR]], i8 %[[NOTMASK]] seq_cst, align 1
// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
// ARM: store volatile i8 %[[RES]], ptr @sink, align 1
// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 %[[IDXHI]]
// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
// ARM: %[[BYTE:[^ ]*]] = atomicrmw or i8* %[[BYTEADDR]], i8 %[[MASK]] seq_cst, align 1
// ARM: %[[BYTE:[^ ]*]] = atomicrmw or ptr %[[BYTEADDR]], i8 %[[MASK]] seq_cst, align 1
// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
// ARM: store volatile i8 %[[RES]], ptr @sink, align 1
// Just look for the atomicrmw instructions.
// ARM-LABEL: define dso_local {{.*}}void @test_arm(i32* noundef %base, i32 noundef %idx)
// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} acquire, align 1
// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} release, align 1
// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} monotonic, align 1
// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} acquire, align 1
// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} release, align 1
// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} monotonic, align 1
// ARM-LABEL: define dso_local {{.*}}void @test_arm(ptr noundef %base, i32 noundef %idx)
// ARM: atomicrmw and ptr %{{.*}}, i8 {{.*}} acquire, align 1
// ARM: atomicrmw and ptr %{{.*}}, i8 {{.*}} release, align 1
// ARM: atomicrmw and ptr %{{.*}}, i8 {{.*}} monotonic, align 1
// ARM: atomicrmw or ptr %{{.*}}, i8 {{.*}} acquire, align 1
// ARM: atomicrmw or ptr %{{.*}}, i8 {{.*}} release, align 1
// ARM: atomicrmw or ptr %{{.*}}, i8 {{.*}} monotonic, align 1

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -no-opaque-pointers -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s
#include <stdarg.h>
// CHECK-LABEL: define{{.*}} void @f_void()
@ -26,7 +26,7 @@ struct small {
int *a, *b;
};
// CHECK-LABEL: define{{.*}} %struct.small @f_small(i32* %x.coerce0, i32* %x.coerce1)
// CHECK-LABEL: define{{.*}} %struct.small @f_small(ptr %x.coerce0, ptr %x.coerce1)
struct small f_small(struct small x) {
x.a += *x.b;
x.b = 0;
@ -39,7 +39,7 @@ struct medium {
int *c, *d;
};
// CHECK-LABEL: define{{.*}} %struct.medium @f_medium(%struct.medium* noundef %x)
// CHECK-LABEL: define{{.*}} %struct.medium @f_medium(ptr noundef %x)
struct medium f_medium(struct medium x) {
x.a += *x.b;
x.b = 0;
@ -53,7 +53,7 @@ struct large {
int x;
};
// CHECK-LABEL: define{{.*}} void @f_large(%struct.large* noalias sret(%struct.large) align 8 %agg.result, %struct.large* noundef %x)
// CHECK-LABEL: define{{.*}} void @f_large(ptr noalias sret(%struct.large) align 8 %agg.result, ptr noundef %x)
struct large f_large(struct large x) {
x.a += *x.b;
x.b = 0;
@ -120,8 +120,8 @@ void call_tiny(void) {
f_tiny(x);
}
// CHECK-LABEL: define{{.*}} signext i32 @f_variable(i8* noundef %f, ...)
// CHECK: %ap = alloca i8*
// CHECK-LABEL: define{{.*}} signext i32 @f_variable(ptr noundef %f, ...)
// CHECK: %ap = alloca ptr
// CHECK: call void @llvm.va_start
//
int f_variable(char *f, ...) {
@ -131,50 +131,45 @@ int f_variable(char *f, ...) {
va_start(ap, f);
while ((c = *f++)) switch (c) {
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 8
// CHECK-DAG: store i8* %[[NXT]], i8** %ap
// CHECK-DAG: %[[EXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 4
// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[EXT]] to i32*
// CHECK-DAG: load i32, i32* %[[ADR]]
// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8
// CHECK-DAG: store ptr %[[NXT]], ptr %ap
// CHECK-DAG: %[[EXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 4
// CHECK-DAG: load i32, ptr %[[EXT]]
// CHECK: br
case 'i':
s += va_arg(ap, int);
break;
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 8
// CHECK-DAG: store i8* %[[NXT]], i8** %ap
// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to i64*
// CHECK-DAG: load i64, i64* %[[ADR]]
// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8
// CHECK-DAG: store ptr %[[NXT]], ptr %ap
// CHECK-DAG: load i64, ptr %[[CUR]]
// CHECK: br
case 'l':
s += va_arg(ap, long);
break;
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 8
// CHECK-DAG: store i8* %[[NXT]], i8** %ap
// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.tiny*
// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8
// CHECK-DAG: store ptr %[[NXT]], ptr %ap
// CHECK: br
case 't':
s += va_arg(ap, struct tiny).a;
break;
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 16
// CHECK-DAG: store i8* %[[NXT]], i8** %ap
// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.small*
// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 16
// CHECK-DAG: store ptr %[[NXT]], ptr %ap
// CHECK: br
case 's':
s += *va_arg(ap, struct small).a;
break;
// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 8
// CHECK-DAG: store i8* %[[NXT]], i8** %ap
// CHECK-DAG: %[[IND:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.medium**
// CHECK-DAG: %[[ADR:[^ ]+]] = load %struct.medium*, %struct.medium** %[[IND]]
// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8
// CHECK-DAG: store ptr %[[NXT]], ptr %ap
// CHECK-DAG: %[[ADR:[^ ]+]] = load ptr, ptr %[[CUR]]
// CHECK: br
case 'm':
s += *va_arg(ap, struct medium).a;

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
// RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
// RUN: -o - -mconstructor-aliases -fcxx-exceptions -fexceptions | FileCheck %s
extern "C" int basic_filter(int v, ...);
@ -14,20 +14,18 @@ extern "C" void test_freefunc(int p1) {
}
// CHECK-LABEL: define dso_local void @test_freefunc(i32 noundef %p1)
// CHECK: @llvm.localescape(i32* %[[p1_ptr:[^, ]*]], i32* %[[l1_ptr:[^, ]*]])
// CHECK: store i32 %p1, i32* %[[p1_ptr]], align 4
// CHECK: store i32 13, i32* %[[l1_ptr]], align 4
// CHECK: @llvm.localescape(ptr %[[p1_ptr:[^, ]*]], ptr %[[l1_ptr:[^, ]*]])
// CHECK: store i32 %p1, ptr %[[p1_ptr]], align 4
// CHECK: store i32 13, ptr %[[l1_ptr]], align 4
// CHECK: invoke void @might_crash()
// CHECK-LABEL: define internal noundef i32 @"?filt$0@0@test_freefunc@@"(i8* noundef %exception_pointers, i8* noundef %frame_pointer)
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer)
// CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32*
// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 1)
// CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
// CHECK: %[[s1:[^ ]*]] = load i32, i32* @"?s1@?1??test_freefunc@@9@4HA", align 4
// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
// CHECK: %[[p1:[^ ]*]] = load i32, i32* %[[p1_ptr]]
// CHECK-LABEL: define internal noundef i32 @"?filt$0@0@test_freefunc@@"(ptr noundef %exception_pointers, ptr noundef %frame_pointer)
// CHECK: %[[fp:[^ ]*]] = call ptr @llvm.eh.recoverfp(ptr @test_freefunc, ptr %frame_pointer)
// CHECK: %[[p1_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @test_freefunc, ptr %[[fp]], i32 0)
// CHECK: %[[l1_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @test_freefunc, ptr %[[fp]], i32 1)
// CHECK: %[[s1:[^ ]*]] = load i32, ptr @"?s1@?1??test_freefunc@@9@4HA", align 4
// CHECK: %[[l1:[^ ]*]] = load i32, ptr %[[l1_i8]]
// CHECK: %[[p1:[^ ]*]] = load i32, ptr %[[p1_i8]]
// CHECK: call i32 (i32, ...) @basic_filter(i32 noundef %[[p1]], i32 noundef %[[l1]], i32 noundef %[[s1]])
struct S {
@ -43,22 +41,20 @@ void S::test_method() {
}
}
// CHECK-LABEL: define dso_local void @"?test_method@S@@QEAAXXZ"(%struct.S* {{[^,]*}} %this)
// CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]], %struct.S** %[[this_addr:[^, ]*]])
// CHECK: store %struct.S* %this, %struct.S** %[[this_addr]], align 8
// CHECK: store i32 13, i32* %[[l1_addr]], align 4
// CHECK-LABEL: define dso_local void @"?test_method@S@@QEAAXXZ"(ptr {{[^,]*}} %this)
// CHECK: @llvm.localescape(ptr %[[l1_addr:[^, ]*]], ptr %[[this_addr:[^, ]*]])
// CHECK: store ptr %this, ptr %[[this_addr]], align 8
// CHECK: store i32 13, ptr %[[l1_addr]], align 4
// CHECK: invoke void @might_crash()
// CHECK-LABEL: define internal noundef i32 @"?filt$0@0@test_method@S@@"(i8* noundef %exception_pointers, i8* noundef %frame_pointer)
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
// CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 1)
// CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %struct.S**
// CHECK: %[[this:[^ ]*]] = load %struct.S*, %struct.S** %[[this_ptr]], align 8
// CHECK: %[[m1_ptr:[^ ]*]] = getelementptr inbounds %struct.S, %struct.S* %[[this]], i32 0, i32 0
// CHECK: %[[m1:[^ ]*]] = load i32, i32* %[[m1_ptr]]
// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
// CHECK-LABEL: define internal noundef i32 @"?filt$0@0@test_method@S@@"(ptr noundef %exception_pointers, ptr noundef %frame_pointer)
// CHECK: %[[fp:[^ ]*]] = call ptr @llvm.eh.recoverfp(ptr @"?test_method@S@@QEAAXXZ", ptr %frame_pointer)
// CHECK: %[[l1_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"?test_method@S@@QEAAXXZ", ptr %[[fp]], i32 0)
// CHECK: %[[this_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"?test_method@S@@QEAAXXZ", ptr %[[fp]], i32 1)
// CHECK: %[[this:[^ ]*]] = load ptr, ptr %[[this_i8]], align 8
// CHECK: %[[m1_ptr:[^ ]*]] = getelementptr inbounds %struct.S, ptr %[[this]], i32 0, i32 0
// CHECK: %[[m1:[^ ]*]] = load i32, ptr %[[m1_ptr]]
// CHECK: %[[l1:[^ ]*]] = load i32, ptr %[[l1_i8]]
// CHECK: call i32 (i32, ...) @basic_filter(i32 noundef %[[l1]], i32 noundef %[[m1]])
struct V {
@ -74,24 +70,21 @@ void V::test_virtual(int p1) {
}
}
// CHECK-LABEL: define dso_local void @"?test_virtual@V@@QEAAXH@Z"(%struct.V* {{[^,]*}} %this, i32 noundef %p1)
// CHECK: @llvm.localescape(%struct.V** %[[this_addr:[^, ]*]], i32* %[[p1_addr:[^, ]*]])
// CHECK: store i32 %p1, i32* %[[p1_addr]], align 4
// CHECK: store %struct.V* %this, %struct.V** %[[this_addr]], align 8
// CHECK-LABEL: define dso_local void @"?test_virtual@V@@QEAAXH@Z"(ptr {{[^,]*}} %this, i32 noundef %p1)
// CHECK: @llvm.localescape(ptr %[[this_addr:[^, ]*]], ptr %[[p1_addr:[^, ]*]])
// CHECK: store i32 %p1, ptr %[[p1_addr]], align 4
// CHECK: store ptr %this, ptr %[[this_addr]], align 8
// CHECK: invoke void @might_crash()
// CHECK-LABEL: define internal void @"?fin$0@0@test_virtual@V@@"(i8 noundef %abnormal_termination, i8* noundef %frame_pointer)
// CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.V*, i32)* @"?test_virtual@V@@QEAAXH@Z" to i8*), i8* %frame_pointer, i32 0)
// CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %struct.V**
// CHECK: %[[this:[^ ]*]] = load %struct.V*, %struct.V** %[[this_ptr]], align 8
// CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.V*, i32)* @"?test_virtual@V@@QEAAXH@Z" to i8*), i8* %frame_pointer, i32 1)
// CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32*
// CHECK: %[[p1:[^ ]*]] = load i32, i32* %[[p1_ptr]]
// CHECK: %[[this_2:[^ ]*]] = bitcast %struct.V* %[[this]] to void (%struct.V*, i32)***
// CHECK: %[[vtable:[^ ]*]] = load void (%struct.V*, i32)**, void (%struct.V*, i32)*** %[[this_2]], align 8
// CHECK: %[[vfn:[^ ]*]] = getelementptr inbounds void (%struct.V*, i32)*, void (%struct.V*, i32)** %[[vtable]], i64 0
// CHECK: %[[virt:[^ ]*]] = load void (%struct.V*, i32)*, void (%struct.V*, i32)** %[[vfn]], align 8
// CHECK: call void %[[virt]](%struct.V* {{[^,]*}} %[[this]], i32 noundef %[[p1]])
// CHECK-LABEL: define internal void @"?fin$0@0@test_virtual@V@@"(i8 noundef %abnormal_termination, ptr noundef %frame_pointer)
// CHECK: %[[this_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"?test_virtual@V@@QEAAXH@Z", ptr %frame_pointer, i32 0)
// CHECK: %[[this:[^ ]*]] = load ptr, ptr %[[this_i8]], align 8
// CHECK: %[[p1_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"?test_virtual@V@@QEAAXH@Z", ptr %frame_pointer, i32 1)
// CHECK: %[[p1:[^ ]*]] = load i32, ptr %[[p1_i8]]
// CHECK: %[[vtable:[^ ]*]] = load ptr, ptr %[[this]], align 8
// CHECK: %[[vfn:[^ ]*]] = getelementptr inbounds ptr, ptr %[[vtable]], i64 0
// CHECK: %[[virt:[^ ]*]] = load ptr, ptr %[[vfn]], align 8
// CHECK: call void %[[virt]](ptr {{[^,]*}} %[[this]], i32 noundef %[[p1]])
void test_lambda() {
int l1 = 13;
@ -105,23 +98,21 @@ void test_lambda() {
lambda();
}
// CHECK-LABEL: define internal void @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(%class.anon* {{[^,]*}} %this)
// CHECK: @llvm.localescape(%class.anon** %[[this_addr:[^, ]*]], i32* %[[l2_addr:[^, ]*]])
// CHECK: store %class.anon* %this, %class.anon** %[[this_addr]], align 8
// CHECK: store i32 42, i32* %[[l2_addr]], align 4
// CHECK-LABEL: define internal void @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(ptr {{[^,]*}} %this)
// CHECK: @llvm.localescape(ptr %[[this_addr:[^, ]*]], ptr %[[l2_addr:[^, ]*]])
// CHECK: store ptr %this, ptr %[[this_addr]], align 8
// CHECK: store i32 42, ptr %[[l2_addr]], align 4
// CHECK: invoke void @might_crash()
// CHECK-LABEL: define internal noundef i32 @"?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* noundef %exception_pointers, i8* noundef %frame_pointer)
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %frame_pointer)
// CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %class.anon**
// CHECK: %[[this:[^ ]*]] = load %class.anon*, %class.anon** %[[this_ptr]], align 8
// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %[[fp]], i32 1)
// CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32*
// CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]]
// CHECK: %[[l1_ref_ptr:[^ ]*]] = getelementptr inbounds %class.anon, %class.anon* %[[this]], i32 0, i32 0
// CHECK: %[[l1_ref:[^ ]*]] = load i32*, i32** %[[l1_ref_ptr]]
// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ref]]
// CHECK-LABEL: define internal noundef i32 @"?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(ptr noundef %exception_pointers, ptr noundef %frame_pointer)
// CHECK: %[[fp:[^ ]*]] = call ptr @llvm.eh.recoverfp(ptr @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ", ptr %frame_pointer)
// CHECK: %[[this_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ", ptr %[[fp]], i32 0)
// CHECK: %[[this:[^ ]*]] = load ptr, ptr %[[this_i8]], align 8
// CHECK: %[[l2_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ", ptr %[[fp]], i32 1)
// CHECK: %[[l2:[^ ]*]] = load i32, ptr %[[l2_i8]]
// CHECK: %[[l1_ref_ptr:[^ ]*]] = getelementptr inbounds %class.anon, ptr %[[this]], i32 0, i32 0
// CHECK: %[[l1_ref:[^ ]*]] = load ptr, ptr %[[l1_ref_ptr]]
// CHECK: %[[l1:[^ ]*]] = load i32, ptr %[[l1_ref]]
// CHECK: call i32 (i32, ...) @basic_filter(i32 noundef %[[l1]], i32 noundef %[[l2]])
struct U {
@ -138,10 +129,9 @@ void U::this_in_lambda() {
lambda();
}
// CHECK-LABEL: define internal noundef i32 @"?filt$0@0@?R<lambda_1>@?0??this_in_lambda@U@@QEAAXXZ@"(i8* noundef %exception_pointers, i8* noundef %frame_pointer)
// CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon.0*)* @"??R<lambda_1>@?0??this_in_lambda@U@@QEAAXXZ@QEBA@XZ" to i8*), i8* %[[fp:[^ ]*]], i32 0)
// CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %class.anon.0**
// CHECK: %[[this:[^ ]*]] = load %class.anon.0*, %class.anon.0** %[[this_ptr]], align 8
// CHECK: %[[actual_this_ptr:[^ ]*]] = getelementptr inbounds %class.anon.0, %class.anon.0* %[[this]], i32 0, i32 0
// CHECK: %[[actual_this:[^ ]*]] = load %struct.U*, %struct.U** %[[actual_this_ptr]], align 8
// CHECK: call i32 (i32, ...) @basic_filter(i32 noundef 0, %struct.U* noundef %[[actual_this]])
// CHECK-LABEL: define internal noundef i32 @"?filt$0@0@?R<lambda_1>@?0??this_in_lambda@U@@QEAAXXZ@"(ptr noundef %exception_pointers, ptr noundef %frame_pointer)
// CHECK: %[[this_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"??R<lambda_1>@?0??this_in_lambda@U@@QEAAXXZ@QEBA@XZ", ptr %[[fp:[^ ]*]], i32 0)
// CHECK: %[[this:[^ ]*]] = load ptr, ptr %[[this_i8]], align 8
// CHECK: %[[actual_this_ptr:[^ ]*]] = getelementptr inbounds %class.anon.0, ptr %[[this]], i32 0, i32 0
// CHECK: %[[actual_this:[^ ]*]] = load ptr, ptr %[[actual_this_ptr]], align 8
// CHECK: call i32 (i32, ...) @basic_filter(i32 noundef 0, ptr noundef %[[actual_this]])

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -no-opaque-pointers %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t
// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t
// RUN: FileCheck %s < %t
// RUN: FileCheck --check-prefix=BITCODE %s < %t.ll
@ -156,17 +156,15 @@ struct C : public A, public B {
// BITCODE-LABEL: define {{.*}}"?ffun@test4@@YAXAAUC@1@@Z
void ffun(C &c) {
// BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8*
// BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, i8* [[THIS1]], i32 4
// BITCODE: call x86_thiscallcc {{.*}}(i8* noundef [[THIS2]])
// BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, ptr {{.*}}, i32 4
// BITCODE: call x86_thiscallcc {{.*}}(ptr noundef [[THIS2]])
c.bar();
}
// BITCODE-LABEL: define {{.*}}"?fop@test4@@YAXAAUC@1@@Z
void fop(C &c) {
// BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8*
// BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, i8* [[THIS1]], i32 4
// BITCODE: call x86_thiscallcc {{.*}}(i8* noundef [[THIS2]])
// BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8, ptr {{.*}}, i32 4
// BITCODE: call x86_thiscallcc {{.*}}(ptr noundef [[THIS2]])
-c;
}
@ -189,12 +187,9 @@ void C::g(NonTrivial o) {
whatsthis = this;
}
// BITCODE-LABEL: define dso_local void @"?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca(<{ i8*, %"struct.pr30293::NonTrivial" }>) %0)
// BITCODE: %[[thisaddr:[^ ]*]] = getelementptr inbounds <{ i8*, %"struct.pr30293::NonTrivial" }>, <{ i8*, %"struct.pr30293::NonTrivial" }>* {{.*}}, i32 0, i32 0
// BITCODE: %[[thisaddr1:[^ ]*]] = bitcast i8** %[[thisaddr]] to %"struct.pr30293::C"**
// BITCODE: %[[this1:[^ ]*]] = load %"struct.pr30293::C"*, %"struct.pr30293::C"** %[[thisaddr1]], align 4
// BITCODE: %[[this2:[^ ]*]] = bitcast %"struct.pr30293::C"* %[[this1]] to i8*
// BITCODE: %[[this3:[^ ]*]] = getelementptr inbounds i8, i8* %[[this2]], i32 -4
// BITCODE: %[[this4:[^ ]*]] = bitcast i8* %[[this3]] to %"struct.pr30293::C"*
// BITCODE: store %"struct.pr30293::C"* %[[this4]], %"struct.pr30293::C"** @"?whatsthis@pr30293@@3PAUC@1@A", align 4
// BITCODE-LABEL: define dso_local void @"?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(ptr inalloca(<{ ptr, %"struct.pr30293::NonTrivial" }>) %0)
// BITCODE: %[[thisaddr:[^ ]*]] = getelementptr inbounds <{ ptr, %"struct.pr30293::NonTrivial" }>, ptr {{.*}}, i32 0, i32 0
// BITCODE: %[[this1:[^ ]*]] = load ptr, ptr %[[thisaddr]], align 4
// BITCODE: %[[this3:[^ ]*]] = getelementptr inbounds i8, ptr %[[this1]], i32 -4
// BITCODE: store ptr %[[this3]], ptr @"?whatsthis@pr30293@@3PAUC@1@A", align 4
}