module GHC.Cmm.Opt (
constantFoldNode,
constantFoldExpr,
cmmMachOpFold,
cmmMachOpFoldM
) where
import GHC.Prelude
import GHC.Cmm.Utils
import GHC.Cmm
import GHC.Utils.Misc
import GHC.Utils.Panic
import GHC.Platform
import Data.Maybe
constantFoldNode :: Platform -> CmmNode e x -> CmmNode e x
constantFoldNode :: forall (e :: Extensibility) (x :: Extensibility).
Platform -> CmmNode e x -> CmmNode e x
constantFoldNode Platform
platform = (CmmExpr -> CmmExpr) -> CmmNode e x -> CmmNode e x
forall (e :: Extensibility) (x :: Extensibility).
(CmmExpr -> CmmExpr) -> CmmNode e x -> CmmNode e x
mapExp (Platform -> CmmExpr -> CmmExpr
constantFoldExpr Platform
platform)
constantFoldExpr :: Platform -> CmmExpr -> CmmExpr
constantFoldExpr :: Platform -> CmmExpr -> CmmExpr
constantFoldExpr Platform
platform = (CmmExpr -> CmmExpr) -> CmmExpr -> CmmExpr
wrapRecExp CmmExpr -> CmmExpr
f
where f :: CmmExpr -> CmmExpr
f (CmmMachOp MachOp
op [CmmExpr]
args) = Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform MachOp
op [CmmExpr]
args
f (CmmRegOff CmmReg
r Int
0) = CmmReg -> CmmExpr
CmmReg CmmReg
r
f CmmExpr
e = CmmExpr
e
cmmMachOpFold
:: Platform
-> MachOp
-> [CmmExpr]
-> CmmExpr
cmmMachOpFold :: Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform MachOp
op [CmmExpr]
args = CmmExpr -> Maybe CmmExpr -> CmmExpr
forall a. a -> Maybe a -> a
fromMaybe (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp MachOp
op [CmmExpr]
args) (Platform -> MachOp -> [CmmExpr] -> Maybe CmmExpr
cmmMachOpFoldM Platform
platform MachOp
op [CmmExpr]
args)
cmmMachOpFoldM
:: Platform
-> MachOp
-> [CmmExpr]
-> Maybe CmmExpr
cmmMachOpFoldM :: Platform -> MachOp -> [CmmExpr] -> Maybe CmmExpr
cmmMachOpFoldM Platform
_ MachOp
op [CmmLit (CmmInt Integer
x Width
rep)]
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! case MachOp
op of
MO_S_Neg Width
_ -> CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (-Integer
x) Width
rep)
MO_Not Width
_ -> CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer -> Integer
forall a. Bits a => a -> a
complement Integer
x) Width
rep)
MO_SF_Conv Width
_from Width
to -> CmmLit -> CmmExpr
CmmLit (Rational -> Width -> CmmLit
CmmFloat (Integer -> Rational
forall a. Num a => Integer -> a
fromInteger Integer
x) Width
to)
MO_SS_Conv Width
from Width
to -> CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Width -> Integer -> Integer
narrowS Width
from Integer
x) Width
to)
MO_UU_Conv Width
from Width
to -> CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Width -> Integer -> Integer
narrowU Width
from Integer
x) Width
to)
MO_XX_Conv Width
from Width
to -> CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Width -> Integer -> Integer
narrowS Width
from Integer
x) Width
to)
MachOp
_ -> String -> CmmExpr
forall a. HasCallStack => String -> a
panic (String -> CmmExpr) -> String -> CmmExpr
forall a b. (a -> b) -> a -> b
$ String
"cmmMachOpFoldM: unknown unary op: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ MachOp -> String
forall a. Show a => a -> String
show MachOp
op
cmmMachOpFoldM Platform
_ MachOp
op [CmmExpr
_shiftee, CmmLit (CmmInt Integer
shift Width
_)]
| Just Width
width <- MachOp -> Maybe Width
isShift MachOp
op
, Integer
shift Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Int
widthInBits Width
width)
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
0 Width
width)
where
isShift :: MachOp -> Maybe Width
isShift (MO_Shl Width
w) = Width -> Maybe Width
forall a. a -> Maybe a
Just Width
w
isShift (MO_U_Shr Width
w) = Width -> Maybe Width
forall a. a -> Maybe a
Just Width
w
isShift (MO_S_Shr Width
w) = Width -> Maybe Width
forall a. a -> Maybe a
Just Width
w
isShift MachOp
_ = Maybe Width
forall a. Maybe a
Nothing
cmmMachOpFoldM Platform
_ (MO_SS_Conv Width
rep1 Width
rep2) [CmmExpr
x] | Width
rep1 Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
rep2 = CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
cmmMachOpFoldM Platform
_ (MO_UU_Conv Width
rep1 Width
rep2) [CmmExpr
x] | Width
rep1 Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
rep2 = CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
cmmMachOpFoldM Platform
_ (MO_XX_Conv Width
rep1 Width
rep2) [CmmExpr
x] | Width
rep1 Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
rep2 = CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
cmmMachOpFoldM Platform
platform MachOp
conv_outer [CmmMachOp MachOp
conv_inner [CmmExpr
x]]
| Just (Width
rep1,Width
rep2,Bool
signed1) <- MachOp -> Maybe (Width, Width, Bool)
isIntConversion MachOp
conv_inner,
Just (Width
_, Width
rep3,Bool
signed2) <- MachOp -> Maybe (Width, Width, Bool)
isIntConversion MachOp
conv_outer
= case () of
()
_ | Width
rep1 Width -> Width -> Bool
forall a. Ord a => a -> a -> Bool
< Width
rep2 Bool -> Bool -> Bool
&& Width
rep1 Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
rep3 -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
| Width
rep1 Width -> Width -> Bool
forall a. Ord a => a -> a -> Bool
< Width
rep2 Bool -> Bool -> Bool
&& Width
rep2 Width -> Width -> Bool
forall a. Ord a => a -> a -> Bool
> Width
rep3 ->
CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform (Bool -> Width -> Width -> MachOp
intconv Bool
signed1 Width
rep1 Width
rep3) [CmmExpr
x]
| Width
rep1 Width -> Width -> Bool
forall a. Ord a => a -> a -> Bool
< Width
rep2 Bool -> Bool -> Bool
&& Width
rep2 Width -> Width -> Bool
forall a. Ord a => a -> a -> Bool
< Width
rep3 Bool -> Bool -> Bool
&& Bool
signed1 Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
signed2 ->
CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform (Bool -> Width -> Width -> MachOp
intconv Bool
signed1 Width
rep1 Width
rep3) [CmmExpr
x]
| Width
rep1 Width -> Width -> Bool
forall a. Ord a => a -> a -> Bool
> Width
rep2 Bool -> Bool -> Bool
&& Width
rep2 Width -> Width -> Bool
forall a. Ord a => a -> a -> Bool
> Width
rep3 ->
CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform (Width -> Width -> MachOp
MO_UU_Conv Width
rep1 Width
rep3) [CmmExpr
x]
| Bool
otherwise ->
Maybe CmmExpr
forall a. Maybe a
Nothing
where
isIntConversion :: MachOp -> Maybe (Width, Width, Bool)
isIntConversion (MO_UU_Conv Width
rep1 Width
rep2)
= (Width, Width, Bool) -> Maybe (Width, Width, Bool)
forall a. a -> Maybe a
Just (Width
rep1,Width
rep2,Bool
False)
isIntConversion (MO_SS_Conv Width
rep1 Width
rep2)
= (Width, Width, Bool) -> Maybe (Width, Width, Bool)
forall a. a -> Maybe a
Just (Width
rep1,Width
rep2,Bool
True)
isIntConversion MachOp
_ = Maybe (Width, Width, Bool)
forall a. Maybe a
Nothing
intconv :: Bool -> Width -> Width -> MachOp
intconv Bool
True = Width -> Width -> MachOp
MO_SS_Conv
intconv Bool
False = Width -> Width -> MachOp
MO_UU_Conv
cmmMachOpFoldM Platform
platform MachOp
mop [CmmLit (CmmInt Integer
x Width
xrep), CmmLit (CmmInt Integer
y Width
_)]
= case MachOp
mop of
MO_Eq Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (if Integer
x_u Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
y_u then Integer
1 else Integer
0) (Platform -> Width
wordWidth Platform
platform))
MO_Ne Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (if Integer
x_u Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer
y_u then Integer
1 else Integer
0) (Platform -> Width
wordWidth Platform
platform))
MO_U_Gt Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (if Integer
x_u Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
y_u then Integer
1 else Integer
0) (Platform -> Width
wordWidth Platform
platform))
MO_U_Ge Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (if Integer
x_u Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
y_u then Integer
1 else Integer
0) (Platform -> Width
wordWidth Platform
platform))
MO_U_Lt Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (if Integer
x_u Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
y_u then Integer
1 else Integer
0) (Platform -> Width
wordWidth Platform
platform))
MO_U_Le Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (if Integer
x_u Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
y_u then Integer
1 else Integer
0) (Platform -> Width
wordWidth Platform
platform))
MO_S_Gt Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (if Integer
x_s Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
y_s then Integer
1 else Integer
0) (Platform -> Width
wordWidth Platform
platform))
MO_S_Ge Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (if Integer
x_s Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
y_s then Integer
1 else Integer
0) (Platform -> Width
wordWidth Platform
platform))
MO_S_Lt Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (if Integer
x_s Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
y_s then Integer
1 else Integer
0) (Platform -> Width
wordWidth Platform
platform))
MO_S_Le Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (if Integer
x_s Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
y_s then Integer
1 else Integer
0) (Platform -> Width
wordWidth Platform
platform))
MO_Add Width
r -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
y) Width
r)
MO_Sub Width
r -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
y) Width
r)
MO_Mul Width
r -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
y) Width
r)
MO_U_Quot Width
r | Integer
y Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer
0 -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x_u Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`quot` Integer
y_u) Width
r)
MO_U_Rem Width
r | Integer
y Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer
0 -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x_u Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`rem` Integer
y_u) Width
r)
MO_S_Quot Width
r | Integer
y Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer
0 -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x_s Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`quot` Integer
y_s) Width
r)
MO_S_Rem Width
r | Integer
y Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer
0 -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x_s Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`rem` Integer
y_s) Width
r)
MO_And Width
r -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
.&. Integer
y) Width
r)
MO_Or Width
r -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
.|. Integer
y) Width
r)
MO_Xor Width
r -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
`xor` Integer
y) Width
r)
MO_Shl Width
r -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`shiftL` Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
y) Width
r)
MO_U_Shr Width
r -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x_u Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`shiftR` Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
y) Width
r)
MO_S_Shr Width
r -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
x_s Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`shiftR` Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
y) Width
r)
MachOp
_ -> Maybe CmmExpr
forall a. Maybe a
Nothing
where
x_u :: Integer
x_u = Width -> Integer -> Integer
narrowU Width
xrep Integer
x
y_u :: Integer
y_u = Width -> Integer -> Integer
narrowU Width
xrep Integer
y
x_s :: Integer
x_s = Width -> Integer -> Integer
narrowS Width
xrep Integer
x
y_s :: Integer
y_s = Width -> Integer -> Integer
narrowS Width
xrep Integer
y
cmmMachOpFoldM Platform
platform MachOp
op [x :: CmmExpr
x@(CmmLit CmmLit
_), CmmExpr
y]
| Bool -> Bool
not (CmmExpr -> Bool
isLit CmmExpr
y) Bool -> Bool -> Bool
&& MachOp -> Bool
isCommutableMachOp MachOp
op
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! (Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform MachOp
op [CmmExpr
y, CmmExpr
x])
cmmMachOpFoldM Platform
platform MachOp
mop1 [CmmMachOp MachOp
mop2 [CmmExpr
arg1,CmmExpr
arg2], CmmExpr
arg3]
| MachOp
mop2 MachOp -> MachOp -> Bool
`associates_with` MachOp
mop1
Bool -> Bool -> Bool
&& Bool -> Bool
not (CmmExpr -> Bool
isLit CmmExpr
arg1) Bool -> Bool -> Bool
&& Bool -> Bool
not (CmmExpr -> Bool
isPicReg CmmExpr
arg1)
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! (Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform MachOp
mop2 [CmmExpr
arg1, Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform MachOp
mop1 [CmmExpr
arg2,CmmExpr
arg3]])
where
MO_Add{} associates_with :: MachOp -> MachOp -> Bool
`associates_with` MO_Sub{} = Bool
True
MachOp
mop1 `associates_with` MachOp
mop2 =
MachOp
mop1 MachOp -> MachOp -> Bool
forall a. Eq a => a -> a -> Bool
== MachOp
mop2 Bool -> Bool -> Bool
&& MachOp -> Bool
isAssociativeMachOp MachOp
mop1
cmmMachOpFoldM Platform
platform mop1 :: MachOp
mop1@(MO_Add{}) [CmmMachOp mop2 :: MachOp
mop2@(MO_Sub{}) [CmmExpr
arg1,CmmExpr
arg2], CmmExpr
arg3]
| Bool -> Bool
not (CmmExpr -> Bool
isLit CmmExpr
arg1) Bool -> Bool -> Bool
&& Bool -> Bool
not (CmmExpr -> Bool
isPicReg CmmExpr
arg1)
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! (Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform MachOp
mop1 [CmmExpr
arg1, Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform MachOp
mop2 [CmmExpr
arg3,CmmExpr
arg2]])
cmmMachOpFoldM Platform
_ MO_Add{} [ CmmMachOp op :: MachOp
op@MO_Add{} [CmmExpr
pic, CmmLit CmmLit
lit]
, CmmLit (CmmInt Integer
n Width
rep) ]
| CmmExpr -> Bool
isPicReg CmmExpr
pic
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp MachOp
op [CmmExpr
pic, CmmLit -> CmmExpr
CmmLit (CmmLit -> CmmExpr) -> CmmLit -> CmmExpr
forall a b. (a -> b) -> a -> b
$ CmmLit -> Int -> CmmLit
cmmOffsetLit CmmLit
lit Int
off ]
where off :: Int
off = Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Integer -> Integer
narrowS Width
rep Integer
n)
cmmMachOpFoldM Platform
_ (MO_Add Width
_) [CmmReg CmmReg
reg, CmmLit (CmmInt Integer
n Width
rep)]
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmReg -> Int -> CmmExpr
cmmRegOff CmmReg
reg (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Integer -> Integer
narrowS Width
rep Integer
n))
cmmMachOpFoldM Platform
_ (MO_Add Width
_) [CmmRegOff CmmReg
reg Int
off, CmmLit (CmmInt Integer
n Width
rep)]
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmReg -> Int -> CmmExpr
cmmRegOff CmmReg
reg (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Integer -> Integer
narrowS Width
rep Integer
n))
cmmMachOpFoldM Platform
_ (MO_Sub Width
_) [CmmReg CmmReg
reg, CmmLit (CmmInt Integer
n Width
rep)]
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmReg -> Int -> CmmExpr
cmmRegOff CmmReg
reg (- Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Integer -> Integer
narrowS Width
rep Integer
n))
cmmMachOpFoldM Platform
_ (MO_Sub Width
_) [CmmRegOff CmmReg
reg Int
off, CmmLit (CmmInt Integer
n Width
rep)]
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmReg -> Int -> CmmExpr
cmmRegOff CmmReg
reg (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
- Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Integer -> Integer
narrowS Width
rep Integer
n))
cmmMachOpFoldM Platform
_ (MO_Add Width
_) [CmmLit CmmLit
lit, CmmLit (CmmInt Integer
i Width
rep)]
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (CmmLit -> Int -> CmmLit
cmmOffsetLit CmmLit
lit (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Integer -> Integer
narrowU Width
rep Integer
i)))
cmmMachOpFoldM Platform
_ (MO_Add Width
_) [CmmLit (CmmInt Integer
i Width
rep), CmmLit CmmLit
lit]
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (CmmLit -> Int -> CmmLit
cmmOffsetLit CmmLit
lit (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Integer -> Integer
narrowU Width
rep Integer
i)))
cmmMachOpFoldM Platform
_ (MO_Sub Width
_) [CmmLit CmmLit
lit, CmmLit (CmmInt Integer
i Width
rep)]
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (CmmLit -> Int -> CmmLit
cmmOffsetLit CmmLit
lit (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Integer
forall a. Num a => a -> a
negate (Width -> Integer -> Integer
narrowU Width
rep Integer
i))))
cmmMachOpFoldM Platform
platform MachOp
cmp [CmmMachOp MachOp
conv [CmmExpr
x], CmmLit (CmmInt Integer
i Width
_)]
|
Platform -> Arch
platformArch Platform
platform Arch -> [Arch] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Arch
ArchX86, Arch
ArchX86_64],
Just (Width
rep, Bool
signed, Width -> Integer -> Integer
narrow_fn) <- MachOp -> Maybe (Width, Bool, Width -> Integer -> Integer)
maybe_conversion MachOp
conv,
Just MachOp
narrow_cmp <- MachOp -> Width -> Bool -> Maybe MachOp
maybe_comparison MachOp
cmp Width
rep Bool
signed,
Integer
i Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Width -> Integer -> Integer
narrow_fn Width
rep Integer
i
= CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! (Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform MachOp
narrow_cmp [CmmExpr
x, CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
i Width
rep)])
where
maybe_conversion :: MachOp -> Maybe (Width, Bool, Width -> Integer -> Integer)
maybe_conversion (MO_UU_Conv Width
from Width
to)
| Width
to Width -> Width -> Bool
forall a. Ord a => a -> a -> Bool
> Width
from
= (Width, Bool, Width -> Integer -> Integer)
-> Maybe (Width, Bool, Width -> Integer -> Integer)
forall a. a -> Maybe a
Just (Width
from, Bool
False, Width -> Integer -> Integer
narrowU)
maybe_conversion (MO_SS_Conv Width
from Width
to)
| Width
to Width -> Width -> Bool
forall a. Ord a => a -> a -> Bool
> Width
from
= (Width, Bool, Width -> Integer -> Integer)
-> Maybe (Width, Bool, Width -> Integer -> Integer)
forall a. a -> Maybe a
Just (Width
from, Bool
True, Width -> Integer -> Integer
narrowS)
maybe_conversion MachOp
_ = Maybe (Width, Bool, Width -> Integer -> Integer)
forall a. Maybe a
Nothing
maybe_comparison :: MachOp -> Width -> Bool -> Maybe MachOp
maybe_comparison (MO_U_Gt Width
_) Width
rep Bool
_ = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_U_Gt Width
rep)
maybe_comparison (MO_U_Ge Width
_) Width
rep Bool
_ = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_U_Ge Width
rep)
maybe_comparison (MO_U_Lt Width
_) Width
rep Bool
_ = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_U_Lt Width
rep)
maybe_comparison (MO_U_Le Width
_) Width
rep Bool
_ = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_U_Le Width
rep)
maybe_comparison (MO_Eq Width
_) Width
rep Bool
_ = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_Eq Width
rep)
maybe_comparison (MO_S_Gt Width
_) Width
rep Bool
True = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_S_Gt Width
rep)
maybe_comparison (MO_S_Ge Width
_) Width
rep Bool
True = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_S_Ge Width
rep)
maybe_comparison (MO_S_Lt Width
_) Width
rep Bool
True = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_S_Lt Width
rep)
maybe_comparison (MO_S_Le Width
_) Width
rep Bool
True = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_S_Le Width
rep)
maybe_comparison (MO_S_Gt Width
_) Width
rep Bool
False = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_U_Gt Width
rep)
maybe_comparison (MO_S_Ge Width
_) Width
rep Bool
False = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_U_Ge Width
rep)
maybe_comparison (MO_S_Lt Width
_) Width
rep Bool
False = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_U_Lt Width
rep)
maybe_comparison (MO_S_Le Width
_) Width
rep Bool
False = MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Width -> MachOp
MO_U_Le Width
rep)
maybe_comparison MachOp
_ Width
_ Bool
_ = Maybe MachOp
forall a. Maybe a
Nothing
cmmMachOpFoldM Platform
platform MachOp
mop [CmmExpr
x, y :: CmmExpr
y@(CmmLit (CmmInt Integer
0 Width
_))]
= case MachOp
mop of
MO_Add Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_Sub Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_Mul Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
y
MO_And Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
y
MO_Or Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_Xor Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_Shl Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_S_Shr Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_U_Shr Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_Ne Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_Eq Width
_ | Just CmmExpr
x' <- CmmExpr -> Maybe CmmExpr
maybeInvertCmmExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x'
MO_U_Gt Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_S_Gt Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_U_Lt Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
zero
MO_S_Lt Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
zero
MO_U_Ge Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
one
MO_S_Ge Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
one
MO_U_Le Width
_ | Just CmmExpr
x' <- CmmExpr -> Maybe CmmExpr
maybeInvertCmmExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x'
MO_S_Le Width
_ | Just CmmExpr
x' <- CmmExpr -> Maybe CmmExpr
maybeInvertCmmExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x'
MachOp
_ -> Maybe CmmExpr
forall a. Maybe a
Nothing
where
zero :: CmmExpr
zero = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
0 (Platform -> Width
wordWidth Platform
platform))
one :: CmmExpr
one = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
1 (Platform -> Width
wordWidth Platform
platform))
cmmMachOpFoldM Platform
platform MachOp
mop [CmmExpr
x, (CmmLit (CmmInt Integer
1 Width
rep))]
= case MachOp
mop of
MO_Mul Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_S_Quot Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_U_Quot Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_S_Rem Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
0 Width
rep)
MO_U_Rem Width
_ -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
0 Width
rep)
MO_Ne Width
_ | Just CmmExpr
x' <- CmmExpr -> Maybe CmmExpr
maybeInvertCmmExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x'
MO_Eq Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_U_Lt Width
_ | Just CmmExpr
x' <- CmmExpr -> Maybe CmmExpr
maybeInvertCmmExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x'
MO_S_Lt Width
_ | Just CmmExpr
x' <- CmmExpr -> Maybe CmmExpr
maybeInvertCmmExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x'
MO_U_Gt Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
zero
MO_S_Gt Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
zero
MO_U_Le Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
one
MO_S_Le Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
one
MO_U_Ge Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MO_S_Ge Width
_ | CmmExpr -> Bool
isComparisonExpr CmmExpr
x -> CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
x
MachOp
_ -> Maybe CmmExpr
forall a. Maybe a
Nothing
where
zero :: CmmExpr
zero = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
0 (Platform -> Width
wordWidth Platform
platform))
one :: CmmExpr
one = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
1 (Platform -> Width
wordWidth Platform
platform))
cmmMachOpFoldM Platform
platform MachOp
mop [CmmExpr
x, (CmmLit (CmmInt Integer
n Width
_))]
= case MachOp
mop of
MO_Mul Width
rep
| Just Integer
p <- Integer -> Maybe Integer
exactLog2 Integer
n ->
CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! (Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform (Width -> MachOp
MO_Shl Width
rep) [CmmExpr
x, CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
p (Width -> CmmLit) -> Width -> CmmLit
forall a b. (a -> b) -> a -> b
$ Platform -> Width
wordWidth Platform
platform)])
MO_U_Quot Width
rep
| Just Integer
p <- Integer -> Maybe Integer
exactLog2 Integer
n ->
CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! (Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform (Width -> MachOp
MO_U_Shr Width
rep) [CmmExpr
x, CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
p (Width -> CmmLit) -> Width -> CmmLit
forall a b. (a -> b) -> a -> b
$ Platform -> Width
wordWidth Platform
platform)])
MO_U_Rem Width
rep
| Just Integer
_ <- Integer -> Maybe Integer
exactLog2 Integer
n ->
CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! (Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform (Width -> MachOp
MO_And Width
rep) [CmmExpr
x, CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1) Width
rep)])
MO_S_Quot Width
rep
| Just Integer
p <- Integer -> Maybe Integer
exactLog2 Integer
n,
CmmReg CmmReg
_ <- CmmExpr
x ->
CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! (Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform (Width -> MachOp
MO_S_Shr Width
rep)
[Width -> Integer -> CmmExpr
signedQuotRemHelper Width
rep Integer
p, CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
p (Width -> CmmLit) -> Width -> CmmLit
forall a b. (a -> b) -> a -> b
$ Platform -> Width
wordWidth Platform
platform)])
MO_S_Rem Width
rep
| Just Integer
p <- Integer -> Maybe Integer
exactLog2 Integer
n,
CmmReg CmmReg
_ <- CmmExpr
x ->
CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just (CmmExpr -> Maybe CmmExpr) -> CmmExpr -> Maybe CmmExpr
forall a b. (a -> b) -> a -> b
$! (Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform (Width -> MachOp
MO_Sub Width
rep)
[CmmExpr
x, Platform -> MachOp -> [CmmExpr] -> CmmExpr
cmmMachOpFold Platform
platform (Width -> MachOp
MO_And Width
rep)
[Width -> Integer -> CmmExpr
signedQuotRemHelper Width
rep Integer
p, CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (- Integer
n) Width
rep)]])
MachOp
_ -> Maybe CmmExpr
forall a. Maybe a
Nothing
where
signedQuotRemHelper :: Width -> Integer -> CmmExpr
signedQuotRemHelper :: Width -> Integer -> CmmExpr
signedQuotRemHelper Width
rep Integer
p = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Add Width
rep) [CmmExpr
x, CmmExpr
x2]
where
bits :: Integer
bits = Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Int
widthInBits Width
rep) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1
shr :: MachOp
shr = if Integer
p Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
1 then Width -> MachOp
MO_U_Shr Width
rep else Width -> MachOp
MO_S_Shr Width
rep
x1 :: CmmExpr
x1 = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp MachOp
shr [CmmExpr
x, CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
bits (Width -> CmmLit) -> Width -> CmmLit
forall a b. (a -> b) -> a -> b
$ Platform -> Width
wordWidth Platform
platform)]
x2 :: CmmExpr
x2 = if Integer
p Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
1 then CmmExpr
x1 else
MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_And Width
rep) [CmmExpr
x1, CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Integer
nInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1) Width
rep)]
cmmMachOpFoldM Platform
_ MachOp
_ [CmmExpr]
_ = Maybe CmmExpr
forall a. Maybe a
Nothing
isPicReg :: CmmExpr -> Bool
isPicReg :: CmmExpr -> Bool
isPicReg (CmmReg (CmmGlobal GlobalReg
PicBaseReg)) = Bool
True
isPicReg CmmExpr
_ = Bool
False