Tidy up whitespace.
This commit is contained in:
@@ -1699,7 +1699,7 @@ fpromote = Instruction(
|
|||||||
This is an exact operation.
|
This is an exact operation.
|
||||||
|
|
||||||
Cretonne currently only supports two floating point formats
|
Cretonne currently only supports two floating point formats
|
||||||
- :type:`f32` and :type:`f64`. This may change in the future.
|
- :type:`f32` and :type:`f64`. This may change in the future.
|
||||||
|
|
||||||
The result type must have the same number of vector lanes as the input,
|
The result type must have the same number of vector lanes as the input,
|
||||||
and the result lanes must not have fewer bits than the input lanes. If
|
and the result lanes must not have fewer bits than the input lanes. If
|
||||||
@@ -1715,10 +1715,10 @@ fdemote = Instruction(
|
|||||||
by rounding to nearest, ties to even.
|
by rounding to nearest, ties to even.
|
||||||
|
|
||||||
Cretonne currently only supports two floating point formats
|
Cretonne currently only supports two floating point formats
|
||||||
- :type:`f32` and :type:`f64`. This may change in the future.
|
- :type:`f32` and :type:`f64`. This may change in the future.
|
||||||
|
|
||||||
The result type must have the same number of vector lanes as the input,
|
The result type must have the same number of vector lanes as the input,
|
||||||
and the result lanes must not have more bits than the input lanes. If
|
and the result lanes must not have more bits than the input lanes. If
|
||||||
the input and output types are the same, this is a no-op.
|
the input and output types are the same, this is a no-op.
|
||||||
""",
|
""",
|
||||||
ins=x, outs=a, constraints=WiderOrEq(Float, FloatTo))
|
ins=x, outs=a, constraints=WiderOrEq(Float, FloatTo))
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ def check_concrete_typing_rtl(var_types, rtl):
|
|||||||
# type: (VarTyping, Rtl) -> None
|
# type: (VarTyping, Rtl) -> None
|
||||||
"""
|
"""
|
||||||
Check that a concrete type assignment var_types (Dict[Var, TypeVar]) is
|
Check that a concrete type assignment var_types (Dict[Var, TypeVar]) is
|
||||||
valid for an Rtl rtl. Specifically check that:
|
valid for an Rtl rtl. Specifically check that:
|
||||||
|
|
||||||
1) For each Var v \in rtl, v is defined in var_types
|
1) For each Var v \in rtl, v is defined in var_types
|
||||||
|
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ class TypeEnv(object):
|
|||||||
# type: (TypeVar, TypeVar) -> None
|
# type: (TypeVar, TypeVar) -> None
|
||||||
"""
|
"""
|
||||||
Record a that the free tv1 is part of the same equivalence class as
|
Record a that the free tv1 is part of the same equivalence class as
|
||||||
tv2. The canonical representative of the merged class is tv2's
|
tv2. The canonical representative of the merged class is tv2's
|
||||||
cannonical representative.
|
cannonical representative.
|
||||||
"""
|
"""
|
||||||
assert not tv1.is_derived
|
assert not tv1.is_derived
|
||||||
@@ -364,9 +364,9 @@ class TypeEnv(object):
|
|||||||
# type: (TypeVar) -> int
|
# type: (TypeVar) -> int
|
||||||
"""
|
"""
|
||||||
Get the rank of tv in the partial order. TVs directly associated with a
|
Get the rank of tv in the partial order. TVs directly associated with a
|
||||||
Var get their rank from the Var (see register()). Internally generated
|
Var get their rank from the Var (see register()). Internally generated
|
||||||
non-derived TVs implicitly get the lowest rank (0). Derived variables
|
non-derived TVs implicitly get the lowest rank (0). Derived variables
|
||||||
get their rank from their free typevar. Singletons have the highest
|
get their rank from their free typevar. Singletons have the highest
|
||||||
rank. TVs associated with vars in a source pattern have a higher rank
|
rank. TVs associated with vars in a source pattern have a higher rank
|
||||||
than TVs associted with temporary vars.
|
than TVs associted with temporary vars.
|
||||||
"""
|
"""
|
||||||
@@ -381,7 +381,7 @@ class TypeEnv(object):
|
|||||||
def register(self, v):
|
def register(self, v):
|
||||||
# type: (Var) -> None
|
# type: (Var) -> None
|
||||||
"""
|
"""
|
||||||
Register a new Var v. This computes a rank for the associated TypeVar
|
Register a new Var v. This computes a rank for the associated TypeVar
|
||||||
for v, which is used to impose a partial order on type variables.
|
for v, which is used to impose a partial order on type variables.
|
||||||
"""
|
"""
|
||||||
self.vars.add(v)
|
self.vars.add(v)
|
||||||
@@ -848,7 +848,7 @@ def ti_def(definition, typ):
|
|||||||
def ti_rtl(rtl, typ):
|
def ti_rtl(rtl, typ):
|
||||||
# type: (Rtl, TypeEnv) -> TypingOrError
|
# type: (Rtl, TypeEnv) -> TypingOrError
|
||||||
"""
|
"""
|
||||||
Perform type inference on an Rtl in a starting type env typ. Return an
|
Perform type inference on an Rtl in a starting type env typ. Return an
|
||||||
updated type environment or error.
|
updated type environment or error.
|
||||||
"""
|
"""
|
||||||
for (i, d) in enumerate(rtl.rtl):
|
for (i, d) in enumerate(rtl.rtl):
|
||||||
@@ -866,7 +866,7 @@ def ti_rtl(rtl, typ):
|
|||||||
def ti_xform(xform, typ):
|
def ti_xform(xform, typ):
|
||||||
# type: (XForm, TypeEnv) -> TypingOrError
|
# type: (XForm, TypeEnv) -> TypingOrError
|
||||||
"""
|
"""
|
||||||
Perform type inference on an Rtl in a starting type env typ. Return an
|
Perform type inference on an Rtl in a starting type env typ. Return an
|
||||||
updated type environment or error.
|
updated type environment or error.
|
||||||
"""
|
"""
|
||||||
typ_or_err = ti_rtl(xform.src, typ)
|
typ_or_err = ti_rtl(xform.src, typ)
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ class Rtl(object):
|
|||||||
# type: (Rtl) -> None
|
# type: (Rtl) -> None
|
||||||
"""
|
"""
|
||||||
Given that there is only 1 possible concrete typing T for self, assign
|
Given that there is only 1 possible concrete typing T for self, assign
|
||||||
a singleton TV with type t=T[v] for each Var v \in self. Its an error
|
a singleton TV with type t=T[v] for each Var v \in self. Its an error
|
||||||
to call this on an Rtl with more than 1 possible typing. This modifies
|
to call this on an Rtl with more than 1 possible typing. This modifies
|
||||||
the Rtl in-place.
|
the Rtl in-place.
|
||||||
"""
|
"""
|
||||||
from .ti import ti_rtl, TypeEnv
|
from .ti import ti_rtl, TypeEnv
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ def unwrap_inst(iref, node, fmt):
|
|||||||
fmt.format('let typeof_{0} = pos.func.dfg.value_type({0});', v)
|
fmt.format('let typeof_{0} = pos.func.dfg.value_type({0});', v)
|
||||||
|
|
||||||
# If the node has results, detach the values.
|
# If the node has results, detach the values.
|
||||||
# Place the values in locals.
|
# Place the values in locals.
|
||||||
replace_inst = False
|
replace_inst = False
|
||||||
if len(node.defs) > 0:
|
if len(node.defs) > 0:
|
||||||
if node.defs == node.defs[0].dst_def.defs:
|
if node.defs == node.defs[0].dst_def.defs:
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ rflags = Operand('rflags', iflags)
|
|||||||
bsr = Instruction(
|
bsr = Instruction(
|
||||||
'x86_bsr', r"""
|
'x86_bsr', r"""
|
||||||
Bit Scan Reverse -- returns the bit-index of the most significant 1
|
Bit Scan Reverse -- returns the bit-index of the most significant 1
|
||||||
in the word. Result is undefined if the argument is zero. However, it
|
in the word. Result is undefined if the argument is zero. However, it
|
||||||
sets the Z flag depending on the argument, so it is at least easy to
|
sets the Z flag depending on the argument, so it is at least easy to
|
||||||
detect and handle that case.
|
detect and handle that case.
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ bsr = Instruction(
|
|||||||
bsf = Instruction(
|
bsf = Instruction(
|
||||||
'x86_bsf', r"""
|
'x86_bsf', r"""
|
||||||
Bit Scan Forwards -- returns the bit-index of the least significant 1
|
Bit Scan Forwards -- returns the bit-index of the least significant 1
|
||||||
in the word. Is otherwise identical to 'bsr', just above.
|
in the word. Is otherwise identical to 'bsr', just above.
|
||||||
""",
|
""",
|
||||||
ins=x, outs=(y, rflags))
|
ins=x, outs=(y, rflags))
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ def verify_semantics(inst, src, xforms):
|
|||||||
# type: (Instruction, Rtl, InstructionSemantics) -> None
|
# type: (Instruction, Rtl, InstructionSemantics) -> None
|
||||||
"""
|
"""
|
||||||
Verify that the semantics transforms in xforms correctly describe the
|
Verify that the semantics transforms in xforms correctly describe the
|
||||||
instruction described by the src Rtl. This involves checking that:
|
instruction described by the src Rtl. This involves checking that:
|
||||||
0) src is a single instance of inst
|
0) src is a single instance of inst
|
||||||
1) For all x\in xforms x.src is a single instance of inst
|
1) For all x\in xforms x.src is a single instance of inst
|
||||||
2) For any concrete values V of Literals in inst:
|
2) For any concrete values V of Literals in inst:
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ impl<F: Forest> Path<F> {
|
|||||||
fn split_and_insert(&mut self, mut key: F::Key, value: F::Value, pool: &mut NodePool<F>) {
|
fn split_and_insert(&mut self, mut key: F::Key, value: F::Value, pool: &mut NodePool<F>) {
|
||||||
let orig_root = self.node[0];
|
let orig_root = self.node[0];
|
||||||
|
|
||||||
// Loop invariant: We need to split the node at `level` and then retry a failed insertion.
|
// Loop invariant: We need to split the node at `level` and then retry a failed insertion.
|
||||||
// The items to insert are either `(key, ins_node)` or `(key, value)`.
|
// The items to insert are either `(key, ins_node)` or `(key, value)`.
|
||||||
let mut ins_node = None;
|
let mut ins_node = None;
|
||||||
let mut split;
|
let mut split;
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Math helpers for division by (non-power-of-2) constants. This is based
|
// Math helpers for division by (non-power-of-2) constants. This is based
|
||||||
// on the presentation in "Hacker's Delight" by Henry Warren, 2003. There
|
// on the presentation in "Hacker's Delight" by Henry Warren, 2003. There
|
||||||
// are four cases: {unsigned, signed} x {32 bit, 64 bit}. The word size
|
// are four cases: {unsigned, signed} x {32 bit, 64 bit}. The word size
|
||||||
// makes little difference, but the signed-vs-unsigned aspect has a large
|
// makes little difference, but the signed-vs-unsigned aspect has a large
|
||||||
// effect. Therefore everything is presented in the order U32 U64 S32 S64
|
// effect. Therefore everything is presented in the order U32 U64 S32 S64
|
||||||
// so as to emphasise the similarity of the U32 and U64 cases and the S32
|
// so as to emphasise the similarity of the U32 and U64 cases and the S32
|
||||||
// and S64 cases.
|
// and S64 cases.
|
||||||
|
|
||||||
@@ -478,7 +478,7 @@ mod tests {
|
|||||||
fn test_magic_generators_dont_panic() {
|
fn test_magic_generators_dont_panic() {
|
||||||
// The point of this is to check that the magic number generators
|
// The point of this is to check that the magic number generators
|
||||||
// don't panic with integer wraparounds, especially at boundary
|
// don't panic with integer wraparounds, especially at boundary
|
||||||
// cases for their arguments. The actual results are thrown away.
|
// cases for their arguments. The actual results are thrown away.
|
||||||
let mut total: u64 = 0;
|
let mut total: u64 = 0;
|
||||||
println!("Testing UP magicU32");
|
println!("Testing UP magicU32");
|
||||||
for x in 2..(200 * 1000u32) {
|
for x in 2..(200 * 1000u32) {
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ where
|
|||||||
// We theoretically allow for call instructions that return a number of fixed results before
|
// We theoretically allow for call instructions that return a number of fixed results before
|
||||||
// the call return values. In practice, it doesn't happen.
|
// the call return values. In practice, it doesn't happen.
|
||||||
let fixed_results = pos.func.dfg[call].opcode().constraints().fixed_results();
|
let fixed_results = pos.func.dfg[call].opcode().constraints().fixed_results();
|
||||||
assert_eq!(fixed_results, 0, "Fixed results on calls not supported");
|
assert_eq!(fixed_results, 0, "Fixed results on calls not supported");
|
||||||
|
|
||||||
let results = pos.func.dfg.detach_results(call);
|
let results = pos.func.dfg.detach_results(call);
|
||||||
let mut next_res = 0;
|
let mut next_res = 0;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use timing;
|
|||||||
// Simple math helpers
|
// Simple math helpers
|
||||||
|
|
||||||
// if `x` is a power of two, or the negation thereof, return the power along
|
// if `x` is a power of two, or the negation thereof, return the power along
|
||||||
// with a boolean that indicates whether `x` is negative. Else return None.
|
// with a boolean that indicates whether `x` is negative. Else return None.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn isPowerOf2_S32(x: i32) -> Option<(bool, u32)> {
|
fn isPowerOf2_S32(x: i32) -> Option<(bool, u32)> {
|
||||||
// We have to special-case this because abs(x) isn't representable.
|
// We have to special-case this because abs(x) isn't representable.
|
||||||
@@ -128,10 +128,10 @@ fn get_div_info(inst: Inst, dfg: &DataFlowGraph) -> Option<DivRemByConstInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: should we actually bother to do this (that is, manually match
|
// TODO: should we actually bother to do this (that is, manually match
|
||||||
// the case that the second argument is an iconst)? Or should we assume
|
// the case that the second argument is an iconst)? Or should we assume
|
||||||
// that some previous constant propagation pass has pushed all such
|
// that some previous constant propagation pass has pushed all such
|
||||||
// immediates to their use points, creating BinaryImm instructions
|
// immediates to their use points, creating BinaryImm instructions
|
||||||
// instead? For now we take the conservative approach.
|
// instead? For now we take the conservative approach.
|
||||||
if let &InstructionData::Binary { opcode, args } = idata {
|
if let &InstructionData::Binary { opcode, args } = idata {
|
||||||
let (isSigned, isRem) = match opcode {
|
let (isSigned, isRem) = match opcode {
|
||||||
Opcode::Udiv => (false, false),
|
Opcode::Udiv => (false, false),
|
||||||
@@ -153,10 +153,10 @@ fn get_div_info(inst: Inst, dfg: &DataFlowGraph) -> Option<DivRemByConstInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actually do the transformation given a bundle containing the relevant
|
// Actually do the transformation given a bundle containing the relevant
|
||||||
// information. `divrem_info` describes a div or rem by a constant, that
|
// information. `divrem_info` describes a div or rem by a constant, that
|
||||||
// `pos` currently points at, and `inst` is the associated instruction.
|
// `pos` currently points at, and `inst` is the associated instruction.
|
||||||
// `inst` is replaced by a sequence of other operations that calculate the
|
// `inst` is replaced by a sequence of other operations that calculate the
|
||||||
// same result. Note that there are various `divrem_info` cases where we
|
// same result. Note that there are various `divrem_info` cases where we
|
||||||
// cannot do any transformation, in which case `inst` is left unchanged.
|
// cannot do any transformation, in which case `inst` is left unchanged.
|
||||||
fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCursor, inst: Inst) {
|
fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCursor, inst: Inst) {
|
||||||
let isRem = match *divrem_info {
|
let isRem = match *divrem_info {
|
||||||
@@ -234,7 +234,7 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso
|
|||||||
qf = q1;
|
qf = q1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Now qf holds the final quotient. If necessary calculate the
|
// Now qf holds the final quotient. If necessary calculate the
|
||||||
// remainder instead.
|
// remainder instead.
|
||||||
if isRem {
|
if isRem {
|
||||||
let tt = pos.ins().imul_imm(qf, d as i64);
|
let tt = pos.ins().imul_imm(qf, d as i64);
|
||||||
@@ -306,7 +306,7 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso
|
|||||||
qf = q1;
|
qf = q1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Now qf holds the final quotient. If necessary calculate the
|
// Now qf holds the final quotient. If necessary calculate the
|
||||||
// remainder instead.
|
// remainder instead.
|
||||||
if isRem {
|
if isRem {
|
||||||
let tt = pos.ins().imul_imm(qf, d as i64);
|
let tt = pos.ins().imul_imm(qf, d as i64);
|
||||||
@@ -382,7 +382,7 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso
|
|||||||
};
|
};
|
||||||
let t1 = pos.ins().ushr_imm(q3, 31);
|
let t1 = pos.ins().ushr_imm(q3, 31);
|
||||||
let qf = pos.ins().iadd(q3, t1);
|
let qf = pos.ins().iadd(q3, t1);
|
||||||
// Now qf holds the final quotient. If necessary calculate
|
// Now qf holds the final quotient. If necessary calculate
|
||||||
// the remainder instead.
|
// the remainder instead.
|
||||||
if isRem {
|
if isRem {
|
||||||
let tt = pos.ins().imul_imm(qf, d as i64);
|
let tt = pos.ins().imul_imm(qf, d as i64);
|
||||||
@@ -459,7 +459,7 @@ fn do_divrem_transformation(divrem_info: &DivRemByConstInfo, pos: &mut FuncCurso
|
|||||||
};
|
};
|
||||||
let t1 = pos.ins().ushr_imm(q3, 63);
|
let t1 = pos.ins().ushr_imm(q3, 63);
|
||||||
let qf = pos.ins().iadd(q3, t1);
|
let qf = pos.ins().iadd(q3, t1);
|
||||||
// Now qf holds the final quotient. If necessary calculate
|
// Now qf holds the final quotient. If necessary calculate
|
||||||
// the remainder instead.
|
// the remainder instead.
|
||||||
if isRem {
|
if isRem {
|
||||||
let tt = pos.ins().imul_imm(qf, d);
|
let tt = pos.ins().imul_imm(qf, d);
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/********************************* Stack misc ***************************************
|
/********************************* Stack misc ***************************************
|
||||||
* `drop`, `nop`, `unreachable` and `select`.
|
* `drop`, `nop`, `unreachable` and `select`.
|
||||||
***********************************************************************************/
|
***********************************************************************************/
|
||||||
Operator::Drop => {
|
Operator::Drop => {
|
||||||
state.pop1();
|
state.pop1();
|
||||||
|
|||||||
Reference in New Issue
Block a user