1 /************************************************************************** 2 * 3 * Copyright 2013 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 /** 30 * @file 31 * Helper 32 * 33 * The functions in this file implement arthmetic operations with support 34 * for overflow detection and reporting. 35 * 36 */ 37 38 #include "lp_bld_arit_overflow.h" 39 40 #include "lp_bld_type.h" 41 #include "lp_bld_const.h" 42 #include "lp_bld_init.h" 43 #include "lp_bld_intr.h" 44 #include "lp_bld_logic.h" 45 #include "lp_bld_pack.h" 46 #include "lp_bld_debug.h" 47 #include "lp_bld_bitarit.h" 48 49 #include "util/u_memory.h" 50 #include "util/u_debug.h" 51 #include "util/u_math.h" 52 #include "util/u_string.h" 53 #include "util/u_cpu_detect.h" 54 55 #include <float.h> 56 57 58 static LLVMValueRef 59 build_binary_int_overflow(struct gallivm_state *gallivm, 60 const char *intr_prefix, 61 LLVMValueRef a, 62 LLVMValueRef b, 63 LLVMValueRef *ofbit) 64 { 65 LLVMBuilderRef builder = gallivm->builder; 66 char intr_str[256]; 67 LLVMTypeRef type_ref; 68 LLVMTypeKind type_kind; 69 unsigned type_width; 70 LLVMTypeRef oelems[2]; 71 LLVMValueRef oresult; 72 LLVMTypeRef otype; 73 74 debug_assert(LLVMTypeOf(a) == LLVMTypeOf(b)); 75 type_ref = LLVMTypeOf(a); 76 type_kind = LLVMGetTypeKind(type_ref); 77 78 debug_assert(type_kind == LLVMIntegerTypeKind); 79 type_width = LLVMGetIntTypeWidth(type_ref); 80 81 debug_assert(type_width == 16 || type_width == 32 || type_width == 64); 82 83 util_snprintf(intr_str, sizeof intr_str, "%s.i%u", 84 intr_prefix, type_width); 85 86 oelems[0] = type_ref; 87 oelems[1] = LLVMInt1TypeInContext(gallivm->context); 88 89 otype = LLVMStructTypeInContext(gallivm->context, oelems, 2, FALSE); 90 oresult = lp_build_intrinsic_binary(builder, intr_str, 91 otype, a, b); 92 if (ofbit) { 93 if (*ofbit) { 94 *ofbit = LLVMBuildOr( 95 builder, *ofbit, 96 LLVMBuildExtractValue(builder, oresult, 1, ""), ""); 97 } else { 98 *ofbit = LLVMBuildExtractValue(builder, oresult, 1, ""); 99 } 100 } 101 102 return LLVMBuildExtractValue(builder, oresult, 0, ""); 103 } 104 105 /** 106 * Performs unsigned addition of two integers and reports 107 * overflow if detected. 108 * 109 * The values @a and @b must be of the same integer type. If 110 * an overflow is detected the IN/OUT @ofbit parameter is used: 111 * - if it's pointing to a null value, the overflow bit is simply 112 * stored inside the variable it's pointing to, 113 * - if it's pointing to a valid value, then that variable, 114 * which must be of i1 type, is ORed with the newly detected 115 * overflow bit. This is done to allow chaining of a number of 116 * overflow functions together without having to test the 117 * overflow bit after every single one. 118 */ 119 LLVMValueRef 120 lp_build_uadd_overflow(struct gallivm_state *gallivm, 121 LLVMValueRef a, 122 LLVMValueRef b, 123 LLVMValueRef *ofbit) 124 { 125 return build_binary_int_overflow(gallivm, "llvm.uadd.with.overflow", 126 a, b, ofbit); 127 } 128 129 /** 130 * Performs unsigned subtraction of two integers and reports 131 * overflow if detected. 132 * 133 * The values @a and @b must be of the same integer type. If 134 * an overflow is detected the IN/OUT @ofbit parameter is used: 135 * - if it's pointing to a null value, the overflow bit is simply 136 * stored inside the variable it's pointing to, 137 * - if it's pointing to a valid value, then that variable, 138 * which must be of i1 type, is ORed with the newly detected 139 * overflow bit. This is done to allow chaining of a number of 140 * overflow functions together without having to test the 141 * overflow bit after every single one. 142 */ 143 LLVMValueRef 144 lp_build_usub_overflow(struct gallivm_state *gallivm, 145 LLVMValueRef a, 146 LLVMValueRef b, 147 LLVMValueRef *ofbit) 148 { 149 return build_binary_int_overflow(gallivm, "llvm.usub.with.overflow", 150 a, b, ofbit); 151 } 152 153 /** 154 * Performs unsigned multiplication of two integers and 155 * reports overflow if detected. 156 * 157 * The values @a and @b must be of the same integer type. If 158 * an overflow is detected the IN/OUT @ofbit parameter is used: 159 * - if it's pointing to a null value, the overflow bit is simply 160 * stored inside the variable it's pointing to, 161 * - if it's pointing to a valid value, then that variable, 162 * which must be of i1 type, is ORed with the newly detected 163 * overflow bit. This is done to allow chaining of a number of 164 * overflow functions together without having to test the 165 * overflow bit after every single one. 166 */ 167 LLVMValueRef 168 lp_build_umul_overflow(struct gallivm_state *gallivm, 169 LLVMValueRef a, 170 LLVMValueRef b, 171 LLVMValueRef *ofbit) 172 { 173 return build_binary_int_overflow(gallivm, "llvm.umul.with.overflow", 174 a, b, ofbit); 175 } 176