// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir // RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll // RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll // RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG void foo(void) { // CIR-LABEL: cir.func no_inline dso_local @_Z3foov() // CIR: %[[V0:.*]] = cir.alloca !cir.array, !cir.ptr>, ["f4"] {alignment = 16 : i64} // CIR: %[[V1:.*]] = cir.alloca !cir.array, !cir.ptr>, ["f8"] {alignment = 16 : i64} // CIR: %[[V2:.*]] = cir.cast array_to_ptrdecay %[[V0]] : !cir.ptr> -> !cir.ptr // CIR: %[[V3:.*]] = cir.cast bitcast %[[V2]] : !cir.ptr -> !cir.ptr // CIR: %[[V4:.*]] = cir.cast array_to_ptrdecay %[[V1]] : !cir.ptr> -> !cir.ptr // CIR: %[[V5:.*]] = cir.cast bitcast %[[V4]] : !cir.ptr -> !cir.ptr // CIR: %[[V6:.*]] = cir.const #cir.int<4> : !u64i // CIR: %[[V7:.*]] = cir.const #cir.int<4> : !u64i // CIR: %[[V8:.*]] = cir.mul %[[V6]], %[[V7]] : !u64i // CIR: cir.libc.memmove %[[V8]] bytes from %[[V3]] to %[[V5]] : !cir.ptr, !u64i // CIR: cir.return // LLVM-LABEL: define dso_local void @_Z3foov() // LLVM: %[[V1:.*]] = alloca [4 x float], i64 1, align 16 // LLVM: %[[V2:.*]] = alloca [8 x float], i64 1, align 16 // LLVM: %[[V3:.*]] = getelementptr float, ptr %[[V1]], i32 0 // LLVM: %[[V4:.*]] = getelementptr float, ptr %[[V2]], i32 0 // LLVM: call void @llvm.memmove.p0.p0.i64(ptr %[[V4]], ptr %[[V3]], i64 16, i1 false) // LLVM: ret void // OGCG-LABEL: define dso_local void @_Z3foov() // OGCG: %[[V1:.*]] = alloca [4 x float], align 16 // OGCG: %[[V2:.*]] = alloca [8 x float], align 16 // OGCG: %[[V3:.*]] = getelementptr inbounds [4 x float], ptr %[[V1]], i64 0, i64 0 // OGCG: %[[V4:.*]] = getelementptr inbounds [8 x float], ptr %[[V2]], i64 0, i64 0 // OGCG: call void @llvm.memmove.p0.p0.i64(ptr align 16 %[[V4]], ptr align 16 %[[V3]], i64 16, i1 false) // OGCG: ret void float f4[4]; float f8[8]; __builtin_bcopy(f4, f8, sizeof(float) * 4); } void test_conditional_bcopy(void) { // CIR-LABEL: cir.func {{.*}} @_Z22test_conditional_bcopyv() // CIR: cir.ternary // CIR: cir.ternary // CIR: cir.libc.memmove {{.*}} bytes from {{.*}} to {{.*}} : !cir.ptr, !u64i // CIR: false // CIR: false // CIR: cir.libc.memmove {{.*}} bytes from {{.*}} to {{.*}} : !cir.ptr, !u64i // LLVM-LABEL: define{{.*}} void @_Z22test_conditional_bcopyv // LLVM: br // LLVM: call void @llvm.memmove // LLVM: br // LLVM: call void @llvm.memmove // LLVM-NOT: phi // OGCG-LABEL: define{{.*}} void @_Z22test_conditional_bcopyv // LLVM: br // OGCG: call void @llvm.memmove // LLVM: br // OGCG: call void @llvm.memmove // OGCG-NOT: phi char dst[20]; char src[20]; int _sz = 20, len = 20; return (_sz ? ((_sz >= len) ? __builtin_bcopy(src, dst, len) : foo()) : __builtin_bcopy(src, dst, len)); } void another_conditional_bcopy(char *dst, char *src, int sz, int len) { // CIR-LABEL: cir.func no_inline dso_local @_Z25another_conditional_bcopyPcS_ii // CIR: cir.if // CIR: cir.libc.memmove {{.*}} bytes from {{.*}} to {{.*}} : !cir.ptr, !u64i // cir: else // CIR: cir.libc.memmove {{.*}} bytes from {{.*}} to {{.*}} : !cir.ptr, !u64i // LLVM-LABEL: define{{.*}} void @_Z25another_conditional_bcopyPcS_ii // LLVM: br // LLVM: call void @llvm.memmove // LLVM: br // LLVM: call void @llvm.memmove // LLVM-NOT: phi // OGCG-LABEL: define{{.*}} void @_Z25another_conditional_bcopyPcS_ii // OGCG: br // OGCG: call void @llvm.memmove // OGCG: br // OGCG: call void @llvm.memmove // OGCG-NOT: phi if (sz >= len) __builtin_bcopy(src, dst, len); else __builtin_bcopy(src, dst, len * 2); } #define size_t __SIZE_TYPE__ extern "C" void bcopy(const void *__src, void *__dest, size_t __n); // CIR: @_Z9testbcopyPKvPvm( // CIR: cir.libc.memmove {{.*}} bytes from {{.*}} to {{.*}} : !cir.ptr, !u64i // CIR: cir.return // LLVM: @_Z9testbcopyPKvPvm( // LLVM: call void @llvm.memmove.p0.p0.i64(ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i1 false) // LLVM: ret void // OGCG: @_Z9testbcopyPKvPvm( // OGCG: call void @llvm.memmove.p0.p0.i64(ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i1 false) // OGCG: ret void void testbcopy(const void *src, void *dest, size_t n) { bcopy(src, dest, n); } // CIR-LABEL: @testaddressof( // CIR: %[[SRC:.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["src", init] // CIR: %[[DEST:.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["dest", init] // CIR: %[[SRC_TO_VOIDPTR:.*]] = cir.cast bitcast %[[SRC]] : !cir.ptr> -> !cir.ptr // CIR: %[[DEST_TO_VOIDPTR:.*]] = cir.cast bitcast %[[DEST]] : !cir.ptr> -> !cir.ptr // CIR: cir.libc.memmove {{.*}} bytes from %[[SRC_TO_VOIDPTR]] to %[[DEST_TO_VOIDPTR]] // LLVM-LABEL: @testaddressof( // LLVM: %[[SRC:.*]] = alloca ptr // LLVM: %[[DEST:.*]] = alloca ptr // LLVM: call void @llvm.memmove.p0.p0.i64(ptr %[[DEST]], ptr %[[SRC]], i64 {{.*}}, i1 false) // OGCG-LABEL: @testaddressof( // OGCG: %[[SRC:.*]] = alloca ptr // OGCG: %[[DEST:.*]] = alloca ptr // OGCG: call void @llvm.memmove.p0.p0.i64(ptr {{.*}}%[[DEST]], ptr {{.*}}%[[SRC]], i64 {{.*}}, i1 false) extern "C" void testaddressof(const char *src, const char *dest, size_t n) { __builtin_bcopy(__builtin_addressof(src), __builtin_addressof(dest), n); }