Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2009 VMware, Inc.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. /**
  29.  * @file
  30.  * Convenient representation of SIMD types.
  31.  *
  32.  * @author Jose Fonseca <jfonseca@vmware.com>
  33.  */
  34.  
  35.  
  36. #ifndef LP_BLD_TYPE_H
  37. #define LP_BLD_TYPE_H
  38.  
  39.  
  40. #include "util/u_format.h"
  41. #include "pipe/p_compiler.h"
  42. #include "gallivm/lp_bld.h"
  43.  
  44. /**
  45.  * Native SIMD architecture width available at runtime.
  46.  *
  47.  * Using this width should give the best performance,
  48.  * and it determines the necessary alignment of vector variables.
  49.  */
  50. extern unsigned lp_native_vector_width;
  51.  
  52. /**
  53.  * Maximum supported vector width (not necessarily supported at run-time).
  54.  *
  55.  * Should only be used when lp_native_vector_width isn't available,
  56.  * i.e. sizing/alignment of non-malloced variables.
  57.  */
  58. #define LP_MAX_VECTOR_WIDTH 256
  59.  
  60. /**
  61.  * Minimum vector alignment for static variable alignment
  62.  *
  63.  * It should always be a constant equal to LP_MAX_VECTOR_WIDTH/8.  An
  64.  * expression is non-portable.
  65.  */
  66. #define LP_MIN_VECTOR_ALIGN 32
  67.  
  68. /**
  69.  * Several functions can only cope with vectors of length up to this value.
  70.  * You may need to increase that value if you want to represent bigger vectors.
  71.  */
  72. #define LP_MAX_VECTOR_LENGTH (LP_MAX_VECTOR_WIDTH/8)
  73.  
  74. /**
  75.  * The LLVM type system can't conveniently express all the things we care about
  76.  * on the types used for intermediate computations, such as signed vs unsigned,
  77.  * normalized values, or fixed point.
  78.  */
  79. struct lp_type {
  80.    /**
  81.     * Floating-point. Cannot be used with fixed. Integer numbers are
  82.     * represented by this zero.
  83.     */
  84.    unsigned floating:1;
  85.  
  86.    /**
  87.     * Fixed-point. Cannot be used with floating. Integer numbers are
  88.     * represented by this zero.
  89.     */
  90.    unsigned fixed:1;
  91.  
  92.    /**
  93.     * Whether it can represent negative values or not.
  94.     *
  95.     * If this is not set for floating point, it means that all values are
  96.     * assumed to be positive.
  97.     */
  98.    unsigned sign:1;
  99.  
  100.    /**
  101.     * Whether values are normalized to fit [0, 1] interval, or [-1, 1]
  102.     * interval for signed types.
  103.     *
  104.     * For integer types it means the representable integer range should be
  105.     * interpreted as the interval above.
  106.     *
  107.     * For floating and fixed point formats it means the values should be
  108.     * clamped to the interval above.
  109.     */
  110.    unsigned norm:1;
  111.  
  112.    /**
  113.     * Element width.
  114.     *
  115.     * For fixed point values, the fixed point is assumed to be at half the
  116.     * width.
  117.     */
  118.    unsigned width:14;
  119.  
  120.    /**
  121.     * Vector length.  If length==1, this is a scalar (float/int) type.
  122.     *
  123.     * width*length should be a power of two greater or equal to eight.
  124.     *
  125.     * @sa LP_MAX_VECTOR_LENGTH
  126.     */
  127.    unsigned length:14;
  128. };
  129.  
  130.  
  131. /**
  132.  * We need most of the information here in order to correctly and efficiently
  133.  * translate an arithmetic operation into LLVM IR. Putting it here avoids the
  134.  * trouble of passing it as parameters.
  135.  */
  136. struct lp_build_context
  137. {
  138.    struct gallivm_state *gallivm;
  139.  
  140.    /**
  141.     * This not only describes the input/output LLVM types, but also whether
  142.     * to normalize/clamp the results.
  143.     */
  144.    struct lp_type type;
  145.  
  146.    /** Same as lp_build_elem_type(type) */
  147.    LLVMTypeRef elem_type;
  148.  
  149.    /** Same as lp_build_vec_type(type) */
  150.    LLVMTypeRef vec_type;
  151.  
  152.    /** Same as lp_build_int_elem_type(type) */
  153.    LLVMTypeRef int_elem_type;
  154.  
  155.    /** Same as lp_build_int_vec_type(type) */
  156.    LLVMTypeRef int_vec_type;
  157.  
  158.    /** Same as lp_build_undef(type) */
  159.    LLVMValueRef undef;
  160.  
  161.    /** Same as lp_build_zero(type) */
  162.    LLVMValueRef zero;
  163.  
  164.    /** Same as lp_build_one(type) */
  165.    LLVMValueRef one;
  166. };
  167.  
  168.  
  169. /**
  170.  * Converts a format description into an lp_type.
  171.  *
  172.  * Only works with "array formats".
  173.  *
  174.  * e.g. With PIPE_FORMAT_R32G32B32A32_FLOAT returns an lp_type with float[4]
  175.  */
  176. static INLINE void
  177. lp_type_from_format_desc(struct lp_type* type, const struct util_format_description *format_desc)
  178. {
  179.    assert(format_desc->is_array);
  180.    assert(!format_desc->is_mixed);
  181.  
  182.    memset(type, 0, sizeof(struct lp_type));
  183.    type->floating = format_desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT;
  184.    type->fixed    = format_desc->channel[0].type == UTIL_FORMAT_TYPE_FIXED;
  185.    type->sign     = format_desc->channel[0].type != UTIL_FORMAT_TYPE_UNSIGNED;
  186.    type->norm     = format_desc->channel[0].normalized;
  187.    type->width    = format_desc->channel[0].size;
  188.    type->length   = format_desc->nr_channels;
  189. }
  190.  
  191.  
  192. static INLINE void
  193. lp_type_from_format(struct lp_type* type, enum pipe_format format)
  194. {
  195.    lp_type_from_format_desc(type, util_format_description(format));
  196. }
  197.  
  198.  
  199. static INLINE unsigned
  200. lp_type_width(struct lp_type type)
  201. {
  202.    return type.width * type.length;
  203. }
  204.  
  205.  
  206. /** Create scalar float type */
  207. static INLINE struct lp_type
  208. lp_type_float(unsigned width)
  209. {
  210.    struct lp_type res_type;
  211.  
  212.    memset(&res_type, 0, sizeof res_type);
  213.    res_type.floating = TRUE;
  214.    res_type.sign = TRUE;
  215.    res_type.width = width;
  216.    res_type.length = 1;
  217.  
  218.    return res_type;
  219. }
  220.  
  221.  
  222. /** Create vector of float type */
  223. static INLINE struct lp_type
  224. lp_type_float_vec(unsigned width, unsigned total_width)
  225. {
  226.    struct lp_type res_type;
  227.  
  228.    memset(&res_type, 0, sizeof res_type);
  229.    res_type.floating = TRUE;
  230.    res_type.sign = TRUE;
  231.    res_type.width = width;
  232.    res_type.length = total_width / width;
  233.  
  234.    return res_type;
  235. }
  236.  
  237.  
  238. /** Create scalar int type */
  239. static INLINE struct lp_type
  240. lp_type_int(unsigned width)
  241. {
  242.    struct lp_type res_type;
  243.  
  244.    memset(&res_type, 0, sizeof res_type);
  245.    res_type.sign = TRUE;
  246.    res_type.width = width;
  247.    res_type.length = 1;
  248.  
  249.    return res_type;
  250. }
  251.  
  252.  
  253. /** Create vector int type */
  254. static INLINE struct lp_type
  255. lp_type_int_vec(unsigned width, unsigned total_width)
  256. {
  257.    struct lp_type res_type;
  258.  
  259.    memset(&res_type, 0, sizeof res_type);
  260.    res_type.sign = TRUE;
  261.    res_type.width = width;
  262.    res_type.length = total_width / width;
  263.  
  264.    return res_type;
  265. }
  266.  
  267.  
  268. /** Create scalar uint type */
  269. static INLINE struct lp_type
  270. lp_type_uint(unsigned width)
  271. {
  272.    struct lp_type res_type;
  273.  
  274.    memset(&res_type, 0, sizeof res_type);
  275.    res_type.width = width;
  276.    res_type.length = 1;
  277.  
  278.    return res_type;
  279. }
  280.  
  281.  
  282. /** Create vector uint type */
  283. static INLINE struct lp_type
  284. lp_type_uint_vec(unsigned width, unsigned total_width)
  285. {
  286.    struct lp_type res_type;
  287.  
  288.    memset(&res_type, 0, sizeof res_type);
  289.    res_type.width = width;
  290.    res_type.length = total_width / width;
  291.  
  292.    return res_type;
  293. }
  294.  
  295.  
  296. static INLINE struct lp_type
  297. lp_type_unorm(unsigned width, unsigned total_width)
  298. {
  299.    struct lp_type res_type;
  300.  
  301.    memset(&res_type, 0, sizeof res_type);
  302.    res_type.norm = TRUE;
  303.    res_type.width = width;
  304.    res_type.length = total_width / width;
  305.  
  306.    return res_type;
  307. }
  308.  
  309.  
  310. static INLINE struct lp_type
  311. lp_type_fixed(unsigned width, unsigned total_width)
  312. {
  313.    struct lp_type res_type;
  314.  
  315.    memset(&res_type, 0, sizeof res_type);
  316.    res_type.sign = TRUE;
  317.    res_type.fixed = TRUE;
  318.    res_type.width = width;
  319.    res_type.length = total_width / width;
  320.  
  321.    return res_type;
  322. }
  323.  
  324.  
  325. static INLINE struct lp_type
  326. lp_type_ufixed(unsigned width, unsigned total_width)
  327. {
  328.    struct lp_type res_type;
  329.  
  330.    memset(&res_type, 0, sizeof res_type);
  331.    res_type.fixed = TRUE;
  332.    res_type.width = width;
  333.    res_type.length = total_width / width;
  334.  
  335.    return res_type;
  336. }
  337.  
  338.  
  339. LLVMTypeRef
  340. lp_build_elem_type(struct gallivm_state *gallivm, struct lp_type type);
  341.  
  342.  
  343. LLVMTypeRef
  344. lp_build_vec_type(struct gallivm_state *gallivm, struct lp_type type);
  345.  
  346.  
  347. boolean
  348. lp_check_elem_type(struct lp_type type, LLVMTypeRef elem_type);
  349.  
  350.  
  351. boolean
  352. lp_check_vec_type(struct lp_type type, LLVMTypeRef vec_type);
  353.  
  354.  
  355. boolean
  356. lp_check_value(struct lp_type type, LLVMValueRef val);
  357.  
  358.  
  359. LLVMTypeRef
  360. lp_build_int_elem_type(struct gallivm_state *gallivm, struct lp_type type);
  361.  
  362.  
  363. LLVMTypeRef
  364. lp_build_int_vec_type(struct gallivm_state *gallivm, struct lp_type type);
  365.  
  366.  
  367. static INLINE struct lp_type
  368. lp_float32_vec4_type(void)
  369. {
  370.    struct lp_type type;
  371.  
  372.    memset(&type, 0, sizeof(type));
  373.    type.floating = TRUE;
  374.    type.sign = TRUE;
  375.    type.norm = FALSE;
  376.    type.width = 32;
  377.    type.length = 4;
  378.  
  379.    return type;
  380. }
  381.  
  382.  
  383. static INLINE struct lp_type
  384. lp_int32_vec4_type(void)
  385. {
  386.    struct lp_type type;
  387.  
  388.    memset(&type, 0, sizeof(type));
  389.    type.floating = FALSE;
  390.    type.sign = TRUE;
  391.    type.norm = FALSE;
  392.    type.width = 32;
  393.    type.length = 4;
  394.  
  395.    return type;
  396. }
  397.  
  398.  
  399. static INLINE struct lp_type
  400. lp_unorm8_vec4_type(void)
  401. {
  402.    struct lp_type type;
  403.  
  404.    memset(&type, 0, sizeof(type));
  405.    type.floating = FALSE;
  406.    type.sign = FALSE;
  407.    type.norm = TRUE;
  408.    type.width = 8;
  409.    type.length = 4;
  410.  
  411.    return type;
  412. }
  413.  
  414.  
  415. struct lp_type
  416. lp_elem_type(struct lp_type type);
  417.  
  418.  
  419. struct lp_type
  420. lp_uint_type(struct lp_type type);
  421.  
  422.  
  423. struct lp_type
  424. lp_int_type(struct lp_type type);
  425.  
  426.  
  427. struct lp_type
  428. lp_wider_type(struct lp_type type);
  429.  
  430.  
  431. unsigned
  432. lp_sizeof_llvm_type(LLVMTypeRef t);
  433.  
  434.  
  435. const char *
  436. lp_typekind_name(LLVMTypeKind t);
  437.  
  438.  
  439. void
  440. lp_dump_llvmtype(LLVMTypeRef t);
  441.  
  442.  
  443. void
  444. lp_build_context_init(struct lp_build_context *bld,
  445.                       struct gallivm_state *gallivm,
  446.                       struct lp_type type);
  447.  
  448.  
  449. unsigned
  450. lp_build_count_instructions(LLVMValueRef function);
  451.  
  452.  
  453. #endif /* !LP_BLD_TYPE_H */
  454.