Start a very simple GVN pass (#79)

* Skeleton simple_gvn pass.
* Basic testing infrastructure for simple-gvn.
* Add can_load and can_store flags to instructions.
* Move the replace_values function into the DataFlowGraph.
* Make InstructionData derive from Hash, PartialEq, and Eq.
* Make EntityList's hash and eq functions panic.
* Change Ieee32 and Ieee64 to store u32 and u64, respectively.
This commit is contained in:
Dan Gohman
2017-05-18 18:18:57 -07:00
committed by Jakob Stoklund Olesen
parent 1d8efaad83
commit c826aefa0a
16 changed files with 256 additions and 57 deletions

View File

@@ -201,7 +201,7 @@ load = Instruction(
This is a polymorphic instruction that can load any value type which
has a memory representation.
""",
ins=(Flags, p, Offset), outs=a)
ins=(Flags, p, Offset), outs=a, can_load=True)
store = Instruction(
'store', r"""
@@ -210,7 +210,7 @@ store = Instruction(
This is a polymorphic instruction that can store any value type with a
memory representation.
""",
ins=(Flags, x, p, Offset))
ins=(Flags, x, p, Offset), can_store=True)
iExt8 = TypeVar(
'iExt8', 'An integer type with more than 8 bits',
@@ -224,7 +224,7 @@ uload8 = Instruction(
This is equivalent to ``load.i8`` followed by ``uextend``.
""",
ins=(Flags, p, Offset), outs=a)
ins=(Flags, p, Offset), outs=a, can_load=True)
sload8 = Instruction(
'sload8', r"""
@@ -232,7 +232,7 @@ sload8 = Instruction(
This is equivalent to ``load.i8`` followed by ``uextend``.
""",
ins=(Flags, p, Offset), outs=a)
ins=(Flags, p, Offset), outs=a, can_load=True)
istore8 = Instruction(
'istore8', r"""
@@ -240,7 +240,7 @@ istore8 = Instruction(
This is equivalent to ``ireduce.i8`` followed by ``store.i8``.
""",
ins=(Flags, x, p, Offset))
ins=(Flags, x, p, Offset), can_store=True)
iExt16 = TypeVar(
'iExt16', 'An integer type with more than 16 bits',
@@ -254,7 +254,7 @@ uload16 = Instruction(
This is equivalent to ``load.i16`` followed by ``uextend``.
""",
ins=(Flags, p, Offset), outs=a)
ins=(Flags, p, Offset), outs=a, can_load=True)
sload16 = Instruction(
'sload16', r"""
@@ -262,7 +262,7 @@ sload16 = Instruction(
This is equivalent to ``load.i16`` followed by ``uextend``.
""",
ins=(Flags, p, Offset), outs=a)
ins=(Flags, p, Offset), outs=a, can_load=True)
istore16 = Instruction(
'istore16', r"""
@@ -270,7 +270,7 @@ istore16 = Instruction(
This is equivalent to ``ireduce.i16`` followed by ``store.i8``.
""",
ins=(Flags, x, p, Offset))
ins=(Flags, x, p, Offset), can_store=True)
iExt32 = TypeVar(
'iExt32', 'An integer type with more than 32 bits',
@@ -284,7 +284,7 @@ uload32 = Instruction(
This is equivalent to ``load.i32`` followed by ``uextend``.
""",
ins=(Flags, p, Offset), outs=a)
ins=(Flags, p, Offset), outs=a, can_load=True)
sload32 = Instruction(
'sload32', r"""
@@ -292,7 +292,7 @@ sload32 = Instruction(
This is equivalent to ``load.i32`` followed by ``uextend``.
""",
ins=(Flags, p, Offset), outs=a)
ins=(Flags, p, Offset), outs=a, can_load=True)
istore32 = Instruction(
'istore32', r"""
@@ -300,7 +300,7 @@ istore32 = Instruction(
This is equivalent to ``ireduce.i32`` followed by ``store.i8``.
""",
ins=(Flags, x, p, Offset))
ins=(Flags, x, p, Offset), can_store=True)
x = Operand('x', Mem, doc='Value to be stored')
a = Operand('a', Mem, doc='Value loaded')
@@ -316,7 +316,7 @@ stack_load = Instruction(
access cannot go out of bounds, i.e.
:math:`sizeof(a) + Offset <= sizeof(SS)`.
""",
ins=(SS, Offset), outs=a)
ins=(SS, Offset), outs=a, can_load=True)
stack_store = Instruction(
'stack_store', r"""
@@ -329,7 +329,7 @@ stack_store = Instruction(
access cannot go out of bounds, i.e.
:math:`sizeof(a) + Offset <= sizeof(SS)`.
""",
ins=(x, SS, Offset))
ins=(x, SS, Offset), can_store=True)
stack_addr = Instruction(
'stack_addr', r"""
@@ -357,7 +357,7 @@ heap_load = Instruction(
Trap if the heap access would be out of bounds.
""",
ins=(p, Offset), outs=a)
ins=(p, Offset), outs=a, can_load=True)
heap_store = Instruction(
'heap_store', r"""
@@ -365,7 +365,7 @@ heap_store = Instruction(
Trap if the heap access would be out of bounds.
""",
ins=(x, p, Offset))
ins=(x, p, Offset), can_store=True)
heap_addr = Instruction(
'heap_addr', r"""

View File

@@ -85,6 +85,8 @@ class Instruction(object):
:param is_call: This is a call instruction.
:param is_return: This is a return instruction.
:param can_trap: This instruction can trap.
:param can_load: This instruction can load from memory.
:param can_store: This instruction can store to memory.
"""
# Boolean instruction attributes that can be passed as keyword arguments to
@@ -95,6 +97,8 @@ class Instruction(object):
'is_branch': 'True for all branch or jump instructions.',
'is_call': 'Is this a call instruction?',
'is_return': 'Is this a return instruction?',
'can_load': 'Can this instruction read from memory?',
'can_store': 'Can this instruction write to memory?',
'can_trap': 'Can this instruction cause a trap?',
}

View File

@@ -228,7 +228,7 @@ def gen_opcodes(groups, fmt):
fmt.doc_comment('An instruction opcode.')
fmt.doc_comment('')
fmt.doc_comment('All instructions from all supported ISAs are present.')
fmt.line('#[derive(Copy, Clone, PartialEq, Eq, Debug)]')
fmt.line('#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]')
instrs = []
# We explicitly set the discriminant of the first variant to 1, which