2013-04-30 3 views
2

В следующей программе переменная out всегда печатает как 0, если она скомпилирована с оптимизацией выше O1. Переменная out корректно печатает с любым уровнем оптимизации, если я раскомментирую строку cout в функции digitTruncate.Переменная оптимизирована до нуля

Я делаю что-то «неопределенное» или это проблема с компилятором?

#include <iostream> 
#include "mytime.hpp" 
#include <stdint.h> 

template <class IN> 
int32_t 
digitTruncate (IN data_in, uint32_t digits, uint64_t* data_out, 
       int32_t bits = -1, bool safe = false) 
{ 
    if (bits == -1) 
    bits = (digits/0.3010299957) + 1; 
    if (!safe) 
    { 
    if (bits > (int32_t)sizeof(data_in) * 8) 
     return -1; 
    } 
    *data_out = (data_in & (0xffffffffffffffff >> (64 - bits))); 
    //std::cout << *data_out << std::endl; 
    return (bits/8) + 1; 
} 

int 
main() 
{ 
    uint64_t cycles1, cycles2; 
    uint32_t out; 
    char* block = new char[8]; 
    cycles1 = mytime::cycles(); 
    for (int i = 0; i < 10000; i++) 
    { 
    uint32_t init = (uint32_t)mytime::cycles(); 
    digitTruncate(init, 5, ((uint64_t*)block), 17, true); 
    out = *((uint32_t*)block); 
    } 
    cycles2 = mytime::cycles(); 
    std::cout << cycles2 - cycles1 << std::endl; 
    std::cout << "results: " << out << std::endl; 

    return 0; 
} 
+0

Я не думаю, что это проблема с компилятором, я перечислял возможности. –

+0

@Mysticial Почему комментирование строки 'cout' предотвращает запись в блок? Это совершенно другая линия. Вышеприведенный код находится в «состоянии комментариев». –

+0

@chewsocks Упс, я неправильно читаю ваш вопрос, комментируя 'digitTruncate'. Виноват. – Mysticial

ответ

1

Поскольку значение out в петле мертво, для последней итерации, за исключением, и функция не имеет другие, чем установка block побочных эффектов (и, таким образом out), компилятор может свободно устранить петлю, и просто оцените последнюю итерацию. Большая часть кода из этой последней итерации также может быть сложен.

Таким образом, вы в конечном итоге только с двумя последовательными вызовами mytime::cycles(), которые, вероятно, имеют значение 0 ...

компилятора, вероятно, первые инлайн вызова, а затем упрощает его до нуля, а не отмечая что он фактически ничего не делает, но общий эффект тот же.

+0

Интересно, я не думал, что он оптимизирует целые куски кода. Не будет ли это делать ложное предположение, сделав это, поскольку «out» необходимо изменить, чтобы иметь правильный выход после цикла? –

+0

@chewsocks: вы не показываете определение 'mytime :: cycles', поэтому трудно сказать, что компилятор может понять из этого, но многие бит' block' всегда будут установлены на 0 независимо от того, что ввод есть. –

3

Обращаясь к block как указатель на uint64_t и uint32_t, вы нарушаете строгие правила псевдонимов. Компилятору разрешено предполагать, что к определенному адресу обращаются (с псевдонимом) только char* и еще один тип. Вы используете два типа: char*, поэтому все ставки не учитываются в том, что сделает оптимизатор компилятора.

Смежные вопросы