File: array_equals_memcmp.d

package info (click to toggle)
ldc 1%3A1.40.0-5
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 63,308 kB
  • sloc: cpp: 85,368; ansic: 21,877; makefile: 1,705; sh: 1,018; asm: 584; objc: 135; exp: 48; python: 12
file content (146 lines) | stat: -rw-r--r-- 3,449 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// 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]));
}