1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2010 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 18bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci * 22bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 23bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 24bf215546Sopenharmony_ci * of the Software. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "util/u_debug.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include "lp_bld_type.h" 32bf215546Sopenharmony_ci#include "lp_bld_debug.h" 33bf215546Sopenharmony_ci#include "lp_bld_const.h" 34bf215546Sopenharmony_ci#include "lp_bld_bitarit.h" 35bf215546Sopenharmony_ci#include "lp_bld_intr.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci/** 38bf215546Sopenharmony_ci * Return (a | b) 39bf215546Sopenharmony_ci */ 40bf215546Sopenharmony_ciLLVMValueRef 41bf215546Sopenharmony_cilp_build_or(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b) 42bf215546Sopenharmony_ci{ 43bf215546Sopenharmony_ci LLVMBuilderRef builder = bld->gallivm->builder; 44bf215546Sopenharmony_ci const struct lp_type type = bld->type; 45bf215546Sopenharmony_ci LLVMValueRef res; 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci assert(lp_check_value(type, a)); 48bf215546Sopenharmony_ci assert(lp_check_value(type, b)); 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci /* can't do bitwise ops on floating-point values */ 51bf215546Sopenharmony_ci if (type.floating) { 52bf215546Sopenharmony_ci a = LLVMBuildBitCast(builder, a, bld->int_vec_type, ""); 53bf215546Sopenharmony_ci b = LLVMBuildBitCast(builder, b, bld->int_vec_type, ""); 54bf215546Sopenharmony_ci } 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci res = LLVMBuildOr(builder, a, b, ""); 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci if (type.floating) { 59bf215546Sopenharmony_ci res = LLVMBuildBitCast(builder, res, bld->vec_type, ""); 60bf215546Sopenharmony_ci } 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci return res; 63bf215546Sopenharmony_ci} 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci/* bitwise XOR (a ^ b) */ 66bf215546Sopenharmony_ciLLVMValueRef 67bf215546Sopenharmony_cilp_build_xor(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b) 68bf215546Sopenharmony_ci{ 69bf215546Sopenharmony_ci LLVMBuilderRef builder = bld->gallivm->builder; 70bf215546Sopenharmony_ci const struct lp_type type = bld->type; 71bf215546Sopenharmony_ci LLVMValueRef res; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci assert(lp_check_value(type, a)); 74bf215546Sopenharmony_ci assert(lp_check_value(type, b)); 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci /* can't do bitwise ops on floating-point values */ 77bf215546Sopenharmony_ci if (type.floating) { 78bf215546Sopenharmony_ci a = LLVMBuildBitCast(builder, a, bld->int_vec_type, ""); 79bf215546Sopenharmony_ci b = LLVMBuildBitCast(builder, b, bld->int_vec_type, ""); 80bf215546Sopenharmony_ci } 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci res = LLVMBuildXor(builder, a, b, ""); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci if (type.floating) { 85bf215546Sopenharmony_ci res = LLVMBuildBitCast(builder, res, bld->vec_type, ""); 86bf215546Sopenharmony_ci } 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci return res; 89bf215546Sopenharmony_ci} 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci/** 92bf215546Sopenharmony_ci * Return (a & b) 93bf215546Sopenharmony_ci */ 94bf215546Sopenharmony_ciLLVMValueRef 95bf215546Sopenharmony_cilp_build_and(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b) 96bf215546Sopenharmony_ci{ 97bf215546Sopenharmony_ci LLVMBuilderRef builder = bld->gallivm->builder; 98bf215546Sopenharmony_ci const struct lp_type type = bld->type; 99bf215546Sopenharmony_ci LLVMValueRef res; 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci assert(lp_check_value(type, a)); 102bf215546Sopenharmony_ci assert(lp_check_value(type, b)); 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci /* can't do bitwise ops on floating-point values */ 105bf215546Sopenharmony_ci if (type.floating) { 106bf215546Sopenharmony_ci a = LLVMBuildBitCast(builder, a, bld->int_vec_type, ""); 107bf215546Sopenharmony_ci b = LLVMBuildBitCast(builder, b, bld->int_vec_type, ""); 108bf215546Sopenharmony_ci } 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci res = LLVMBuildAnd(builder, a, b, ""); 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci if (type.floating) { 113bf215546Sopenharmony_ci res = LLVMBuildBitCast(builder, res, bld->vec_type, ""); 114bf215546Sopenharmony_ci } 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci return res; 117bf215546Sopenharmony_ci} 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci/** 121bf215546Sopenharmony_ci * Return (a & ~b) 122bf215546Sopenharmony_ci */ 123bf215546Sopenharmony_ciLLVMValueRef 124bf215546Sopenharmony_cilp_build_andnot(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b) 125bf215546Sopenharmony_ci{ 126bf215546Sopenharmony_ci LLVMBuilderRef builder = bld->gallivm->builder; 127bf215546Sopenharmony_ci const struct lp_type type = bld->type; 128bf215546Sopenharmony_ci LLVMValueRef res; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci assert(lp_check_value(type, a)); 131bf215546Sopenharmony_ci assert(lp_check_value(type, b)); 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci /* can't do bitwise ops on floating-point values */ 134bf215546Sopenharmony_ci if (type.floating) { 135bf215546Sopenharmony_ci a = LLVMBuildBitCast(builder, a, bld->int_vec_type, ""); 136bf215546Sopenharmony_ci b = LLVMBuildBitCast(builder, b, bld->int_vec_type, ""); 137bf215546Sopenharmony_ci } 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci res = LLVMBuildNot(builder, b, ""); 140bf215546Sopenharmony_ci res = LLVMBuildAnd(builder, a, res, ""); 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci if (type.floating) { 143bf215546Sopenharmony_ci res = LLVMBuildBitCast(builder, res, bld->vec_type, ""); 144bf215546Sopenharmony_ci } 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci return res; 147bf215546Sopenharmony_ci} 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci/* bitwise NOT */ 150bf215546Sopenharmony_ciLLVMValueRef 151bf215546Sopenharmony_cilp_build_not(struct lp_build_context *bld, LLVMValueRef a) 152bf215546Sopenharmony_ci{ 153bf215546Sopenharmony_ci LLVMBuilderRef builder = bld->gallivm->builder; 154bf215546Sopenharmony_ci const struct lp_type type = bld->type; 155bf215546Sopenharmony_ci LLVMValueRef res; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci assert(lp_check_value(type, a)); 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci if (type.floating) { 160bf215546Sopenharmony_ci a = LLVMBuildBitCast(builder, a, bld->int_vec_type, ""); 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci res = LLVMBuildNot(builder, a, ""); 163bf215546Sopenharmony_ci if (type.floating) { 164bf215546Sopenharmony_ci res = LLVMBuildBitCast(builder, res, bld->vec_type, ""); 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci return res; 167bf215546Sopenharmony_ci} 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci/** 170bf215546Sopenharmony_ci * Shift left. 171bf215546Sopenharmony_ci * Result is undefined if the shift count is not smaller than the type width. 172bf215546Sopenharmony_ci */ 173bf215546Sopenharmony_ciLLVMValueRef 174bf215546Sopenharmony_cilp_build_shl(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b) 175bf215546Sopenharmony_ci{ 176bf215546Sopenharmony_ci LLVMBuilderRef builder = bld->gallivm->builder; 177bf215546Sopenharmony_ci const struct lp_type type = bld->type; 178bf215546Sopenharmony_ci LLVMValueRef res; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci assert(!type.floating); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci assert(lp_check_value(type, a)); 183bf215546Sopenharmony_ci assert(lp_check_value(type, b)); 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci (void)type; 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci res = LLVMBuildShl(builder, a, b, ""); 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci return res; 190bf215546Sopenharmony_ci} 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci/** 194bf215546Sopenharmony_ci * Shift right. 195bf215546Sopenharmony_ci * Result is undefined if the shift count is not smaller than the type width. 196bf215546Sopenharmony_ci */ 197bf215546Sopenharmony_ciLLVMValueRef 198bf215546Sopenharmony_cilp_build_shr(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b) 199bf215546Sopenharmony_ci{ 200bf215546Sopenharmony_ci LLVMBuilderRef builder = bld->gallivm->builder; 201bf215546Sopenharmony_ci const struct lp_type type = bld->type; 202bf215546Sopenharmony_ci LLVMValueRef res; 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci assert(!type.floating); 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci assert(lp_check_value(type, a)); 207bf215546Sopenharmony_ci assert(lp_check_value(type, b)); 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci if (type.sign) { 210bf215546Sopenharmony_ci res = LLVMBuildAShr(builder, a, b, ""); 211bf215546Sopenharmony_ci } else { 212bf215546Sopenharmony_ci res = LLVMBuildLShr(builder, a, b, ""); 213bf215546Sopenharmony_ci } 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci return res; 216bf215546Sopenharmony_ci} 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci/** 220bf215546Sopenharmony_ci * Shift left with immediate. 221bf215546Sopenharmony_ci * The immediate shift count must be smaller than the type width. 222bf215546Sopenharmony_ci */ 223bf215546Sopenharmony_ciLLVMValueRef 224bf215546Sopenharmony_cilp_build_shl_imm(struct lp_build_context *bld, LLVMValueRef a, unsigned imm) 225bf215546Sopenharmony_ci{ 226bf215546Sopenharmony_ci LLVMValueRef b = lp_build_const_int_vec(bld->gallivm, bld->type, imm); 227bf215546Sopenharmony_ci assert(imm < bld->type.width); 228bf215546Sopenharmony_ci return lp_build_shl(bld, a, b); 229bf215546Sopenharmony_ci} 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci/** 233bf215546Sopenharmony_ci * Shift right with immediate. 234bf215546Sopenharmony_ci * The immediate shift count must be smaller than the type width. 235bf215546Sopenharmony_ci */ 236bf215546Sopenharmony_ciLLVMValueRef 237bf215546Sopenharmony_cilp_build_shr_imm(struct lp_build_context *bld, LLVMValueRef a, unsigned imm) 238bf215546Sopenharmony_ci{ 239bf215546Sopenharmony_ci LLVMValueRef b = lp_build_const_int_vec(bld->gallivm, bld->type, imm); 240bf215546Sopenharmony_ci assert(imm < bld->type.width); 241bf215546Sopenharmony_ci return lp_build_shr(bld, a, b); 242bf215546Sopenharmony_ci} 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ciLLVMValueRef 245bf215546Sopenharmony_cilp_build_popcount(struct lp_build_context *bld, LLVMValueRef a) 246bf215546Sopenharmony_ci{ 247bf215546Sopenharmony_ci LLVMBuilderRef builder = bld->gallivm->builder; 248bf215546Sopenharmony_ci LLVMValueRef result; 249bf215546Sopenharmony_ci char intr_str[256]; 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci lp_format_intrinsic(intr_str, sizeof(intr_str), "llvm.ctpop", bld->vec_type); 252bf215546Sopenharmony_ci result = lp_build_intrinsic_unary(builder, intr_str, bld->vec_type, a); 253bf215546Sopenharmony_ci return result; 254bf215546Sopenharmony_ci} 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ciLLVMValueRef 257bf215546Sopenharmony_cilp_build_bitfield_reverse(struct lp_build_context *bld, LLVMValueRef a) 258bf215546Sopenharmony_ci{ 259bf215546Sopenharmony_ci LLVMBuilderRef builder = bld->gallivm->builder; 260bf215546Sopenharmony_ci LLVMValueRef result; 261bf215546Sopenharmony_ci char intr_str[256]; 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci lp_format_intrinsic(intr_str, sizeof(intr_str), "llvm.bitreverse", bld->vec_type); 264bf215546Sopenharmony_ci result = lp_build_intrinsic_unary(builder, intr_str, bld->vec_type, a); 265bf215546Sopenharmony_ci return result; 266bf215546Sopenharmony_ci} 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ciLLVMValueRef 269bf215546Sopenharmony_cilp_build_cttz(struct lp_build_context *bld, LLVMValueRef a) 270bf215546Sopenharmony_ci{ 271bf215546Sopenharmony_ci LLVMBuilderRef builder = bld->gallivm->builder; 272bf215546Sopenharmony_ci LLVMValueRef result; 273bf215546Sopenharmony_ci char intr_str[256]; 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci lp_format_intrinsic(intr_str, sizeof(intr_str), "llvm.cttz", bld->vec_type); 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci LLVMValueRef undef_val = LLVMConstNull(LLVMInt1TypeInContext(bld->gallivm->context)); 278bf215546Sopenharmony_ci result = lp_build_intrinsic_binary(builder, intr_str, bld->vec_type, a, undef_val); 279bf215546Sopenharmony_ci return LLVMBuildSelect(builder, LLVMBuildICmp(builder, LLVMIntEQ, a, bld->zero, ""), 280bf215546Sopenharmony_ci lp_build_const_int_vec(bld->gallivm, bld->type, -1), result, ""); 281bf215546Sopenharmony_ci} 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ciLLVMValueRef 284bf215546Sopenharmony_cilp_build_ctlz(struct lp_build_context *bld, LLVMValueRef a) 285bf215546Sopenharmony_ci{ 286bf215546Sopenharmony_ci LLVMBuilderRef builder = bld->gallivm->builder; 287bf215546Sopenharmony_ci LLVMValueRef result; 288bf215546Sopenharmony_ci char intr_str[256]; 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci lp_format_intrinsic(intr_str, sizeof(intr_str), "llvm.ctlz", bld->vec_type); 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci LLVMValueRef undef_val = LLVMConstNull(LLVMInt1TypeInContext(bld->gallivm->context)); 293bf215546Sopenharmony_ci result = lp_build_intrinsic_binary(builder, intr_str, bld->vec_type, a, undef_val); 294bf215546Sopenharmony_ci return result; 295bf215546Sopenharmony_ci} 296