summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorÖmer Sinan Ağacan <omeragacan@gmail.com>2016-05-27 05:18:47 -0400
committerÖmer Sinan Ağacan <omeragacan@gmail.com>2016-05-27 05:19:06 -0400
commitcd50d236a4b29a9932ce4e12972db1fdd69f31be (patch)
tree9d80dcf6324c10aaecfaf806cc40fdb33df0ca39 /compiler
parent5b145c98900470c09ed6555e481b19cb27ec8b14 (diff)
downloadhaskell-cd50d236a4b29a9932ce4e12972db1fdd69f31be.tar.gz
StgCmmCon: Do not generate moves from unused fields to local variables
Say we have a record like this: data Rec = Rec { f1 :: Int , f2 :: Int , f3 :: Int , f4 :: Int , f5 :: Int } Before this patch, the code generated for `f1` looked like this: f1_entry() {offset ... cJT: _sI6::P64 = R1; _sI7::P64 = P64[_sI6::P64 + 7]; _sI8::P64 = P64[_sI6::P64 + 15]; _sI9::P64 = P64[_sI6::P64 + 23]; _sIa::P64 = P64[_sI6::P64 + 31]; _sIb::P64 = P64[_sI6::P64 + 39]; R1 = _sI7::P64 & (-8); Sp = Sp + 8; call (I64[R1])(R1) args: 8, res: 0, upd: 8; } Note how all fields of the record are moved to local variables, even though they're never used. These moves make it to the final assembly: f1_info: ... _cJT: movq 7(%rbx),%rax movq 15(%rbx),%rcx movq 23(%rbx),%rcx movq 31(%rbx),%rcx movq 39(%rbx),%rbx movq %rax,%rbx andq $-8,%rbx addq $8,%rbp jmp *(%rbx) With this patch we stop generating these move instructions. Cmm becomes this: f1_entry() {offset ... cJT: _sI6::P64 = R1; _sI7::P64 = P64[_sI6::P64 + 7]; R1 = _sI7::P64 & (-8); Sp = Sp + 8; call (I64[R1])(R1) args: 8, res: 0, upd: 8; } Assembly becomes this: f1_info: ... _cJT: movq 7(%rbx),%rax movq %rax,%rbx andq $-8,%rbx addq $8,%rbp jmp *(%rbx) It turns out CmmSink already optimizes this, but it's better to generate better code in the first place. Reviewers: simonmar, simonpj, austin, bgamari Reviewed By: simonmar, simonpj Subscribers: rwbarton, thomie Differential Revision: https://phabricator.haskell.org/D2269
Diffstat (limited to 'compiler')
-rw-r--r--compiler/codeGen/StgCmmCon.hs19
1 files changed, 13 insertions, 6 deletions
diff --git a/compiler/codeGen/StgCmmCon.hs b/compiler/codeGen/StgCmmCon.hs
index 745dd720eb..04257dd991 100644
--- a/compiler/codeGen/StgCmmCon.hs
+++ b/compiler/codeGen/StgCmmCon.hs
@@ -43,6 +43,7 @@ import PrelInfo
import Outputable
import Platform
import Util
+import MonadUtils (mapMaybeM)
import Control.Monad
import Data.Char
@@ -258,12 +259,18 @@ bindConArgs (DataAlt con) base args
-- The binding below forces the masking out of the tag bits
-- when accessing the constructor field.
- bind_arg :: (NonVoid Id, VirtualHpOffset) -> FCode LocalReg
- bind_arg (arg, offset)
- = do emit $ mkTaggedObjectLoad dflags (idToReg dflags arg) base offset tag
- bindArgToReg arg
- mapM bind_arg args_w_offsets
+ bind_arg :: (NonVoid Id, VirtualHpOffset) -> FCode (Maybe LocalReg)
+ bind_arg (arg@(NonVoid b), offset)
+ | isDeadBinder b =
+ -- Do not load unused fields from objects to local variables.
+ -- (CmmSink can optimize this, but it's cheap and common enough
+ -- to handle here)
+ return Nothing
+ | otherwise = do
+ emit $ mkTaggedObjectLoad dflags (idToReg dflags arg) base offset tag
+ Just <$> bindArgToReg arg
+
+ mapMaybeM bind_arg args_w_offsets
bindConArgs _other_con _base args
= ASSERT( null args ) return []
-