/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/External/isl/isl_sort.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * The code of this file was taken from http://jeffreystedfast.blogspot.be, |
3 | | * where it was posted in 2011 by Jeffrey Stedfast under the MIT license. |
4 | | * The MIT license text is as follows: |
5 | | * |
6 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | | * of this software and associated documentation files (the "Software"), to |
8 | | * deal in the Software without restriction, including without limitation the |
9 | | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
10 | | * sell copies of the Software, and to permit persons to whom the Software is |
11 | | * furnished to do so, subject to the following conditions: |
12 | | * |
13 | | * The above copyright notice and this permission notice shall be included in |
14 | | * all copies or substantial portions of the Software. |
15 | | * |
16 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
21 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
22 | | * IN THE SOFTWARE. |
23 | | */ |
24 | | |
25 | | #include <errno.h> |
26 | | #include <string.h> |
27 | | #include <stdlib.h> |
28 | | #include <isl_sort.h> |
29 | | |
30 | 2.46M | #define MID(lo, hi) (lo + ((hi - lo) >> 1)) |
31 | | |
32 | | /* The code here is an optimized merge sort. Starting from a generic merge sort |
33 | | * the following optimizations were applied: |
34 | | * |
35 | | * o Batching of memcpy() calls: Instead of calling memcpy() to copy each and |
36 | | * every element into a temporary buffer, blocks of elements are copied |
37 | | * at a time. |
38 | | * |
39 | | * o To reduce the number of memcpy() calls further, copying leading |
40 | | * and trailing elements into our temporary buffer is avoided, in case it is |
41 | | * not necessary to merge them. |
42 | | * |
43 | | * A further optimization could be to specialize memcpy calls based on the |
44 | | * size of the types we compare. For now, this code does not include the |
45 | | * relevant optimization, as clang e.g. inlines a very efficient memcpy() |
46 | | * implementation. It is not clear, that the specialized version as provided in |
47 | | * the blog post, is really superior to the one that will be inlined by |
48 | | * default. So we decided to keep the code simple until this optimization was |
49 | | * proven to be beneficial. |
50 | | */ |
51 | | |
52 | | static void |
53 | | msort (void *array, void *buf, size_t low, size_t high, size_t size, |
54 | | int (* compare) (const void *, const void *, void *), void *arg) |
55 | 2.46M | { |
56 | 2.46M | char *a1, *al, *am, *ah, *ls, *hs, *lo, *hi, *b; |
57 | 2.46M | size_t copied = 0; |
58 | 2.46M | size_t mid; |
59 | 2.46M | |
60 | 2.46M | mid = MID (low, high); |
61 | 2.46M | |
62 | 2.46M | if (mid + 1 < high) |
63 | 814k | msort (array, buf, mid + 1, high, size, compare, arg); |
64 | 2.46M | |
65 | 2.46M | if (mid > low) |
66 | 1.25M | msort (array, buf, low, mid, size, compare, arg); |
67 | 2.46M | |
68 | 2.46M | ah = ((char *) array) + ((high + 1) * size); |
69 | 2.46M | am = ((char *) array) + ((mid + 1) * size); |
70 | 2.46M | a1 = al = ((char *) array) + (low * size); |
71 | 2.46M | |
72 | 2.46M | b = (char *) buf; |
73 | 2.46M | lo = al; |
74 | 2.46M | hi = am; |
75 | 2.46M | |
76 | 2.74M | do { |
77 | 2.74M | ls = lo; |
78 | 2.74M | hs = hi; |
79 | 2.74M | |
80 | 2.74M | if (lo > al || hi > am2.56M ) { |
81 | 275k | /* our last loop already compared lo & hi and found lo <= hi */ |
82 | 275k | lo += size; |
83 | 275k | } |
84 | 2.74M | |
85 | 7.05M | while (lo < am && compare (lo, hi, arg) <= 04.99M ) |
86 | 4.31M | lo += size; |
87 | 2.74M | |
88 | 2.74M | if (lo < am) { |
89 | 678k | if (copied == 0) { |
90 | 539k | /* avoid copying the leading items */ |
91 | 539k | a1 = lo; |
92 | 539k | ls = lo; |
93 | 539k | } |
94 | 678k | |
95 | 678k | /* our last compare tells us hi < lo */ |
96 | 678k | hi += size; |
97 | 678k | |
98 | 1.11M | while (hi < ah && compare (hi, lo, arg) < 0710k ) |
99 | 434k | hi += size; |
100 | 678k | |
101 | 678k | if (lo > ls) { |
102 | 138k | memcpy (b, ls, lo - ls); |
103 | 138k | copied += (lo - ls); |
104 | 138k | b += (lo - ls); |
105 | 138k | } |
106 | 678k | |
107 | 678k | memcpy (b, hs, hi - hs); |
108 | 678k | copied += (hi - hs); |
109 | 678k | b += (hi - hs); |
110 | 2.06M | } else if (copied) { |
111 | 137k | memcpy (b, ls, lo - ls); |
112 | 137k | copied += (lo - ls); |
113 | 137k | b += (lo - ls); |
114 | 137k | |
115 | 137k | /* copy everything we needed to re-order back into array */ |
116 | 137k | memcpy (a1, buf, copied); |
117 | 137k | return; |
118 | 1.92M | } else { |
119 | 1.92M | /* everything already in order */ |
120 | 1.92M | return; |
121 | 1.92M | } |
122 | 678k | } while (hi < ah); |
123 | 2.46M | |
124 | 2.46M | if (402k lo < am402k ) { |
125 | 402k | memcpy (b, lo, am - lo); |
126 | 402k | copied += (am - lo); |
127 | 402k | } |
128 | 402k | |
129 | 402k | memcpy (a1, buf, copied); |
130 | 402k | } |
131 | | |
132 | | static int |
133 | | MergeSort (void *base, size_t nmemb, size_t size, |
134 | | int (* compare) (const void *, const void *, void *), void *arg) |
135 | 459k | { |
136 | 459k | void *tmp; |
137 | 459k | |
138 | 459k | if (nmemb < 2) |
139 | 58.1k | return 0; |
140 | 401k | |
141 | 401k | if (!(tmp = malloc (nmemb * size))) { |
142 | 0 | errno = ENOMEM; |
143 | 0 | return -1; |
144 | 0 | } |
145 | 401k | |
146 | 401k | msort (base, tmp, 0, nmemb - 1, size, compare, arg); |
147 | 401k | |
148 | 401k | free (tmp); |
149 | 401k | |
150 | 401k | return 0; |
151 | 401k | } |
152 | | |
153 | | int isl_sort(void *const pbase, size_t total_elems, size_t size, |
154 | | int (*cmp)(const void *, const void *, void *arg), void *arg) |
155 | 459k | { |
156 | 459k | return MergeSort (pbase, total_elems, size, cmp, arg); |
157 | 459k | } |