[Mesa-dev] [PATCH 1/2] draw/gallivm: export overflow arithmetic to its own file

Jose Fonseca jfonseca at vmware.com
Thu Jun 27 14:49:26 PDT 2013


Series looks great.

Thanks.

Jose

----- Original Message -----
> We'll be reusing this code so lets put it in a common file
> and use it in the draw module.
> 
> Signed-off-by: Zack Rusin <zackr at vmware.com>
> ---
>  src/gallium/auxiliary/Makefile.sources             |    1 +
>  src/gallium/auxiliary/draw/draw_llvm.c             |   55 ++-----
>  .../auxiliary/gallivm/lp_bld_arit_overflow.c       |  165
>  ++++++++++++++++++++
>  .../auxiliary/gallivm/lp_bld_arit_overflow.h       |   57 +++++++
>  4 files changed, 234 insertions(+), 44 deletions(-)
>  create mode 100644 src/gallium/auxiliary/gallivm/lp_bld_arit_overflow.c
>  create mode 100644 src/gallium/auxiliary/gallivm/lp_bld_arit_overflow.h
> 
> diff --git a/src/gallium/auxiliary/Makefile.sources
> b/src/gallium/auxiliary/Makefile.sources
> index 20ff5ba..4751762 100644
> --- a/src/gallium/auxiliary/Makefile.sources
> +++ b/src/gallium/auxiliary/Makefile.sources
> @@ -163,6 +163,7 @@ GENERATED_SOURCES := \
>  
>  GALLIVM_SOURCES := \
>          gallivm/lp_bld_arit.c \
> +        gallivm/lp_bld_arit_overflow.c \
>          gallivm/lp_bld_assert.c \
>          gallivm/lp_bld_bitarit.c \
>          gallivm/lp_bld_const.c \
> diff --git a/src/gallium/auxiliary/draw/draw_llvm.c
> b/src/gallium/auxiliary/draw/draw_llvm.c
> index 33cccfe..97b463f 100644
> --- a/src/gallium/auxiliary/draw/draw_llvm.c
> +++ b/src/gallium/auxiliary/draw/draw_llvm.c
> @@ -32,6 +32,7 @@
>  #include "draw_gs.h"
>  
>  #include "gallivm/lp_bld_arit.h"
> +#include "gallivm/lp_bld_arit_overflow.h"
>  #include "gallivm/lp_bld_logic.h"
>  #include "gallivm/lp_bld_const.h"
>  #include "gallivm/lp_bld_swizzle.h"
> @@ -699,13 +700,7 @@ generate_fetch(struct gallivm_state *gallivm,
>     LLVMValueRef temp_ptr =
>        lp_build_alloca(gallivm,
>                        lp_build_vec_type(gallivm, lp_float32_vec4_type()),
>                        "");
> -   LLVMValueRef ofbit, oresult;
> -   LLVMTypeRef oelems[2] = {
> -      LLVMInt32TypeInContext(gallivm->context),
> -      LLVMInt1TypeInContext(gallivm->context)
> -   };
> -   LLVMTypeRef otype = LLVMStructTypeInContext(gallivm->context,
> -                                               oelems, 2, FALSE);
> +   LLVMValueRef ofbit = NULL;
>     struct lp_build_if_state if_ctx;
>  
>     if (velem->instance_divisor) {
> @@ -715,44 +710,16 @@ generate_fetch(struct gallivm_state *gallivm,
>                              "instance_divisor");
>     }
>  
> -   oresult = lp_build_intrinsic_binary(builder,
> -                                       "llvm.umul.with.overflow.i32",
> -                                       otype, vb_stride, index);
> -   ofbit = LLVMBuildExtractValue(builder, oresult, 1, "");
> -   stride = LLVMBuildExtractValue(builder, oresult, 0, "");
> -
> -   oresult = lp_build_intrinsic_binary(builder,
> -                                       "llvm.uadd.with.overflow.i32",
> -                                       otype, stride, vb_buffer_offset);
> -   ofbit = LLVMBuildOr(
> -      builder, ofbit,
> -      LLVMBuildExtractValue(builder, oresult,  1, ""),
> -      "");
> -   stride = LLVMBuildExtractValue(builder, oresult, 0, "");
> -
> -   oresult = lp_build_intrinsic_binary(
> -      builder,
> -      "llvm.uadd.with.overflow.i32",
> -      otype, stride,
> -      lp_build_const_int32(gallivm, velem->src_offset));
> -   ofbit = LLVMBuildOr(
> -      builder, ofbit,
> -      LLVMBuildExtractValue(builder, oresult, 1, ""),
> -      "");
> -   stride = LLVMBuildExtractValue(builder, oresult,  0, "");
> -
> -
> -   oresult = lp_build_intrinsic_binary(
> -      builder,
> -      "llvm.uadd.with.overflow.i32",
> -      otype, stride,
> +   stride = lp_build_umul_overflow(gallivm, vb_stride, index, &ofbit);
> +   stride = lp_build_uadd_overflow(gallivm, stride, vb_buffer_offset,
> &ofbit);
> +   stride = lp_build_uadd_overflow(
> +      gallivm, stride,
> +      lp_build_const_int32(gallivm, velem->src_offset), &ofbit);
> +   needed_buffer_size = lp_build_uadd_overflow(
> +      gallivm, stride,
>        lp_build_const_int32(gallivm,
> -                           util_format_get_blocksize(velem->src_format)));
> -   ofbit = LLVMBuildOr(
> -      builder, ofbit,
> -      LLVMBuildExtractValue(builder, oresult, 1, ""),
> -      "");
> -   needed_buffer_size = LLVMBuildExtractValue(builder, oresult, 0, "");
> +                           util_format_get_blocksize(velem->src_format)),
> +      &ofbit);
>  
>     buffer_overflowed = LLVMBuildICmp(builder, LLVMIntUGT,
>                                       needed_buffer_size, buffer_size,
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit_overflow.c
> b/src/gallium/auxiliary/gallivm/lp_bld_arit_overflow.c
> new file mode 100644
> index 0000000..f17e17a
> --- /dev/null
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit_overflow.c
> @@ -0,0 +1,165 @@
> +/**************************************************************************
> + *
> + * Copyright 2013
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + **************************************************************************/
> +
> +
> +/**
> + * @file
> + * Helper
> + *
> + * The functions in this file implement arthmetic operations with support
> + * for overflow detection and reporting.
> + *
> + */
> +
> +#include "lp_bld_arit_overflow.h"
> +
> +#include "lp_bld_type.h"
> +#include "lp_bld_const.h"
> +#include "lp_bld_init.h"
> +#include "lp_bld_intr.h"
> +#include "lp_bld_logic.h"
> +#include "lp_bld_pack.h"
> +#include "lp_bld_debug.h"
> +#include "lp_bld_bitarit.h"
> +
> +#include "util/u_memory.h"
> +#include "util/u_debug.h"
> +#include "util/u_math.h"
> +#include "util/u_string.h"
> +#include "util/u_cpu_detect.h"
> +
> +#include <float.h>
> +
> +
> +static LLVMValueRef
> +build_binary_int_overflow(struct gallivm_state *gallivm,
> +                          const char *intr_prefix,
> +                          LLVMValueRef a,
> +                          LLVMValueRef b,
> +                          LLVMValueRef *ofbit)
> +{
> +   static const int MAX_INTR_STR = 256;
> +   LLVMBuilderRef builder = gallivm->builder;
> +   char intr_str[MAX_INTR_STR];
> +   LLVMTypeRef type_ref;
> +   LLVMTypeKind type_kind;
> +   LLVMTypeRef oelems[2] = {
> +      LLVMInt32TypeInContext(gallivm->context),
> +      LLVMInt1TypeInContext(gallivm->context)
> +   };
> +   LLVMValueRef oresult;
> +   LLVMTypeRef otype;
> +
> +   debug_assert(LLVMTypeOf(a) == LLVMTypeOf(b));
> +   type_ref = LLVMTypeOf(a);
> +   type_kind = LLVMGetTypeKind(type_ref);
> +
> +   debug_assert(type_kind == LLVMIntegerTypeKind);
> +
> +   switch (LLVMGetIntTypeWidth(type_ref)) {
> +   case 16:
> +      snprintf(intr_str, MAX_INTR_STR - 1, "%s.i16",
> +               intr_prefix);
> +      oelems[0] = LLVMInt16TypeInContext(gallivm->context);
> +      break;
> +   case 32:
> +      snprintf(intr_str, MAX_INTR_STR - 1, "%s.i32",
> +               intr_prefix);
> +      oelems[0] = LLVMInt32TypeInContext(gallivm->context);
> +      break;
> +   case 64:
> +      snprintf(intr_str, MAX_INTR_STR - 1, "%s.i64",
> +               intr_prefix);
> +      oelems[0] = LLVMInt64TypeInContext(gallivm->context);
> +      break;
> +   default:
> +      debug_assert(!"Unsupported integer width in overflow computation!");
> +   }
> +
> +   otype = LLVMStructTypeInContext(gallivm->context, oelems, 2, FALSE);
> +   oresult = lp_build_intrinsic_binary(builder, intr_str,
> +                                       otype, a, b);
> +   if (ofbit) {
> +      if (*ofbit) {
> +         *ofbit = LLVMBuildOr(
> +            builder, *ofbit,
> +            LLVMBuildExtractValue(builder, oresult, 1, ""), "");
> +      } else {
> +         *ofbit = LLVMBuildExtractValue(builder, oresult, 1, "");
> +      }
> +   }
> +
> +   return LLVMBuildExtractValue(builder, oresult, 0, "");
> +}
> +
> +/**
> + * Performs unsigned addition of two integers and reports
> + * overflow if detected.
> + *
> + * The values @a and @b must be of the same integer type. If
> + * an overflow is detected the IN/OUT @ofbit parameter is used:
> + * - if it's pointing to a null value, the overflow bit is simply
> + *   stored inside the varaible it's pointing to,
> + * - if it's pointing to a valid value, then that variable,
> + *   which must be of i1 type, is ORed with the newly detected
> + *   overflow bit. This is done to allow chaining of a number of
> + *   overflow functions together without having to test the
> + *   overflow bit after every single one.
> + */
> +LLVMValueRef
> +lp_build_uadd_overflow(struct gallivm_state *gallivm,
> +                       LLVMValueRef a,
> +                       LLVMValueRef b,
> +                       LLVMValueRef *ofbit)
> +{
> +   return build_binary_int_overflow(gallivm, "llvm.uadd.with.overflow",
> +                                    a, b, ofbit);
> +}
> +
> +/**
> + * Performs unsigned multiplication of  two integers and
> + * reports overflow if detected.
> + *
> + * The values @a and @b must be of the same integer type. If
> + * an overflow is detected the IN/OUT @ofbit parameter is used:
> + * - if it's pointing to a null value, the overflow bit is simply
> + *   stored inside the varaible it's pointing to,
> + * - if it's pointing to a valid value, then that variable,
> + *   which must be of i1 type, is ORed with the newly detected
> + *   overflow bit. This is done to allow chaining of a number of
> + *   overflow functions together without having to test the
> + *   overflow bit after every single one.
> + */
> +LLVMValueRef
> +lp_build_umul_overflow(struct gallivm_state *gallivm,
> +                       LLVMValueRef a,
> +                       LLVMValueRef b,
> +                       LLVMValueRef *ofbit)
> +{
> +   return build_binary_int_overflow(gallivm, "llvm.umul.with.overflow",
> +                                    a, b, ofbit);
> +}
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit_overflow.h
> b/src/gallium/auxiliary/gallivm/lp_bld_arit_overflow.h
> new file mode 100644
> index 0000000..8c35a04
> --- /dev/null
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit_overflow.h
> @@ -0,0 +1,57 @@
> +/**************************************************************************
> + *
> + * Copyright 2013 VMware, Inc.
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + **************************************************************************/
> +
> +/**
> + * @file
> + * Helper arithmetic functions with support for overflow detection
> + * and reporting.
> + *
> + * @author Zack Rusin <zackr at vmware.com>
> + */
> +
> +
> +#ifndef LP_BLD_ARIT_OVERFLOW_H
> +#define LP_BLD_ARIT_OVERFLOW_H
> +
> +
> +#include "gallivm/lp_bld.h"
> +
> +struct gallivm_state;
> +
> +LLVMValueRef
> +lp_build_uadd_overflow(struct gallivm_state *gallivm,
> +                       LLVMValueRef a,
> +                       LLVMValueRef b,
> +                       LLVMValueRef *ofbit);
> +
> +LLVMValueRef
> +lp_build_umul_overflow(struct gallivm_state *gallivm,
> +                       LLVMValueRef a,
> +                       LLVMValueRef b,
> +                       LLVMValueRef *ofbit);
> +
> +#endif /* !LP_BLD_ARIT_OVERFLOW_H */
> --
> 1.7.10.4
> 


More information about the mesa-dev mailing list