| 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,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); |
| 8284 | 8284 | ||
| 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 intrinsics | 8286 | // 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 the | 8300 | .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 | }; |
| 8339 | 8311 | ||
| 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 | } |
| 8374 | 8374 | ||
| 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 | } |
| 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 | 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); |
| 9534 | 9533 | ||
| 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}); | ||
| 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 | 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 | } |
| 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 | 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); |
| 9564 | 9544 | ||
| 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}); | ||
| 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 | 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 | } |
| 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 | 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 | } |
| 9613 | 9578 | ||
| 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 | ); | ||
| 9630 | 9580 | ||
| 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 | } |
| 2730 | 2768 | ||
| ... | @@ -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 | } |
| 2930 | 2987 | ||
| ... | @@ -3017,6 +3074,12 @@ pub const Function = struct { | ... | @@ -3017,6 +3074,12 @@ pub const Function = struct { |
| 3017 | mask: Value, | 3074 | mask: Value, |
| 3018 | }; | 3075 | }; |
| 3019 | 3076 | ||
| 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 | } |
| 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 | pub const WipUnimplemented = struct { | 4474 | pub const WipUnimplemented = struct { |
| 4334 | instruction: Instruction.Index, | 4475 | instruction: Instruction.Index, |
| 4335 | 4476 | ||
| ... | @@ -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; |
| 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 | 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; |
| 1031 | 1088 |
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 | } |
| 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 | LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | 584 | LLVMValueRef 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, |
| 141 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size, | 141 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size, |
| 142 | unsigned Align, bool isVolatile); | 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 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | 167 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); |
| 145 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | 168 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); |
| 146 | 169 |