Commit c14e8aea authored by Stefan Behnel's avatar Stefan Behnel

code cleanup for if-const dead code removal: move handling into...

code cleanup for if-const dead code removal: move handling into ConstantFolding transform, where it can also replace the entire node

--HG--
rename : tests/run/consts.pyx => tests/run/if_const.pyx
parent 7fbed8c3
...@@ -3880,24 +3880,8 @@ class IfStatNode(StatNode): ...@@ -3880,24 +3880,8 @@ class IfStatNode(StatNode):
if self.else_clause: if self.else_clause:
self.else_clause.analyse_expressions(env) self.else_clause.analyse_expressions(env)
# eliminate dead code based on constant condition results
if_clauses = []
condition_result = None
for if_clause in self.if_clauses:
condition_result = if_clause.get_constant_condition_result()
if condition_result != False:
if_clauses.append(if_clause)
if condition_result == True:
# other conditions can no longer apply
self.else_clause = None
break
self.if_clauses = if_clauses
# FIXME: if only one active code body is left here, we can
# replace the whole node
def generate_execution_code(self, code): def generate_execution_code(self, code):
code.mark_pos(self.pos) code.mark_pos(self.pos)
if self.if_clauses:
end_label = code.new_label() end_label = code.new_label()
for if_clause in self.if_clauses: for if_clause in self.if_clauses:
if_clause.generate_execution_code(code, end_label) if_clause.generate_execution_code(code, end_label)
...@@ -3906,8 +3890,6 @@ class IfStatNode(StatNode): ...@@ -3906,8 +3890,6 @@ class IfStatNode(StatNode):
self.else_clause.generate_execution_code(code) self.else_clause.generate_execution_code(code)
code.putln("}") code.putln("}")
code.put_label(end_label) code.put_label(end_label)
elif self.else_clause:
self.else_clause.generate_execution_code(code)
def annotate(self, code): def annotate(self, code):
for if_clause in self.if_clauses: for if_clause in self.if_clauses:
...@@ -3938,7 +3920,7 @@ class IfClauseNode(Node): ...@@ -3938,7 +3920,7 @@ class IfClauseNode(Node):
def get_constant_condition_result(self): def get_constant_condition_result(self):
if self.condition.has_constant_result(): if self.condition.has_constant_result():
return self.condition.constant_result return bool(self.condition.constant_result)
else: else:
return None return None
......
...@@ -2570,6 +2570,36 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): ...@@ -2570,6 +2570,36 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
#new_node = new_node.coerce_to(node.type, self.current_scope) #new_node = new_node.coerce_to(node.type, self.current_scope)
return new_node return new_node
def visit_PrimaryCmpNode(self, node):
self._calculate_const(node)
if node.constant_result is ExprNodes.not_a_constant:
return node
bool_result = bool(node.constant_result)
return ExprNodes.BoolNode(node.pos, value=bool_result,
constant_result=bool_result)
def visit_IfStatNode(self, node):
self.visitchildren(node)
# eliminate dead code based on constant condition results
if_clauses = []
condition_result = None
for if_clause in node.if_clauses:
condition_result = if_clause.get_constant_condition_result()
# condition_result is True, False or None (unknown)
if condition_result != False:
if_clauses.append(if_clause)
if condition_result == True:
# other conditions can no longer apply
node.else_clause = None
break
if not if_clauses:
return node.else_clause # if None, deletes the node completely
elif len(if_clauses) == 1 and condition_result == True:
return if_clauses[0].body
else:
node.if_clauses = if_clauses
return node
# in the future, other nodes can have their own handler method here # in the future, other nodes can have their own handler method here
# that can replace them with a constant result node # that can replace them with a constant result node
......
...@@ -67,6 +67,7 @@ def arithm(): ...@@ -67,6 +67,7 @@ def arithm():
""" """
return 9*2+3*8//6-10 return 9*2+3*8//6-10
@cython.test_fail_if_path_exists("//BinopNode")
def parameters(): def parameters():
""" """
>>> parameters() == _func(-1 -2, - (-3+4), 1*2*3) >>> parameters() == _func(-1 -2, - (-3+4), 1*2*3)
...@@ -74,6 +75,7 @@ def parameters(): ...@@ -74,6 +75,7 @@ def parameters():
""" """
return _func(-1 -2, - (-3+4), 1*2*3) return _func(-1 -2, - (-3+4), 1*2*3)
@cython.test_fail_if_path_exists("//BinopNode")
def lists(): def lists():
""" """
>>> lists() == [1,2,3] + [4,5,6] >>> lists() == [1,2,3] + [4,5,6]
...@@ -81,75 +83,10 @@ def lists(): ...@@ -81,75 +83,10 @@ def lists():
""" """
return [1,2,3] + [4,5,6] return [1,2,3] + [4,5,6]
def int_bool_result():
"""
>>> int_bool_result()
True
"""
if 5:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def if_compare_true():
"""
>>> if_compare_true()
True
"""
if 0 == 0:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def if_compare_false():
"""
>>> if_compare_false()
False
"""
if 0 == 1 or 1 == 0:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode") @cython.test_fail_if_path_exists("//PrimaryCmpNode")
def if_compare_cascaded():
"""
>>> if_compare_cascaded()
True
"""
if 0 < 1 < 2 < 3:
return True
else:
return False
@cython.test_fail_if_path_exists("//CoerceToBooleanNode",
"//ListNode")
def list_bool_result():
"""
>>> list_bool_result()
True
"""
if [1,2,3]:
return True
else:
return False
def compile_time_DEF(): def compile_time_DEF():
""" """
>>> compile_time_DEF() >>> compile_time_DEF()
(1, False, True, True, False) (1, False, True, True, False)
""" """
return INT_VAL, INT_VAL == 0, INT_VAL != 0, INT_VAL == 1, INT_VAL != 1 return INT_VAL, INT_VAL == 0, INT_VAL != 0, INT_VAL == 1, INT_VAL != 1
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def compile_time_DEF_if():
"""
>>> compile_time_DEF_if()
True
"""
if INT_VAL != 0:
return True
else:
return False
cimport cython
DEF INT_VAL = 1
def int_bool_result():
"""
>>> int_bool_result()
True
"""
if 5:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode",
"//IfStatNode")
def if_compare_true():
"""
>>> if_compare_true()
True
"""
if 0 == 0:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode",
"//IfStatNode")
def if_compare_false():
"""
>>> if_compare_false()
False
"""
if 0 == 1:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode",
"//IfStatNode")
def if_compare_or_true():
"""
>>> if_compare_or_true()
True
"""
if 0 == 1 or 1 == 1:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode",
"//IfStatNode")
def if_compare_or_false():
"""
>>> if_compare_or_false()
False
"""
if 0 == 1 or 1 == 0:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode",
"//IfStatNode")
def if_compare_and_true():
"""
>>> if_compare_and_true()
True
"""
if 0 == 0 and 1 == 1:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode",
"//IfStatNode")
def if_compare_and_false():
"""
>>> if_compare_and_false()
False
"""
if 1 == 1 and 1 == 0:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode",
"//IfStatNode")
def if_compare_cascaded():
"""
>>> if_compare_cascaded()
True
"""
if 0 < 1 < 2 < 3:
return True
else:
return False
@cython.test_fail_if_path_exists("//CoerceToBooleanNode",
"//ListNode",
"//IfStatNode")
def list_bool_result_true():
"""
>>> list_bool_result_true()
True
"""
if [1,2,3]:
return True
else:
return False
@cython.test_fail_if_path_exists("//CoerceToBooleanNode",
"//ListNode",
"//IfStatNode")
def list_bool_result_false():
"""
>>> list_bool_result_false()
False
"""
if []:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode",
"//IfStatNode")
def compile_time_DEF_if():
"""
>>> compile_time_DEF_if()
True
"""
if INT_VAL != 0:
return True
else:
return False
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment