| author | |
| committer | |
| log | f80fd7e1a6bd3d4f9094301a3815909ce64a3696 |
| tree | 54e423d7053945cadb7a76a3af46baf64e9f817f |
| parent | 94879506ea8fe51310f38b3db1bc1ea1e71a4389 |
| parent | 2a733051bb5da245ac377f8771a482a85fb88519 |
| signature |
stage1/stage2: Simplify divTrunc impl5 files changed, 25 insertions(+), 33 deletions(-)
lib/std/math/trunc.zig+4| ... | @@ -21,6 +21,10 @@ pub fn trunc(x: anytype) @TypeOf(x) { | ... | @@ -21,6 +21,10 @@ pub fn trunc(x: anytype) @TypeOf(x) { |
| 21 | f32 => trunc32(x), | 21 | f32 => trunc32(x), |
| 22 | f64 => trunc64(x), | 22 | f64 => trunc64(x), |
| 23 | f128 => trunc128(x), | 23 | f128 => trunc128(x), |
| 24 | |||
| 25 | // TODO this is not correct for some targets | ||
| 26 | c_longdouble => @floatCast(c_longdouble, trunc128(x)), | ||
| 27 | |||
| 24 | else => @compileError("trunc not implemented for " ++ @typeName(T)), | 28 | else => @compileError("trunc not implemented for " ++ @typeName(T)), |
| 25 | }; | 29 | }; |
| 26 | } | 30 | } |
lib/std/special/c_stage1.zig+7| ... | @@ -763,6 +763,13 @@ export fn truncf(a: f32) f32 { | ... | @@ -763,6 +763,13 @@ export fn truncf(a: f32) f32 { |
| 763 | return math.trunc(a); | 763 | return math.trunc(a); |
| 764 | } | 764 | } |
| 765 | 765 | ||
| 766 | export fn truncl(a: c_longdouble) c_longdouble { | ||
| 767 | if (!long_double_is_f128) { | ||
| 768 | @panic("TODO implement this"); | ||
| 769 | } | ||
| 770 | return math.trunc(a); | ||
| 771 | } | ||
| 772 | |||
| 766 | export fn round(a: f64) f64 { | 773 | export fn round(a: f64) f64 { |
| 767 | return math.round(a); | 774 | return math.round(a); |
| 768 | } | 775 | } |
src/codegen/llvm.zig+5-6| ... | @@ -2874,13 +2874,8 @@ pub const FuncGen = struct { | ... | @@ -2874,13 +2874,8 @@ pub const FuncGen = struct { |
| 2874 | const inst_ty = self.air.typeOfIndex(inst); | 2874 | const inst_ty = self.air.typeOfIndex(inst); |
| 2875 | 2875 | ||
| 2876 | if (inst_ty.isRuntimeFloat()) { | 2876 | if (inst_ty.isRuntimeFloat()) { |
| 2877 | const result_llvm_ty = try self.dg.llvmType(inst_ty); | ||
| 2878 | const zero = result_llvm_ty.constNull(); | ||
| 2879 | const result = self.builder.buildFDiv(lhs, rhs, ""); | 2877 | const result = self.builder.buildFDiv(lhs, rhs, ""); |
| 2880 | const ceiled = try self.callCeil(result, inst_ty); | 2878 | return self.callTrunc(result, inst_ty); |
| 2881 | const floored = try self.callFloor(result, inst_ty); | ||
| 2882 | const ltz = self.builder.buildFCmp(.OLT, lhs, zero, ""); | ||
| 2883 | return self.builder.buildSelect(ltz, ceiled, floored, ""); | ||
| 2884 | } | 2879 | } |
| 2885 | if (inst_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, ""); | 2880 | if (inst_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, ""); |
| 2886 | return self.builder.buildUDiv(lhs, rhs, ""); | 2881 | return self.builder.buildUDiv(lhs, rhs, ""); |
| ... | @@ -3641,6 +3636,10 @@ pub const FuncGen = struct { | ... | @@ -3641,6 +3636,10 @@ pub const FuncGen = struct { |
| 3641 | return self.callFloatUnary(arg, ty, "ceil"); | 3636 | return self.callFloatUnary(arg, ty, "ceil"); |
| 3642 | } | 3637 | } |
| 3643 | 3638 | ||
| 3639 | fn callTrunc(self: *FuncGen, arg: *const llvm.Value, ty: Type) !*const llvm.Value { | ||
| 3640 | return self.callFloatUnary(arg, ty, "trunc"); | ||
| 3641 | } | ||
| 3642 | |||
| 3644 | fn callFloatUnary(self: *FuncGen, arg: *const llvm.Value, ty: Type, name: []const u8) !*const llvm.Value { | 3643 | fn callFloatUnary(self: *FuncGen, arg: *const llvm.Value, ty: Type, name: []const u8) !*const llvm.Value { |
| 3645 | const target = self.dg.module.getTarget(); | 3644 | const target = self.dg.module.getTarget(); |
| 3646 | 3645 |
src/stage1/codegen.cpp+1-27| ... | @@ -2964,33 +2964,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast | ... | @@ -2964,33 +2964,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast |
| 2964 | } | 2964 | } |
| 2965 | return result; | 2965 | return result; |
| 2966 | case DivKindTrunc: | 2966 | case DivKindTrunc: |
| 2967 | { | 2967 | return gen_float_op(g, result, operand_type, BuiltinFnIdTrunc); |
| 2968 | LLVMBasicBlockRef ltz_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivTruncLTZero"); | ||
| 2969 | LLVMBasicBlockRef gez_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivTruncGEZero"); | ||
| 2970 | LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivTruncEnd"); | ||
| 2971 | LLVMValueRef ltz = LLVMBuildFCmp(g->builder, LLVMRealOLT, val1, zero, ""); | ||
| 2972 | if (operand_type->id == ZigTypeIdVector) { | ||
| 2973 | ltz = ZigLLVMBuildOrReduce(g->builder, ltz); | ||
| 2974 | } | ||
| 2975 | LLVMBuildCondBr(g->builder, ltz, ltz_block, gez_block); | ||
| 2976 | |||
| 2977 | LLVMPositionBuilderAtEnd(g->builder, ltz_block); | ||
| 2978 | LLVMValueRef ceiled = gen_float_op(g, result, operand_type, BuiltinFnIdCeil); | ||
| 2979 | LLVMBasicBlockRef ceiled_end_block = LLVMGetInsertBlock(g->builder); | ||
| 2980 | LLVMBuildBr(g->builder, end_block); | ||
| 2981 | |||
| 2982 | LLVMPositionBuilderAtEnd(g->builder, gez_block); | ||
| 2983 | LLVMValueRef floored = gen_float_op(g, result, operand_type, BuiltinFnIdFloor); | ||
| 2984 | LLVMBasicBlockRef floored_end_block = LLVMGetInsertBlock(g->builder); | ||
| 2985 | LLVMBuildBr(g->builder, end_block); | ||
| 2986 | |||
| 2987 | LLVMPositionBuilderAtEnd(g->builder, end_block); | ||
| 2988 | LLVMValueRef phi = LLVMBuildPhi(g->builder, get_llvm_type(g, operand_type), ""); | ||
| 2989 | LLVMValueRef incoming_values[] = { ceiled, floored }; | ||
| 2990 | LLVMBasicBlockRef incoming_blocks[] = { ceiled_end_block, floored_end_block }; | ||
| 2991 | LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2); | ||
| 2992 | return phi; | ||
| 2993 | } | ||
| 2994 | case DivKindFloor: | 2968 | case DivKindFloor: |
| 2995 | return gen_float_op(g, result, operand_type, BuiltinFnIdFloor); | 2969 | return gen_float_op(g, result, operand_type, BuiltinFnIdFloor); |
| 2996 | } | 2970 | } |
test/behavior/math.zig+8| ... | @@ -282,12 +282,20 @@ fn testDivision() !void { | ... | @@ -282,12 +282,20 @@ fn testDivision() !void { |
| 282 | 282 | ||
| 283 | try expect(divTrunc(i32, 5, 3) == 1); | 283 | try expect(divTrunc(i32, 5, 3) == 1); |
| 284 | try expect(divTrunc(i32, -5, 3) == -1); | 284 | try expect(divTrunc(i32, -5, 3) == -1); |
| 285 | try expect(divTrunc(i32, 9, -10) == 0); | ||
| 286 | try expect(divTrunc(i32, -9, 10) == 0); | ||
| 285 | try expect(divTrunc(f16, 5.0, 3.0) == 1.0); | 287 | try expect(divTrunc(f16, 5.0, 3.0) == 1.0); |
| 286 | try expect(divTrunc(f16, -5.0, 3.0) == -1.0); | 288 | try expect(divTrunc(f16, -5.0, 3.0) == -1.0); |
| 289 | try expect(divTrunc(f16, 9.0, -10.0) == 0.0); | ||
| 290 | try expect(divTrunc(f16, -9.0, 10.0) == 0.0); | ||
| 287 | try expect(divTrunc(f32, 5.0, 3.0) == 1.0); | 291 | try expect(divTrunc(f32, 5.0, 3.0) == 1.0); |
| 288 | try expect(divTrunc(f32, -5.0, 3.0) == -1.0); | 292 | try expect(divTrunc(f32, -5.0, 3.0) == -1.0); |
| 293 | try expect(divTrunc(f32, 9.0, -10.0) == 0.0); | ||
| 294 | try expect(divTrunc(f32, -9.0, 10.0) == 0.0); | ||
| 289 | try expect(divTrunc(f64, 5.0, 3.0) == 1.0); | 295 | try expect(divTrunc(f64, 5.0, 3.0) == 1.0); |
| 290 | try expect(divTrunc(f64, -5.0, 3.0) == -1.0); | 296 | try expect(divTrunc(f64, -5.0, 3.0) == -1.0); |
| 297 | try expect(divTrunc(f64, 9.0, -10.0) == 0.0); | ||
| 298 | try expect(divTrunc(f64, -9.0, 10.0) == 0.0); | ||
| 291 | try expect(divTrunc(i32, 10, 12) == 0); | 299 | try expect(divTrunc(i32, 10, 12) == 0); |
| 292 | try expect(divTrunc(i32, -14, 12) == -1); | 300 | try expect(divTrunc(i32, -14, 12) == -1); |
| 293 | try expect(divTrunc(i32, -2, 12) == 0); | 301 | try expect(divTrunc(i32, -2, 12) == 0); |