Что отбрасывается gcc -flto - PullRequest
0 голосов
/ 04 мая 2018

Я собираю нашу прошивку для stm32 с arm-none-eabi-gcc 6.3.1.

Если я включаю оптимизацию во время соединения, она все равно компилируется и загружается и на ~ 10 кБ меньше, чем без -ftlo, но есть небольшая поломка.

Как мне отладить это?

Есть ли способ заставить gcc сказать мне, что он (неправильно) отбрасывает во время оптимизации во время соединения?

1 Ответ

0 голосов
/ 09 мая 2018

Сроки

Оптимизация кода должна и сделает его более быстрым, что может вызвать проблемы с оборудованием, которое ожидает его немного медленнее.

Пример:

void GPIO_Test() {
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6 | GPIO_PIN_7, GPIO_PIN_SET);
    GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

Это работает без -lto, но не может установить высокий уровень выходов, когда -lto включен. Зачем? Поскольку в большинстве моделей STM32 требуется небольшая задержка между включением часов в RCC и использованием периферийных устройств (это упоминается в сообщениях об ошибках). Вызов функции обеспечит требуемую задержку, но с -lto компилятор может встроить функции в другие модули, уменьшая задержку.

Отсутствует volatile

Распространенным источником проблем с -lto является то, что он может оптимизировать доступ к переменным, которые должны были быть объявлены как volatile, но это не так, даже если доступ инкапсулирован в вызов функции в другом модуле.

Давайте посмотрим на простой пример.

mainloop.c:

while(1) {
  if(button_pressed()) {
    do_stuff();
  }
}

button.c:

int button_flag;
void button_interrupt_handler() {
    button_flag = GPIOx->IDR & SOME_BIT;
}

void button_pressed() {
  return button_flag;
}

Без -lto вызов функции в другом модуле обрабатывается как черный ящик с возможными побочными эффектами, вызов всегда генерируется, а результат всегда оценивается. Другими словами, каждый вызов функции другого модуля действует как неявный барьер памяти. С -lto барьер больше не существует, компилятор может эффективно встроить или иным образом оптимизировать функции в других модулях.

...