Как стать автором
Обновить

Комментарии 10

Понимаю, что перевод, но хотелось бы видеть конечный ассемблерный код с оптимизациями и без, чтобы понять уйдёт весь лишний оверхед в функции sum или нет?
Вот компиляция Go 1.12:
        text    "".sum(SB), NOSPLIT|ABIInternal, $0-32
        funcdata        $0, gclocals·1a65e721a2ccc325b382662e7ffee780(SB)
        funcdata        $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
        funcdata        $3, gclocals·568470801006e5c0dc3947ea998fe279(SB)
        pcdata  $2, $0
        pcdata  $0, $0
        movq    "".numbers+16(SP), AX
        pcdata  $2, $1
        pcdata  $0, $1
        movq    "".numbers+8(SP), CX
        xorl    DX, DX
        xorl    BX, BX
        jmp     sum_pc30
sum_pc16:
        leaq    1(DX), SI
        movq    (CX)(DX*8), DI
        addq    DI, BX
        movq    SI, DX
sum_pc30:
        cmpq    DX, AX
        jlt     sum_pc16
        pcdata  $2, $0
        movq    BX, "".~r1+32(SP)
        ret

Никаких JUMP вначале и всего 4 переменных: слайс, его длина, его вместимость (не используется) и n в качестве возвращаемого.
godbolt.org/z/44KBE5
И правильный пример LLVM IR из статьи (в оригинале тоже ошибка):
define i64 @sum(i64* %ptr, i64 %len, i64 %cap) {
  br label %for.loop

for.loop:                                         ; preds = %for.body, %entry
  %0 = phi i64 [ 0, %entry ], [ %5, %for.body ]
  %1 = phi i64 [ 0, %entry ], [ %6, %for.body ]
  %2 = icmp slt i64 %1, %len
  br i1 %2, label %for.body, label %for.done

for.body:                                         ; preds = %for.loop
  %3 = getelementptr i64, i64* %ptr, i64 %1
  %4 = load i64, i64* %3
  %5 = add i64 %0, %4
  %6 = add i64 %1, 1
  br label %for.loop

for.done:                                         ; preds = %for.loop
  ret i64 %0
}


И конечное представление LLVM IR -> ASM:
sum:                                    # @sum
        xor     eax, eax
        xor     ecx, ecx
        cmp     rcx, rsi
        jge     .LBB0_3
.LBB0_2:                                # %for.body
        add     rax, qword ptr [rdi + 8*rcx]
        inc     rcx
        cmp     rcx, rsi
        jl      .LBB0_2
.LBB0_3:                                # %for.done
        ret

godbolt.org/z/jfYKHj
А теперь сравните с gcc с O2:
godbolt.org/z/jPnH-3

gcc не анролит лупы без приказа. Так что кланг с дефолтовые параметрами будет много быстрее особенно если сумируем большуший массив

Решение о представлении типа Go int принимается при создании LLVM IR-кода. Это — одна из многих причин того, что LLVM IR-код не является, как многие думают, платформенно-независимым.

Тут у меня мозг немного сломался. В LLVM IR как раз у всех переменных тип проставлен явно: i64. i64 останется i64 вне зависимости от платформы. То есть полученный код как раз является платформонезависимым (как минимум по этому вопросу), в отличие от int в Go, который, как утверждается, будет зависеть от платформы.


Такой код, созданный для одной платформы, нельзя просто взять и скомпилировать для другой платформы

Конечно же можно, если платформа является Тьюринг-полной.

Видимо i64 должен поддерживаться платформой наивно. Int Go транслируется в int64 или int32 в зависимости от целевой платформы.


Соответственно нельзя скомпилировать код с INT64 на платформу, где его нет, на условный 386. Для его поддержки уже первичный транслятор должен принимать решение какими структурами и способами работать с парой i32 как с одним i64

Соответственно нельзя скомпилировать код с INT64 на платформу, где его нет

Конечно же можно, если платформа является Тьюринг-полной (все платформы являются).


Возможно LLVM не умеет компилировать LLVM IR-код с INT64 на платформу, где его нет. Но это ограничение LLVM, а не кода и не есть признак платформозависимого кода.


Просто автор не понимает, что значат термины.

Под "нельзя скомпилировать" в данном контексте я имел в виду "не может или не хочет". И, похоже, именно не хочет по своей идеологии: LLVM IR-код — это именно low level код, примитивные типы или поддерживаются целевой платформой или нет, эмуляции типа int64 === {low: int32; high: int32} не происходит.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий