aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/llvm.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-03-17 17:24:35 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-17 17:24:35 -0700
commit7233a3324aaa5b3995606f24b2b961149219986b (patch)
tree009a83fa10f489f0d6da4f77f07a4d0c8ca4e388 /src/codegen/llvm.zig
parent76e103057ea6037d3bb3e44cd33880a9a91609fb (diff)
downloadzig-7233a3324aaa5b3995606f24b2b961149219986b.tar.gz
zig-7233a3324aaa5b3995606f24b2b961149219986b.zip
stage2: implement `@reduce`
Notably, Value.eql and Value.hash are improved to treat NaN as equal to itself, so that Type/Value can be hash map keys. Likewise float hashing normalizes the float value before computing the hash.
Diffstat (limited to 'src/codegen/llvm.zig')
-rw-r--r--src/codegen/llvm.zig45
1 files changed, 45 insertions, 0 deletions
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;