Цель gcc для AVX2, отключающая набор инструкций SSE - PullRequest
0 голосов
/ 23 июня 2018

У нас есть модуль перевода, который мы хотим скомпилировать с AVX2 (только этот): Это говорит GCC заранее, первая строка в файле:

#pragma GCC target "arch=core-avx2,tune=core-avx2"

Раньше это работало с GCC 4.8 и 4.9, но с 6 года (пробовал 7 и 8 тоже) мы получаем это предупреждение (которое мы рассматриваем как ошибку):

error: SSE instruction set disabled, using 387 arithmetics

По первой функции, возвращающей число с плавающей запятой. Я попытался включить обратно SSE 4.2 (и AVX и AVX2), как это

#pragma GCC target "sse4.2,arch=core-avx2,tune=core-avx2"

Но этого недостаточно, ошибка сохраняется.

EDIT:

Соответствующие флаги компилятора, мы ориентируемся на AVX для большинства вещей:

-mfpmath=sse,387 -march=corei7-avx -mtune=corei7-avx

EDIT2: минимальный образец:

#pragma GCC target "arch=core-avx2,tune=core-avx2"

#include <immintrin.h>
#include <math.h>

static inline float
lg1pf( float x ) {
    return log1pf(x)*1.44269504088896338700465f;
}

int main()
{
  log1pf(2.0f);
}

Скомпилировано так:

gcc -o test test.c -O2 -Wall -Werror -pedantic -std=c99 -mfpmath=sse,387 -march=corei7-avx -mtune=corei7-avx

In file included from /home/xxx/gcc-7.1.0/lib/gcc/x86_64-pc-linux-gnu/7.1.0/include/immintrin.h:45:0,
                 from test.c:3:
/home/xxx/gcc-7.1.0/lib/gcc/x86_64-pc-linux-gnu/7.1.0/include/avx512fintrin.h: In function ‘_mm_add_round_sd’:
/home/xxx/gcc-7.1.0/lib/gcc/x86_64-pc-linux-gnu/7.1.0/include/avx512fintrin.h:1412:1: error: SSE register return with SSE disabled
 {
 ^

Детали GCC (у меня нет флагов, которые использовались для его компиляции) gcc - версия GCC (GCC) 7.1.0 Copyright (C) 2017 Free Software Foundation, Inc. Это бесплатное программное обеспечение; см. источник для условий копирования. Здесь нет гарантия; даже не для ИЗДЕЛИИ или ФИТНЕСА ДЛЯ ОСОБЕННОЙ ЦЕЛИ.

Потенциальное решение

#pragma GCC target "avx2"

Работало у меня без других изменений в коде. Применение атрибута к отдельным функциям также не сработало:

Связанная проблема:

__attribute__((__target__("arch=broadwell")))  // does not compile
__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }

__attribute__((__target__("avx2,arch=broadwell"))) // does not compile
__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }

__attribute__((__target__("avx2"))) // compiles
__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }

1 Ответ

0 голосов
/ 23 июня 2018

Это похоже на ошибку.#pragma GCC target до #include <immintrin.h> как-то ломает заголовок, ИДК почему.Даже если AVX2 был включен в командной строке с -march=haswell, #pragma, похоже, нарушает встраивание любых встроенных функций, определенных после этого.

Вы можете использовать #pragma после заголовка,но затем использование экземпляров, которые не были включены в командной строке, завершается неудачей.

Даже более современное имя цели, такое как #pragma GCC target "arch=haswell", вызывает ошибку, так что старые туманные имена целей, такие как corei7-avx, не работаютв общем.Они все еще работают в командной строке.Если вы хотите включить что-то для всего файла, стандартным способом является использование параметров компилятора и , а не прагм.

GCC заявляет, что поддерживает целевые параметры для каждой функции с прагмамиили __attribute__, хотя.https://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html.


Насколько я могу поиграть с этим ( проводник компилятора Godbolt с gcc8.1 ).Clang не затронут, потому что он игнорирует #pragma GCC target.(Это означает, что #pragma не очень переносим; вы, вероятно, хотите, чтобы ваш код работал с любым компилятором GNU C, а не только с самим gcc.)

 // breaks gcc when before immintrin.h
 // #pragma GCC target "arch=haswell"

#include <immintrin.h>
#include <math.h>

//#pragma GCC target "arch=core-avx2,tune=core-avx2"
#pragma GCC target "arch=haswell"

//static inline 
float
lg1pf( float x ) {
    return log1pf(x)*1.44269504088896338700465f;
}

// can accept / return wide vectors
__m128 nop(__m128 a) { return a; }
__m256 require_avx(__m256 a) { return a; }
// but error on using intrinsics if #include happened without target options
//__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }

// this works, though, because AVX is enabled at this point
// presumably so would  __builtin_ia32_whatever
// Without `arch=haswell`, this breaks, so we know the pragma "worked"
__m256 use_native_vec(__m256 a) { return a+a; }
...