]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
experimental -fshort-logic, currently perl-like - might have to use NOT(NOT(x)) to...
authorWolfgang (Blub) Bumiller <blub@speed.at>
Wed, 21 Nov 2012 15:08:08 +0000 (16:08 +0100)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Wed, 21 Nov 2012 15:08:08 +0000 (16:08 +0100)
ast.c
opts.def

diff --git a/ast.c b/ast.c
index e7d5f099a58592133b24044952e6f8a48011b029..7487e2332798f0a4512f3602cfd802263ee46715 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1513,13 +1513,58 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
         return true;
     }
 
+    if (OPTS_FLAG(SHORT_LOGIC) &&
+        (self->op == INSTR_AND || self->op == INSTR_OR))
+    {
+        /* short circuit evaluation */
+        ir_block *other, *merge;
+        ir_block *from_left, *from_right;
+        ir_instr *phi;
+        size_t    merge_id;
+
+        merge_id = vec_size(func->blocks);
+        merge = ir_function_create_block(func->ir_func, ast_function_label(func, "sce_merge"));
+
+        cgen = self->left->expression.codegen;
+        if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
+            return false;
+
+        from_left = func->curblock;
+        other = ir_function_create_block(func->ir_func, ast_function_label(func, "sce_other"));
+        if (self->op == INSTR_AND) {
+            if (!ir_block_create_if(func->curblock, left, other, merge))
+                return false;
+        } else {
+            if (!ir_block_create_if(func->curblock, left, merge, other))
+                return false;
+        }
+
+        func->curblock = other;
+        cgen = self->right->expression.codegen;
+        if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
+            return false;
+        from_right = func->curblock;
+
+        if (!ir_block_create_jump(func->curblock, merge))
+            return false;
+
+        vec_remove(func->ir_func->blocks, merge_id, 1);
+        vec_push(func->ir_func->blocks, merge);
+
+        func->curblock = merge;
+        phi = ir_block_create_phi(func->curblock, ast_function_label(func, "sce_value"), TYPE_FLOAT);
+        ir_phi_add(phi, from_left, left);
+        ir_phi_add(phi, from_right, right);
+        *out = ir_phi_value(phi);
+        self->expression.outr = *out;
+        return true;
+    }
+
     cgen = self->left->expression.codegen;
-    /* lvalue! */
     if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
         return false;
 
     cgen = self->right->expression.codegen;
-    /* rvalue! */
     if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
         return false;
 
index 705eb0c4faee396beb2876f362254f314bd70959..46c7122a62cac16a7e0d82dc267471863fd897ff 100644 (file)
--- a/opts.def
+++ b/opts.def
@@ -33,6 +33,7 @@
     GMQCC_DEFINE_FLAG(ADJUST_VECTOR_FIELDS)
     GMQCC_DEFINE_FLAG(FTEPP)
     GMQCC_DEFINE_FLAG(RELAXED_SWITCH)
+    GMQCC_DEFINE_FLAG(SHORT_LOGIC)
 #endif
 
 /* warning flags */