Я не могу проверить это, потому что у меня нет для этого цепочки инструментов, но этот тип ошибки часто можно обойти, переписав код немного.Как правило, этого не должно происходить, и об этом следует сообщать как об ошибке, но вы используете специфическую для процессора функциональность, которая, вероятно, менее хорошо протестирована и отшлифована, чем остальная часть компилятора.
Поскольку это регистрошибка разлива, и у вас есть несколько указателей. Я очень подозреваю, что компилятор может пытаться загрузить больше данных в регистры, чем нужно, из-за страха, что может произойти некоторое наложение алиасинга (что, вероятно, на самом деле не происходит).Ниже я расскажу о возможности этого, а также сделаю несколько других вещей, которые могут уменьшить сложность кода с точки зрения компилятора (хотя это может выглядеть не так).
#include<stdio.h>
#include"arm_neon.h"
#define IMAGE_HEIGHT 480
#define IMAGE_WIDTH 640
float32_t integral_image[IMAGE_HEIGHT][IMAGE_WIDTH];
float32x4_t box_area_compute3(int, int , int , int , unsigned int , float);
inline int min(int, int);
int main()
{
box_area_compute3(1, 1, 4, 4, 2, 0);
return 0;
}
/* By putting these in separate functions the compiler will initially
* think about them by themselves, without the complications of the
* surrounding code. This may give it the abiltiy to optimise the
* code somewhat before trying to inline it.
* This may also serve to make it more obvious to the compiler that
* the local variables are dead after their use (since they are
* dead after the call returns, and that the lifetimes of some variable
* cannot actually overlap (hopefully reducing the register needs).
*/
static inline float32x4_t do_it2(float32_t *tl, float32_t *tr, float32_t *bl, float32_t * br) {
float32x4x2_t top_left, top_right, bottom_left, bottom_right;
float32x4_t A, B;
top_left = vld2q_f32(tl);
top_right = vld2q_f32(tr);
bottom_left = vld2q_f32(bl);
bottom_right = vld2q_f32(br);
/* By spreading this across several statements I have created several
* additional sequence points. The compiler does not think that it
* has to dereference all of the pointers before doing any of the
* computations.... maybe. */
A = vaddq_f32(*top_left.val, *bottom_right.val);
B = vsubq_f32(A, *top_right.val);
return vsubq_f32(B, *bottom_left);
}
static inline float32x4_t do_it4(float32_t *tl, float32_t *tr, float32_t *bl, float32_t * br) {
float32x4x4_t top_left, top_right, bottom_left, bottom_right;
float32x4_t A, B;
top_left = vld4q_f32(tl);
top_right = vld4q_f32(tr);
bottom_left = vld4q_f32(bl);
bottom_right = vld4q_f32(br);
A = vaddq_f32(*top_left.val, *bottom_right.val);
B = vsubq_f32(A, *top_right.val);
return vsubq_f32(B, *bottom_left);
}
float32x4_t box_area_compute3(int row, int col, int num_rows, int num_cols, unsigned int step_size, float three)
{
unsigned int height = IMAGE_HEIGHT;
unsigned int width = IMAGE_WIDTH;
int temp_row = row + num_rows;
int temp_col = col + num_cols;
int r1 = (min(row, height))- 1 ;
int r2 = (min(temp_row, height)) - 1;
int c1 = (min(col, width)) - 1;
int c2 = (min(temp_col, width)) - 1;
float32x4_t v128_areas;
float32_t *tl = (float32_t *)integral_image[r1] + c1;
float32_t *tr = (float32_t *)integral_image[r1] + c2;
float32_t *bl = (float32_t *)integral_image[r2] + c1;
float32_t *br = (float32_t *)integral_image[r2] + c2;
switch (step_size) {
case 2:
v128_areas = do_it2(tl, tr, bl, br);
break;
case 4:
v128_areas = do_it4(tl, tr, bl, br);
break;
}
if(three == 3.0)
v128_areas = vmulq_n_f32(v128_areas, three);
return v128_areas;
}
inline int min(int X, int Y)
{
return (X < Y ? X : Y);
}
Я надеюсь, что это поможет, и что я не внес никаких ошибок.