authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-05 23:05:02-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-08-05 23:05:02-04:00
log1c7798a3cde9e8dad31c276aab4c1affb2043ad2
tree870480a2191982b63e6b4a29152e26db373a286b
parent68f84964b3d80e5b976810208a14c31268a181e1
parente149f1e1de8f79a66a97da1700d9a64fc2983211
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #16705 from antlilja/builder-intrinsics

Implement more intrinsics in new LLVM IR builder API and remove uses of LLVM owns API

5 files changed, 461 insertions(+), 133 deletions(-)

src/codegen/llvm.zig+83-133
...@@ -5100,11 +5100,11 @@ pub const FuncGen = struct {...@@ -5100,11 +5100,11 @@ pub const FuncGen = struct {
5100 .memcpy => try self.airMemcpy(inst),5100 .memcpy => try self.airMemcpy(inst),
5101 .set_union_tag => try self.airSetUnionTag(inst),5101 .set_union_tag => try self.airSetUnionTag(inst),
5102 .get_union_tag => try self.airGetUnionTag(inst),5102 .get_union_tag => try self.airGetUnionTag(inst),
5103 .clz => try self.airClzCtz(inst, "llvm.ctlz"),5103 .clz => try self.airClzCtz(inst, .@"llvm.ctlz."),
5104 .ctz => try self.airClzCtz(inst, "llvm.cttz"),5104 .ctz => try self.airClzCtz(inst, .@"llvm.cttz."),
5105 .popcount => try self.airBitOp(inst, "llvm.ctpop"),5105 .popcount => try self.airBitOp(inst, .@"llvm.ctpop."),
5106 .byte_swap => try self.airByteSwap(inst, "llvm.bswap"),5106 .byte_swap => try self.airByteSwap(inst),
5107 .bit_reverse => try self.airBitOp(inst, "llvm.bitreverse"),5107 .bit_reverse => try self.airBitOp(inst, .@"llvm.bitreverse."),
5108 .tag_name => try self.airTagName(inst),5108 .tag_name => try self.airTagName(inst),
5109 .error_name => try self.airErrorName(inst),5109 .error_name => try self.airErrorName(inst),
5110 .splat => try self.airSplat(inst),5110 .splat => try self.airSplat(inst),
...@@ -8282,8 +8282,7 @@ pub const FuncGen = struct {...@@ -8282,8 +8282,7 @@ pub const FuncGen = struct {
8282 const scalar_ty = ty.scalarType(mod);8282 const scalar_ty = ty.scalarType(mod);
8283 const llvm_ty = try o.lowerType(ty);8283 const llvm_ty = try o.lowerType(ty);
82848284
8285 const intrinsics_allowed = op != .tan and intrinsicsAllowed(scalar_ty, target);8285 if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {
8286 const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) {
8287 // Some operations are dedicated LLVM instructions, not available as intrinsics8286 // Some operations are dedicated LLVM instructions, not available as intrinsics
8288 .neg => return self.wip.un(.fneg, params[0], ""),8287 .neg => return self.wip.un(.fneg, params[0], ""),
8289 .add => return self.wip.bin(.fadd, params[0], params[1], ""),8288 .add => return self.wip.bin(.fadd, params[0], params[1], ""),
...@@ -8293,83 +8292,84 @@ pub const FuncGen = struct {...@@ -8293,83 +8292,84 @@ pub const FuncGen = struct {
8293 .fmod => return self.wip.bin(.frem, params[0], params[1], ""),8292 .fmod => return self.wip.bin(.frem, params[0], params[1], ""),
8294 .fmax => return self.wip.bin(.@"llvm.maxnum.", params[0], params[1], ""),8293 .fmax => return self.wip.bin(.@"llvm.maxnum.", params[0], params[1], ""),
8295 .fmin => return self.wip.bin(.@"llvm.minnum.", params[0], params[1], ""),8294 .fmin => return self.wip.bin(.@"llvm.minnum.", params[0], params[1], ""),
8296 else => .{ .intrinsic = "llvm." ++ @tagName(op) },8295 .ceil => return self.wip.un(.@"llvm.ceil.", params[0], ""),
8297 } else b: {8296 .cos => return self.wip.un(.@"llvm.cos.", params[0], ""),
8298 const float_bits = scalar_ty.floatBits(target);8297 .exp => return self.wip.un(.@"llvm.exp.", params[0], ""),
8299 break :b switch (op) {8298 .exp2 => return self.wip.un(.@"llvm.exp2.", params[0], ""),
8300 .neg => {8299 .fabs => return self.wip.un(.@"llvm.fabs.", params[0], ""),
8301 // In this case we can generate a softfloat negation by XORing the8300 .floor => return self.wip.un(.@"llvm.floor.", params[0], ""),
8302 // bits with a constant.8301 .log => return self.wip.un(.@"llvm.log.", params[0], ""),
8303 const int_ty = try o.builder.intType(@intCast(float_bits));8302 .log10 => return self.wip.un(.@"llvm.log10.", params[0], ""),
8304 const cast_ty = try llvm_ty.changeScalar(int_ty, &o.builder);8303 .log2 => return self.wip.un(.@"llvm.log2.", params[0], ""),
8305 const sign_mask = try o.builder.splatValue(8304 .round => return self.wip.un(.@"llvm.round.", params[0], ""),
8306 cast_ty,8305 .sin => return self.wip.un(.@"llvm.sin.", params[0], ""),
8307 try o.builder.intConst(int_ty, @as(u128, 1) << @intCast(float_bits - 1)),8306 .sqrt => return self.wip.un(.@"llvm.sqrt.", params[0], ""),
8308 );8307 .trunc => return self.wip.un(.@"llvm.trunc.", params[0], ""),
8309 const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, "");8308 .fma => return self.wip.fusedMultiplyAdd(params[0], params[1], params[2]),
8310 const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, "");8309 .tan => unreachable,
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 };
8338 };8310 };
83398311
8340 const llvm_fn = switch (strat) {8312 const float_bits = scalar_ty.floatBits(target);
8341 .intrinsic => |fn_name| try self.getIntrinsic(fn_name, &.{llvm_ty}),8313 const fn_name = switch (op) {
8342 .libc => |fn_name| b: {8314 .neg => {
8343 const scalar_llvm_ty = llvm_ty.scalarType(&o.builder);8315 // In this case we can generate a softfloat negation by XORing the
8344 const libc_fn = try self.getLibcFunction(8316 // bits with a constant.
8345 fn_name,8317 const int_ty = try o.builder.intType(@intCast(float_bits));
8346 ([1]Builder.Type{scalar_llvm_ty} ** 3)[0..params.len],8318 const cast_ty = try llvm_ty.changeScalar(int_ty, &o.builder);
8347 scalar_llvm_ty,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) {8323 const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, "");
8350 const result = try o.builder.poisonValue(llvm_ty);8324 const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, "");
8351 return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(mod));8325 return self.wip.cast(.bitcast, result, llvm_ty, "");
8352 }
8353
8354 break :b libc_fn.toLlvm(&o.builder);
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(8352
8358 llvm_ty,8353 const scalar_llvm_ty = llvm_ty.scalarType(&o.builder);
8359 ([1]Builder.Type{llvm_ty} ** 3)[0..params.len],8354 const libc_fn = try self.getLibcFunction(
8360 .normal,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;8359 if (ty.zigTypeTag(mod) == .Vector) {
8363 for (&llvm_params, params) |*llvm_param, param| llvm_param.* = param.toLlvm(&self.wip);8360 const result = try o.builder.poisonValue(llvm_ty);
8364 return (try self.wip.unimplemented(llvm_ty, "")).finish(self.builder.buildCallOld(8361 return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(mod));
8365 llvm_fn_ty.toLlvm(&o.builder),8362 }
8366 llvm_fn,8363
8367 &llvm_params,8364 return self.wip.call(
8368 params_len,8365 .normal,
8369 .C,8366 .ccc,
8370 .Auto,8367 .none,
8368 libc_fn.typeOf(&o.builder),
8369 libc_fn.toValue(&o.builder),
8370 &params,
8371 "",8371 "",
8372 ), &self.wip);8372 );
8373 }8373 }
83748374
8375 fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {8375 fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -9526,64 +9526,29 @@ pub const FuncGen = struct {...@@ -9526,64 +9526,29 @@ pub const FuncGen = struct {
9526 return self.buildFloatOp(.neg, operand_ty, 1, .{operand});9526 return self.buildFloatOp(.neg, operand_ty, 1, .{operand});
9527 }9527 }
95289528
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 const o = self.dg.object;9530 const o = self.dg.object;
9531 const ty_op = self.air.instructions.items(.data)[inst].ty_op;9531 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
9532 const operand_ty = self.typeOf(ty_op.operand);
9533 const operand = try self.resolveInst(ty_op.operand);9532 const operand = try self.resolveInst(ty_op.operand);
95349533
9535 const llvm_operand_ty = try o.lowerType(operand_ty);9534 const wrong_size_result = try self.wip.bin(intrinsic, operand, (try o.builder.intConst(.i1, 0)).toValue(), "");
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});
95389535
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 const result_ty = self.typeOfIndex(inst);9536 const result_ty = self.typeOfIndex(inst);
9556 return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");9537 return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");
9557 }9538 }
95589539
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 const o = self.dg.object;9541 const o = self.dg.object;
9561 const ty_op = self.air.instructions.items(.data)[inst].ty_op;9542 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
9562 const operand_ty = self.typeOf(ty_op.operand);
9563 const operand = try self.resolveInst(ty_op.operand);9543 const operand = try self.resolveInst(ty_op.operand);
95649544
9565 const llvm_operand_ty = try o.lowerType(operand_ty);9545 const wrong_size_result = try self.wip.un(intrinsic, operand, "");
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});
95689546
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 const result_ty = self.typeOfIndex(inst);9547 const result_ty = self.typeOfIndex(inst);
9583 return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");9548 return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");
9584 }9549 }
95859550
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 const o = self.dg.object;9552 const o = self.dg.object;
9588 const mod = o.module;9553 const mod = o.module;
9589 const ty_op = self.air.instructions.items(.data)[inst].ty_op;9554 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
...@@ -9611,22 +9576,7 @@ pub const FuncGen = struct {...@@ -9611,22 +9576,7 @@ pub const FuncGen = struct {
9611 bits = bits + 8;9576 bits = bits + 8;
9612 }9577 }
96139578
9614 const llvm_fn_ty = try o.builder.fnType(llvm_operand_ty, &.{llvm_operand_ty}, .normal);9579 const wrong_size_result = try self.wip.un(.@"llvm.bswap.", operand, "");
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 );
96309580
9631 const result_ty = self.typeOfIndex(inst);9581 const result_ty = self.typeOfIndex(inst);
9632 return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");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,6 +2416,25 @@ pub const Function = struct {
2416 inttoptr,2416 inttoptr,
2417 @"llvm.maxnum.",2417 @"llvm.maxnum.",
2418 @"llvm.minnum.",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 @"llvm.sadd.sat.",2438 @"llvm.sadd.sat.",
2420 @"llvm.smax.",2439 @"llvm.smax.",
2421 @"llvm.smin.",2440 @"llvm.smin.",
...@@ -2558,6 +2577,8 @@ pub const Function = struct {...@@ -2558,6 +2577,8 @@ pub const Function = struct {
2558 .@"fsub fast",2577 .@"fsub fast",
2559 .@"llvm.maxnum.",2578 .@"llvm.maxnum.",
2560 .@"llvm.minnum.",2579 .@"llvm.minnum.",
2580 .@"llvm.ctlz.",
2581 .@"llvm.cttz.",
2561 .@"llvm.sadd.sat.",2582 .@"llvm.sadd.sat.",
2562 .@"llvm.smax.",2583 .@"llvm.smax.",
2563 .@"llvm.smin.",2584 .@"llvm.smin.",
...@@ -2689,6 +2710,22 @@ pub const Function = struct {...@@ -2689,6 +2710,22 @@ pub const Function = struct {
2689 .changeScalarAssumeCapacity(.i1, wip.builder),2710 .changeScalarAssumeCapacity(.i1, wip.builder),
2690 .fneg,2711 .fneg,
2691 .@"fneg fast",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 => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip),2729 => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip),
2693 .getelementptr,2730 .getelementptr,
2694 .@"getelementptr inbounds",2731 .@"getelementptr inbounds",
...@@ -2725,6 +2762,7 @@ pub const Function = struct {...@@ -2725,6 +2762,7 @@ pub const Function = struct {
2725 },2762 },
2726 .unimplemented => @enumFromInt(instruction.data),2763 .unimplemented => @enumFromInt(instruction.data),
2727 .va_arg => wip.extraData(VaArg, instruction.data).type,2764 .va_arg => wip.extraData(VaArg, instruction.data).type,
2765 .@"llvm.fma." => wip.extraData(FusedMultiplyAdd, instruction.data).a.typeOfWip(wip),
2728 };2766 };
2729 }2767 }
27302768
...@@ -2755,6 +2793,8 @@ pub const Function = struct {...@@ -2755,6 +2793,8 @@ pub const Function = struct {
2755 .@"fsub fast",2793 .@"fsub fast",
2756 .@"llvm.maxnum.",2794 .@"llvm.maxnum.",
2757 .@"llvm.minnum.",2795 .@"llvm.minnum.",
2796 .@"llvm.ctlz.",
2797 .@"llvm.cttz.",
2758 .@"llvm.sadd.sat.",2798 .@"llvm.sadd.sat.",
2759 .@"llvm.smax.",2799 .@"llvm.smax.",
2760 .@"llvm.smin.",2800 .@"llvm.smin.",
...@@ -2887,6 +2927,22 @@ pub const Function = struct {...@@ -2887,6 +2927,22 @@ pub const Function = struct {
2887 .changeScalarAssumeCapacity(.i1, builder),2927 .changeScalarAssumeCapacity(.i1, builder),
2888 .fneg,2928 .fneg,
2889 .@"fneg fast",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 => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder),2946 => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder),
2891 .getelementptr,2947 .getelementptr,
2892 .@"getelementptr inbounds",2948 .@"getelementptr inbounds",
...@@ -2925,6 +2981,7 @@ pub const Function = struct {...@@ -2925,6 +2981,7 @@ pub const Function = struct {
2925 },2981 },
2926 .unimplemented => @enumFromInt(instruction.data),2982 .unimplemented => @enumFromInt(instruction.data),
2927 .va_arg => function.extraData(VaArg, instruction.data).type,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 }
29302987
...@@ -3017,6 +3074,12 @@ pub const Function = struct {...@@ -3017,6 +3074,12 @@ pub const Function = struct {
3017 mask: Value,3074 mask: Value,
3018 };3075 };
30193076
3077 pub const FusedMultiplyAdd = struct {
3078 a: Value,
3079 b: Value,
3080 c: Value,
3081 };
3082
3020 pub const ExtractValue = struct {3083 pub const ExtractValue = struct {
3021 val: Value,3084 val: Value,
3022 indices_len: u32,3085 indices_len: u32,
...@@ -3424,7 +3487,24 @@ pub const WipFunction = struct {...@@ -3424,7 +3487,24 @@ pub const WipFunction = struct {
3424 switch (tag) {3487 switch (tag) {
3425 .fneg,3488 .fneg,
3426 .@"fneg fast",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 => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()),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 else => unreachable,3508 else => unreachable,
3429 }3509 }
3430 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);3510 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
...@@ -3433,10 +3513,43 @@ pub const WipFunction = struct {...@@ -3433,10 +3513,43 @@ pub const WipFunction = struct {
3433 switch (tag) {3513 switch (tag) {
3434 .fneg => self.llvm.builder.setFastMath(false),3514 .fneg => self.llvm.builder.setFastMath(false),
3435 .@"fneg fast" => self.llvm.builder.setFastMath(true),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 else => unreachable,3533 else => unreachable,
3437 }3534 }
3438 self.llvm.instructions.appendAssumeCapacity(switch (tag) {3535 self.llvm.instructions.appendAssumeCapacity(switch (tag) {
3439 .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg,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 else => unreachable,3553 else => unreachable,
3441 }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self)));3554 }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self)));
3442 }3555 }
...@@ -3514,6 +3627,9 @@ pub const WipFunction = struct {...@@ -3514,6 +3627,9 @@ pub const WipFunction = struct {
3514 .urem,3627 .urem,
3515 .xor,3628 .xor,
3516 => assert(lhs.typeOfWip(self) == rhs.typeOfWip(self)),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 else => unreachable,3633 else => unreachable,
3518 }3634 }
3519 try self.ensureUnusedExtraCapacity(1, Instruction.Binary, 0);3635 try self.ensureUnusedExtraCapacity(1, Instruction.Binary, 0);
...@@ -3551,6 +3667,8 @@ pub const WipFunction = struct {...@@ -3551,6 +3667,8 @@ pub const WipFunction = struct {
3551 .fsub, .@"fsub fast" => &llvm.Builder.buildFSub,3667 .fsub, .@"fsub fast" => &llvm.Builder.buildFSub,
3552 .@"llvm.maxnum." => &llvm.Builder.buildMaxNum,3668 .@"llvm.maxnum." => &llvm.Builder.buildMaxNum,
3553 .@"llvm.minnum." => &llvm.Builder.buildMinNum,3669 .@"llvm.minnum." => &llvm.Builder.buildMinNum,
3670 .@"llvm.ctlz." => &llvm.Builder.buildCTLZ,
3671 .@"llvm.cttz." => &llvm.Builder.buildCTTZ,
3554 .@"llvm.sadd.sat." => &llvm.Builder.buildSAddSat,3672 .@"llvm.sadd.sat." => &llvm.Builder.buildSAddSat,
3555 .@"llvm.smax." => &llvm.Builder.buildSMax,3673 .@"llvm.smax." => &llvm.Builder.buildSMax,
3556 .@"llvm.smin." => &llvm.Builder.buildSMin,3674 .@"llvm.smin." => &llvm.Builder.buildSMin,
...@@ -4330,6 +4448,29 @@ pub const WipFunction = struct {...@@ -4330,6 +4448,29 @@ pub const WipFunction = struct {
4330 return instruction.toValue();4448 return instruction.toValue();
4331 }4449 }
43324450
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 pub const WipUnimplemented = struct {4474 pub const WipUnimplemented = struct {
4334 instruction: Instruction.Index,4475 instruction: Instruction.Index,
43354476
...@@ -4558,6 +4699,8 @@ pub const WipFunction = struct {...@@ -4558,6 +4699,8 @@ pub const WipFunction = struct {
4558 .@"icmp ult",4699 .@"icmp ult",
4559 .@"llvm.maxnum.",4700 .@"llvm.maxnum.",
4560 .@"llvm.minnum.",4701 .@"llvm.minnum.",
4702 .@"llvm.ctlz.",
4703 .@"llvm.cttz.",
4561 .@"llvm.sadd.sat.",4704 .@"llvm.sadd.sat.",
4562 .@"llvm.smax.",4705 .@"llvm.smax.",
4563 .@"llvm.smin.",4706 .@"llvm.smin.",
...@@ -4685,6 +4828,22 @@ pub const WipFunction = struct {...@@ -4685,6 +4828,22 @@ pub const WipFunction = struct {
4685 .fneg,4828 .fneg,
4686 .@"fneg fast",4829 .@"fneg fast",
4687 .ret,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 => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))),4847 => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))),
4689 .getelementptr,4848 .getelementptr,
4690 .@"getelementptr inbounds",4849 .@"getelementptr inbounds",
...@@ -4790,6 +4949,14 @@ pub const WipFunction = struct {...@@ -4790,6 +4949,14 @@ pub const WipFunction = struct {
4790 .type = extra.type,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 function.instructions.appendAssumeCapacity(instruction);4961 function.instructions.appendAssumeCapacity(instruction);
4795 names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip)4962 names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip)
...@@ -7561,6 +7728,22 @@ pub fn printUnbuffered(...@@ -7561,6 +7728,22 @@ pub fn printUnbuffered(
7561 .fneg,7728 .fneg,
7562 .@"fneg fast",7729 .@"fneg fast",
7563 .ret,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 => |tag| {7747 => |tag| {
7565 const val: Value = @enumFromInt(instruction.data);7748 const val: Value = @enumFromInt(instruction.data);
7566 try writer.print(" {s} {%}\n", .{7749 try writer.print(" {s} {%}\n", .{
...@@ -7617,6 +7800,8 @@ pub fn printUnbuffered(...@@ -7617,6 +7800,8 @@ pub fn printUnbuffered(
7617 },7800 },
7618 .@"llvm.maxnum.",7801 .@"llvm.maxnum.",
7619 .@"llvm.minnum.",7802 .@"llvm.minnum.",
7803 .@"llvm.ctlz.",
7804 .@"llvm.cttz.",
7620 .@"llvm.sadd.sat.",7805 .@"llvm.sadd.sat.",
7621 .@"llvm.smax.",7806 .@"llvm.smax.",
7622 .@"llvm.smin.",7807 .@"llvm.smin.",
...@@ -7781,6 +7966,19 @@ pub fn printUnbuffered(...@@ -7781,6 +7966,19 @@ pub fn printUnbuffered(
7781 extra.type.fmt(self),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 try writer.writeByte('}');7984 try writer.writeByte('}');
src/codegen/llvm/bindings.zig+57
...@@ -1026,6 +1026,63 @@ pub const Builder = opaque {...@@ -1026,6 +1026,63 @@ pub const Builder = opaque {
1026 pub const buildMinNum = ZigLLVMBuildMinNum;1026 pub const buildMinNum = ZigLLVMBuildMinNum;
1027 extern fn ZigLLVMBuildMinNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;1027 extern fn ZigLLVMBuildMinNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
10281028
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 pub const buildUMax = ZigLLVMBuildUMax;1086 pub const buildUMax = ZigLLVMBuildUMax;
1030 extern fn ZigLLVMBuildUMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;1087 extern fn ZigLLVMBuildUMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
10311088
src/zig_llvm.cpp+100
...@@ -481,6 +481,106 @@ LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef...@@ -481,6 +481,106 @@ LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef
481 return wrap(call_inst);481 return wrap(call_inst);
482}482}
483483
484LLVMValueRef 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
489LLVMValueRef 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
494LLVMValueRef 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
499LLVMValueRef 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
504LLVMValueRef 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
509LLVMValueRef 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
514LLVMValueRef 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
519LLVMValueRef 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
524LLVMValueRef 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
529LLVMValueRef 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
534LLVMValueRef 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
539LLVMValueRef 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
544LLVMValueRef 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
549LLVMValueRef 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
554LLVMValueRef 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
559LLVMValueRef 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
564LLVMValueRef 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
569LLVMValueRef 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
574LLVMValueRef 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
484LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {584LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
485 CallInst *call_inst = unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS), name);585 CallInst *call_inst = unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS), name);
486 return wrap(call_inst);586 return wrap(call_inst);
src/zig_llvm.h+23
...@@ -141,6 +141,29 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst,...@@ -141,6 +141,29 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst,
141ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size,141ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size,
142 unsigned Align, bool isVolatile);142 unsigned Align, bool isVolatile);
143143
144ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCeil(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
145ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCos(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
146ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
147ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp2(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
148ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFAbs(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
149ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFloor(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
150ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
151ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog10(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
152ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog2(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
153ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildRound(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
154ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
155ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
156ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
157
158ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
159ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
160ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
161
162ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
163ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
164
165ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char* name);
166
144ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);167ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
145ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);168ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
146169