#include "pipe/p_compiler.h"
#include "gallivm/lp_bld.h"
+/**
+ * Native SIMD architecture width available at runtime.
+ *
+ * Using this width should give the best performance,
+ * and it determines the necessary alignment of vector variables.
+ */
+extern unsigned lp_native_vector_width;
+/**
+ * Maximum supported vector width (not necessarily supported at run-time).
+ *
+ * Should only be used when lp_native_vector_width isn't available,
+ * i.e. sizing/alignment of non-malloced variables.
+ */
+#define LP_MAX_VECTOR_WIDTH 256
/**
- * Native SIMD register width.
+ * Minimum vector alignment for static variable alignment
*
- * 128 for all architectures we care about.
+ * It should always be a constant equal to LP_MAX_VECTOR_WIDTH/8. An
+ * expression is non-portable.
*/
-#define LP_NATIVE_VECTOR_WIDTH 128
+#define LP_MIN_VECTOR_ALIGN 32
/**
* Several functions can only cope with vectors of length up to this value.
* You may need to increase that value if you want to represent bigger vectors.
*/
-#define LP_MAX_VECTOR_LENGTH 16
-
+#define LP_MAX_VECTOR_LENGTH (LP_MAX_VECTOR_WIDTH/8)
/**
* The LLVM type system can't conveniently express all the things we care about
*/
struct lp_build_context
{
- LLVMBuilderRef builder;
+ struct gallivm_state *gallivm;
/**
* This not only describes the input/output LLVM types, but also whether
*/
struct lp_type type;
- /** Same as lp_build_undef(type) */
+ /** Same as lp_build_elem_type(type) */
LLVMTypeRef elem_type;
- /** Same as lp_build_undef(type) */
+ /** Same as lp_build_vec_type(type) */
LLVMTypeRef vec_type;
- /** Same as lp_build_undef(type) */
+ /** Same as lp_build_int_elem_type(type) */
LLVMTypeRef int_elem_type;
- /** Same as lp_build_undef(type) */
+ /** Same as lp_build_int_vec_type(type) */
LLVMTypeRef int_vec_type;
/** Same as lp_build_undef(type) */
};
+static INLINE unsigned
+lp_type_width(struct lp_type type)
+{
+ return type.width * type.length;
+}
+
+
/** Create scalar float type */
static INLINE struct lp_type
lp_type_float(unsigned width)
/** Create vector of float type */
static INLINE struct lp_type
-lp_type_float_vec(unsigned width)
+lp_type_float_vec(unsigned width, unsigned total_width)
{
struct lp_type res_type;
res_type.floating = TRUE;
res_type.sign = TRUE;
res_type.width = width;
- res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+ res_type.length = total_width / width;
return res_type;
}
/** Create vector int type */
static INLINE struct lp_type
-lp_type_int_vec(unsigned width)
+lp_type_int_vec(unsigned width, unsigned total_width)
{
struct lp_type res_type;
memset(&res_type, 0, sizeof res_type);
res_type.sign = TRUE;
res_type.width = width;
- res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+ res_type.length = total_width / width;
return res_type;
}
/** Create vector uint type */
static INLINE struct lp_type
-lp_type_uint_vec(unsigned width)
+lp_type_uint_vec(unsigned width, unsigned total_width)
{
struct lp_type res_type;
memset(&res_type, 0, sizeof res_type);
res_type.width = width;
- res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+ res_type.length = total_width / width;
return res_type;
}
static INLINE struct lp_type
-lp_type_unorm(unsigned width)
+lp_type_unorm(unsigned width, unsigned total_width)
{
struct lp_type res_type;
memset(&res_type, 0, sizeof res_type);
res_type.norm = TRUE;
res_type.width = width;
- res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+ res_type.length = total_width / width;
return res_type;
}
static INLINE struct lp_type
-lp_type_fixed(unsigned width)
+lp_type_fixed(unsigned width, unsigned total_width)
{
struct lp_type res_type;
res_type.sign = TRUE;
res_type.fixed = TRUE;
res_type.width = width;
- res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+ res_type.length = total_width / width;
return res_type;
}
static INLINE struct lp_type
-lp_type_ufixed(unsigned width)
+lp_type_ufixed(unsigned width, unsigned total_width)
{
struct lp_type res_type;
memset(&res_type, 0, sizeof res_type);
res_type.fixed = TRUE;
res_type.width = width;
- res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+ res_type.length = total_width / width;
return res_type;
}
LLVMTypeRef
-lp_build_elem_type(struct lp_type type);
+lp_build_elem_type(struct gallivm_state *gallivm, struct lp_type type);
LLVMTypeRef
-lp_build_vec_type(struct lp_type type);
+lp_build_vec_type(struct gallivm_state *gallivm, struct lp_type type);
boolean
LLVMTypeRef
-lp_build_int_elem_type(struct lp_type type);
+lp_build_int_elem_type(struct gallivm_state *gallivm, struct lp_type type);
LLVMTypeRef
-lp_build_int_vec_type(struct lp_type type);
+lp_build_int_vec_type(struct gallivm_state *gallivm, struct lp_type type);
-LLVMTypeRef
-lp_build_int32_vec4_type(void);
+static INLINE struct lp_type
+lp_float32_vec4_type(void)
+{
+ struct lp_type type;
+
+ memset(&type, 0, sizeof(type));
+ type.floating = TRUE;
+ type.sign = TRUE;
+ type.norm = FALSE;
+ type.width = 32;
+ type.length = 4;
+
+ return type;
+}
+
+
+static INLINE struct lp_type
+lp_int32_vec4_type(void)
+{
+ struct lp_type type;
+
+ memset(&type, 0, sizeof(type));
+ type.floating = FALSE;
+ type.sign = TRUE;
+ type.norm = FALSE;
+ type.width = 32;
+ type.length = 4;
+
+ return type;
+}
+
+
+static INLINE struct lp_type
+lp_unorm8_vec4_type(void)
+{
+ struct lp_type type;
+
+ memset(&type, 0, sizeof(type));
+ type.floating = FALSE;
+ type.sign = FALSE;
+ type.norm = TRUE;
+ type.width = 8;
+ type.length = 4;
+
+ return type;
+}
+
+
+struct lp_type
+lp_elem_type(struct lp_type type);
struct lp_type
void
lp_build_context_init(struct lp_build_context *bld,
- LLVMBuilderRef builder,
+ struct gallivm_state *gallivm,
struct lp_type type);
+unsigned
+lp_build_count_instructions(LLVMValueRef function);
+
+
#endif /* !LP_BLD_TYPE_H */