mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-04 00:55:49 +03:00
146 lines
3.4 KiB
D
146 lines
3.4 KiB
D
// Tests that static array (in)equality is optimized to a memcmp call when valid.
|
|
// More importantly: test that memcmp is _not_ used when it is not valid.
|
|
|
|
// RUN: %ldc -c -output-ll -of=%t.ll %s && FileCheck %s --check-prefix=LLVM < %t.ll
|
|
// RUN: %ldc -O3 -c -output-s -of=%t.s %s && FileCheck %s --check-prefix=ASM < %t.s
|
|
// RUN: %ldc -O3 -run %s
|
|
|
|
module mod;
|
|
|
|
struct ThreeBytes
|
|
{
|
|
byte a;
|
|
byte b;
|
|
byte c;
|
|
}
|
|
|
|
align(4) struct ThreeBytesAligned
|
|
{
|
|
byte a;
|
|
byte b;
|
|
byte c;
|
|
}
|
|
|
|
struct Packed
|
|
{
|
|
byte a;
|
|
byte b;
|
|
byte c;
|
|
byte d;
|
|
}
|
|
|
|
struct PackedPacked
|
|
{
|
|
Packed a;
|
|
Packed b;
|
|
}
|
|
|
|
struct WithPadding
|
|
{
|
|
int b;
|
|
byte a;
|
|
}
|
|
|
|
// LLVM-LABEL: define{{.*}} @{{.*}}two_uints
|
|
bool two_uints(ref uint[2] a, const ref uint[2] b)
|
|
{
|
|
// LLVM: call i32 @memcmp({{.*}}, {{.*}}, i{{32|64}} 8)
|
|
return a == b;
|
|
}
|
|
|
|
// LLVM-LABEL: define{{.*}} @{{.*}}unequal_two_uints
|
|
bool unequal_two_uints(ref uint[2] a, uint[2] b)
|
|
{
|
|
// LLVM: call i32 @memcmp({{.*}}, {{.*}}, i{{32|64}} 8)
|
|
return a != b;
|
|
}
|
|
|
|
// LLVM-LABEL: define{{.*}} @{{.*}}two_floats
|
|
bool two_floats(float[2] a, float[2] b)
|
|
{
|
|
// LLVM-NOT: memcmp
|
|
return a == b;
|
|
}
|
|
|
|
// LLVM-LABEL: define{{.*}} @{{.*}}four_bools
|
|
// ASM-LABEL: four_bools{{.*}}:
|
|
bool four_bools(bool[4] a, bool[4] b)
|
|
{
|
|
// LLVM: call i32 @memcmp({{.*}}, {{.*}}, i{{32|64}} 4)
|
|
|
|
// Make sure that LLVM recognizes and optimizes-out the call to memcmp for 4 byte arrays:
|
|
// ASM-NOT: {{(mem|b)cmp}}
|
|
return a == b;
|
|
}
|
|
|
|
// LLVM-LABEL: define{{.*}} @{{.*}}array_of_array
|
|
// ASM-LABEL: array_of_array{{.*}}:
|
|
bool array_of_array(byte[3][3] a, const byte[3][3] b)
|
|
{
|
|
// LLVM: call i32 @memcmp({{.*}}, {{.*}}, i{{32|64}} 9)
|
|
return a == b;
|
|
}
|
|
|
|
// LLVM-LABEL: define{{.*}} @{{.*}}int3_short3
|
|
bool int3_short3(int[3] a, short[3] b)
|
|
{
|
|
// LLVM-NOT: memcmp
|
|
return a == b;
|
|
// LLVM-LABEL: ret i1
|
|
}
|
|
|
|
// LLVM-LABEL: define{{.*}} @{{.*}}pointer3
|
|
bool pointer3(int*[3] a, int*[3] b)
|
|
{
|
|
// LLVM: call i32 @memcmp({{.*}}, {{.*}}, i{{32|64}} {{12|24}})
|
|
return a == b;
|
|
}
|
|
|
|
// LLVM-LABEL: define{{.*}} @{{.*}}enum3
|
|
enum E : char { a, b, c, d, e, f };
|
|
bool enum3(E[3] a, E[3] b)
|
|
{
|
|
// LLVM: call i32 @memcmp({{.*}}, {{.*}}, i{{32|64}} 3)
|
|
return a == b;
|
|
}
|
|
|
|
class K {}
|
|
// LLVM-LABEL: define{{.*}} @{{.*}}klass2
|
|
bool klass2(K[2] a, K[2] b)
|
|
{
|
|
// LLVM-NOT: memcmp
|
|
return a == b;
|
|
// LLVM-LABEL: ret i1
|
|
}
|
|
|
|
void main()
|
|
{
|
|
uint[2] a = [1, 2];
|
|
uint[2] b = [1, 2];
|
|
uint[2] c = [2, 1];
|
|
assert(two_uints(a, a));
|
|
assert(two_uints(a, b));
|
|
assert(!two_uints(a, c));
|
|
assert(!unequal_two_uints(a, b));
|
|
assert(unequal_two_uints(a, c));
|
|
|
|
assert( two_floats([1.0f, 2.0f], [1.0f, 2.0f]));
|
|
assert(!two_floats([1.0f, 2.0f], [2.0f, 1.0f]));
|
|
|
|
assert( four_bools([true, false, true, false], [true, false, true, false]));
|
|
assert(!four_bools([true, false, true, false], [true, false, true, true]));
|
|
|
|
assert( array_of_array([[1,2,3],[4,5,6],[7,8,9]],[[1,2,3],[4,5,6],[7,8,9]]));
|
|
assert(!array_of_array([[1,2,3],[4,5,6],[7,8,9]],[[6,6,6],[4,5,6],[7,8,9]]));
|
|
|
|
assert( int3_short3([1, 2, 3], [1, 2, 3]));
|
|
assert(!int3_short3([1, 2, 3], [3, 2, 3]));
|
|
|
|
int aaa = 666;
|
|
int bbb = 333;
|
|
assert( pointer3([&aaa, &bbb, &aaa], [&aaa, &bbb, &aaa]));
|
|
assert(!pointer3([&aaa, &bbb, &aaa], [&bbb, &bbb, &aaa]));
|
|
|
|
assert( enum3([E.a, E.e, E.b], [E.a, E.e, E.b]));
|
|
assert(!enum3([E.a, E.e, E.b], [E.a, E.e, E.f]));
|
|
}
|