| author | |
| committer | |
| log | 1c7798a3cde9e8dad31c276aab4c1affb2043ad2 |
| tree | 870480a2191982b63e6b4a29152e26db373a286b |
| parent | 68f84964b3d80e5b976810208a14c31268a181e1 |
| parent | e149f1e1de8f79a66a97da1700d9a64fc2983211 |
| signature |
Implement more intrinsics in new LLVM IR builder API and remove uses of LLVM owns API5 files changed, 461 insertions(+), 133 deletions(-)
src/codegen/llvm.zig+83-133| ... | ... | @@ -5100,11 +5100,11 @@ pub const FuncGen = struct { |
| 5100 | 5100 | .memcpy => try self.airMemcpy(inst), |
| 5101 | 5101 | .set_union_tag => try self.airSetUnionTag(inst), |
| 5102 | 5102 | .get_union_tag => try self.airGetUnionTag(inst), |
| 5103 | .clz => try self.airClzCtz(inst, "llvm.ctlz"), | |
| 5104 | .ctz => try self.airClzCtz(inst, "llvm.cttz"), | |
| 5105 | .popcount => try self.airBitOp(inst, "llvm.ctpop"), | |
| 5106 | .byte_swap => try self.airByteSwap(inst, "llvm.bswap"), | |
| 5107 | .bit_reverse => try self.airBitOp(inst, "llvm.bitreverse"), | |
| 5103 | .clz => try self.airClzCtz(inst, .@"llvm.ctlz."), | |
| 5104 | .ctz => try self.airClzCtz(inst, .@"llvm.cttz."), | |
| 5105 | .popcount => try self.airBitOp(inst, .@"llvm.ctpop."), | |
| 5106 | .byte_swap => try self.airByteSwap(inst), | |
| 5107 | .bit_reverse => try self.airBitOp(inst, .@"llvm.bitreverse."), | |
| 5108 | 5108 | .tag_name => try self.airTagName(inst), |
| 5109 | 5109 | .error_name => try self.airErrorName(inst), |
| 5110 | 5110 | .splat => try self.airSplat(inst), |
| ... | ... | @@ -8282,8 +8282,7 @@ pub const FuncGen = struct { |
| 8282 | 8282 | const scalar_ty = ty.scalarType(mod); |
| 8283 | 8283 | const llvm_ty = try o.lowerType(ty); |
| 8284 | 8284 | |
| 8285 | const intrinsics_allowed = op != .tan and intrinsicsAllowed(scalar_ty, target); | |
| 8286 | const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) { | |
| 8285 | if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) { | |
| 8287 | 8286 | // Some operations are dedicated LLVM instructions, not available as intrinsics |
| 8288 | 8287 | .neg => return self.wip.un(.fneg, params[0], ""), |
| 8289 | 8288 | .add => return self.wip.bin(.fadd, params[0], params[1], ""), |
| ... | ... | @@ -8293,83 +8292,84 @@ pub const FuncGen = struct { |
| 8293 | 8292 | .fmod => return self.wip.bin(.frem, params[0], params[1], ""), |
| 8294 | 8293 | .fmax => return self.wip.bin(.@"llvm.maxnum.", params[0], params[1], ""), |
| 8295 | 8294 | .fmin => return self.wip.bin(.@"llvm.minnum.", params[0], params[1], ""), |
| 8296 | else => .{ .intrinsic = "llvm." ++ @tagName(op) }, | |
| 8297 | } else b: { | |
| 8298 | const float_bits = scalar_ty.floatBits(target); | |
| 8299 | break :b switch (op) { | |
| 8300 | .neg => { | |
| 8301 | // In this case we can generate a softfloat negation by XORing the | |
| 8302 | // bits with a constant. | |
| 8303 | const int_ty = try o.builder.intType(@intCast(float_bits)); | |
| 8304 | const cast_ty = try llvm_ty.changeScalar(int_ty, &o.builder); | |
| 8305 | const sign_mask = try o.builder.splatValue( | |
| 8306 | cast_ty, | |
| 8307 | try o.builder.intConst(int_ty, @as(u128, 1) << @intCast(float_bits - 1)), | |
| 8308 | ); | |
| 8309 | const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, ""); | |
| 8310 | const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, ""); | |
| 8311 | return self.wip.cast(.bitcast, result, llvm_ty, ""); | |
| 8312 | }, | |
| 8313 | .add, .sub, .div, .mul => .{ .libc = try o.builder.fmt("__{s}{s}f3", .{ | |
| 8314 | @tagName(op), compilerRtFloatAbbrev(float_bits), | |
| 8315 | }) }, | |
| 8316 | .ceil, | |
| 8317 | .cos, | |
| 8318 | .exp, | |
| 8319 | .exp2, | |
| 8320 | .fabs, | |
| 8321 | .floor, | |
| 8322 | .fma, | |
| 8323 | .fmax, | |
| 8324 | .fmin, | |
| 8325 | .fmod, | |
| 8326 | .log, | |
| 8327 | .log10, | |
| 8328 | .log2, | |
| 8329 | .round, | |
| 8330 | .sin, | |
| 8331 | .sqrt, | |
| 8332 | .tan, | |
| 8333 | .trunc, | |
| 8334 | => .{ .libc = try o.builder.fmt("{s}{s}{s}", .{ | |
| 8335 | libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits), | |
| 8336 | }) }, | |
| 8337 | }; | |
| 8295 | .ceil => return self.wip.un(.@"llvm.ceil.", params[0], ""), | |
| 8296 | .cos => return self.wip.un(.@"llvm.cos.", params[0], ""), | |
| 8297 | .exp => return self.wip.un(.@"llvm.exp.", params[0], ""), | |
| 8298 | .exp2 => return self.wip.un(.@"llvm.exp2.", params[0], ""), | |
| 8299 | .fabs => return self.wip.un(.@"llvm.fabs.", params[0], ""), | |
| 8300 | .floor => return self.wip.un(.@"llvm.floor.", params[0], ""), | |
| 8301 | .log => return self.wip.un(.@"llvm.log.", params[0], ""), | |
| 8302 | .log10 => return self.wip.un(.@"llvm.log10.", params[0], ""), | |
| 8303 | .log2 => return self.wip.un(.@"llvm.log2.", params[0], ""), | |
| 8304 | .round => return self.wip.un(.@"llvm.round.", params[0], ""), | |
| 8305 | .sin => return self.wip.un(.@"llvm.sin.", params[0], ""), | |
| 8306 | .sqrt => return self.wip.un(.@"llvm.sqrt.", params[0], ""), | |
| 8307 | .trunc => return self.wip.un(.@"llvm.trunc.", params[0], ""), | |
| 8308 | .fma => return self.wip.fusedMultiplyAdd(params[0], params[1], params[2]), | |
| 8309 | .tan => unreachable, | |
| 8338 | 8310 | }; |
| 8339 | 8311 | |
| 8340 | const llvm_fn = switch (strat) { | |
| 8341 | .intrinsic => |fn_name| try self.getIntrinsic(fn_name, &.{llvm_ty}), | |
| 8342 | .libc => |fn_name| b: { | |
| 8343 | const scalar_llvm_ty = llvm_ty.scalarType(&o.builder); | |
| 8344 | const libc_fn = try self.getLibcFunction( | |
| 8345 | fn_name, | |
| 8346 | ([1]Builder.Type{scalar_llvm_ty} ** 3)[0..params.len], | |
| 8347 | scalar_llvm_ty, | |
| 8312 | const float_bits = scalar_ty.floatBits(target); | |
| 8313 | const fn_name = switch (op) { | |
| 8314 | .neg => { | |
| 8315 | // In this case we can generate a softfloat negation by XORing the | |
| 8316 | // bits with a constant. | |
| 8317 | const int_ty = try o.builder.intType(@intCast(float_bits)); | |
| 8318 | const cast_ty = try llvm_ty.changeScalar(int_ty, &o.builder); | |
| 8319 | const sign_mask = try o.builder.splatValue( | |
| 8320 | cast_ty, | |
| 8321 | try o.builder.intConst(int_ty, @as(u128, 1) << @intCast(float_bits - 1)), | |
| 8348 | 8322 | ); |
| 8349 | if (ty.zigTypeTag(mod) == .Vector) { | |
| 8350 | const result = try o.builder.poisonValue(llvm_ty); | |
| 8351 | return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(mod)); | |
| 8352 | } | |
| 8353 | ||
| 8354 | break :b libc_fn.toLlvm(&o.builder); | |
| 8323 | const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, ""); | |
| 8324 | const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, ""); | |
| 8325 | return self.wip.cast(.bitcast, result, llvm_ty, ""); | |
| 8355 | 8326 | }, |
| 8327 | .add, .sub, .div, .mul => try o.builder.fmt("__{s}{s}f3", .{ | |
| 8328 | @tagName(op), compilerRtFloatAbbrev(float_bits), | |
| 8329 | }), | |
| 8330 | .ceil, | |
| 8331 | .cos, | |
| 8332 | .exp, | |
| 8333 | .exp2, | |
| 8334 | .fabs, | |
| 8335 | .floor, | |
| 8336 | .fma, | |
| 8337 | .fmax, | |
| 8338 | .fmin, | |
| 8339 | .fmod, | |
| 8340 | .log, | |
| 8341 | .log10, | |
| 8342 | .log2, | |
| 8343 | .round, | |
| 8344 | .sin, | |
| 8345 | .sqrt, | |
| 8346 | .tan, | |
| 8347 | .trunc, | |
| 8348 | => try o.builder.fmt("{s}{s}{s}", .{ | |
| 8349 | libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits), | |
| 8350 | }), | |
| 8356 | 8351 | }; |
| 8357 | const llvm_fn_ty = try o.builder.fnType( | |
| 8358 | llvm_ty, | |
| 8359 | ([1]Builder.Type{llvm_ty} ** 3)[0..params.len], | |
| 8360 | .normal, | |
| 8352 | ||
| 8353 | const scalar_llvm_ty = llvm_ty.scalarType(&o.builder); | |
| 8354 | const libc_fn = try self.getLibcFunction( | |
| 8355 | fn_name, | |
| 8356 | ([1]Builder.Type{scalar_llvm_ty} ** 3)[0..params.len], | |
| 8357 | scalar_llvm_ty, | |
| 8361 | 8358 | ); |
| 8362 | var llvm_params: [params_len]*llvm.Value = undefined; | |
| 8363 | for (&llvm_params, params) |*llvm_param, param| llvm_param.* = param.toLlvm(&self.wip); | |
| 8364 | return (try self.wip.unimplemented(llvm_ty, "")).finish(self.builder.buildCallOld( | |
| 8365 | llvm_fn_ty.toLlvm(&o.builder), | |
| 8366 | llvm_fn, | |
| 8367 | &llvm_params, | |
| 8368 | params_len, | |
| 8369 | .C, | |
| 8370 | .Auto, | |
| 8359 | if (ty.zigTypeTag(mod) == .Vector) { | |
| 8360 | const result = try o.builder.poisonValue(llvm_ty); | |
| 8361 | return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(mod)); | |
| 8362 | } | |
| 8363 | ||
| 8364 | return self.wip.call( | |
| 8365 | .normal, | |
| 8366 | .ccc, | |
| 8367 | .none, | |
| 8368 | libc_fn.typeOf(&o.builder), | |
| 8369 | libc_fn.toValue(&o.builder), | |
| 8370 | &params, | |
| 8371 | 8371 | "", |
| 8372 | ), &self.wip); | |
| 8372 | ); | |
| 8373 | 8373 | } |
| 8374 | 8374 | |
| 8375 | 8375 | fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -9526,64 +9526,29 @@ pub const FuncGen = struct { |
| 9526 | 9526 | return self.buildFloatOp(.neg, operand_ty, 1, .{operand}); |
| 9527 | 9527 | } |
| 9528 | 9528 | |
| 9529 | fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !Builder.Value { | |
| 9529 | fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Function.Instruction.Tag) !Builder.Value { | |
| 9530 | 9530 | const o = self.dg.object; |
| 9531 | 9531 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 9532 | const operand_ty = self.typeOf(ty_op.operand); | |
| 9533 | 9532 | const operand = try self.resolveInst(ty_op.operand); |
| 9534 | 9533 | |
| 9535 | const llvm_operand_ty = try o.lowerType(operand_ty); | |
| 9536 | const llvm_fn_ty = try o.builder.fnType(llvm_operand_ty, &.{ llvm_operand_ty, .i1 }, .normal); | |
| 9537 | const fn_val = try self.getIntrinsic(llvm_fn_name, &.{llvm_operand_ty}); | |
| 9534 | const wrong_size_result = try self.wip.bin(intrinsic, operand, (try o.builder.intConst(.i1, 0)).toValue(), ""); | |
| 9538 | 9535 | |
| 9539 | const params = [_]*llvm.Value{ | |
| 9540 | operand.toLlvm(&self.wip), | |
| 9541 | Builder.Constant.false.toLlvm(&o.builder), | |
| 9542 | }; | |
| 9543 | const wrong_size_result = (try self.wip.unimplemented(llvm_operand_ty, "")).finish( | |
| 9544 | self.builder.buildCallOld( | |
| 9545 | llvm_fn_ty.toLlvm(&o.builder), | |
| 9546 | fn_val, | |
| 9547 | &params, | |
| 9548 | params.len, | |
| 9549 | .C, | |
| 9550 | .Auto, | |
| 9551 | "", | |
| 9552 | ), | |
| 9553 | &self.wip, | |
| 9554 | ); | |
| 9555 | 9536 | const result_ty = self.typeOfIndex(inst); |
| 9556 | 9537 | return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), ""); |
| 9557 | 9538 | } |
| 9558 | 9539 | |
| 9559 | fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !Builder.Value { | |
| 9540 | fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Function.Instruction.Tag) !Builder.Value { | |
| 9560 | 9541 | const o = self.dg.object; |
| 9561 | 9542 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 9562 | const operand_ty = self.typeOf(ty_op.operand); | |
| 9563 | 9543 | const operand = try self.resolveInst(ty_op.operand); |
| 9564 | 9544 | |
| 9565 | const llvm_operand_ty = try o.lowerType(operand_ty); | |
| 9566 | const llvm_fn_ty = try o.builder.fnType(llvm_operand_ty, &.{llvm_operand_ty}, .normal); | |
| 9567 | const fn_val = try self.getIntrinsic(llvm_fn_name, &.{llvm_operand_ty}); | |
| 9545 | const wrong_size_result = try self.wip.un(intrinsic, operand, ""); | |
| 9568 | 9546 | |
| 9569 | const params = [_]*llvm.Value{operand.toLlvm(&self.wip)}; | |
| 9570 | const wrong_size_result = (try self.wip.unimplemented(llvm_operand_ty, "")).finish( | |
| 9571 | self.builder.buildCallOld( | |
| 9572 | llvm_fn_ty.toLlvm(&o.builder), | |
| 9573 | fn_val, | |
| 9574 | &params, | |
| 9575 | params.len, | |
| 9576 | .C, | |
| 9577 | .Auto, | |
| 9578 | "", | |
| 9579 | ), | |
| 9580 | &self.wip, | |
| 9581 | ); | |
| 9582 | 9547 | const result_ty = self.typeOfIndex(inst); |
| 9583 | 9548 | return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), ""); |
| 9584 | 9549 | } |
| 9585 | 9550 | |
| 9586 | fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !Builder.Value { | |
| 9551 | fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { | |
| 9587 | 9552 | const o = self.dg.object; |
| 9588 | 9553 | const mod = o.module; |
| 9589 | 9554 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| ... | ... | @@ -9611,22 +9576,7 @@ pub const FuncGen = struct { |
| 9611 | 9576 | bits = bits + 8; |
| 9612 | 9577 | } |
| 9613 | 9578 | |
| 9614 | const llvm_fn_ty = try o.builder.fnType(llvm_operand_ty, &.{llvm_operand_ty}, .normal); | |
| 9615 | const fn_val = try self.getIntrinsic(llvm_fn_name, &.{llvm_operand_ty}); | |
| 9616 | ||
| 9617 | const params = [_]*llvm.Value{operand.toLlvm(&self.wip)}; | |
| 9618 | const wrong_size_result = (try self.wip.unimplemented(llvm_operand_ty, "")).finish( | |
| 9619 | self.builder.buildCallOld( | |
| 9620 | llvm_fn_ty.toLlvm(&o.builder), | |
| 9621 | fn_val, | |
| 9622 | &params, | |
| 9623 | params.len, | |
| 9624 | .C, | |
| 9625 | .Auto, | |
| 9626 | "", | |
| 9627 | ), | |
| 9628 | &self.wip, | |
| 9629 | ); | |
| 9579 | const wrong_size_result = try self.wip.un(.@"llvm.bswap.", operand, ""); | |
| 9630 | 9580 | |
| 9631 | 9581 | const result_ty = self.typeOfIndex(inst); |
| 9632 | 9582 | return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), ""); |
src/codegen/llvm/Builder.zig+198| ... | ... | @@ -2416,6 +2416,25 @@ pub const Function = struct { |
| 2416 | 2416 | inttoptr, |
| 2417 | 2417 | @"llvm.maxnum.", |
| 2418 | 2418 | @"llvm.minnum.", |
| 2419 | @"llvm.ceil.", | |
| 2420 | @"llvm.cos.", | |
| 2421 | @"llvm.exp.", | |
| 2422 | @"llvm.exp2.", | |
| 2423 | @"llvm.fabs.", | |
| 2424 | @"llvm.floor.", | |
| 2425 | @"llvm.log.", | |
| 2426 | @"llvm.log10.", | |
| 2427 | @"llvm.log2.", | |
| 2428 | @"llvm.round.", | |
| 2429 | @"llvm.sin.", | |
| 2430 | @"llvm.sqrt.", | |
| 2431 | @"llvm.trunc.", | |
| 2432 | @"llvm.fma.", | |
| 2433 | @"llvm.bitreverse.", | |
| 2434 | @"llvm.bswap.", | |
| 2435 | @"llvm.ctpop.", | |
| 2436 | @"llvm.ctlz.", | |
| 2437 | @"llvm.cttz.", | |
| 2419 | 2438 | @"llvm.sadd.sat.", |
| 2420 | 2439 | @"llvm.smax.", |
| 2421 | 2440 | @"llvm.smin.", |
| ... | ... | @@ -2558,6 +2577,8 @@ pub const Function = struct { |
| 2558 | 2577 | .@"fsub fast", |
| 2559 | 2578 | .@"llvm.maxnum.", |
| 2560 | 2579 | .@"llvm.minnum.", |
| 2580 | .@"llvm.ctlz.", | |
| 2581 | .@"llvm.cttz.", | |
| 2561 | 2582 | .@"llvm.sadd.sat.", |
| 2562 | 2583 | .@"llvm.smax.", |
| 2563 | 2584 | .@"llvm.smin.", |
| ... | ... | @@ -2689,6 +2710,22 @@ pub const Function = struct { |
| 2689 | 2710 | .changeScalarAssumeCapacity(.i1, wip.builder), |
| 2690 | 2711 | .fneg, |
| 2691 | 2712 | .@"fneg fast", |
| 2713 | .@"llvm.ceil.", | |
| 2714 | .@"llvm.cos.", | |
| 2715 | .@"llvm.exp.", | |
| 2716 | .@"llvm.exp2.", | |
| 2717 | .@"llvm.fabs.", | |
| 2718 | .@"llvm.floor.", | |
| 2719 | .@"llvm.log.", | |
| 2720 | .@"llvm.log10.", | |
| 2721 | .@"llvm.log2.", | |
| 2722 | .@"llvm.round.", | |
| 2723 | .@"llvm.sin.", | |
| 2724 | .@"llvm.sqrt.", | |
| 2725 | .@"llvm.trunc.", | |
| 2726 | .@"llvm.bitreverse.", | |
| 2727 | .@"llvm.bswap.", | |
| 2728 | .@"llvm.ctpop.", | |
| 2692 | 2729 | => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip), |
| 2693 | 2730 | .getelementptr, |
| 2694 | 2731 | .@"getelementptr inbounds", |
| ... | ... | @@ -2725,6 +2762,7 @@ pub const Function = struct { |
| 2725 | 2762 | }, |
| 2726 | 2763 | .unimplemented => @enumFromInt(instruction.data), |
| 2727 | 2764 | .va_arg => wip.extraData(VaArg, instruction.data).type, |
| 2765 | .@"llvm.fma." => wip.extraData(FusedMultiplyAdd, instruction.data).a.typeOfWip(wip), | |
| 2728 | 2766 | }; |
| 2729 | 2767 | } |
| 2730 | 2768 | |
| ... | ... | @@ -2755,6 +2793,8 @@ pub const Function = struct { |
| 2755 | 2793 | .@"fsub fast", |
| 2756 | 2794 | .@"llvm.maxnum.", |
| 2757 | 2795 | .@"llvm.minnum.", |
| 2796 | .@"llvm.ctlz.", | |
| 2797 | .@"llvm.cttz.", | |
| 2758 | 2798 | .@"llvm.sadd.sat.", |
| 2759 | 2799 | .@"llvm.smax.", |
| 2760 | 2800 | .@"llvm.smin.", |
| ... | ... | @@ -2887,6 +2927,22 @@ pub const Function = struct { |
| 2887 | 2927 | .changeScalarAssumeCapacity(.i1, builder), |
| 2888 | 2928 | .fneg, |
| 2889 | 2929 | .@"fneg fast", |
| 2930 | .@"llvm.ceil.", | |
| 2931 | .@"llvm.cos.", | |
| 2932 | .@"llvm.exp.", | |
| 2933 | .@"llvm.exp2.", | |
| 2934 | .@"llvm.fabs.", | |
| 2935 | .@"llvm.floor.", | |
| 2936 | .@"llvm.log.", | |
| 2937 | .@"llvm.log10.", | |
| 2938 | .@"llvm.log2.", | |
| 2939 | .@"llvm.round.", | |
| 2940 | .@"llvm.sin.", | |
| 2941 | .@"llvm.sqrt.", | |
| 2942 | .@"llvm.trunc.", | |
| 2943 | .@"llvm.bitreverse.", | |
| 2944 | .@"llvm.bswap.", | |
| 2945 | .@"llvm.ctpop.", | |
| 2890 | 2946 | => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder), |
| 2891 | 2947 | .getelementptr, |
| 2892 | 2948 | .@"getelementptr inbounds", |
| ... | ... | @@ -2925,6 +2981,7 @@ pub const Function = struct { |
| 2925 | 2981 | }, |
| 2926 | 2982 | .unimplemented => @enumFromInt(instruction.data), |
| 2927 | 2983 | .va_arg => function.extraData(VaArg, instruction.data).type, |
| 2984 | .@"llvm.fma." => function.extraData(FusedMultiplyAdd, instruction.data).a.typeOf(function_index, builder), | |
| 2928 | 2985 | }; |
| 2929 | 2986 | } |
| 2930 | 2987 | |
| ... | ... | @@ -3017,6 +3074,12 @@ pub const Function = struct { |
| 3017 | 3074 | mask: Value, |
| 3018 | 3075 | }; |
| 3019 | 3076 | |
| 3077 | pub const FusedMultiplyAdd = struct { | |
| 3078 | a: Value, | |
| 3079 | b: Value, | |
| 3080 | c: Value, | |
| 3081 | }; | |
| 3082 | ||
| 3020 | 3083 | pub const ExtractValue = struct { |
| 3021 | 3084 | val: Value, |
| 3022 | 3085 | indices_len: u32, |
| ... | ... | @@ -3424,7 +3487,24 @@ pub const WipFunction = struct { |
| 3424 | 3487 | switch (tag) { |
| 3425 | 3488 | .fneg, |
| 3426 | 3489 | .@"fneg fast", |
| 3490 | .@"llvm.ceil.", | |
| 3491 | .@"llvm.cos.", | |
| 3492 | .@"llvm.exp.", | |
| 3493 | .@"llvm.exp2.", | |
| 3494 | .@"llvm.fabs.", | |
| 3495 | .@"llvm.floor.", | |
| 3496 | .@"llvm.log.", | |
| 3497 | .@"llvm.log10.", | |
| 3498 | .@"llvm.log2.", | |
| 3499 | .@"llvm.round.", | |
| 3500 | .@"llvm.sin.", | |
| 3501 | .@"llvm.sqrt.", | |
| 3502 | .@"llvm.trunc.", | |
| 3427 | 3503 | => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()), |
| 3504 | .@"llvm.bitreverse.", | |
| 3505 | .@"llvm.bswap.", | |
| 3506 | .@"llvm.ctpop.", | |
| 3507 | => assert(val.typeOfWip(self).scalarType(self.builder).isInteger(self.builder)), | |
| 3428 | 3508 | else => unreachable, |
| 3429 | 3509 | } |
| 3430 | 3510 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| ... | ... | @@ -3433,10 +3513,43 @@ pub const WipFunction = struct { |
| 3433 | 3513 | switch (tag) { |
| 3434 | 3514 | .fneg => self.llvm.builder.setFastMath(false), |
| 3435 | 3515 | .@"fneg fast" => self.llvm.builder.setFastMath(true), |
| 3516 | .@"llvm.ceil.", | |
| 3517 | .@"llvm.cos.", | |
| 3518 | .@"llvm.exp.", | |
| 3519 | .@"llvm.exp2.", | |
| 3520 | .@"llvm.fabs.", | |
| 3521 | .@"llvm.floor.", | |
| 3522 | .@"llvm.log.", | |
| 3523 | .@"llvm.log10.", | |
| 3524 | .@"llvm.log2.", | |
| 3525 | .@"llvm.round.", | |
| 3526 | .@"llvm.sin.", | |
| 3527 | .@"llvm.sqrt.", | |
| 3528 | .@"llvm.trunc.", | |
| 3529 | .@"llvm.bitreverse.", | |
| 3530 | .@"llvm.bswap.", | |
| 3531 | .@"llvm.ctpop.", | |
| 3532 | => {}, | |
| 3436 | 3533 | else => unreachable, |
| 3437 | 3534 | } |
| 3438 | 3535 | self.llvm.instructions.appendAssumeCapacity(switch (tag) { |
| 3439 | 3536 | .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg, |
| 3537 | .@"llvm.ceil." => &llvm.Builder.buildCeil, | |
| 3538 | .@"llvm.cos." => &llvm.Builder.buildCos, | |
| 3539 | .@"llvm.exp." => &llvm.Builder.buildExp, | |
| 3540 | .@"llvm.exp2." => &llvm.Builder.buildExp2, | |
| 3541 | .@"llvm.fabs." => &llvm.Builder.buildFAbs, | |
| 3542 | .@"llvm.floor." => &llvm.Builder.buildFloor, | |
| 3543 | .@"llvm.log." => &llvm.Builder.buildLog, | |
| 3544 | .@"llvm.log10." => &llvm.Builder.buildLog10, | |
| 3545 | .@"llvm.log2." => &llvm.Builder.buildLog2, | |
| 3546 | .@"llvm.round." => &llvm.Builder.buildRound, | |
| 3547 | .@"llvm.sin." => &llvm.Builder.buildSin, | |
| 3548 | .@"llvm.sqrt." => &llvm.Builder.buildSqrt, | |
| 3549 | .@"llvm.trunc." => &llvm.Builder.buildFTrunc, | |
| 3550 | .@"llvm.bitreverse." => &llvm.Builder.buildBitReverse, | |
| 3551 | .@"llvm.bswap." => &llvm.Builder.buildBSwap, | |
| 3552 | .@"llvm.ctpop." => &llvm.Builder.buildCTPop, | |
| 3440 | 3553 | else => unreachable, |
| 3441 | 3554 | }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self))); |
| 3442 | 3555 | } |
| ... | ... | @@ -3514,6 +3627,9 @@ pub const WipFunction = struct { |
| 3514 | 3627 | .urem, |
| 3515 | 3628 | .xor, |
| 3516 | 3629 | => assert(lhs.typeOfWip(self) == rhs.typeOfWip(self)), |
| 3630 | .@"llvm.ctlz.", | |
| 3631 | .@"llvm.cttz.", | |
| 3632 | => assert(lhs.typeOfWip(self).scalarType(self.builder).isInteger(self.builder) and rhs.typeOfWip(self) == .i1), | |
| 3517 | 3633 | else => unreachable, |
| 3518 | 3634 | } |
| 3519 | 3635 | try self.ensureUnusedExtraCapacity(1, Instruction.Binary, 0); |
| ... | ... | @@ -3551,6 +3667,8 @@ pub const WipFunction = struct { |
| 3551 | 3667 | .fsub, .@"fsub fast" => &llvm.Builder.buildFSub, |
| 3552 | 3668 | .@"llvm.maxnum." => &llvm.Builder.buildMaxNum, |
| 3553 | 3669 | .@"llvm.minnum." => &llvm.Builder.buildMinNum, |
| 3670 | .@"llvm.ctlz." => &llvm.Builder.buildCTLZ, | |
| 3671 | .@"llvm.cttz." => &llvm.Builder.buildCTTZ, | |
| 3554 | 3672 | .@"llvm.sadd.sat." => &llvm.Builder.buildSAddSat, |
| 3555 | 3673 | .@"llvm.smax." => &llvm.Builder.buildSMax, |
| 3556 | 3674 | .@"llvm.smin." => &llvm.Builder.buildSMin, |
| ... | ... | @@ -4330,6 +4448,29 @@ pub const WipFunction = struct { |
| 4330 | 4448 | return instruction.toValue(); |
| 4331 | 4449 | } |
| 4332 | 4450 | |
| 4451 | pub fn fusedMultiplyAdd(self: *WipFunction, a: Value, b: Value, c: Value) Allocator.Error!Value { | |
| 4452 | assert(a.typeOfWip(self) == b.typeOfWip(self) and a.typeOfWip(self) == c.typeOfWip(self)); | |
| 4453 | try self.ensureUnusedExtraCapacity(1, Instruction.FusedMultiplyAdd, 0); | |
| 4454 | const instruction = try self.addInst("", .{ | |
| 4455 | .tag = .@"llvm.fma.", | |
| 4456 | .data = self.addExtraAssumeCapacity(Instruction.FusedMultiplyAdd{ | |
| 4457 | .a = a, | |
| 4458 | .b = b, | |
| 4459 | .c = c, | |
| 4460 | }), | |
| 4461 | }); | |
| 4462 | if (self.builder.useLibLlvm()) { | |
| 4463 | self.llvm.instructions.appendAssumeCapacity(llvm.Builder.buildFMA( | |
| 4464 | self.llvm.builder, | |
| 4465 | a.toLlvm(self), | |
| 4466 | b.toLlvm(self), | |
| 4467 | c.toLlvm(self), | |
| 4468 | instruction.llvmName(self), | |
| 4469 | )); | |
| 4470 | } | |
| 4471 | return instruction.toValue(); | |
| 4472 | } | |
| 4473 | ||
| 4333 | 4474 | pub const WipUnimplemented = struct { |
| 4334 | 4475 | instruction: Instruction.Index, |
| 4335 | 4476 | |
| ... | ... | @@ -4558,6 +4699,8 @@ pub const WipFunction = struct { |
| 4558 | 4699 | .@"icmp ult", |
| 4559 | 4700 | .@"llvm.maxnum.", |
| 4560 | 4701 | .@"llvm.minnum.", |
| 4702 | .@"llvm.ctlz.", | |
| 4703 | .@"llvm.cttz.", | |
| 4561 | 4704 | .@"llvm.sadd.sat.", |
| 4562 | 4705 | .@"llvm.smax.", |
| 4563 | 4706 | .@"llvm.smin.", |
| ... | ... | @@ -4685,6 +4828,22 @@ pub const WipFunction = struct { |
| 4685 | 4828 | .fneg, |
| 4686 | 4829 | .@"fneg fast", |
| 4687 | 4830 | .ret, |
| 4831 | .@"llvm.ceil.", | |
| 4832 | .@"llvm.cos.", | |
| 4833 | .@"llvm.exp.", | |
| 4834 | .@"llvm.exp2.", | |
| 4835 | .@"llvm.fabs.", | |
| 4836 | .@"llvm.floor.", | |
| 4837 | .@"llvm.log.", | |
| 4838 | .@"llvm.log10.", | |
| 4839 | .@"llvm.log2.", | |
| 4840 | .@"llvm.round.", | |
| 4841 | .@"llvm.sin.", | |
| 4842 | .@"llvm.sqrt.", | |
| 4843 | .@"llvm.trunc.", | |
| 4844 | .@"llvm.bitreverse.", | |
| 4845 | .@"llvm.bswap.", | |
| 4846 | .@"llvm.ctpop.", | |
| 4688 | 4847 | => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))), |
| 4689 | 4848 | .getelementptr, |
| 4690 | 4849 | .@"getelementptr inbounds", |
| ... | ... | @@ -4790,6 +4949,14 @@ pub const WipFunction = struct { |
| 4790 | 4949 | .type = extra.type, |
| 4791 | 4950 | }); |
| 4792 | 4951 | }, |
| 4952 | .@"llvm.fma." => { | |
| 4953 | const extra = self.extraData(Instruction.FusedMultiplyAdd, instruction.data); | |
| 4954 | instruction.data = wip_extra.addExtra(Instruction.FusedMultiplyAdd{ | |
| 4955 | .a = instructions.map(extra.a), | |
| 4956 | .b = instructions.map(extra.b), | |
| 4957 | .c = instructions.map(extra.c), | |
| 4958 | }); | |
| 4959 | }, | |
| 4793 | 4960 | } |
| 4794 | 4961 | function.instructions.appendAssumeCapacity(instruction); |
| 4795 | 4962 | names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip) |
| ... | ... | @@ -7561,6 +7728,22 @@ pub fn printUnbuffered( |
| 7561 | 7728 | .fneg, |
| 7562 | 7729 | .@"fneg fast", |
| 7563 | 7730 | .ret, |
| 7731 | .@"llvm.ceil.", | |
| 7732 | .@"llvm.cos.", | |
| 7733 | .@"llvm.exp.", | |
| 7734 | .@"llvm.exp2.", | |
| 7735 | .@"llvm.fabs.", | |
| 7736 | .@"llvm.floor.", | |
| 7737 | .@"llvm.log.", | |
| 7738 | .@"llvm.log10.", | |
| 7739 | .@"llvm.log2.", | |
| 7740 | .@"llvm.round.", | |
| 7741 | .@"llvm.sin.", | |
| 7742 | .@"llvm.sqrt.", | |
| 7743 | .@"llvm.trunc.", | |
| 7744 | .@"llvm.bitreverse.", | |
| 7745 | .@"llvm.bswap.", | |
| 7746 | .@"llvm.ctpop.", | |
| 7564 | 7747 | => |tag| { |
| 7565 | 7748 | const val: Value = @enumFromInt(instruction.data); |
| 7566 | 7749 | try writer.print(" {s} {%}\n", .{ |
| ... | ... | @@ -7617,6 +7800,8 @@ pub fn printUnbuffered( |
| 7617 | 7800 | }, |
| 7618 | 7801 | .@"llvm.maxnum.", |
| 7619 | 7802 | .@"llvm.minnum.", |
| 7803 | .@"llvm.ctlz.", | |
| 7804 | .@"llvm.cttz.", | |
| 7620 | 7805 | .@"llvm.sadd.sat.", |
| 7621 | 7806 | .@"llvm.smax.", |
| 7622 | 7807 | .@"llvm.smin.", |
| ... | ... | @@ -7781,6 +7966,19 @@ pub fn printUnbuffered( |
| 7781 | 7966 | extra.type.fmt(self), |
| 7782 | 7967 | }); |
| 7783 | 7968 | }, |
| 7969 | .@"llvm.fma." => { | |
| 7970 | const extra = | |
| 7971 | function.extraData(Function.Instruction.FusedMultiplyAdd, instruction.data); | |
| 7972 | const ty = instruction_index.typeOf(function_index, self); | |
| 7973 | try writer.print(" %{} = call {%} @llvm.fma.{m}({%}, {%}, {%})\n", .{ | |
| 7974 | instruction_index.name(&function).fmt(self), | |
| 7975 | ty.fmt(self), | |
| 7976 | ty.fmt(self), | |
| 7977 | extra.a.fmt(function_index, self), | |
| 7978 | extra.b.fmt(function_index, self), | |
| 7979 | extra.c.fmt(function_index, self), | |
| 7980 | }); | |
| 7981 | }, | |
| 7784 | 7982 | } |
| 7785 | 7983 | } |
| 7786 | 7984 | try writer.writeByte('}'); |
src/codegen/llvm/bindings.zig+57| ... | ... | @@ -1026,6 +1026,63 @@ pub const Builder = opaque { |
| 1026 | 1026 | pub const buildMinNum = ZigLLVMBuildMinNum; |
| 1027 | 1027 | extern fn ZigLLVMBuildMinNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; |
| 1028 | 1028 | |
| 1029 | pub const buildCeil = ZigLLVMBuildCeil; | |
| 1030 | extern fn ZigLLVMBuildCeil(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1031 | ||
| 1032 | pub const buildCos = ZigLLVMBuildCos; | |
| 1033 | extern fn ZigLLVMBuildCos(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1034 | ||
| 1035 | pub const buildExp = ZigLLVMBuildExp; | |
| 1036 | extern fn ZigLLVMBuildExp(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1037 | ||
| 1038 | pub const buildExp2 = ZigLLVMBuildExp2; | |
| 1039 | extern fn ZigLLVMBuildExp2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1040 | ||
| 1041 | pub const buildFAbs = ZigLLVMBuildFAbs; | |
| 1042 | extern fn ZigLLVMBuildFAbs(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1043 | ||
| 1044 | pub const buildFloor = ZigLLVMBuildFloor; | |
| 1045 | extern fn ZigLLVMBuildFloor(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1046 | ||
| 1047 | pub const buildLog = ZigLLVMBuildLog; | |
| 1048 | extern fn ZigLLVMBuildLog(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1049 | ||
| 1050 | pub const buildLog10 = ZigLLVMBuildLog10; | |
| 1051 | extern fn ZigLLVMBuildLog10(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1052 | ||
| 1053 | pub const buildLog2 = ZigLLVMBuildLog2; | |
| 1054 | extern fn ZigLLVMBuildLog2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1055 | ||
| 1056 | pub const buildRound = ZigLLVMBuildRound; | |
| 1057 | extern fn ZigLLVMBuildRound(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1058 | ||
| 1059 | pub const buildSin = ZigLLVMBuildSin; | |
| 1060 | extern fn ZigLLVMBuildSin(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1061 | ||
| 1062 | pub const buildSqrt = ZigLLVMBuildSqrt; | |
| 1063 | extern fn ZigLLVMBuildSqrt(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1064 | ||
| 1065 | pub const buildFTrunc = ZigLLVMBuildFTrunc; | |
| 1066 | extern fn ZigLLVMBuildFTrunc(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1067 | ||
| 1068 | pub const buildBitReverse = ZigLLVMBuildBitReverse; | |
| 1069 | extern fn ZigLLVMBuildBitReverse(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1070 | ||
| 1071 | pub const buildBSwap = ZigLLVMBuildBSwap; | |
| 1072 | extern fn ZigLLVMBuildBSwap(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1073 | ||
| 1074 | pub const buildCTPop = ZigLLVMBuildCTPop; | |
| 1075 | extern fn ZigLLVMBuildCTPop(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1076 | ||
| 1077 | pub const buildCTLZ = ZigLLVMBuildCTLZ; | |
| 1078 | extern fn ZigLLVMBuildCTLZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; | |
| 1079 | ||
| 1080 | pub const buildCTTZ = ZigLLVMBuildCTTZ; | |
| 1081 | extern fn ZigLLVMBuildCTTZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; | |
| 1082 | ||
| 1083 | pub const buildFMA = ZigLLVMBuildFMA; | |
| 1084 | extern fn ZigLLVMBuildFMA(builder: *Builder, a: *Value, b: *Value, c: *Value, name: [*:0]const u8) *Value; | |
| 1085 | ||
| 1029 | 1086 | pub const buildUMax = ZigLLVMBuildUMax; |
| 1030 | 1087 | extern fn ZigLLVMBuildUMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; |
| 1031 | 1088 |
src/zig_llvm.cpp+100| ... | ... | @@ -481,6 +481,106 @@ LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef |
| 481 | 481 | return wrap(call_inst); |
| 482 | 482 | } |
| 483 | 483 | |
| 484 | LLVMValueRef ZigLLVMBuildCeil(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 485 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::ceil, unwrap(V), nullptr, name); | |
| 486 | return wrap(call_inst); | |
| 487 | } | |
| 488 | ||
| 489 | LLVMValueRef ZigLLVMBuildCos(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 490 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::cos, unwrap(V), nullptr, name); | |
| 491 | return wrap(call_inst); | |
| 492 | } | |
| 493 | ||
| 494 | LLVMValueRef ZigLLVMBuildExp(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 495 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::exp, unwrap(V), nullptr, name); | |
| 496 | return wrap(call_inst); | |
| 497 | } | |
| 498 | ||
| 499 | LLVMValueRef ZigLLVMBuildExp2(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 500 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::exp2, unwrap(V), nullptr, name); | |
| 501 | return wrap(call_inst); | |
| 502 | } | |
| 503 | ||
| 504 | LLVMValueRef ZigLLVMBuildFAbs(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 505 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::fabs, unwrap(V), nullptr, name); | |
| 506 | return wrap(call_inst); | |
| 507 | } | |
| 508 | ||
| 509 | LLVMValueRef ZigLLVMBuildFloor(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 510 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::floor, unwrap(V), nullptr, name); | |
| 511 | return wrap(call_inst); | |
| 512 | } | |
| 513 | ||
| 514 | LLVMValueRef ZigLLVMBuildLog(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 515 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log, unwrap(V), nullptr, name); | |
| 516 | return wrap(call_inst); | |
| 517 | } | |
| 518 | ||
| 519 | LLVMValueRef ZigLLVMBuildLog10(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 520 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log10, unwrap(V), nullptr, name); | |
| 521 | return wrap(call_inst); | |
| 522 | } | |
| 523 | ||
| 524 | LLVMValueRef ZigLLVMBuildLog2(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 525 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log2, unwrap(V), nullptr, name); | |
| 526 | return wrap(call_inst); | |
| 527 | } | |
| 528 | ||
| 529 | LLVMValueRef ZigLLVMBuildRound(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 530 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::round, unwrap(V), nullptr, name); | |
| 531 | return wrap(call_inst); | |
| 532 | } | |
| 533 | ||
| 534 | LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 535 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::sin, unwrap(V), nullptr, name); | |
| 536 | return wrap(call_inst); | |
| 537 | } | |
| 538 | ||
| 539 | LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 540 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::sqrt, unwrap(V), nullptr, name); | |
| 541 | return wrap(call_inst); | |
| 542 | } | |
| 543 | ||
| 544 | LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 545 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::trunc, unwrap(V), nullptr, name); | |
| 546 | return wrap(call_inst); | |
| 547 | } | |
| 548 | ||
| 549 | LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 550 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bitreverse, unwrap(V), nullptr, name); | |
| 551 | return wrap(call_inst); | |
| 552 | } | |
| 553 | ||
| 554 | LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 555 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bswap, unwrap(V), nullptr, name); | |
| 556 | return wrap(call_inst); | |
| 557 | } | |
| 558 | ||
| 559 | LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 560 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::ctpop, unwrap(V), nullptr, name); | |
| 561 | return wrap(call_inst); | |
| 562 | } | |
| 563 | ||
| 564 | LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 565 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ctlz, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 566 | return wrap(call_inst); | |
| 567 | } | |
| 568 | ||
| 569 | LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 570 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::cttz, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 571 | return wrap(call_inst); | |
| 572 | } | |
| 573 | ||
| 574 | LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char *name) { | |
| 575 | llvm::Type* types[1] = { | |
| 576 | unwrap(A)->getType(), | |
| 577 | }; | |
| 578 | llvm::Value* values[3] = {unwrap(A), unwrap(B), unwrap(C)}; | |
| 579 | ||
| 580 | CallInst *call_inst = unwrap(builder)->CreateIntrinsic(Intrinsic::fma, types, values, nullptr, name); | |
| 581 | return wrap(call_inst); | |
| 582 | } | |
| 583 | ||
| 484 | 584 | LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { |
| 485 | 585 | CallInst *call_inst = unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS), name); |
| 486 | 586 | return wrap(call_inst); |
src/zig_llvm.h+23| ... | ... | @@ -141,6 +141,29 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, |
| 141 | 141 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size, |
| 142 | 142 | unsigned Align, bool isVolatile); |
| 143 | 143 | |
| 144 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCeil(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 145 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCos(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 146 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 147 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp2(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 148 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFAbs(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 149 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFloor(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 150 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 151 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog10(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 152 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog2(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 153 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildRound(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 154 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 155 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 156 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 157 | ||
| 158 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 159 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 160 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 161 | ||
| 162 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 163 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 164 | ||
| 165 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char* name); | |
| 166 | ||
| 144 | 167 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); |
| 145 | 168 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); |
| 146 | 169 |