__assume
Specyficzne dla firmy Microsoft
Przekazuje wskazówkę optymalizatorowi.
Składnia
__assume(
expression
)
Parametry
expression
W przypadku kodu osiągalnego każde wyrażenie, które przyjmuje się do wartości .true
Użyj 0
polecenia , aby wskazać niemożliwy do osiągnięcia kod optymalizatora.
Uwagi
Optymalizator zakłada, że warunek reprezentowany przez expression
element znajduje się w punkcie, w którym słowo kluczowe pojawia true
się i pozostaje prawdziwe do momentu expression
modyfikacji (na przykład przez przypisanie do zmiennej). Selektywne użycie wskazówek przekazywanych do optymalizatora przez __assume
może poprawić optymalizację.
__assume
Jeśli instrukcja jest zapisywana jako sprzeczność (wyrażenie, które zawsze daje wartość false
), zawsze jest traktowane jako __assume(0)
. Jeśli kod nie działa zgodnie z oczekiwaniami, upewnij się, że expression
zdefiniowany kod jest prawidłowy i true
, zgodnie z wcześniejszym opisem. Instrukcja __assume(0)
jest szczególnym przypadkiem. Użyj polecenia __assume(0)
, aby wskazać ścieżkę kodu, która nie może zostać osiągnięta.
Ostrzeżenie
Program nie może zawierać nieprawidłowej __assume
instrukcji na dostępnej ścieżce. Jeśli kompilator może osiągnąć nieprawidłową __assume
instrukcję, program może spowodować nieprzewidywalne i potencjalnie niebezpieczne zachowanie.
Aby uzyskać zgodność z poprzednimi wersjami, jest synonimem, _assume
__assume
chyba że określono opcję /Za
kompilatora (Wyłącz rozszerzenia języka).
__assume
nie jest prawdziwym wewnętrznym. Nie musi być zadeklarowana jako funkcja i nie może być używana w #pragma intrinsic
dyrektywie. Mimo że żaden kod nie jest generowany, wpływ na kod wygenerowany przez optymalizator ma wpływ.
Używaj __assume
tylko wtedy ASSERT
, gdy asercji nie można odzyskać. Nie używaj __assume
asercji, dla której masz kolejny kod odzyskiwania błędów, ponieważ kompilator może zoptymalizować kod obsługi błędów.
Wymagania
Nieodłączny | Architektura |
---|---|
__assume |
x86, ARM, x64, ARM64, ARM64EC |
Przykład
W poniższym przykładzie pokazano, jak użyć __assume(0)
polecenia , aby wskazać, że default
nie można osiągnąć wielkości liter instrukcji switch
. Jest to najbardziej typowe użycie metody __assume(0)
. W tym miejscu programista wie, że jedynymi możliwymi danymi wejściowymi p
będzie 1 lub 2. Jeśli dla programu zostanie przekazana p
inna wartość, program stanie się nieprawidłowy i powoduje nieprzewidywalne zachowanie.
// compiler_intrinsics__assume.cpp
void func1(int /*ignored*/)
{
}
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.
}
}
W wyniku instrukcji __assume(0)
kompilator nie generuje kodu w celu przetestowania, czy p
ma wartość, która nie jest reprezentowana w instrukcji case.
Jeśli nie masz pewności, że wyrażenie będzie zawsze true
w czasie wykonywania, możesz użyć assert
funkcji w celu ochrony kodu. Ta definicja makra opakowuje instrukcję __assume
za pomocą sprawdzania:
#define ASSUME(e) (((e) || (assert(e), (e))), __assume(e))
default
Aby optymalizacja przypadku działała, __assume(0)
instrukcja musi być pierwszą instrukcją w treści default
sprawy. Niestety element assert
w makrze ASSUME
uniemożliwia kompilatorowi wykonanie tej optymalizacji. Alternatywnie możesz użyć oddzielnego makra, jak pokazano poniżej:
#ifdef DEBUG
// This code is supposed to be unreachable, so assert
# define NODEFAULT assert(0)
#else
# define NODEFAULT __assume(0)
#endif
// . . .
default:
NODEFAULT;
END Microsoft Specific