Skip to content

Commit 5b1fdac

Browse files
committed
Point: apply hoist/restrict optimizations
1 parent 6590b1b commit 5b1fdac

1 file changed

Lines changed: 61 additions & 44 deletions

File tree

src/libImaging/Point.c

Lines changed: 61 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,31 @@ typedef struct {
2727

2828
static void
2929
im_point_8_8(Imaging imOut, Imaging imIn, im_point_context *context) {
30-
int x, y;
3130
/* 8-bit source, 8-bit destination */
3231
UINT8 *table = (UINT8 *)context->table;
33-
for (y = 0; y < imIn->ysize; y++) {
34-
UINT8 *in = imIn->image8[y];
35-
UINT8 *out = imOut->image8[y];
36-
for (x = 0; x < imIn->xsize; x++) {
32+
// Invariant over the loop.
33+
int xsize = imIn->xsize, ysize = imIn->ysize;
34+
for (int y = 0; y < ysize; y++) {
35+
// restrict safe: imIn is read-only, imOut is a fresh allocation.
36+
UINT8 *restrict in = imIn->image8[y];
37+
UINT8 *restrict out = imOut->image8[y];
38+
for (int x = 0; x < xsize; x++) {
3739
out[x] = table[in[x]];
3840
}
3941
}
4042
}
4143

4244
static void
4345
im_point_2x8_2x8(Imaging imOut, Imaging imIn, im_point_context *context) {
44-
int x, y;
4546
/* 2x8-bit source, 2x8-bit destination */
4647
UINT8 *table = (UINT8 *)context->table;
47-
for (y = 0; y < imIn->ysize; y++) {
48-
UINT8 *in = (UINT8 *)imIn->image[y];
49-
UINT8 *out = (UINT8 *)imOut->image[y];
50-
for (x = 0; x < imIn->xsize; x++) {
48+
// Invariant over the loop.
49+
int xsize = imIn->xsize, ysize = imIn->ysize;
50+
for (int y = 0; y < ysize; y++) {
51+
// restrict safe: imIn is read-only, imOut is a fresh allocation.
52+
UINT8 *restrict in = (UINT8 *)imIn->image[y];
53+
UINT8 *restrict out = (UINT8 *)imOut->image[y];
54+
for (int x = 0; x < xsize; x++) {
5155
out[0] = table[in[0]];
5256
out[3] = table[in[3] + 256];
5357
in += 4;
@@ -58,13 +62,15 @@ im_point_2x8_2x8(Imaging imOut, Imaging imIn, im_point_context *context) {
5862

5963
static void
6064
im_point_3x8_3x8(Imaging imOut, Imaging imIn, im_point_context *context) {
61-
int x, y;
6265
/* 3x8-bit source, 3x8-bit destination */
6366
UINT8 *table = (UINT8 *)context->table;
64-
for (y = 0; y < imIn->ysize; y++) {
65-
UINT8 *in = (UINT8 *)imIn->image[y];
66-
UINT8 *out = (UINT8 *)imOut->image[y];
67-
for (x = 0; x < imIn->xsize; x++) {
67+
// Invariant over the loop.
68+
int xsize = imIn->xsize, ysize = imIn->ysize;
69+
for (int y = 0; y < ysize; y++) {
70+
// restrict safe: imIn is read-only, imOut is a fresh allocation.
71+
UINT8 *restrict in = (UINT8 *)imIn->image[y];
72+
UINT8 *restrict out = (UINT8 *)imOut->image[y];
73+
for (int x = 0; x < xsize; x++) {
6874
out[0] = table[in[0]];
6975
out[1] = table[in[1] + 256];
7076
out[2] = table[in[2] + 512];
@@ -76,13 +82,15 @@ im_point_3x8_3x8(Imaging imOut, Imaging imIn, im_point_context *context) {
7682

7783
static void
7884
im_point_4x8_4x8(Imaging imOut, Imaging imIn, im_point_context *context) {
79-
int x, y;
8085
/* 4x8-bit source, 4x8-bit destination */
8186
UINT8 *table = (UINT8 *)context->table;
82-
for (y = 0; y < imIn->ysize; y++) {
83-
UINT8 *in = (UINT8 *)imIn->image[y];
84-
UINT8 *out = (UINT8 *)imOut->image[y];
85-
for (x = 0; x < imIn->xsize; x++) {
87+
// Invariant over the loop.
88+
int xsize = imIn->xsize, ysize = imIn->ysize;
89+
for (int y = 0; y < ysize; y++) {
90+
// restrict safe: imIn is read-only, imOut is a fresh allocation.
91+
UINT8 *restrict in = (UINT8 *)imIn->image[y];
92+
UINT8 *restrict out = (UINT8 *)imOut->image[y];
93+
for (int x = 0; x < xsize; x++) {
8694
out[0] = table[in[0]];
8795
out[1] = table[in[1] + 256];
8896
out[2] = table[in[2] + 512];
@@ -95,27 +103,31 @@ im_point_4x8_4x8(Imaging imOut, Imaging imIn, im_point_context *context) {
95103

96104
static void
97105
im_point_8_32(Imaging imOut, Imaging imIn, im_point_context *context) {
98-
int x, y;
99106
/* 8-bit source, 32-bit destination */
100107
char *table = (char *)context->table;
101-
for (y = 0; y < imIn->ysize; y++) {
102-
UINT8 *in = imIn->image8[y];
103-
INT32 *out = imOut->image32[y];
104-
for (x = 0; x < imIn->xsize; x++) {
108+
// Invariant over the loop.
109+
int xsize = imIn->xsize, ysize = imIn->ysize;
110+
for (int y = 0; y < ysize; y++) {
111+
// restrict safe: imIn is read-only, imOut is a fresh allocation.
112+
UINT8 *restrict in = imIn->image8[y];
113+
INT32 *restrict out = imOut->image32[y];
114+
for (int x = 0; x < xsize; x++) {
105115
memcpy(out + x, table + in[x] * sizeof(INT32), sizeof(INT32));
106116
}
107117
}
108118
}
109119

110120
static void
111121
im_point_32_8(Imaging imOut, Imaging imIn, im_point_context *context) {
112-
int x, y;
113122
/* 32-bit source, 8-bit destination */
114123
UINT8 *table = (UINT8 *)context->table;
115-
for (y = 0; y < imIn->ysize; y++) {
116-
INT32 *in = imIn->image32[y];
117-
UINT8 *out = imOut->image8[y];
118-
for (x = 0; x < imIn->xsize; x++) {
124+
// Invariant over the loop.
125+
int xsize = imIn->xsize, ysize = imIn->ysize;
126+
for (int y = 0; y < ysize; y++) {
127+
// restrict safe: imIn is read-only, imOut is a fresh allocation.
128+
INT32 *restrict in = imIn->image32[y];
129+
UINT8 *restrict out = imOut->image8[y];
130+
for (int x = 0; x < xsize; x++) {
119131
int v = in[x];
120132
if (v < 0) {
121133
v = 0;
@@ -208,37 +220,41 @@ ImagingPointTransform(Imaging imIn, double scale, double offset) {
208220

209221
ImagingSectionCookie cookie;
210222
Imaging imOut;
211-
int x, y;
212223

213224
if (!imIn || (imIn->mode != IMAGING_MODE_I && imIn->mode != IMAGING_MODE_I_16 &&
214225
imIn->mode != IMAGING_MODE_F)) {
215226
return (Imaging)ImagingError_ModeError();
216227
}
217228

218-
imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize);
229+
// Invariant over the loops.
230+
int xsize = imIn->xsize, ysize = imIn->ysize;
231+
232+
imOut = ImagingNew(imIn->mode, xsize, ysize);
219233
if (!imOut) {
220234
return NULL;
221235
}
222236

223237
switch (imIn->type) {
224238
case IMAGING_TYPE_INT32:
225239
ImagingSectionEnter(&cookie);
226-
for (y = 0; y < imIn->ysize; y++) {
227-
INT32 *in = imIn->image32[y];
228-
INT32 *out = imOut->image32[y];
240+
for (int y = 0; y < ysize; y++) {
241+
// restrict safe: imIn is read-only, imOut is a fresh allocation.
242+
INT32 *restrict in = imIn->image32[y];
243+
INT32 *restrict out = imOut->image32[y];
229244
/* FIXME: add clipping? */
230-
for (x = 0; x < imIn->xsize; x++) {
245+
for (int x = 0; x < xsize; x++) {
231246
out[x] = in[x] * scale + offset;
232247
}
233248
}
234249
ImagingSectionLeave(&cookie);
235250
break;
236251
case IMAGING_TYPE_FLOAT32:
237252
ImagingSectionEnter(&cookie);
238-
for (y = 0; y < imIn->ysize; y++) {
239-
FLOAT32 *in = (FLOAT32 *)imIn->image32[y];
240-
FLOAT32 *out = (FLOAT32 *)imOut->image32[y];
241-
for (x = 0; x < imIn->xsize; x++) {
253+
for (int y = 0; y < ysize; y++) {
254+
// restrict safe: imIn is read-only, imOut is a fresh allocation.
255+
FLOAT32 *restrict in = (FLOAT32 *)imIn->image32[y];
256+
FLOAT32 *restrict out = (FLOAT32 *)imOut->image32[y];
257+
for (int x = 0; x < xsize; x++) {
242258
out[x] = in[x] * scale + offset;
243259
}
244260
}
@@ -247,11 +263,12 @@ ImagingPointTransform(Imaging imIn, double scale, double offset) {
247263
case IMAGING_TYPE_SPECIAL:
248264
if (imIn->mode == IMAGING_MODE_I_16) {
249265
ImagingSectionEnter(&cookie);
250-
for (y = 0; y < imIn->ysize; y++) {
251-
char *in = (char *)imIn->image[y];
252-
char *out = (char *)imOut->image[y];
266+
for (int y = 0; y < ysize; y++) {
267+
// restrict safe: imIn is read-only, imOut is a fresh allocation.
268+
char *restrict in = imIn->image[y];
269+
char *restrict out = imOut->image[y];
253270
/* FIXME: add clipping? */
254-
for (x = 0; x < imIn->xsize; x++) {
271+
for (int x = 0; x < xsize; x++) {
255272
UINT16 v;
256273
memcpy(&v, in + x * sizeof(v), sizeof(v));
257274
v = v * scale + offset;

0 commit comments

Comments
 (0)