| ... | @@ -2416,6 +2416,20 @@ pub const Function = struct { | ... | @@ -2416,6 +2416,20 @@ 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.", |
| 2419 | @"llvm.sadd.sat.", | 2433 | @"llvm.sadd.sat.", |
| 2420 | @"llvm.smax.", | 2434 | @"llvm.smax.", |
| 2421 | @"llvm.smin.", | 2435 | @"llvm.smin.", |
| ... | @@ -2689,6 +2703,19 @@ pub const Function = struct { | ... | @@ -2689,6 +2703,19 @@ pub const Function = struct { |
| 2689 | .changeScalarAssumeCapacity(.i1, wip.builder), | 2703 | .changeScalarAssumeCapacity(.i1, wip.builder), |
| 2690 | .fneg, | 2704 | .fneg, |
| 2691 | .@"fneg fast", | 2705 | .@"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.", |
| 2692 | => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip), | 2719 | => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip), |
| 2693 | .getelementptr, | 2720 | .getelementptr, |
| 2694 | .@"getelementptr inbounds", | 2721 | .@"getelementptr inbounds", |
| ... | @@ -2725,6 +2752,7 @@ pub const Function = struct { | ... | @@ -2725,6 +2752,7 @@ pub const Function = struct { |
| 2725 | }, | 2752 | }, |
| 2726 | .unimplemented => @enumFromInt(instruction.data), | 2753 | .unimplemented => @enumFromInt(instruction.data), |
| 2727 | .va_arg => wip.extraData(VaArg, instruction.data).type, | 2754 | .va_arg => wip.extraData(VaArg, instruction.data).type, |
| | 2755 | .@"llvm.fma." => wip.extraData(FusedMultiplyAdd, instruction.data).a.typeOfWip(wip), |
| 2728 | }; | 2756 | }; |
| 2729 | } | 2757 | } |
| 2730 | | 2758 | |
| ... | @@ -2887,6 +2915,19 @@ pub const Function = struct { | ... | @@ -2887,6 +2915,19 @@ pub const Function = struct { |
| 2887 | .changeScalarAssumeCapacity(.i1, builder), | 2915 | .changeScalarAssumeCapacity(.i1, builder), |
| 2888 | .fneg, | 2916 | .fneg, |
| 2889 | .@"fneg fast", | 2917 | .@"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.", |
| 2890 | => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder), | 2931 | => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder), |
| 2891 | .getelementptr, | 2932 | .getelementptr, |
| 2892 | .@"getelementptr inbounds", | 2933 | .@"getelementptr inbounds", |
| ... | @@ -2925,6 +2966,7 @@ pub const Function = struct { | ... | @@ -2925,6 +2966,7 @@ pub const Function = struct { |
| 2925 | }, | 2966 | }, |
| 2926 | .unimplemented => @enumFromInt(instruction.data), | 2967 | .unimplemented => @enumFromInt(instruction.data), |
| 2927 | .va_arg => function.extraData(VaArg, instruction.data).type, | 2968 | .va_arg => function.extraData(VaArg, instruction.data).type, |
| | 2969 | .@"llvm.fma." => function.extraData(FusedMultiplyAdd, instruction.data).a.typeOf(function_index, builder), |
| 2928 | }; | 2970 | }; |
| 2929 | } | 2971 | } |
| 2930 | | 2972 | |
| ... | @@ -3017,6 +3059,12 @@ pub const Function = struct { | ... | @@ -3017,6 +3059,12 @@ pub const Function = struct { |
| 3017 | mask: Value, | 3059 | mask: Value, |
| 3018 | }; | 3060 | }; |
| 3019 | | 3061 | |
| | 3062 | pub const FusedMultiplyAdd = struct { |
| | 3063 | a: Value, |
| | 3064 | b: Value, |
| | 3065 | c: Value, |
| | 3066 | }; |
| | 3067 | |
| 3020 | pub const ExtractValue = struct { | 3068 | pub const ExtractValue = struct { |
| 3021 | val: Value, | 3069 | val: Value, |
| 3022 | indices_len: u32, | 3070 | indices_len: u32, |
| ... | @@ -3424,6 +3472,19 @@ pub const WipFunction = struct { | ... | @@ -3424,6 +3472,19 @@ pub const WipFunction = struct { |
| 3424 | switch (tag) { | 3472 | switch (tag) { |
| 3425 | .fneg, | 3473 | .fneg, |
| 3426 | .@"fneg fast", | 3474 | .@"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.", |
| 3427 | => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()), | 3488 | => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()), |
| 3428 | else => unreachable, | 3489 | else => unreachable, |
| 3429 | } | 3490 | } |
| ... | @@ -3433,10 +3494,37 @@ pub const WipFunction = struct { | ... | @@ -3433,10 +3494,37 @@ pub const WipFunction = struct { |
| 3433 | switch (tag) { | 3494 | switch (tag) { |
| 3434 | .fneg => self.llvm.builder.setFastMath(false), | 3495 | .fneg => self.llvm.builder.setFastMath(false), |
| 3435 | .@"fneg fast" => self.llvm.builder.setFastMath(true), | 3496 | .@"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 | => {}, |
| 3436 | else => unreachable, | 3511 | else => unreachable, |
| 3437 | } | 3512 | } |
| 3438 | self.llvm.instructions.appendAssumeCapacity(switch (tag) { | 3513 | self.llvm.instructions.appendAssumeCapacity(switch (tag) { |
| 3439 | .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg, | 3514 | .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, |
| 3440 | else => unreachable, | 3528 | else => unreachable, |
| 3441 | }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self))); | 3529 | }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self))); |
| 3442 | } | 3530 | } |
| ... | @@ -4330,6 +4418,29 @@ pub const WipFunction = struct { | ... | @@ -4330,6 +4418,29 @@ pub const WipFunction = struct { |
| 4330 | return instruction.toValue(); | 4418 | return instruction.toValue(); |
| 4331 | } | 4419 | } |
| 4332 | | 4420 | |
| | 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 | |
| 4333 | pub const WipUnimplemented = struct { | 4444 | pub const WipUnimplemented = struct { |
| 4334 | instruction: Instruction.Index, | 4445 | instruction: Instruction.Index, |
| 4335 | | 4446 | |
| ... | @@ -4685,6 +4796,19 @@ pub const WipFunction = struct { | ... | @@ -4685,6 +4796,19 @@ pub const WipFunction = struct { |
| 4685 | .fneg, | 4796 | .fneg, |
| 4686 | .@"fneg fast", | 4797 | .@"fneg fast", |
| 4687 | .ret, | 4798 | .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.", |
| 4688 | => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))), | 4812 | => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))), |
| 4689 | .getelementptr, | 4813 | .getelementptr, |
| 4690 | .@"getelementptr inbounds", | 4814 | .@"getelementptr inbounds", |
| ... | @@ -4790,6 +4914,14 @@ pub const WipFunction = struct { | ... | @@ -4790,6 +4914,14 @@ pub const WipFunction = struct { |
| 4790 | .type = extra.type, | 4914 | .type = extra.type, |
| 4791 | }); | 4915 | }); |
| 4792 | }, | 4916 | }, |
| | 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 | }, |
| 4793 | } | 4925 | } |
| 4794 | function.instructions.appendAssumeCapacity(instruction); | 4926 | function.instructions.appendAssumeCapacity(instruction); |
| 4795 | names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip) | 4927 | names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip) |
| ... | @@ -7561,6 +7693,19 @@ pub fn printUnbuffered( | ... | @@ -7561,6 +7693,19 @@ pub fn printUnbuffered( |
| 7561 | .fneg, | 7693 | .fneg, |
| 7562 | .@"fneg fast", | 7694 | .@"fneg fast", |
| 7563 | .ret, | 7695 | .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.", |
| 7564 | => |tag| { | 7709 | => |tag| { |
| 7565 | const val: Value = @enumFromInt(instruction.data); | 7710 | const val: Value = @enumFromInt(instruction.data); |
| 7566 | try writer.print(" {s} {%}\n", .{ | 7711 | try writer.print(" {s} {%}\n", .{ |
| ... | @@ -7781,6 +7926,19 @@ pub fn printUnbuffered( | ... | @@ -7781,6 +7926,19 @@ pub fn printUnbuffered( |
| 7781 | extra.type.fmt(self), | 7926 | extra.type.fmt(self), |
| 7782 | }); | 7927 | }); |
| 7783 | }, | 7928 | }, |
| | 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 | }, |
| 7784 | } | 7942 | } |
| 7785 | } | 7943 | } |
| 7786 | try writer.writeByte('}'); | 7944 | try writer.writeByte('}'); |