authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2023-08-05 23:57:39+02:00
committergravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2023-08-06 01:46:51+02:00
log63dcffdf9ff146e05a374cdb4d2e5097def8c202
treec3bf87754784f7eafc9e7278236a38033354af49
parentb8c9d5ae98e7a8ff9b8fbaa53f5800281a61c048
signaturelock-open Commit is signed but in an unrecognized format.

Implement fp intrinsics in new LLVM IR builder

Intrinsics implemented * llvm.ceil * llvm.cos * llvm.exp * llvm.exp2 * llvm.fabs * llvm.floor * llvm.log * llvm.log10 * llvm.log2 * llvm.round * llvm.sin * llvm.trunc * llvm.fma

4 files changed, 291 insertions(+), 0 deletions(-)

src/codegen/llvm/Builder.zig+158
......@@ -2416,6 +2416,20 @@ pub const Function = struct {
24162416 inttoptr,
24172417 @"llvm.maxnum.",
24182418 @"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.",
24192433 @"llvm.sadd.sat.",
24202434 @"llvm.smax.",
24212435 @"llvm.smin.",
......@@ -2689,6 +2703,19 @@ pub const Function = struct {
26892703 .changeScalarAssumeCapacity(.i1, wip.builder),
26902704 .fneg,
26912705 .@"fneg fast",
2706 .@"llvm.ceil.",
2707 .@"llvm.cos.",
2708 .@"llvm.exp.",
2709 .@"llvm.exp2.",
2710 .@"llvm.fabs.",
2711 .@"llvm.floor.",
2712 .@"llvm.log.",
2713 .@"llvm.log10.",
2714 .@"llvm.log2.",
2715 .@"llvm.round.",
2716 .@"llvm.sin.",
2717 .@"llvm.sqrt.",
2718 .@"llvm.trunc.",
26922719 => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip),
26932720 .getelementptr,
26942721 .@"getelementptr inbounds",
......@@ -2725,6 +2752,7 @@ pub const Function = struct {
27252752 },
27262753 .unimplemented => @enumFromInt(instruction.data),
27272754 .va_arg => wip.extraData(VaArg, instruction.data).type,
2755 .@"llvm.fma." => wip.extraData(FusedMultiplyAdd, instruction.data).a.typeOfWip(wip),
27282756 };
27292757 }
27302758
......@@ -2887,6 +2915,19 @@ pub const Function = struct {
28872915 .changeScalarAssumeCapacity(.i1, builder),
28882916 .fneg,
28892917 .@"fneg fast",
2918 .@"llvm.ceil.",
2919 .@"llvm.cos.",
2920 .@"llvm.exp.",
2921 .@"llvm.exp2.",
2922 .@"llvm.fabs.",
2923 .@"llvm.floor.",
2924 .@"llvm.log.",
2925 .@"llvm.log10.",
2926 .@"llvm.log2.",
2927 .@"llvm.round.",
2928 .@"llvm.sin.",
2929 .@"llvm.sqrt.",
2930 .@"llvm.trunc.",
28902931 => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder),
28912932 .getelementptr,
28922933 .@"getelementptr inbounds",
......@@ -2925,6 +2966,7 @@ pub const Function = struct {
29252966 },
29262967 .unimplemented => @enumFromInt(instruction.data),
29272968 .va_arg => function.extraData(VaArg, instruction.data).type,
2969 .@"llvm.fma." => function.extraData(FusedMultiplyAdd, instruction.data).a.typeOf(function_index, builder),
29282970 };
29292971 }
29302972
......@@ -3017,6 +3059,12 @@ pub const Function = struct {
30173059 mask: Value,
30183060 };
30193061
3062 pub const FusedMultiplyAdd = struct {
3063 a: Value,
3064 b: Value,
3065 c: Value,
3066 };
3067
30203068 pub const ExtractValue = struct {
30213069 val: Value,
30223070 indices_len: u32,
......@@ -3424,6 +3472,19 @@ pub const WipFunction = struct {
34243472 switch (tag) {
34253473 .fneg,
34263474 .@"fneg fast",
3475 .@"llvm.ceil.",
3476 .@"llvm.cos.",
3477 .@"llvm.exp.",
3478 .@"llvm.exp2.",
3479 .@"llvm.fabs.",
3480 .@"llvm.floor.",
3481 .@"llvm.log.",
3482 .@"llvm.log10.",
3483 .@"llvm.log2.",
3484 .@"llvm.round.",
3485 .@"llvm.sin.",
3486 .@"llvm.sqrt.",
3487 .@"llvm.trunc.",
34273488 => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()),
34283489 else => unreachable,
34293490 }
......@@ -3433,10 +3494,37 @@ pub const WipFunction = struct {
34333494 switch (tag) {
34343495 .fneg => self.llvm.builder.setFastMath(false),
34353496 .@"fneg fast" => self.llvm.builder.setFastMath(true),
3497 .@"llvm.ceil.",
3498 .@"llvm.cos.",
3499 .@"llvm.exp.",
3500 .@"llvm.exp2.",
3501 .@"llvm.fabs.",
3502 .@"llvm.floor.",
3503 .@"llvm.log.",
3504 .@"llvm.log10.",
3505 .@"llvm.log2.",
3506 .@"llvm.round.",
3507 .@"llvm.sin.",
3508 .@"llvm.sqrt.",
3509 .@"llvm.trunc.",
3510 => {},
34363511 else => unreachable,
34373512 }
34383513 self.llvm.instructions.appendAssumeCapacity(switch (tag) {
34393514 .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg,
3515 .@"llvm.ceil." => &llvm.Builder.buildCeil,
3516 .@"llvm.cos." => &llvm.Builder.buildCos,
3517 .@"llvm.exp." => &llvm.Builder.buildExp,
3518 .@"llvm.exp2." => &llvm.Builder.buildExp2,
3519 .@"llvm.fabs." => &llvm.Builder.buildFAbs,
3520 .@"llvm.floor." => &llvm.Builder.buildFloor,
3521 .@"llvm.log." => &llvm.Builder.buildLog,
3522 .@"llvm.log10." => &llvm.Builder.buildLog10,
3523 .@"llvm.log2." => &llvm.Builder.buildLog2,
3524 .@"llvm.round." => &llvm.Builder.buildRound,
3525 .@"llvm.sin." => &llvm.Builder.buildSin,
3526 .@"llvm.sqrt." => &llvm.Builder.buildSqrt,
3527 .@"llvm.trunc." => &llvm.Builder.buildFTrunc,
34403528 else => unreachable,
34413529 }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self)));
34423530 }
......@@ -4330,6 +4418,29 @@ pub const WipFunction = struct {
43304418 return instruction.toValue();
43314419 }
43324420
4421 pub fn fusedMultiplyAdd(self: *WipFunction, a: Value, b: Value, c: Value) Allocator.Error!Value {
4422 assert(a.typeOfWip(self) == b.typeOfWip(self) and a.typeOfWip(self) == c.typeOfWip(self));
4423 try self.ensureUnusedExtraCapacity(1, Instruction.FusedMultiplyAdd, 0);
4424 const instruction = try self.addInst("", .{
4425 .tag = .@"llvm.fma.",
4426 .data = self.addExtraAssumeCapacity(Instruction.FusedMultiplyAdd{
4427 .a = a,
4428 .b = b,
4429 .c = c,
4430 }),
4431 });
4432 if (self.builder.useLibLlvm()) {
4433 self.llvm.instructions.appendAssumeCapacity(llvm.Builder.buildFMA(
4434 self.llvm.builder,
4435 a.toLlvm(self),
4436 b.toLlvm(self),
4437 c.toLlvm(self),
4438 instruction.llvmName(self),
4439 ));
4440 }
4441 return instruction.toValue();
4442 }
4443
43334444 pub const WipUnimplemented = struct {
43344445 instruction: Instruction.Index,
43354446
......@@ -4685,6 +4796,19 @@ pub const WipFunction = struct {
46854796 .fneg,
46864797 .@"fneg fast",
46874798 .ret,
4799 .@"llvm.ceil.",
4800 .@"llvm.cos.",
4801 .@"llvm.exp.",
4802 .@"llvm.exp2.",
4803 .@"llvm.fabs.",
4804 .@"llvm.floor.",
4805 .@"llvm.log.",
4806 .@"llvm.log10.",
4807 .@"llvm.log2.",
4808 .@"llvm.round.",
4809 .@"llvm.sin.",
4810 .@"llvm.sqrt.",
4811 .@"llvm.trunc.",
46884812 => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))),
46894813 .getelementptr,
46904814 .@"getelementptr inbounds",
......@@ -4790,6 +4914,14 @@ pub const WipFunction = struct {
47904914 .type = extra.type,
47914915 });
47924916 },
4917 .@"llvm.fma." => {
4918 const extra = self.extraData(Instruction.FusedMultiplyAdd, instruction.data);
4919 instruction.data = wip_extra.addExtra(Instruction.FusedMultiplyAdd{
4920 .a = instructions.map(extra.a),
4921 .b = instructions.map(extra.b),
4922 .c = instructions.map(extra.c),
4923 });
4924 },
47934925 }
47944926 function.instructions.appendAssumeCapacity(instruction);
47954927 names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip)
......@@ -7561,6 +7693,19 @@ pub fn printUnbuffered(
75617693 .fneg,
75627694 .@"fneg fast",
75637695 .ret,
7696 .@"llvm.ceil.",
7697 .@"llvm.cos.",
7698 .@"llvm.exp.",
7699 .@"llvm.exp2.",
7700 .@"llvm.fabs.",
7701 .@"llvm.floor.",
7702 .@"llvm.log.",
7703 .@"llvm.log10.",
7704 .@"llvm.log2.",
7705 .@"llvm.round.",
7706 .@"llvm.sin.",
7707 .@"llvm.sqrt.",
7708 .@"llvm.trunc.",
75647709 => |tag| {
75657710 const val: Value = @enumFromInt(instruction.data);
75667711 try writer.print(" {s} {%}\n", .{
......@@ -7781,6 +7926,19 @@ pub fn printUnbuffered(
77817926 extra.type.fmt(self),
77827927 });
77837928 },
7929 .@"llvm.fma." => {
7930 const extra =
7931 function.extraData(Function.Instruction.FusedMultiplyAdd, instruction.data);
7932 const ty = instruction_index.typeOf(function_index, self);
7933 try writer.print(" %{} = call {%} @llvm.fma.{m}({%}, {%}, {%})\n", .{
7934 instruction_index.name(&function).fmt(self),
7935 ty.fmt(self),
7936 ty.fmt(self),
7937 extra.a.fmt(function_index, self),
7938 extra.b.fmt(function_index, self),
7939 extra.c.fmt(function_index, self),
7940 });
7941 },
77847942 }
77857943 }
77867944 try writer.writeByte('}');
src/codegen/llvm/bindings.zig+42
......@@ -1026,6 +1026,48 @@ pub const Builder = opaque {
10261026 pub const buildMinNum = ZigLLVMBuildMinNum;
10271027 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 buildFMA = ZigLLVMBuildFMA;
1069 extern fn ZigLLVMBuildFMA(builder: *Builder, a: *Value, b: *Value, c: *Value, name: [*:0]const u8) *Value;
1070
10291071 pub const buildUMax = ZigLLVMBuildUMax;
10301072 extern fn ZigLLVMBuildUMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
10311073
src/zig_llvm.cpp+75
......@@ -481,6 +481,81 @@ LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef
481481 return wrap(call_inst);
482482}
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 ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char *name) {
550 llvm::Type* types[1] = {
551 unwrap(A)->getType(),
552 };
553 llvm::Value* values[3] = {unwrap(A), unwrap(B), unwrap(C)};
554
555 CallInst *call_inst = unwrap(builder)->CreateIntrinsic(Intrinsic::fma, types, values, nullptr, name);
556 return wrap(call_inst);
557}
558
484559LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
485560 CallInst *call_inst = unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS), name);
486561 return wrap(call_inst);
src/zig_llvm.h+16
......@@ -141,6 +141,22 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst,
141141ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size,
142142 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 ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char* name);
159
144160ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
145161ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
146162