aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig16
-rw-r--r--src/codegen/llvm.zig45
-rw-r--r--src/codegen/llvm/bindings.zig33
3 files changed, 94 insertions, 0 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index c0c2031116..c306e0a6b0 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1731,6 +1731,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.error_name => try airErrorName(f, inst),
.splat => try airSplat(f, inst),
.shuffle => try airShuffle(f, inst),
+ .reduce => try airReduce(f, inst),
.aggregate_init => try airAggregateInit(f, inst),
.union_init => try airUnionInit(f, inst),
.prefetch => try airPrefetch(f, inst),
@@ -3625,6 +3626,21 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
return f.fail("TODO: C backend: implement airShuffle", .{});
}
+fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
+ if (f.liveness.isUnused(inst)) return CValue.none;
+
+ const inst_ty = f.air.typeOfIndex(inst);
+ const reduce = f.air.instructions.items(.data)[inst].reduce;
+ const operand = try f.resolveInst(reduce.operand);
+ const writer = f.object.writer();
+ const local = try f.allocLocal(inst_ty, .Const);
+ try writer.writeAll(" = ");
+
+ _ = operand;
+ _ = local;
+ return f.fail("TODO: C backend: implement airReduce", .{});
+}
+
fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst)) return CValue.none;
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 8fb2a171ef..481730452c 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -3426,6 +3426,7 @@ pub const FuncGen = struct {
.error_name => try self.airErrorName(inst),
.splat => try self.airSplat(inst),
.shuffle => try self.airShuffle(inst),
+ .reduce => try self.airReduce(inst),
.aggregate_init => try self.airAggregateInit(inst),
.union_init => try self.airUnionInit(inst),
.prefetch => try self.airPrefetch(inst),
@@ -6281,6 +6282,50 @@ pub const FuncGen = struct {
return self.builder.buildShuffleVector(a, b, llvm_mask_value, "");
}
+ fn airReduce(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst)) return null;
+
+ const reduce = self.air.instructions.items(.data)[inst].reduce;
+ const operand = try self.resolveInst(reduce.operand);
+ const scalar_ty = self.air.typeOfIndex(inst);
+
+ // TODO handle the fast math setting
+
+ switch (reduce.operation) {
+ .And => return self.builder.buildAndReduce(operand),
+ .Or => return self.builder.buildOrReduce(operand),
+ .Xor => return self.builder.buildXorReduce(operand),
+ .Min => switch (scalar_ty.zigTypeTag()) {
+ .Int => return self.builder.buildIntMinReduce(operand, scalar_ty.isSignedInt()),
+ .Float => return self.builder.buildFPMinReduce(operand),
+ else => unreachable,
+ },
+ .Max => switch (scalar_ty.zigTypeTag()) {
+ .Int => return self.builder.buildIntMaxReduce(operand, scalar_ty.isSignedInt()),
+ .Float => return self.builder.buildFPMaxReduce(operand),
+ else => unreachable,
+ },
+ .Add => switch (scalar_ty.zigTypeTag()) {
+ .Int => return self.builder.buildAddReduce(operand),
+ .Float => {
+ const scalar_llvm_ty = try self.dg.llvmType(scalar_ty);
+ const neutral_value = scalar_llvm_ty.constReal(-0.0);
+ return self.builder.buildFPAddReduce(neutral_value, operand);
+ },
+ else => unreachable,
+ },
+ .Mul => switch (scalar_ty.zigTypeTag()) {
+ .Int => return self.builder.buildMulReduce(operand),
+ .Float => {
+ const scalar_llvm_ty = try self.dg.llvmType(scalar_ty);
+ const neutral_value = scalar_llvm_ty.constReal(1.0);
+ return self.builder.buildFPMulReduce(neutral_value, operand);
+ },
+ else => unreachable,
+ },
+ }
+ }
+
fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig
index a6c53fddce..b7a3ff7230 100644
--- a/src/codegen/llvm/bindings.zig
+++ b/src/codegen/llvm/bindings.zig
@@ -853,6 +853,39 @@ pub const Builder = opaque {
pub const buildShuffleVector = LLVMBuildShuffleVector;
extern fn LLVMBuildShuffleVector(*const Builder, V1: *const Value, V2: *const Value, Mask: *const Value, Name: [*:0]const u8) *const Value;
+
+ pub const buildAndReduce = ZigLLVMBuildAndReduce;
+ extern fn ZigLLVMBuildAndReduce(B: *const Builder, Val: *const Value) *const Value;
+
+ pub const buildOrReduce = ZigLLVMBuildOrReduce;
+ extern fn ZigLLVMBuildOrReduce(B: *const Builder, Val: *const Value) *const Value;
+
+ pub const buildXorReduce = ZigLLVMBuildXorReduce;
+ extern fn ZigLLVMBuildXorReduce(B: *const Builder, Val: *const Value) *const Value;
+
+ pub const buildIntMaxReduce = ZigLLVMBuildIntMaxReduce;
+ extern fn ZigLLVMBuildIntMaxReduce(B: *const Builder, Val: *const Value, is_signed: bool) *const Value;
+
+ pub const buildIntMinReduce = ZigLLVMBuildIntMinReduce;
+ extern fn ZigLLVMBuildIntMinReduce(B: *const Builder, Val: *const Value, is_signed: bool) *const Value;
+
+ pub const buildFPMaxReduce = ZigLLVMBuildFPMaxReduce;
+ extern fn ZigLLVMBuildFPMaxReduce(B: *const Builder, Val: *const Value) *const Value;
+
+ pub const buildFPMinReduce = ZigLLVMBuildFPMinReduce;
+ extern fn ZigLLVMBuildFPMinReduce(B: *const Builder, Val: *const Value) *const Value;
+
+ pub const buildAddReduce = ZigLLVMBuildAddReduce;
+ extern fn ZigLLVMBuildAddReduce(B: *const Builder, Val: *const Value) *const Value;
+
+ pub const buildMulReduce = ZigLLVMBuildMulReduce;
+ extern fn ZigLLVMBuildMulReduce(B: *const Builder, Val: *const Value) *const Value;
+
+ pub const buildFPAddReduce = ZigLLVMBuildFPAddReduce;
+ extern fn ZigLLVMBuildFPAddReduce(B: *const Builder, Acc: *const Value, Val: *const Value) *const Value;
+
+ pub const buildFPMulReduce = ZigLLVMBuildFPMulReduce;
+ extern fn ZigLLVMBuildFPMulReduce(B: *const Builder, Acc: *const Value, Val: *const Value) *const Value;
};
pub const MDString = opaque {