2013-02-06 23 views
12

Ngôn ngữ LLVM quy định cụ thể các loại nguyên như trong, trong đó N là bit-chiều rộng của số nguyên, và trong khoảng từ 1 đến 2^23-1 (Theo: http://llvm.org/docs/LangRef.html#integer-type)loại nguyên LLVM của

Tôi có 2 câu hỏi :

  1. Khi biên dịch chương trình C xuống cấp LLVM IR, loại nào có thể hạ xuống i1, i2, i3, v.v ...? Nó có vẻ như các loại i8, i16, i32, i64 phải là đủ, vì vậy tôi đã tự hỏi những gì khác gần 8 triệu loại số nguyên được cho.

  2. Có đúng là cả hai loại số nguyên đã ký và không dấu được hạ xuống thành i32? Lý do cho điều đó là gì và tại sao nó không áp dụng cho một cái gì đó giống như float 32-bit (được biểu diễn là f32 trong LLVM)?

Trả lời

15

Trước hết, hãy lưu ý cả hai số nguyên có kích thước tùy ý và không có sự khác biệt giữa số nguyên đã ký và chưa ký là sửa đổi được thêm vào LLVM 2.0. Các phiên bản trước đó chỉ có một vài kiểu số nguyên, với sự phân biệt đã ký/không dấu.

Bây giờ, câu hỏi của bạn:

  1. LLVM, mặc dù được thiết kế với C/C++ trong tâm trí, không cụ thể cho các thứ tiếng. Có nhiều loại số nguyên có thể cho bạn linh hoạt hơn. Bạn không cần phải sử dụng các loại này, tất nhiên - và tôi đoán rằng, như bạn đã đề cập, bất kỳ giao diện C/C++ nào cho LLVM (tức là Clang) có thể chỉ tạo i1, i8, i16, i32 và i64 .

    Chỉnh sửa: dường như tôi đã nhầm lẫn và Clang cũng sử dụng một số loại số nguyên khác, xem bình luận của Jens bên dưới.

  2. Có, LLVM không phân biệt giữa loại số nguyên đã ký và không dấu, vì vậy cả hai sẽ được hạ xuống thành i32. Tuy nhiên, các phép toán trên số nguyên không dấu sẽ được dịch theo kiểu gốc; ví dụ. một bộ phận giữa các số nguyên không dấu sẽ là udiv trong khi giữa chữ ký sẽ là sdiv. Vì số nguyên được biểu thị là two's complement, tuy nhiên, nhiều thao tác (ví dụ: add) không quan tâm đến chữ ký/chưa ký và do đó chỉ có một phiên bản duy nhất.

    Đối với tại sao có sự phân biệt đã được thực hiện trong LLVM giữa signed và unsigned, đọc the details on this enhancement request - trong ngắn hạn, sau khi cả hai đã ký và các phiên bản unsigned dẫn đến một sưng lên IR lớn và đã gây bất lợi cho một số tối ưu, vì vậy nó đã bị bỏ.

    Cuối cùng, bạn hỏi tại sao không có f32 - câu trả lời là tôi không biết, có thể nó được coi là ít hữu ích hơn số nguyên có kích thước tùy ý. Tuy nhiên, lưu ý rằng f32 không thực sự mô tả - nếu bạn muốn các loại dấu phẩy động tùy ý, bạn cần phải chỉ định kích thước của số cơ sở và kích thước của số mũ, chẳng hạn như f23e8 thay vì floatf52e11 thay vì double. Đó là một chút cồng kềnh nếu bạn hỏi tôi, mặc dù tôi đoán floatdouble có thể đã được thực hiện đồng nghĩa với những người.

+0

Thực tế 'f32' không tồn tại đối với các số dấu phẩy động. Lý do tôi hỏi nó là tôi nghĩ nếu cả hai số nguyên ký và unsigned có thể được đại diện bởi i32, thì có lẽ một phao 32-bit cũng có thể được biểu diễn theo cách đó. Tôi đoán đây là một quyết định thiết kế chi tiết như bạn đề cập đến. –

+0

@AliJ Tôi không thấy 'f32' được liệt kê trên [phần lang ref trên các loại dấu phẩy động] (http://llvm.org/docs/LangRef.html#floating-point-types) ... trừ khi bạn có nghĩa là có một triển khai phổ biến được liên kết với tên đó? – Oak

+3

Cảm ơn vì điều này! Khi nó xảy ra, tôi chỉ chạy qua hai hướng dẫn mà Clang tạo ra: 'lưu trữ i576% bla, i576 * bitcast (% class.Foo * @_Global thành i576 *), căn chỉnh 8' và'% 11 = tải i384 *% 10, căn chỉnh 8'. Tôi sẽ giả định rằng chúng được hạ xuống thành một lệnh gọi 'memcpy' hoặc một chuỗi hướng dẫn lưu trữ/tải thông minh sử dụng các loại SIMD. – Jens