Make GVN aware of instructions that write to CPU flags.
This commit is contained in:
@@ -23,3 +23,19 @@ ebb0:
|
|||||||
v5 = iadd v4, v3
|
v5 = iadd v4, v3
|
||||||
return v5
|
return v5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function %cpu_flags() -> b1 {
|
||||||
|
ebb0:
|
||||||
|
v0 = iconst.i32 7
|
||||||
|
v1 = iconst.i32 8
|
||||||
|
v2 = ifcmp v0, v1
|
||||||
|
v3 = trueif eq v2
|
||||||
|
v4 = ifcmp v0, v1
|
||||||
|
v5 = trueif eq v4
|
||||||
|
v6 = bor v3, v5
|
||||||
|
; check: v2 = ifcmp v0, v1
|
||||||
|
; check: v3 = trueif eq v2
|
||||||
|
; check: v4 = ifcmp v0, v1
|
||||||
|
; check: v5 = trueif eq v4
|
||||||
|
return v6
|
||||||
|
}
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ class Instruction(object):
|
|||||||
'can_trap': 'Can this instruction cause a trap?',
|
'can_trap': 'Can this instruction cause a trap?',
|
||||||
'other_side_effects':
|
'other_side_effects':
|
||||||
'Does this instruction have other side effects besides can_*',
|
'Does this instruction have other side effects besides can_*',
|
||||||
|
'writes_cpu_flags': 'Does this instruction write to CPU flags?',
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, name, doc, ins=(), outs=(), constraints=(), **kwargs):
|
def __init__(self, name, doc, ins=(), outs=(), constraints=(), **kwargs):
|
||||||
@@ -144,6 +145,10 @@ class Instruction(object):
|
|||||||
"unknown instruction attribute '" + attr + "'")
|
"unknown instruction attribute '" + attr + "'")
|
||||||
for attr in Instruction.ATTRIBS:
|
for attr in Instruction.ATTRIBS:
|
||||||
setattr(self, attr, not not kwargs.get(attr, False))
|
setattr(self, attr, not not kwargs.get(attr, False))
|
||||||
|
|
||||||
|
# Infer the 'writes_cpu_flags' field value.
|
||||||
|
setattr(self, 'writes_cpu_flags', any(out.is_cpu_flags() for out in self.outs))
|
||||||
|
|
||||||
InstructionGroup.append(self)
|
InstructionGroup.append(self)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|||||||
@@ -242,3 +242,10 @@ class Operand(object):
|
|||||||
dependency.
|
dependency.
|
||||||
"""
|
"""
|
||||||
return self.kind is not VALUE and self.kind is not VARIABLE_ARGS
|
return self.kind is not VALUE and self.kind is not VARIABLE_ARGS
|
||||||
|
|
||||||
|
def is_cpu_flags(self):
|
||||||
|
# type: () -> bool
|
||||||
|
"""
|
||||||
|
Is this a CPU flags operand?
|
||||||
|
"""
|
||||||
|
return self.kind is VALUE and self.typevar.name in ['iflags', 'fflags']
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use scoped_hash_map::ScopedHashMap;
|
|||||||
fn trivially_unsafe_for_gvn(opcode: Opcode) -> bool {
|
fn trivially_unsafe_for_gvn(opcode: Opcode) -> bool {
|
||||||
opcode.is_call() || opcode.is_branch() || opcode.is_terminator() ||
|
opcode.is_call() || opcode.is_branch() || opcode.is_terminator() ||
|
||||||
opcode.is_return() || opcode.can_trap() || opcode.other_side_effects() ||
|
opcode.is_return() || opcode.can_trap() || opcode.other_side_effects() ||
|
||||||
opcode.can_store() || opcode.can_load()
|
opcode.can_store() || opcode.can_load() || opcode.writes_cpu_flags()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform simple GVN on `func`.
|
/// Perform simple GVN on `func`.
|
||||||
|
|||||||
Reference in New Issue
Block a user