mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 13:30:45 +00:00
Merge pull request #10022 from LemonBoy/fix-10001
stage1/stage2: Simplify divTrunc impl
This commit is contained in:
commit
f80fd7e1a6
@ -21,6 +21,10 @@ pub fn trunc(x: anytype) @TypeOf(x) {
|
||||
f32 => trunc32(x),
|
||||
f64 => trunc64(x),
|
||||
f128 => trunc128(x),
|
||||
|
||||
// TODO this is not correct for some targets
|
||||
c_longdouble => @floatCast(c_longdouble, trunc128(x)),
|
||||
|
||||
else => @compileError("trunc not implemented for " ++ @typeName(T)),
|
||||
};
|
||||
}
|
||||
|
||||
@ -763,6 +763,13 @@ export fn truncf(a: f32) f32 {
|
||||
return math.trunc(a);
|
||||
}
|
||||
|
||||
export fn truncl(a: c_longdouble) c_longdouble {
|
||||
if (!long_double_is_f128) {
|
||||
@panic("TODO implement this");
|
||||
}
|
||||
return math.trunc(a);
|
||||
}
|
||||
|
||||
export fn round(a: f64) f64 {
|
||||
return math.round(a);
|
||||
}
|
||||
|
||||
@ -2874,13 +2874,8 @@ pub const FuncGen = struct {
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
|
||||
if (inst_ty.isRuntimeFloat()) {
|
||||
const result_llvm_ty = try self.dg.llvmType(inst_ty);
|
||||
const zero = result_llvm_ty.constNull();
|
||||
const result = self.builder.buildFDiv(lhs, rhs, "");
|
||||
const ceiled = try self.callCeil(result, inst_ty);
|
||||
const floored = try self.callFloor(result, inst_ty);
|
||||
const ltz = self.builder.buildFCmp(.OLT, lhs, zero, "");
|
||||
return self.builder.buildSelect(ltz, ceiled, floored, "");
|
||||
return self.callTrunc(result, inst_ty);
|
||||
}
|
||||
if (inst_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, "");
|
||||
return self.builder.buildUDiv(lhs, rhs, "");
|
||||
@ -3641,6 +3636,10 @@ pub const FuncGen = struct {
|
||||
return self.callFloatUnary(arg, ty, "ceil");
|
||||
}
|
||||
|
||||
fn callTrunc(self: *FuncGen, arg: *const llvm.Value, ty: Type) !*const llvm.Value {
|
||||
return self.callFloatUnary(arg, ty, "trunc");
|
||||
}
|
||||
|
||||
fn callFloatUnary(self: *FuncGen, arg: *const llvm.Value, ty: Type, name: []const u8) !*const llvm.Value {
|
||||
const target = self.dg.module.getTarget();
|
||||
|
||||
|
||||
@ -2964,33 +2964,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast
|
||||
}
|
||||
return result;
|
||||
case DivKindTrunc:
|
||||
{
|
||||
LLVMBasicBlockRef ltz_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivTruncLTZero");
|
||||
LLVMBasicBlockRef gez_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivTruncGEZero");
|
||||
LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivTruncEnd");
|
||||
LLVMValueRef ltz = LLVMBuildFCmp(g->builder, LLVMRealOLT, val1, zero, "");
|
||||
if (operand_type->id == ZigTypeIdVector) {
|
||||
ltz = ZigLLVMBuildOrReduce(g->builder, ltz);
|
||||
}
|
||||
LLVMBuildCondBr(g->builder, ltz, ltz_block, gez_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, ltz_block);
|
||||
LLVMValueRef ceiled = gen_float_op(g, result, operand_type, BuiltinFnIdCeil);
|
||||
LLVMBasicBlockRef ceiled_end_block = LLVMGetInsertBlock(g->builder);
|
||||
LLVMBuildBr(g->builder, end_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, gez_block);
|
||||
LLVMValueRef floored = gen_float_op(g, result, operand_type, BuiltinFnIdFloor);
|
||||
LLVMBasicBlockRef floored_end_block = LLVMGetInsertBlock(g->builder);
|
||||
LLVMBuildBr(g->builder, end_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, end_block);
|
||||
LLVMValueRef phi = LLVMBuildPhi(g->builder, get_llvm_type(g, operand_type), "");
|
||||
LLVMValueRef incoming_values[] = { ceiled, floored };
|
||||
LLVMBasicBlockRef incoming_blocks[] = { ceiled_end_block, floored_end_block };
|
||||
LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
|
||||
return phi;
|
||||
}
|
||||
return gen_float_op(g, result, operand_type, BuiltinFnIdTrunc);
|
||||
case DivKindFloor:
|
||||
return gen_float_op(g, result, operand_type, BuiltinFnIdFloor);
|
||||
}
|
||||
|
||||
@ -282,12 +282,20 @@ fn testDivision() !void {
|
||||
|
||||
try expect(divTrunc(i32, 5, 3) == 1);
|
||||
try expect(divTrunc(i32, -5, 3) == -1);
|
||||
try expect(divTrunc(i32, 9, -10) == 0);
|
||||
try expect(divTrunc(i32, -9, 10) == 0);
|
||||
try expect(divTrunc(f16, 5.0, 3.0) == 1.0);
|
||||
try expect(divTrunc(f16, -5.0, 3.0) == -1.0);
|
||||
try expect(divTrunc(f16, 9.0, -10.0) == 0.0);
|
||||
try expect(divTrunc(f16, -9.0, 10.0) == 0.0);
|
||||
try expect(divTrunc(f32, 5.0, 3.0) == 1.0);
|
||||
try expect(divTrunc(f32, -5.0, 3.0) == -1.0);
|
||||
try expect(divTrunc(f32, 9.0, -10.0) == 0.0);
|
||||
try expect(divTrunc(f32, -9.0, 10.0) == 0.0);
|
||||
try expect(divTrunc(f64, 5.0, 3.0) == 1.0);
|
||||
try expect(divTrunc(f64, -5.0, 3.0) == -1.0);
|
||||
try expect(divTrunc(f64, 9.0, -10.0) == 0.0);
|
||||
try expect(divTrunc(f64, -9.0, 10.0) == 0.0);
|
||||
try expect(divTrunc(i32, 10, 12) == 0);
|
||||
try expect(divTrunc(i32, -14, 12) == -1);
|
||||
try expect(divTrunc(i32, -2, 12) == 0);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user