summaryrefslogtreecommitdiff
path: root/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/llvmGen/LlvmCodeGen/CodeGen.hs')
-rw-r--r--compiler/llvmGen/LlvmCodeGen/CodeGen.hs27
1 files changed, 21 insertions, 6 deletions
diff --git a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
index e812dd445f..65f7d6652c 100644
--- a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
+++ b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
@@ -13,6 +13,7 @@ import Llvm
import LlvmCodeGen.Base
import LlvmCodeGen.Regs
+import BasicTypes (BranchWeight, getWeight, neverFreq)
import BlockId
import CodeGen.Platform ( activeStgRegs, callerSaves )
import CLabel
@@ -38,6 +39,7 @@ import Util
import Control.Monad.Trans.Class
import Control.Monad.Trans.Writer
+import Data.Int (Int32)
import Data.Semigroup ( Semigroup )
import qualified Data.Semigroup as Semigroup
import Data.List ( nub )
@@ -1071,7 +1073,19 @@ For a real example of this, see ./rts/StgStdThunks.cmm
-}
-
+switchMetaData :: BranchWeight -> [BranchWeight] -> MetaAnnot
+switchMetaData defFreq altFreqs =
+ let values = map
+ -- LLVM branch weights are i32 typed so we cap it there.
+ (\w ->
+ min (fromIntegral (maxBound :: Int32))
+ (fromIntegral . getWeight $ w))
+ (defFreq:altFreqs)
+ types = repeat (LMInt $ fromIntegral 32)
+ lits = zipWith LMIntLit values types
+ weights = map (MetaVar . LMLitVar) lits
+ in
+ MetaAnnot (fsLit "branch_weights") $ MetaStruct weights
-- | Switch branch
genSwitch :: CmmExpr -> SwitchTargets -> LlvmM StmtData
@@ -1079,13 +1093,14 @@ genSwitch cond ids = do
(vc, stmts, top) <- exprToVar cond
let ty = getVarType vc
- let labels = [ (mkIntLit ty ix, blockIdToLlvm b)
- | (ix, b) <- switchTargetsCases ids ]
+ let (labels,fs) = unzip [ ((mkIntLit ty ix, blockIdToLlvm b), f)
+ | (ix, (b,f)) <- switchTargetsCases ids ]
-- out of range is undefined, so let's just branch to first label
- let defLbl | Just l <- switchTargetsDefault ids = blockIdToLlvm l
- | otherwise = snd (head labels)
+ let (defLbl,defFreq)
+ | Just (l,f) <- switchTargetsDefault ids = (blockIdToLlvm l,f)
+ | otherwise = (snd (head labels),neverFreq)
- let s1 = Switch vc defLbl labels
+ let s1 = MetaStmt [switchMetaData defFreq fs ] (Switch vc defLbl labels)
return $ (stmts `snocOL` s1, top)