2016-09-19 4 views
0

Как работает анализ псевдонимов с такими ключевыми словами, как __restrict и __noalias? Рассматривает ли это их как доказательство отсутствия наложения псевдонимов? Или просто вычисляет собственные результаты в зависимости от указателей?анализ псевдонима и ключевое слово _restrict - C

Глядя на результатах псевдонима анализа LLVM, во многих узких петлях делают нагрузки-бинарный оператор-магазин последовательности, следующие узкое место был замечен: Даже если входные и выходные указатели были отмечены пространно с __restrict, анализом псевдонима еще предположил их как «MayAlias» и сделал магазины в конце цикла, зависящие от ВСЕХ нагрузок в цикле.

например.

void _BitwiseOr_(unsigned char * __restrict * __restrict src1Addr, unsigned char * __restrict * __restrict src2Addr, unsigned char * __restrict * __restrict destAddr, unsigned int width) { 
     uchar16 * __restrict src1 = (uchar16 * __restrict) *src1Addr; 
     uchar16 * __restrict src2 = (uchar16 * __restrict) *src2Addr; 
     uchar16 * __restrict dest = (uchar16 * __restrict) *destAddr; 


     for (unsigned int i = 0; i < width; i += 4) { 
     *dest++ = *src1++ | *src2++; 
     *dest++ = *src1++ | *src2++; 
     *dest++ = *src1++ | *src2++; 
     *dest++ = *src1++ | *src2++; 
     } 
    } 

.

define void @_BitwiseOr_(i8** noalias nocapture readonly %src1Addr, i8** noalias nocapture readonly %src2Addr, i8** noalias nocapture readonly %destAddr, i32 %width) local_unnamed_addr #0 { 
entry: 
    %0 = bitcast i8** %src1Addr to <16 x i8>** 
    %1 = load <16 x i8>*, <16 x i8>** %0, align 4, !tbaa !2 
    %2 = bitcast i8** %src2Addr to <16 x i8>** 
    %3 = load <16 x i8>*, <16 x i8>** %2, align 4, !tbaa !2  
    %4 = bitcast i8** %destAddr to <16 x i8>** 
    %5 = load <16 x i8>*, <16 x i8>** %4, align 4, !tbaa !2   
    %6 = load <16 x i8>, <16 x i8>* %1, align 8, !tbaa !6 
    %7 = load <16 x i8>, <16 x i8>* %3, align 8, !tbaa !6 
    %or = or <16 x i8> %7, %6 
    store <16 x i8> %or, <16 x i8>* %5, align 8, !tbaa !6 
    ret void 
} 

анализ Алиас отвечает, что только NO Алиасы не между:

i8** src1addr - i8** src2addr, 
i8** src1addr - i8** destaddr, 
i8** src2addr - i8** destaddr, 
i8** destaddr - i8** destaddr, 
i8** src1addr - i8** src1addr, 
i8** src2addr - i8** src2addr 

Почему это не «выгода» использования __restrict ключевого слова? Можно ли заставить его работать?

Над компилируется лязг с:

-cc1 -S -disable-free -main-file-name file.cpp -mllvm -disable-block-placement -funroll-loops -mllvm -unroll-allow-partial -mllvm -tail-merge-size=71 -mllvm -tail-dup-size=70 -fmath-errno -v -gcodeview -dwarf-column-info -coverage-file file.s -O3 -Wall -Werror=implicit-function-declaration -std=c++14 -fdeprecated-macro -fno-dwarf-directory-asm -ferror-limit 19 -fmessage-length 0 -ffreestanding -fallow-half-arguments-and-returns -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -mllvm -no-phi-elim-live-out-early-exit -mllvm -use-cfl-aa=anders -mllvm -use-cfl-aa-in-codegen=anders -mllvm -debug -mllvm -da-delinearize -mllvm -mllvm -enable-tbaa -mllvm -enable-scoped-noalias -mllvm -evaluate-aa-metadata -mllvm -print-all-alias-modref-info 
+0

Какие еще «нет псевдонимов» вы ожидаете? Список, который вы предоставили, по-видимому, охватывает все материалы? – Joky

+0

Я должен ожидать также% 1 -% 3,% 3 -% 5 aka src1 - src2 и т. Д. (Проверить обновленный исходный код) – eternalStudent

ответ

1

Вы должны прочитать правила в C стандарта.

«ограничивающие» указатели могут, конечно, псевдонимы. Просто это порождает в некоторых случаях неопределенное поведение, поэтому они имеют псевдоним, но компилятору полностью разрешено игнорировать это.

Вы также должны знать, что «ограничивать» влияет только на указатели, которые производятся от указателя «ограничения» против указателей, которые гарантированно не получены из одного и того же «ограничивающего» указателя. Например, если p является «ограничивающим» указателем, и вы вызываете f (p), этот вызов может хранить p в любой статической или глобальной переменной указателя. Поэтому, если вы читаете такую ​​переменную указателя после вызова, компилятор не знает, получен ли он из указателя ограничения или нет, и если он получен из p, тогда применяются правила псевдонимов.

+0

Но в соответствии со стандартом C: он не указывает непосредственно, когда сглаживание и не возможно. Однако он устанавливает , что объект одного типа должен иметь свое сохраненное значение, доступное только по ссылке, которая имеет один из нескольких связанных типов. Повторяя эти правила с точки зрения сглаживания, типы, которые совместимы, когда квалификаторы (const, volatile и ограничения) равны , игнорируются! Вот почему мой запрос здесь остается ... – eternalStudent