implement pseudo min/max simd operations
This commit is contained in:
@@ -162,6 +162,16 @@ zeroAwareMax a b
|
|||||||
| isNaN b = b
|
| isNaN b = b
|
||||||
| otherwise = maxNum a b
|
| otherwise = maxNum a b
|
||||||
|
|
||||||
|
nanAwareMin :: IEEE a => a -> a -> a
|
||||||
|
nanAwareMin a b
|
||||||
|
| isNaN a = a
|
||||||
|
| otherwise = minNum a b
|
||||||
|
|
||||||
|
nanAwareMax :: IEEE a => a -> a -> a
|
||||||
|
nanAwareMax a b
|
||||||
|
| isNaN a = a
|
||||||
|
| otherwise = maxNum a b
|
||||||
|
|
||||||
floatFloor :: Float -> Float
|
floatFloor :: Float -> Float
|
||||||
floatFloor a
|
floatFloor a
|
||||||
| isNaN a = a
|
| isNaN a = a
|
||||||
@@ -1932,6 +1942,20 @@ eval budget store inst FunctionInstance { funcType, moduleInstance, code = Funct
|
|||||||
_ -> error "impossible due to validation"
|
_ -> error "impossible due to validation"
|
||||||
in
|
in
|
||||||
return $ Done ctx { stack = VV128 r : rest }
|
return $ Done ctx { stack = VV128 r : rest }
|
||||||
|
step ctx@EvalCtx{ stack = (VV128 v2:VV128 v1:rest) } (FBinOp (BS128 shape) FPMin) =
|
||||||
|
let r = case shape of
|
||||||
|
F32x4 -> lanewise @Word32 shape v1 v2 $ \a b -> floatToWord $ nanAwareMin (wordToFloat a) (wordToFloat b)
|
||||||
|
F64x2 -> lanewise @Word64 shape v1 v2 $ \a b -> doubleToWord $ nanAwareMin (wordToDouble a) (wordToDouble b)
|
||||||
|
_ -> error "impossible due to validation"
|
||||||
|
in
|
||||||
|
return $ Done ctx { stack = VV128 r : rest }
|
||||||
|
step ctx@EvalCtx{ stack = (VV128 v2:VV128 v1:rest) } (FBinOp (BS128 shape) FPMax) =
|
||||||
|
let r = case shape of
|
||||||
|
F32x4 -> lanewise @Word32 shape v1 v2 $ \a b -> floatToWord $ nanAwareMax (wordToFloat a) (wordToFloat b)
|
||||||
|
F64x2 -> lanewise @Word64 shape v1 v2 $ \a b -> doubleToWord $ nanAwareMax (wordToDouble a) (wordToDouble b)
|
||||||
|
_ -> error "impossible due to validation"
|
||||||
|
in
|
||||||
|
return $ Done ctx { stack = VV128 r : rest }
|
||||||
step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FRelOp BS32 FEq) =
|
step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FRelOp BS32 FEq) =
|
||||||
return $ Done ctx { stack = VI32 (if v1 == v2 then 1 else 0) : rest }
|
return $ Done ctx { stack = VI32 (if v1 == v2 then 1 else 0) : rest }
|
||||||
step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FRelOp BS32 FNe) =
|
step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FRelOp BS32 FNe) =
|
||||||
|
|||||||
@@ -532,6 +532,10 @@ import Language.Wasm.Lexer (
|
|||||||
'f64x2.min' { Lexeme _ (TKeyword "f64x2.min") }
|
'f64x2.min' { Lexeme _ (TKeyword "f64x2.min") }
|
||||||
'f32x4.max' { Lexeme _ (TKeyword "f32x4.max") }
|
'f32x4.max' { Lexeme _ (TKeyword "f32x4.max") }
|
||||||
'f64x2.max' { Lexeme _ (TKeyword "f64x2.max") }
|
'f64x2.max' { Lexeme _ (TKeyword "f64x2.max") }
|
||||||
|
'f32x4.pmin' { Lexeme _ (TKeyword "f32x4.pmin") }
|
||||||
|
'f64x2.pmin' { Lexeme _ (TKeyword "f64x2.pmin") }
|
||||||
|
'f32x4.pmax' { Lexeme _ (TKeyword "f32x4.pmax") }
|
||||||
|
'f64x2.pmax' { Lexeme _ (TKeyword "f64x2.pmax") }
|
||||||
'f32x4.abs' { Lexeme _ (TKeyword "f32x4.abs") }
|
'f32x4.abs' { Lexeme _ (TKeyword "f32x4.abs") }
|
||||||
'f64x2.abs' { Lexeme _ (TKeyword "f64x2.abs") }
|
'f64x2.abs' { Lexeme _ (TKeyword "f64x2.abs") }
|
||||||
'f32x4.neg' { Lexeme _ (TKeyword "f32x4.neg") }
|
'f32x4.neg' { Lexeme _ (TKeyword "f32x4.neg") }
|
||||||
@@ -1122,6 +1126,10 @@ plaininstr :: { PlainInstr }
|
|||||||
| 'f64x2.min' { FBinOp (BS128 F64x2) FMin }
|
| 'f64x2.min' { FBinOp (BS128 F64x2) FMin }
|
||||||
| 'f32x4.max' { FBinOp (BS128 F32x4) FMax }
|
| 'f32x4.max' { FBinOp (BS128 F32x4) FMax }
|
||||||
| 'f64x2.max' { FBinOp (BS128 F64x2) FMax }
|
| 'f64x2.max' { FBinOp (BS128 F64x2) FMax }
|
||||||
|
| 'f32x4.pmin' { FBinOp (BS128 F32x4) FPMin }
|
||||||
|
| 'f64x2.pmin' { FBinOp (BS128 F64x2) FPMin }
|
||||||
|
| 'f32x4.pmax' { FBinOp (BS128 F32x4) FPMax }
|
||||||
|
| 'f64x2.pmax' { FBinOp (BS128 F64x2) FPMax }
|
||||||
| 'f32x4.abs' { FUnOp (BS128 F32x4) FAbs }
|
| 'f32x4.abs' { FUnOp (BS128 F32x4) FAbs }
|
||||||
| 'f64x2.abs' { FUnOp (BS128 F64x2) FAbs }
|
| 'f64x2.abs' { FUnOp (BS128 F64x2) FAbs }
|
||||||
| 'f32x4.neg' { FUnOp (BS128 F32x4) FNeg }
|
| 'f32x4.neg' { FUnOp (BS128 F32x4) FNeg }
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ data IRelOp = IEq | INe | ILtU | ILtS | IGtU | IGtS | ILeU | ILeS | IGeU | IGeS
|
|||||||
|
|
||||||
data FUnOp = FAbs | FNeg | FCeil | FFloor | FTrunc | FNearest | FSqrt deriving (Show, Eq, Generic, NFData)
|
data FUnOp = FAbs | FNeg | FCeil | FFloor | FTrunc | FNearest | FSqrt deriving (Show, Eq, Generic, NFData)
|
||||||
|
|
||||||
data FBinOp = FAdd | FSub | FMul | FDiv | FMin | FMax | FCopySign deriving (Show, Eq, Generic, NFData)
|
data FBinOp = FAdd | FSub | FMul | FDiv | FMin | FMax | FCopySign | FPMin | FPMax deriving (Show, Eq, Generic, NFData)
|
||||||
|
|
||||||
data FRelOp = FEq | FNe | FLt | FGt | FLe | FGe deriving (Show, Eq, Generic, NFData)
|
data FRelOp = FEq | FNe | FLt | FGt | FLe | FGe deriving (Show, Eq, Generic, NFData)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ main = do
|
|||||||
filter (List.isPrefixOf "simd") .
|
filter (List.isPrefixOf "simd") .
|
||||||
filter (List.isSuffixOf ".wast")
|
filter (List.isSuffixOf ".wast")
|
||||||
<$> Directory.listDirectory "tests/spec"
|
<$> Directory.listDirectory "tests/spec"
|
||||||
-- let files = ["simd_i32x4_extadd_pairwise_i16x8.wast"]
|
-- let files = ["simd_f32x4_pmin_pmax.wast"]
|
||||||
scriptTestCases <- (`mapM` files) $ \file -> do
|
scriptTestCases <- (`mapM` files) $ \file -> do
|
||||||
test <- LBS.readFile ("tests/spec/" ++ file)
|
test <- LBS.readFile ("tests/spec/" ++ file)
|
||||||
return $ testCase file $ do
|
return $ testCase file $ do
|
||||||
|
|||||||
Reference in New Issue
Block a user