Commit ba3d21ca67

Andrew Kelley <superjoe30@gmail.com>
2017-09-30 22:59:31
better divTrunc codegen
branch and phi instead of select instruction fixes division test for windows. See #302
1 parent 588d286
src/all_types.hpp
@@ -1510,6 +1510,7 @@ struct CodeGen {
     size_t version_patch;
     bool verbose;
     bool verbose_link;
+    bool verbose_ir;
     ErrColor err_color;
     ImportTableEntry *root_import;
     ImportTableEntry *bootstrap_import;
src/codegen.cpp
@@ -1343,10 +1343,28 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_m
                 return result;
             case DivKindTrunc:
                 {
-                    LLVMValueRef floored = gen_floor(g, result, type_entry);
-                    LLVMValueRef ceiled = gen_ceil(g, result, type_entry);
+                    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, "");
-                    return LLVMBuildSelect(g->builder, ltz, ceiled, floored, "");
+                    LLVMBuildCondBr(g->builder, ltz, ltz_block, gez_block);
+
+                    LLVMPositionBuilderAtEnd(g->builder, ltz_block);
+                    LLVMValueRef ceiled = gen_ceil(g, result, type_entry);
+                    LLVMBasicBlockRef ceiled_end_block = LLVMGetInsertBlock(g->builder);
+                    LLVMBuildBr(g->builder, end_block);
+
+                    LLVMPositionBuilderAtEnd(g->builder, gez_block);
+                    LLVMValueRef floored = gen_floor(g, result, type_entry);
+                    LLVMBasicBlockRef floored_end_block = LLVMGetInsertBlock(g->builder);
+                    LLVMBuildBr(g->builder, end_block);
+
+                    LLVMPositionBuilderAtEnd(g->builder, end_block);
+                    LLVMValueRef phi = LLVMBuildPhi(g->builder, type_entry->type_ref, "");
+                    LLVMValueRef incoming_values[] = { ceiled, floored };
+                    LLVMBasicBlockRef incoming_blocks[] = { ceiled_end_block, floored_end_block };
+                    LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
+                    return phi;
                 }
             case DivKindFloor:
                 return gen_floor(g, result, type_entry);
@@ -4080,7 +4098,7 @@ static void validate_inline_fns(CodeGen *g) {
 }
 
 static void do_code_gen(CodeGen *g) {
-    if (g->verbose) {
+    if (g->verbose || g->verbose_ir) {
         fprintf(stderr, "\nCode Generation:\n");
         fprintf(stderr, "------------------\n");
     }
@@ -4358,7 +4376,7 @@ static void do_code_gen(CodeGen *g) {
 
     ZigLLVMDIBuilderFinalize(g->dbuilder);
 
-    if (g->verbose) {
+    if (g->verbose || g->verbose_ir) {
         LLVMDumpModule(g->module);
     }
 
src/main.cpp
@@ -48,6 +48,7 @@ static int usage(const char *arg0) {
         "  --target-os [name]           specify target operating system\n"
         "  --verbose                    turn on compiler debug output\n"
         "  --verbose-link               turn on compiler debug output for linking only\n"
+        "  --verbose-ir                 turn on compiler debug output for IR only\n"
         "  --zig-std-dir [path]         directory where zig standard library resides\n"
         "  -dirafter [dir]              same as -isystem but do it last\n"
         "  -isystem [dir]               add additional search path for other .h files\n"
@@ -186,6 +187,7 @@ int main(int argc, char **argv) {
     const char *out_name = nullptr;
     bool verbose = false;
     bool verbose_link = false;
+    bool verbose_ir = false;
     ErrColor color = ErrColorAuto;
     const char *libc_lib_dir = nullptr;
     const char *libc_static_lib_dir = nullptr;
@@ -352,6 +354,8 @@ int main(int argc, char **argv) {
                 verbose = true;
             } else if (strcmp(arg, "--verbose-link") == 0) {
                 verbose_link = true;
+            } else if (strcmp(arg, "--verbose-ir") == 0) {
+                verbose_ir = true;
             } else if (strcmp(arg, "-mwindows") == 0) {
                 mwindows = true;
             } else if (strcmp(arg, "-mconsole") == 0) {
@@ -630,6 +634,7 @@ int main(int argc, char **argv) {
                 codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker));
             codegen_set_verbose(g, verbose);
             g->verbose_link = verbose_link;
+            g->verbose_ir = verbose_ir;
             codegen_set_errmsg_color(g, color);
 
             for (size_t i = 0; i < lib_dirs.length; i += 1) {