diff --git a/src/ssa/BinaryOp.go b/src/ssa/BinaryOp.go index dc55a44..2ba4887 100644 --- a/src/ssa/BinaryOp.go +++ b/src/ssa/BinaryOp.go @@ -28,7 +28,11 @@ func (a *BinaryOp) Equals(v Value) bool { return false } - return a.Left.Equals(b.Left) && a.Right.Equals(b.Right) + if a.Left.Equals(b.Left) && a.Right.Equals(b.Right) { + return true + } + + return a.IsCommutative() && a.Left.Equals(b.Right) && a.Right.Equals(b.Left) } // Inputs returns the left and right operands. @@ -36,6 +40,16 @@ func (op *BinaryOp) Inputs() []Value { return []Value{op.Left, op.Right} } +// IsCommutative returns true if changing the order of the operands does not change the result. +func (op *BinaryOp) IsCommutative() bool { + switch op.Op { + case token.Add, token.Mul, token.And, token.Or, token.Xor, token.LogicalAnd, token.LogicalOr, token.Equal, token.NotEqual: + return true + default: + return false + } +} + // IsPure returns true if both operands are constant. func (op *BinaryOp) IsPure() bool { return op.Left.IsPure() && op.Right.IsPure() diff --git a/tests/commutativity.q b/tests/commutativity.q new file mode 100644 index 0000000..2b67baf --- /dev/null +++ b/tests/commutativity.q @@ -0,0 +1,21 @@ +main() { + loop a := -10..10 { + loop b := -10..10 { + x := a + b + y := b + a + assert x == y + x = a * b + y = b * a + assert x == y + x = a & b + y = b & a + assert x == y + x = a | b + y = b | a + assert x == y + x = a ^ b + y = b ^ a + assert x == y + } + } +} \ No newline at end of file diff --git a/tests/tests_test.go b/tests/tests_test.go index f39fb31..74b3a31 100644 --- a/tests/tests_test.go +++ b/tests/tests_test.go @@ -77,6 +77,7 @@ var tests = []run{ {"loop-nested-xy", nil, "", "0,0\n0,1\n0,2\n1,0\n1,1\n1,2\n2,0\n2,1\n2,2\n", 0}, {"loop-nested-xyz", nil, "", "0,0,0\n0,0,1\n0,0,2\n0,1,0\n0,1,1\n0,1,2\n0,2,0\n0,2,1\n0,2,2\n1,0,0\n1,0,1\n1,0,2\n1,1,0\n1,1,1\n1,1,2\n1,2,0\n1,2,1\n1,2,2\n2,0,0\n2,0,1\n2,0,2\n2,1,0\n2,1,1\n2,1,2\n2,2,0\n2,2,1\n2,2,2\n", 0}, {"loop-nested-return", nil, "", "..........", 0}, + {"commutativity", nil, "", "", 0}, {"factorial", nil, "", "", 0}, {"fibonacci", nil, "", "", 0}, {"memory", nil, "", "Hello\n", 0},