aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorantlilja <liljaanton2001@gmail.com>2023-08-05 23:57:39 +0200
committerantlilja <liljaanton2001@gmail.com>2023-08-06 01:46:51 +0200
commit63dcffdf9ff146e05a374cdb4d2e5097def8c202 (patch)
treec3bf87754784f7eafc9e7278236a38033354af49 /src/codegen
parentb8c9d5ae98e7a8ff9b8fbaa53f5800281a61c048 (diff)
downloadzig-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')
-rw-r--r--src/codegen/llvm/Builder.zig158
-rw-r--r--src/codegen/llvm/bindings.zig42
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;