diff options
| author | antlilja <liljaanton2001@gmail.com> | 2023-08-05 23:57:39 +0200 |
|---|---|---|
| committer | antlilja <liljaanton2001@gmail.com> | 2023-08-06 01:46:51 +0200 |
| commit | 63dcffdf9ff146e05a374cdb4d2e5097def8c202 (patch) | |
| tree | c3bf87754784f7eafc9e7278236a38033354af49 /src/codegen/llvm | |
| parent | b8c9d5ae98e7a8ff9b8fbaa53f5800281a61c048 (diff) | |
| download | zig-63dcffdf9ff146e05a374cdb4d2e5097def8c202.tar.gz zig-63dcffdf9ff146e05a374cdb4d2e5097def8c202.zip | |
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
Diffstat (limited to 'src/codegen/llvm')
| -rw-r--r-- | src/codegen/llvm/Builder.zig | 158 | ||||
| -rw-r--r-- | src/codegen/llvm/bindings.zig | 42 |
2 files changed, 200 insertions, 0 deletions
diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index c0c01b9f15..d5caff72b0 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -2416,6 +2416,20 @@ pub const Function = struct { inttoptr, @"llvm.maxnum.", @"llvm.minnum.", + @"llvm.ceil.", + @"llvm.cos.", + @"llvm.exp.", + @"llvm.exp2.", + @"llvm.fabs.", + @"llvm.floor.", + @"llvm.log.", + @"llvm.log10.", + @"llvm.log2.", + @"llvm.round.", + @"llvm.sin.", + @"llvm.sqrt.", + @"llvm.trunc.", + @"llvm.fma.", @"llvm.sadd.sat.", @"llvm.smax.", @"llvm.smin.", @@ -2689,6 +2703,19 @@ pub const Function = struct { .changeScalarAssumeCapacity(.i1, wip.builder), .fneg, .@"fneg fast", + .@"llvm.ceil.", + .@"llvm.cos.", + .@"llvm.exp.", + .@"llvm.exp2.", + .@"llvm.fabs.", + .@"llvm.floor.", + .@"llvm.log.", + .@"llvm.log10.", + .@"llvm.log2.", + .@"llvm.round.", + .@"llvm.sin.", + .@"llvm.sqrt.", + .@"llvm.trunc.", => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip), .getelementptr, .@"getelementptr inbounds", @@ -2725,6 +2752,7 @@ pub const Function = struct { }, .unimplemented => @enumFromInt(instruction.data), .va_arg => wip.extraData(VaArg, instruction.data).type, + .@"llvm.fma." => wip.extraData(FusedMultiplyAdd, instruction.data).a.typeOfWip(wip), }; } @@ -2887,6 +2915,19 @@ pub const Function = struct { .changeScalarAssumeCapacity(.i1, builder), .fneg, .@"fneg fast", + .@"llvm.ceil.", + .@"llvm.cos.", + .@"llvm.exp.", + .@"llvm.exp2.", + .@"llvm.fabs.", + .@"llvm.floor.", + .@"llvm.log.", + .@"llvm.log10.", + .@"llvm.log2.", + .@"llvm.round.", + .@"llvm.sin.", + .@"llvm.sqrt.", + .@"llvm.trunc.", => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder), .getelementptr, .@"getelementptr inbounds", @@ -2925,6 +2966,7 @@ pub const Function = struct { }, .unimplemented => @enumFromInt(instruction.data), .va_arg => function.extraData(VaArg, instruction.data).type, + .@"llvm.fma." => function.extraData(FusedMultiplyAdd, instruction.data).a.typeOf(function_index, builder), }; } @@ -3017,6 +3059,12 @@ pub const Function = struct { mask: Value, }; + pub const FusedMultiplyAdd = struct { + a: Value, + b: Value, + c: Value, + }; + pub const ExtractValue = struct { val: Value, indices_len: u32, @@ -3424,6 +3472,19 @@ pub const WipFunction = struct { switch (tag) { .fneg, .@"fneg fast", + .@"llvm.ceil.", + .@"llvm.cos.", + .@"llvm.exp.", + .@"llvm.exp2.", + .@"llvm.fabs.", + .@"llvm.floor.", + .@"llvm.log.", + .@"llvm.log10.", + .@"llvm.log2.", + .@"llvm.round.", + .@"llvm.sin.", + .@"llvm.sqrt.", + .@"llvm.trunc.", => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()), else => unreachable, } @@ -3433,10 +3494,37 @@ pub const WipFunction = struct { switch (tag) { .fneg => self.llvm.builder.setFastMath(false), .@"fneg fast" => self.llvm.builder.setFastMath(true), + .@"llvm.ceil.", + .@"llvm.cos.", + .@"llvm.exp.", + .@"llvm.exp2.", + .@"llvm.fabs.", + .@"llvm.floor.", + .@"llvm.log.", + .@"llvm.log10.", + .@"llvm.log2.", + .@"llvm.round.", + .@"llvm.sin.", + .@"llvm.sqrt.", + .@"llvm.trunc.", + => {}, else => unreachable, } self.llvm.instructions.appendAssumeCapacity(switch (tag) { .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg, + .@"llvm.ceil." => &llvm.Builder.buildCeil, + .@"llvm.cos." => &llvm.Builder.buildCos, + .@"llvm.exp." => &llvm.Builder.buildExp, + .@"llvm.exp2." => &llvm.Builder.buildExp2, + .@"llvm.fabs." => &llvm.Builder.buildFAbs, + .@"llvm.floor." => &llvm.Builder.buildFloor, + .@"llvm.log." => &llvm.Builder.buildLog, + .@"llvm.log10." => &llvm.Builder.buildLog10, + .@"llvm.log2." => &llvm.Builder.buildLog2, + .@"llvm.round." => &llvm.Builder.buildRound, + .@"llvm.sin." => &llvm.Builder.buildSin, + .@"llvm.sqrt." => &llvm.Builder.buildSqrt, + .@"llvm.trunc." => &llvm.Builder.buildFTrunc, else => unreachable, }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self))); } @@ -4330,6 +4418,29 @@ pub const WipFunction = struct { return instruction.toValue(); } + pub fn fusedMultiplyAdd(self: *WipFunction, a: Value, b: Value, c: Value) Allocator.Error!Value { + assert(a.typeOfWip(self) == b.typeOfWip(self) and a.typeOfWip(self) == c.typeOfWip(self)); + try self.ensureUnusedExtraCapacity(1, Instruction.FusedMultiplyAdd, 0); + const instruction = try self.addInst("", .{ + .tag = .@"llvm.fma.", + .data = self.addExtraAssumeCapacity(Instruction.FusedMultiplyAdd{ + .a = a, + .b = b, + .c = c, + }), + }); + if (self.builder.useLibLlvm()) { + self.llvm.instructions.appendAssumeCapacity(llvm.Builder.buildFMA( + self.llvm.builder, + a.toLlvm(self), + b.toLlvm(self), + c.toLlvm(self), + instruction.llvmName(self), + )); + } + return instruction.toValue(); + } + pub const WipUnimplemented = struct { instruction: Instruction.Index, @@ -4685,6 +4796,19 @@ pub const WipFunction = struct { .fneg, .@"fneg fast", .ret, + .@"llvm.ceil.", + .@"llvm.cos.", + .@"llvm.exp.", + .@"llvm.exp2.", + .@"llvm.fabs.", + .@"llvm.floor.", + .@"llvm.log.", + .@"llvm.log10.", + .@"llvm.log2.", + .@"llvm.round.", + .@"llvm.sin.", + .@"llvm.sqrt.", + .@"llvm.trunc.", => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))), .getelementptr, .@"getelementptr inbounds", @@ -4790,6 +4914,14 @@ pub const WipFunction = struct { .type = extra.type, }); }, + .@"llvm.fma." => { + const extra = self.extraData(Instruction.FusedMultiplyAdd, instruction.data); + instruction.data = wip_extra.addExtra(Instruction.FusedMultiplyAdd{ + .a = instructions.map(extra.a), + .b = instructions.map(extra.b), + .c = instructions.map(extra.c), + }); + }, } function.instructions.appendAssumeCapacity(instruction); names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip) @@ -7561,6 +7693,19 @@ pub fn printUnbuffered( .fneg, .@"fneg fast", .ret, + .@"llvm.ceil.", + .@"llvm.cos.", + .@"llvm.exp.", + .@"llvm.exp2.", + .@"llvm.fabs.", + .@"llvm.floor.", + .@"llvm.log.", + .@"llvm.log10.", + .@"llvm.log2.", + .@"llvm.round.", + .@"llvm.sin.", + .@"llvm.sqrt.", + .@"llvm.trunc.", => |tag| { const val: Value = @enumFromInt(instruction.data); try writer.print(" {s} {%}\n", .{ @@ -7781,6 +7926,19 @@ pub fn printUnbuffered( extra.type.fmt(self), }); }, + .@"llvm.fma." => { + const extra = + function.extraData(Function.Instruction.FusedMultiplyAdd, instruction.data); + const ty = instruction_index.typeOf(function_index, self); + try writer.print(" %{} = call {%} @llvm.fma.{m}({%}, {%}, {%})\n", .{ + instruction_index.name(&function).fmt(self), + ty.fmt(self), + ty.fmt(self), + extra.a.fmt(function_index, self), + extra.b.fmt(function_index, self), + extra.c.fmt(function_index, self), + }); + }, } } try writer.writeByte('}'); diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 73473e2d43..cde4990b92 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -1026,6 +1026,48 @@ pub const Builder = opaque { pub const buildMinNum = ZigLLVMBuildMinNum; extern fn ZigLLVMBuildMinNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; + pub const buildCeil = ZigLLVMBuildCeil; + extern fn ZigLLVMBuildCeil(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildCos = ZigLLVMBuildCos; + extern fn ZigLLVMBuildCos(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildExp = ZigLLVMBuildExp; + extern fn ZigLLVMBuildExp(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildExp2 = ZigLLVMBuildExp2; + extern fn ZigLLVMBuildExp2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildFAbs = ZigLLVMBuildFAbs; + extern fn ZigLLVMBuildFAbs(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildFloor = ZigLLVMBuildFloor; + extern fn ZigLLVMBuildFloor(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildLog = ZigLLVMBuildLog; + extern fn ZigLLVMBuildLog(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildLog10 = ZigLLVMBuildLog10; + extern fn ZigLLVMBuildLog10(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildLog2 = ZigLLVMBuildLog2; + extern fn ZigLLVMBuildLog2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildRound = ZigLLVMBuildRound; + extern fn ZigLLVMBuildRound(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildSin = ZigLLVMBuildSin; + extern fn ZigLLVMBuildSin(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildSqrt = ZigLLVMBuildSqrt; + extern fn ZigLLVMBuildSqrt(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildFTrunc = ZigLLVMBuildFTrunc; + extern fn ZigLLVMBuildFTrunc(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; + + pub const buildFMA = ZigLLVMBuildFMA; + extern fn ZigLLVMBuildFMA(builder: *Builder, a: *Value, b: *Value, c: *Value, name: [*:0]const u8) *Value; + pub const buildUMax = ZigLLVMBuildUMax; extern fn ZigLLVMBuildUMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; |
