__assume

Блок, относящийся только к системам Microsoft

Передает подсказку оптимизатору.

__assume(    expression )

Параметры

  • expression
    Любое выражение, которое считается, что принимает значение true.

Заметки

Оптимизатор предполагает, что условие, представленное expression имеет значение true, в точке, где появляется ключевое слово и сохраняет значение true до изменения expression (например, путем присваивания переменной). Выборочное использование подсказок, передаваемых оптимизатору __assume, может улучшить оптимизацию.

Если оператор __assume записывается как противоречие (выражение, которое всегда имеет значение false), он всегда будет рассматриваться как __assume(0). Если код не работает должным образом, убедитесь, что expression, которое было определено, является допустимым и имеет значение true, как было описано ранее. Дополнительные сведения об ожидаемом поведении __assume(0), приведены в последующих комментариях.

Предупреждение

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

__assume не является подлинной встроенной функцией. Не объявлена как функция и не может использоваться в директиве #pragma intrinsic. Несмотря на то, что код не создается, изменяется код, созданный с помощью оптимизатора.

Используйте __assume в ASSERT только, когда утверждение не может быть восстановлено. Не используйте __assume в assert, для которого имеется код восстановления после ошибки, поскольку компилятор может изменить оптимизацию кода обработки ошибок.

Инструкция __assume(0) является особым случаем. Используйте __assume(0) для указания пути к коду, который нельзя достигнуть. Следующий пример показывает, как использовать __assume(0) для указания того, что в вариант по умолчанию инструкции switch нельзя попасть. Это показывает наиболее типичное использование __assume(0).

Требования

Встроенная функция

Архитектура

__assume

x86, ARM, x64

Пример

// compiler_intrinsics__assume.cpp
#ifdef DEBUG
# define ASSERT(e)    ( ((e) || assert(__FILE__, __LINE__) )
#else
# define ASSERT(e)    ( __assume(e) )
#endif

void func1(int i)
{
}

int main(int p)
{
   switch(p){
      case 1:
         func1(1);
         break;
      case 2:
         func1(-1);
         break;
      default:
         __assume(0);
            // This tells the optimizer that the default
            // cannot be reached. As so, it does not have to generate
            // the extra code to check that 'p' has a value 
            // not represented by a case arm. This makes the switch 
            // run faster.
   }
}

Использование __assume(0) сообщает оптимизатору, что вариант по умолчанию недоступен. В примере показано, что программист знает, что ввести для p возможно только будет 1 или 2. Если другое значение передается в p, программа становится недействительной, что приводит к ее непредсказуемому поведению.

В результате использования инструкции __assume(0), компилятор не создает код для тестирования имеет ли p значение, не представленное в операторе case. Чтобы это работало, оператор __assume(0) должен быть первым в теле варианта по умолчанию.

Поскольку компилятор создает код, основанный на __assume, этот код может работать неправильно, если выражение в операторе __assume имеет значение false во время выполнения. Если вы не уверены, что выражение всегда будет иметь значение true во время выполнения, можно использовать функцию assert для защиты кода.

#define ASSERT(e)    ( ((e) || assert(__FILE__, __LINE__)), __assume(e) )

К сожалению, такое использование assert не позволяет компилятору выполнить оптимизацию варианта по умолчанию, как было описано ранее в этом документе. В качестве альтернативы можно использовать отдельный макрос следующим образом.

#ifdef DEBUG
# define NODEFAULT   ASSERT(0)
#else
# define NODEFAULT   __assume(0)
#endif

   default:
      NODEFAULT;

См. также

Ссылки

Встроенные объекты компилятора

Ключевые слова в C++