Missed Optimization in numeric code
In functions like the once below the two negation operations can be safely eliminated. The optimization is valid for all integer and floating point types. The same story is of course true for division.
f_int_1 :: Int -> Int -> Int
f_int_1 x y = (- x) * (-y)
f_double_1 :: Double -> Double -> Double
f_double_1 x y = (- x) * (- y)
Right now we produce:
f_int_1
= \ (x_a2tn :: Int) (y_a2to :: Int) ->
case x_a2tn of { GHC.Types.I# x1_i2ve ->
case y_a2to of { GHC.Types.I# x2_X2vE ->
GHC.Types.I#
(GHC.Prim.*#
(GHC.Prim.negateInt# x1_i2ve) (GHC.Prim.negateInt# x2_X2vE))
}
}
f_double_1
= \ (x_a2tq :: Double) (y_a2tr :: Double) ->
case x_a2tq of { GHC.Types.D# x1_a2vt ->
case y_a2tr of { GHC.Types.D# x2_X2vV ->
GHC.Types.D#
(GHC.Prim.*##
(GHC.Prim.negateDouble# x1_a2vt) (GHC.Prim.negateDouble# x2_X2vV))
}
}
Moreover for the following two functions we could be (at compile time) removing the negation from the variable and pushing it into the constant:
f_int_2 :: Int -> Int
f_int_2 x = 3 * (-x)
f_double_2 :: Double -> Double
f_double_2 x = 3.0 * (-x)
we should be transforming these into:
f_int_2 :: Int -> Int
f_int_2 x = -3 * x
f_double_2 :: Double -> Double
f_double_2 x = -3.0 * x