Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ghc/ghc
  • bgamari/ghc
  • syd/ghc
  • ggreif/ghc
  • watashi/ghc
  • RolandSenn/ghc
  • mpickering/ghc
  • DavidEichmann/ghc
  • carter/ghc
  • harpocrates/ghc
  • ethercrow/ghc
  • mijicd/ghc
  • adamse/ghc
  • alexbiehl/ghc
  • gridaphobe/ghc
  • trofi/ghc
  • supersven/ghc
  • ppk/ghc
  • ulysses4ever/ghc
  • AndreasK/ghc
  • ghuntley/ghc
  • shayne-fletcher-da/ghc
  • fgaz/ghc
  • yav/ghc
  • osa1/ghc
  • mbbx6spp/ghc
  • JulianLeviston/ghc
  • reactormonk/ghc
  • rae/ghc
  • takenobu-hs/ghc
  • michalt/ghc
  • andrewthad/ghc
  • hsyl20/ghc
  • scottgw/ghc
  • sjakobi/ghc
  • angerman/ghc
  • RyanGlScott/ghc
  • hvr/ghc
  • howtonotwin/ghc
  • chessai/ghc
  • m-renaud/ghc
  • brprice/ghc
  • stevehartdata/ghc
  • sighingnow/ghc
  • kgardas/ghc
  • ckoparkar/ghc
  • alp/ghc
  • smaeul/ghc
  • kakkun61/ghc
  • sykloid/ghc
  • newhoggy/ghc
  • toonn/ghc
  • nineonine/ghc
  • Phyx/ghc
  • ezyang/ghc
  • tweag/ghc
  • langston/ghc
  • ndmitchell/ghc
  • rockbmb/ghc
  • artempyanykh/ghc
  • mniip/ghc
  • mynguyenbmc/ghc
  • alexfmpe/ghc
  • crockeea/ghc
  • nh2/ghc
  • vaibhavsagar/ghc
  • phadej/ghc
  • Haskell-mouse/ghc
  • lolotp/ghc
  • spacekitteh/ghc
  • michaelpj/ghc
  • mgsloan/ghc
  • HPCohen/ghc
  • tmobile/ghc
  • radrow/ghc
  • simonmar/ghc
  • _deepfire/ghc
  • Ericson2314/ghc
  • leitao/ghc
  • fumieval/ghc
  • trac-isovector/ghc
  • cblp/ghc
  • xich/ghc
  • ciil/ghc
  • erthalion/ghc
  • xldenis/ghc
  • autotaker/ghc
  • haskell-wasm/ghc
  • kcsongor/ghc
  • agander/ghc
  • Baranowski/ghc
  • trac-dredozubov/ghc
  • 23Skidoo/ghc
  • iustin/ghc
  • ningning/ghc
  • josefs/ghc
  • kabuhr/ghc
  • gallais/ghc
  • dten/ghc
  • expipiplus1/ghc
  • Pluralia/ghc
  • rohanjr/ghc
  • intricate/ghc
  • kirelagin/ghc
  • Javran/ghc
  • DanielG/ghc
  • trac-mizunashi_mana/ghc
  • pparkkin/ghc
  • bollu/ghc
  • ntc2/ghc
  • jaspervdj/ghc
  • JoshMeredith/ghc
  • wz1000/ghc
  • zkourouma/ghc
  • code5hot/ghc
  • jdprice/ghc
  • tdammers/ghc
  • J-mie6/ghc
  • trac-lantti/ghc
  • ch1bo/ghc
  • cgohla/ghc
  • lucamolteni/ghc
  • acairncross/ghc
  • amerocu/ghc
  • chreekat/ghc
  • txsmith/ghc
  • trupill/ghc
  • typetetris/ghc
  • sergv/ghc
  • fryguybob/ghc
  • erikd/ghc
  • trac-roland/ghc
  • setupminimal/ghc
  • Friede80/ghc
  • SkyWriter/ghc
  • xplorld/ghc
  • abrar/ghc
  • obsidiansystems/ghc
  • Icelandjack/ghc
  • adinapoli/ghc
  • trac-matthewbauer/ghc
  • heatsink/ghc
  • dwijnand/ghc
  • Cmdv/ghc
  • alinab/ghc
  • pepeiborra/ghc
  • fommil/ghc
  • luochen1990/ghc
  • rlupton20/ghc
  • applePrincess/ghc
  • lehins/ghc
  • ronmrdechai/ghc
  • leeadam/ghc
  • harendra/ghc
  • mightymosquito1991/ghc
  • trac-gershomb/ghc
  • lucajulian/ghc
  • Rizary/ghc
  • VictorCMiraldo/ghc
  • jamesbrock/ghc
  • andrewdmeier/ghc
  • luke/ghc
  • pranaysashank/ghc
  • cocreature/ghc
  • hithroc/ghc
  • obreitwi/ghc
  • slrtbtfs/ghc
  • kaol/ghc
  • yairchu/ghc
  • Mathemagician98/ghc
  • trac-taylorfausak/ghc
  • leungbk/ghc
  • MichaWiedenmann/ghc
  • chris-martin/ghc
  • TDecki/ghc
  • adithyaov/ghc
  • trac-gelisam/ghc
  • Lysxia/ghc
  • complyue/ghc
  • bwignall/ghc
  • sternmull/ghc
  • sonika/ghc
  • leif/ghc
  • broadwaylamb/ghc
  • myszon/ghc
  • danbroooks/ghc
  • Mechachleopteryx/ghc
  • zardyh/ghc
  • trac-vdukhovni/ghc
  • OmarKhaledAbdo/ghc
  • arrowd/ghc
  • Bodigrim/ghc
  • matheus23/ghc
  • cardenaso11/ghc
  • trac-Athas/ghc
  • mb720/ghc
  • DylanZA/ghc
  • liff/ghc
  • typedrat/ghc
  • trac-claude/ghc
  • jbm/ghc
  • Gertjan423/ghc
  • PHO/ghc
  • JKTKops/ghc
  • kockahonza/ghc
  • msakai/ghc
  • Sir4ur0n/ghc
  • barambani/ghc
  • vishnu.c/ghc
  • dcoutts/ghc
  • trac-runeks/ghc
  • trac-MaxGabriel/ghc
  • lexi.lambda/ghc
  • strake/ghc
  • spavikevik/ghc
  • JakobBruenker/ghc
  • rmanne/ghc
  • gdziadkiewicz/ghc
  • ani/ghc
  • iliastsi/ghc
  • smunix/ghc
  • judah/ghc
  • blackgnezdo/ghc
  • emilypi/ghc
  • trac-bpfoley/ghc
  • muesli4/ghc
  • trac-gkaracha/ghc
  • Kleidukos/ghc
  • nek0/ghc
  • TristanCacqueray/ghc
  • dwulive/ghc
  • mbakke/ghc
  • arybczak/ghc
  • Yang123321/ghc
  • maksbotan/ghc
  • QuietMisdreavus/ghc
  • trac-olshanskydr/ghc
  • emekoi/ghc
  • samuela/ghc
  • josephcsible/ghc
  • dramforever/ghc
  • lpsmith/ghc
  • DenisFrezzato/ghc
  • michivi/ghc
  • jneira/ghc
  • jeffhappily/ghc
  • Ivan-Yudin/ghc
  • nakaji-dayo/ghc
  • gdevanla/ghc
  • galen/ghc
  • fendor/ghc
  • yaitskov/ghc
  • rcythr/ghc
  • awpr/ghc
  • jeremyschlatter/ghc
  • Aver1y/ghc
  • mitchellvitez/ghc
  • merijn/ghc
  • tomjaguarpaw1/ghc
  • trac-NoidedSuper/ghc
  • erewok/ghc
  • trac-junji.hashimoto/ghc
  • adamwespiser/ghc
  • bjaress/ghc
  • jhrcek/ghc
  • leonschoorl/ghc
  • lukasz-golebiewski/ghc
  • sheaf/ghc
  • last-g/ghc
  • carassius1014/ghc
  • eschwartz/ghc
  • dwincort/ghc
  • felixwiemuth/ghc
  • TimWSpence/ghc
  • marcusmonteirodesouza/ghc
  • WJWH/ghc
  • vtols/ghc
  • theobat/ghc
  • BinderDavid/ghc
  • ckoparkar0/ghc
  • alexander-kjeldaas/ghc
  • dme2/ghc
  • philderbeast/ghc
  • aaronallen8455/ghc
  • rayshih/ghc
  • benkard/ghc
  • mpardalos/ghc
  • saidelman/ghc
  • leiftw/ghc
  • ca333/ghc
  • bwroga/ghc
  • nmichael44/ghc
  • trac-crobbins/ghc
  • felixonmars/ghc
  • adityagupta1089/ghc
  • hgsipiere/ghc
  • treeowl/ghc
  • alexpeits/ghc
  • CraigFe/ghc
  • dnlkrgr/ghc
  • kerckhove_ts/ghc
  • cptwunderlich/ghc
  • eiais/ghc
  • hahohihu/ghc
  • sanchayan/ghc
  • lemmih/ghc
  • sehqlr/ghc
  • trac-dbeacham/ghc
  • luite/ghc
  • trac-f-a/ghc
  • vados/ghc
  • luntain/ghc
  • fatho/ghc
  • alexbiehl-gc/ghc
  • dcbdan/ghc
  • tvh/ghc
  • liam-ly/ghc
  • timbobbarnes/ghc
  • GovanifY/ghc
  • shanth2600/ghc
  • gliboc/ghc
  • duog/ghc
  • moxonsghost/ghc
  • zander/ghc
  • masaeedu/ghc
  • georgefst/ghc
  • guibou/ghc
  • nicuveo/ghc
  • mdebruijne/ghc
  • stjordanis/ghc
  • emiflake/ghc
  • wygulmage/ghc
  • frasertweedale/ghc
  • coot/ghc
  • aratamizuki/ghc
  • tsandstr/ghc
  • mrBliss/ghc
  • Anton-Latukha/ghc
  • tadfisher/ghc
  • vapourismo/ghc
  • Sorokin-Anton/ghc
  • basile-henry/ghc
  • trac-mightybyte/ghc
  • AbsoluteNikola/ghc
  • cobrien99/ghc
  • songzh/ghc
  • blamario/ghc
  • aj4ayushjain/ghc
  • trac-utdemir/ghc
  • tangcl/ghc
  • hdgarrood/ghc
  • maerwald/ghc
  • arjun/ghc
  • ratherforky/ghc
  • haskieLambda/ghc
  • EmilGedda/ghc
  • Bogicevic/ghc
  • eddiejessup/ghc
  • kozross/ghc
  • AlistairB/ghc
  • 3Rafal/ghc
  • christiaanb/ghc
  • trac-bit/ghc
  • matsumonkie/ghc
  • trac-parsonsmatt/ghc
  • chisui/ghc
  • jaro/ghc
  • trac-kmiyazato/ghc
  • davidsd/ghc
  • Tritlo/ghc
  • I-B-3/ghc
  • lykahb/ghc
  • AriFordsham/ghc
  • turion1/ghc
  • berberman/ghc
  • christiantakle/ghc
  • zyklotomic/ghc
  • trac-ocramz/ghc
  • CSEdd/ghc
  • doyougnu/ghc
  • mmhat/ghc
  • why-not-try-calmer/ghc
  • plutotulp/ghc
  • kjekac/ghc
  • Manvi07/ghc
  • teo/ghc
  • cactus/ghc
  • CarrieMY/ghc
  • abel/ghc
  • yihming/ghc
  • tsakki/ghc
  • jessicah/ghc
  • oliverbunting/ghc
  • meld/ghc
  • friedbrice/ghc
  • Joald/ghc
  • abarbu/ghc
  • DigitalBrains1/ghc
  • sterni/ghc
  • alexDarcy/ghc
  • hexchain/ghc
  • minimario/ghc
  • zliu41/ghc
  • tommd/ghc
  • jazcarate/ghc
  • peterbecich/ghc
  • alirezaghey/ghc
  • solomon/ghc
  • mikael.urankar/ghc
  • davjam/ghc
  • int-index/ghc
  • MorrowM/ghc
  • nrnrnr/ghc
  • Sonfamm/ghc-test-only
  • afzt1/ghc
  • nguyenhaibinh-tpc/ghc
  • trac-lierdakil/ghc
  • MichaWiedenmann1/ghc
  • jmorag/ghc
  • Ziharrk/ghc
  • trac-MitchellSalad/ghc
  • juampe/ghc
  • jwaldmann/ghc
  • snowleopard/ghc
  • juhp/ghc
  • normalcoder/ghc
  • ksqsf/ghc
  • trac-jberryman/ghc
  • roberth/ghc
  • 1ntEgr8/ghc
  • epworth/ghc
  • MrAdityaAlok/ghc
  • JunmingZhao42/ghc
  • jappeace/ghc
  • trac-Gabriel439/ghc
  • alt-romes/ghc
  • HugoPeters1024/ghc
  • 10ne1/ghc-fork
  • agentultra/ghc
  • Garfield1002/ghc
  • ChickenProp/ghc
  • clyring/ghc
  • MaxHearnden/ghc
  • jumper149/ghc
  • vem/ghc
  • ketzacoatl/ghc
  • Rosuavio/ghc
  • jackohughes/ghc
  • p4l1ly/ghc
  • konsumlamm/ghc
  • shlevy/ghc
  • torsten.schmits/ghc
  • andremarianiello/ghc
  • amesgen/ghc
  • googleson78/ghc
  • InfiniteVerma/ghc
  • uhbif19/ghc
  • yiyunliu/ghc
  • raehik/ghc
  • mrkun/ghc
  • telser/ghc
  • 1Jajen1/ghc
  • slotThe/ghc
  • WinstonHartnett/ghc
  • mpilgrem/ghc
  • dreamsmasher/ghc
  • schuelermine/ghc
  • trac-Viwor/ghc
  • undergroundquizscene/ghc
  • evertedsphere/ghc
  • coltenwebb/ghc
  • oberblastmeister/ghc
  • agrue/ghc
  • lf-/ghc
  • zacwood9/ghc
  • steshaw/ghc
  • high-cloud/ghc
  • SkamDart/ghc
  • PiDelport/ghc
  • maoif/ghc
  • RossPaterson/ghc
  • CharlesTaylor7/ghc
  • ribosomerocker/ghc
  • trac-ramirez7/ghc
  • daig/ghc
  • NicolasT/ghc
  • FinleyMcIlwaine/ghc
  • lawtonnichols/ghc
  • jmtd/ghc
  • ozkutuk/ghc
  • wildsebastian/ghc
  • lrzlin/ghc
  • tobias/ghc
  • fw/ghc
  • hawkinsw/ghc
  • type-dance/ghc
  • rui314/ghc
  • ocharles/ghc
  • wavewave/ghc
  • TheKK/ghc
  • nomeata/ghc
  • trac-csabahruska/ghc
  • jonathanjameswatson/ghc
  • L-as/ghc
  • Axman6/ghc
  • barracuda156/ghc
  • trac-jship/ghc
  • jake-87/ghc
  • meooow/ghc
  • rebeccat/ghc
  • hamana55/ghc
  • Enigmage/ghc
  • kokobd/ghc
  • agevelt/ghc
  • gshen42/ghc
  • chrismwendt/ghc
  • MangoIV/ghc
  • teto/ghc
  • Sookr1/ghc
  • trac-thomasjm/ghc
  • barci2/ghc-dev
  • trac-m4dc4p/ghc
  • dixonary/ghc
  • breakerzirconia/ghc
  • alexsio27444/ghc
  • glocq/ghc
  • sourabhxyz/ghc
  • ryantrinkle/ghc
  • Jade/ghc
  • scedfaliako/ghc
  • martijnbastiaan/ghc
  • trac-george.colpitts/ghc
  • ammarbinfaisal/ghc
  • mimi.vx/ghc
  • lortabac/ghc
  • trac-zyla/ghc
  • benbellick/ghc
  • aadaa-fgtaa/ghc
  • jvanbruegge/ghc
  • archbung/ghc
  • gilmi/ghc
  • mfonism/ghc
  • alex-mckenna/ghc
  • Ei30metry/ghc
  • DiegoDiverio/ghc
  • jorgecunhamendes/ghc
  • liesnikov/ghc
  • akrmn/ghc
  • trac-simplifierticks/ghc
  • jacco/ghc
  • rhendric/ghc
  • damhiya/ghc
  • ryndubei/ghc
  • DaveBarton/ghc
  • trac-Profpatsch/ghc
  • GZGavinZhao/ghc
  • ncfavier/ghc
  • jameshaydon/ghc
  • ajccosta/ghc
  • dschrempf/ghc
  • cydparser/ghc
  • LinuxUserGD/ghc
  • elodielander/ghc
  • facundominguez/ghc
  • psilospore/ghc
  • lachrimae/ghc
  • dylan-thinnes/ghc-type-errors-plugin
  • hamishmack/ghc
  • Leary/ghc
  • lzszt/ghc
  • lyokha/ghc
  • trac-glaubitz/ghc
  • Rewbert/ghc
  • andreabedini/ghc
  • Jasagredo/ghc
  • sol/ghc
  • OlegAlexander/ghc
  • trac-sthibaul/ghc
  • avdv/ghc
  • Wendaolee/ghc
  • ur4t/ghc
  • daylily/ghc
  • boltzmannrain/ghc
  • mmzk1526/ghc
  • trac-fizzixnerd/ghc
  • soulomoon/ghc
  • rwmjones/ghc
  • j14i/ghc
  • tracsis/ghc
  • gesh/ghc
  • flip101/ghc
  • eldritch-cookie/ghc
  • LemonjamesD/ghc
  • pgujjula/ghc
  • skeuchel/ghc
  • noteed/ghc
  • Torrekie/ghc
  • jlwoodwa/ghc
  • ayanamists/ghc
  • husong998/ghc
  • trac-edmundnoble/ghc
  • josephf/ghc
  • contrun/ghc
  • baulig/ghc
  • edsko/ghc
  • mzschr/ghc-issue-24732
  • ulidtko/ghc
  • Arsen/ghc
  • trac-sjoerd_visscher/ghc
  • crumbtoo/ghc
  • L0neGamer/ghc
  • DrewFenwick/ghc
  • benz0li/ghc
  • MaciejWas/ghc
  • jordanrule/ghc
  • trac-qqwy/ghc
  • LiamGoodacre/ghc
  • isomorpheme/ghc
  • trac-danidiaz/ghc
  • Kariim/ghc
  • taimoorzaeem/ghc
  • hololeap/ghc
  • ticat-fp/ghc
  • meritamen/ghc
  • criskell/ghc
  • trac-kraai/ghc
  • aergus/ghc
  • jdral/ghc
  • SamB/ghc
  • Tristian/ghc
  • ywgrit/ghc
  • KatsuPatrick/ghc
  • OsePedro/ghc
  • mpscholten/ghc
  • zaquest/ghc
  • fangyi-zhou/ghc
  • augyg/ghc
  • rkirkman/ghc
  • gulin.serge/ghc-windows-aarch64-bootstrap
  • iris/ghc
  • kwxm/ghc
  • maralorn/ghc
  • rafl/ghc
  • nikshalark/ghc
  • mrcjkb/ghc
  • blackheaven/ghc
  • laurenyim/ghc
  • bolt12/ghc
  • Xitian9/ghc
  • wenkokke/ghc
  • kephas/ghc
651 results
Show changes
Commits on Source (127)
Showing
with 330 additions and 320 deletions
...@@ -129,3 +129,6 @@ ...@@ -129,3 +129,6 @@
[submodule ".arc-linters/arcanist-external-json-linter"] [submodule ".arc-linters/arcanist-external-json-linter"]
path = .arc-linters/arcanist-external-json-linter path = .arc-linters/arcanist-external-json-linter
url = ../arcanist-external-json-linter.git url = ../arcanist-external-json-linter.git
[submodule "hadrian"]
path = hadrian
url = ../hadrian.git
...@@ -1237,15 +1237,18 @@ if test -z "$CC" ...@@ -1237,15 +1237,18 @@ if test -z "$CC"
then then
AC_MSG_ERROR([gcc is required]) AC_MSG_ERROR([gcc is required])
fi fi
GccLT46=NO
AC_CACHE_CHECK([version of gcc], [fp_cv_gcc_version], AC_CACHE_CHECK([version of gcc], [fp_cv_gcc_version],
[ [
# Be sure only to look at the first occurrence of the "version " string; # Be sure only to look at the first occurrence of the "version " string;
# Some Apple compilers emit multiple messages containing this string. # Some Apple compilers emit multiple messages containing this string.
fp_cv_gcc_version="`$CC -v 2>&1 | sed -n -e '1,/version /s/.*version [[^0-9]]*\([[0-9.]]*\).*/\1/p'`" fp_cv_gcc_version="`$CC -v 2>&1 | sed -n -e '1,/version /s/.*version [[^0-9]]*\([[0-9.]]*\).*/\1/p'`"
FP_COMPARE_VERSIONS([$fp_cv_gcc_version], [-lt], [4.7], FP_COMPARE_VERSIONS([$fp_cv_gcc_version], [-lt], [4.4],
[AC_MSG_ERROR([Need at least gcc version 4.7])]) [AC_MSG_ERROR([Need at least gcc version 4.4 (4.7+ recommended)])])
FP_COMPARE_VERSIONS([$fp_cv_gcc_version], [-lt], [4.6], GccLT46=YES)
]) ])
AC_SUBST([GccVersion], [$fp_cv_gcc_version]) AC_SUBST([GccVersion], [$fp_cv_gcc_version])
AC_SUBST(GccLT46)
])# FP_GCC_VERSION ])# FP_GCC_VERSION
dnl Check to see if the C compiler is clang or llvm-gcc dnl Check to see if the C compiler is clang or llvm-gcc
...@@ -1278,6 +1281,24 @@ AC_SUBST(GccIsClang) ...@@ -1278,6 +1281,24 @@ AC_SUBST(GccIsClang)
rm -f conftest.txt rm -f conftest.txt
]) ])
# FP_GCC_SUPPORTS__ATOMICS
# ------------------------
# Does gcc support the __atomic_* family of builtins?
AC_DEFUN([FP_GCC_SUPPORTS__ATOMICS],
[
AC_REQUIRE([AC_PROG_CC])
AC_MSG_CHECKING([whether GCC supports __atomic_ builtins])
echo 'int test(int *x) { int y; __atomic_load(&x, &y, __ATOMIC_SEQ_CST); return x; }' > conftest.c
if $CC -c conftest.c > /dev/null 2>&1; then
CONF_GCC_SUPPORTS__ATOMICS=YES
AC_MSG_RESULT([yes])
else
CONF_GCC_SUPPORTS__ATOMICS=NO
AC_MSG_RESULT([no])
fi
rm -f conftest.c conftest.o
])
# FP_GCC_SUPPORTS_NO_PIE # FP_GCC_SUPPORTS_NO_PIE
# ---------------------- # ----------------------
# Does gcc support the -no-pie option? If so we should pass it to gcc when # Does gcc support the -no-pie option? If so we should pass it to gcc when
...@@ -1848,6 +1869,9 @@ case "$1" in ...@@ -1848,6 +1869,9 @@ case "$1" in
mips*) mips*)
$2="mips" $2="mips"
;; ;;
nios2)
$2="nios2"
;;
powerpc64le*) powerpc64le*)
$2="powerpc64le" $2="powerpc64le"
;; ;;
...@@ -1954,8 +1978,11 @@ AC_DEFUN([GHC_CONVERT_OS],[ ...@@ -1954,8 +1978,11 @@ AC_DEFUN([GHC_CONVERT_OS],[
linux-*|linux) linux-*|linux)
$3="linux" $3="linux"
;; ;;
openbsd*)
$3="openbsd"
;;
# As far as I'm aware, none of these have relevant variants # As far as I'm aware, none of these have relevant variants
freebsd|netbsd|openbsd|dragonfly|hpux|linuxaout|kfreebsdgnu|freebsd2|solaris2|mingw32|darwin|gnu|nextstep2|nextstep3|sunos4|ultrix|haiku) freebsd|netbsd|dragonfly|hpux|linuxaout|kfreebsdgnu|freebsd2|mingw32|darwin|gnu|nextstep2|nextstep3|sunos4|ultrix|haiku)
$3="$1" $3="$1"
;; ;;
aix*) # e.g. powerpc-ibm-aix7.1.3.0 aix*) # e.g. powerpc-ibm-aix7.1.3.0
...@@ -1964,6 +1991,9 @@ AC_DEFUN([GHC_CONVERT_OS],[ ...@@ -1964,6 +1991,9 @@ AC_DEFUN([GHC_CONVERT_OS],[
darwin*) # e.g. aarch64-apple-darwin14 darwin*) # e.g. aarch64-apple-darwin14
$3="darwin" $3="darwin"
;; ;;
solaris2*)
$3="solaris2"
;;
freebsd*) # like i686-gentoo-freebsd7 freebsd*) # like i686-gentoo-freebsd7
# i686-gentoo-freebsd8 # i686-gentoo-freebsd8
# i686-gentoo-freebsd8.2 # i686-gentoo-freebsd8.2
...@@ -2334,6 +2364,7 @@ AC_DEFUN([FIND_LD],[ ...@@ -2334,6 +2364,7 @@ AC_DEFUN([FIND_LD],[
# Make sure the user didn't specify LD manually. # Make sure the user didn't specify LD manually.
if test "z$LD" != "z"; then if test "z$LD" != "z"; then
AC_CHECK_TARGET_TOOL([LD], [ld]) AC_CHECK_TARGET_TOOL([LD], [ld])
LD_NO_GOLD=$LD
return return
fi fi
...@@ -2346,10 +2377,16 @@ AC_DEFUN([FIND_LD],[ ...@@ -2346,10 +2377,16 @@ AC_DEFUN([FIND_LD],[
if test "x$TmpLd" = "x"; then continue; fi if test "x$TmpLd" = "x"; then continue; fi
out=`$TmpLd --version` out=`$TmpLd --version`
LD_NO_GOLD=$TmpLd
case $out in case $out in
"GNU ld"*) FP_CC_LINKER_FLAG_TRY(bfd, $2) ;; "GNU ld"*)
"GNU gold"*) FP_CC_LINKER_FLAG_TRY(gold, $2) ;; FP_CC_LINKER_FLAG_TRY(bfd, $2) ;;
"LLD"*) FP_CC_LINKER_FLAG_TRY(lld, $2) ;; "GNU gold"*)
FP_CC_LINKER_FLAG_TRY(gold, $2)
LD_NO_GOLD=ld
;;
"LLD"*)
FP_CC_LINKER_FLAG_TRY(lld, $2) ;;
*) AC_MSG_NOTICE([unknown linker version $out]) ;; *) AC_MSG_NOTICE([unknown linker version $out]) ;;
esac esac
if test "z$$2" = "z"; then if test "z$$2" = "z"; then
...@@ -2366,12 +2403,16 @@ AC_DEFUN([FIND_LD],[ ...@@ -2366,12 +2403,16 @@ AC_DEFUN([FIND_LD],[
# Fallback # Fallback
AC_CHECK_TARGET_TOOL([LD], [ld]) AC_CHECK_TARGET_TOOL([LD], [ld])
# This isn't entirely safe since $LD may have been discovered to be
$ ld.gold, but what else can we do?
if test "x$LD_NO_GOLD" = "x"; then LD_NO_GOLD=$LD; fi
} }
if test "x$enable_ld_override" = "xyes"; then if test "x$enable_ld_override" = "xyes"; then
find_ld find_ld
else else
AC_CHECK_TARGET_TOOL([LD], [ld]) AC_CHECK_TARGET_TOOL([LD], [ld])
if test "x$LD_NO_GOLD" = "x"; then LD_NO_GOLD=$LD; fi
fi fi
CHECK_LD_COPY_BUG([$1]) CHECK_LD_COPY_BUG([$1])
......
...@@ -654,6 +654,7 @@ rnIfaceCo (IfaceForAllCo bndr co1 co2) ...@@ -654,6 +654,7 @@ rnIfaceCo (IfaceForAllCo bndr co1 co2)
= IfaceForAllCo <$> rnIfaceTvBndr bndr <*> rnIfaceCo co1 <*> rnIfaceCo co2 = IfaceForAllCo <$> rnIfaceTvBndr bndr <*> rnIfaceCo co1 <*> rnIfaceCo co2
rnIfaceCo (IfaceFreeCoVar c) = pure (IfaceFreeCoVar c) rnIfaceCo (IfaceFreeCoVar c) = pure (IfaceFreeCoVar c)
rnIfaceCo (IfaceCoVarCo lcl) = IfaceCoVarCo <$> pure lcl rnIfaceCo (IfaceCoVarCo lcl) = IfaceCoVarCo <$> pure lcl
rnIfaceCo (IfaceHoleCo lcl) = IfaceHoleCo <$> pure lcl
rnIfaceCo (IfaceAxiomInstCo n i cs) rnIfaceCo (IfaceAxiomInstCo n i cs)
= IfaceAxiomInstCo <$> rnIfaceGlobal n <*> pure i <*> mapM rnIfaceCo cs = IfaceAxiomInstCo <$> rnIfaceGlobal n <*> pure i <*> mapM rnIfaceCo cs
rnIfaceCo (IfaceUnivCo s r t1 t2) rnIfaceCo (IfaceUnivCo s r t1 t2)
......
...@@ -34,7 +34,7 @@ module VarEnv ( ...@@ -34,7 +34,7 @@ module VarEnv (
extendDVarEnvList, extendDVarEnvList,
lookupDVarEnv, elemDVarEnv, lookupDVarEnv, elemDVarEnv,
isEmptyDVarEnv, foldDVarEnv, isEmptyDVarEnv, foldDVarEnv,
mapDVarEnv, mapDVarEnv, filterDVarEnv,
modifyDVarEnv, modifyDVarEnv,
alterDVarEnv, alterDVarEnv,
plusDVarEnv, plusDVarEnv_C, plusDVarEnv, plusDVarEnv_C,
...@@ -557,6 +557,9 @@ foldDVarEnv = foldUDFM ...@@ -557,6 +557,9 @@ foldDVarEnv = foldUDFM
mapDVarEnv :: (a -> b) -> DVarEnv a -> DVarEnv b mapDVarEnv :: (a -> b) -> DVarEnv a -> DVarEnv b
mapDVarEnv = mapUDFM mapDVarEnv = mapUDFM
filterDVarEnv :: (a -> Bool) -> DVarEnv a -> DVarEnv a
filterDVarEnv = filterUDFM
alterDVarEnv :: (Maybe a -> Maybe a) -> DVarEnv a -> Var -> DVarEnv a alterDVarEnv :: (Maybe a -> Maybe a) -> DVarEnv a -> Var -> DVarEnv a
alterDVarEnv = alterUDFM alterDVarEnv = alterUDFM
......
...@@ -24,7 +24,6 @@ import qualified Data.List as List ...@@ -24,7 +24,6 @@ import qualified Data.List as List
import Data.Word import Data.Word
import qualified Data.Map as M import qualified Data.Map as M
import Outputable import Outputable
import DynFlags (DynFlags)
import UniqFM import UniqFM
import UniqDFM import UniqDFM
import qualified TrieMap as TM import qualified TrieMap as TM
...@@ -60,11 +59,11 @@ import Control.Arrow (first, second) ...@@ -60,11 +59,11 @@ import Control.Arrow (first, second)
-- rightfully complained: #10397 -- rightfully complained: #10397
-- TODO: Use optimization fuel -- TODO: Use optimization fuel
elimCommonBlocks :: DynFlags -> CmmGraph -> CmmGraph elimCommonBlocks :: CmmGraph -> CmmGraph
elimCommonBlocks dflags g = replaceLabels env $ copyTicks env g elimCommonBlocks g = replaceLabels env $ copyTicks env g
where where
env = iterate dflags mapEmpty blocks_with_key env = iterate mapEmpty blocks_with_key
groups = groupByInt (hash_block dflags) (postorderDfs g) groups = groupByInt hash_block (postorderDfs g)
blocks_with_key = [ [ (successors b, [b]) | b <- bs] | bs <- groups] blocks_with_key = [ [ (successors b, [b]) | b <- bs] | bs <- groups]
-- Invariant: The blocks in the list are pairwise distinct -- Invariant: The blocks in the list are pairwise distinct
...@@ -74,47 +73,42 @@ type Key = [Label] ...@@ -74,47 +73,42 @@ type Key = [Label]
type Subst = LabelMap BlockId type Subst = LabelMap BlockId
-- The outer list groups by hash. We retain this grouping throughout. -- The outer list groups by hash. We retain this grouping throughout.
iterate :: DynFlags -> Subst -> [[(Key, DistinctBlocks)]] -> Subst iterate :: Subst -> [[(Key, DistinctBlocks)]] -> Subst
iterate dflags subst blocks iterate subst blocks
| mapNull new_substs = subst | mapNull new_substs = subst
| otherwise = iterate dflags subst' updated_blocks | otherwise = iterate subst' updated_blocks
where where
grouped_blocks :: [[(Key, [DistinctBlocks])]] grouped_blocks :: [[(Key, [DistinctBlocks])]]
grouped_blocks = map groupByLabel blocks grouped_blocks = map groupByLabel blocks
merged_blocks :: [[(Key, DistinctBlocks)]] merged_blocks :: [[(Key, DistinctBlocks)]]
(new_substs, merged_blocks) = (new_substs, merged_blocks) = List.mapAccumL (List.mapAccumL go) mapEmpty grouped_blocks
List.mapAccumL (List.mapAccumL go) mapEmpty grouped_blocks
where where
go !new_subst1 (k,dbs) = (new_subst1 `mapUnion` new_subst2, (k,db)) go !new_subst1 (k,dbs) = (new_subst1 `mapUnion` new_subst2, (k,db))
where where
(new_subst2, db) = mergeBlockList dflags subst dbs (new_subst2, db) = mergeBlockList subst dbs
subst' = subst `mapUnion` new_substs subst' = subst `mapUnion` new_substs
updated_blocks = map (map (first (map (lookupBid subst')))) merged_blocks updated_blocks = map (map (first (map (lookupBid subst')))) merged_blocks
mergeBlocks :: DynFlags -> Subst mergeBlocks :: Subst -> DistinctBlocks -> DistinctBlocks -> (Subst, DistinctBlocks)
-> DistinctBlocks -> DistinctBlocks mergeBlocks subst existing new = go new
-> (Subst, DistinctBlocks)
mergeBlocks dflags subst existing new = go new
where where
go [] = (mapEmpty, existing) go [] = (mapEmpty, existing)
go (b:bs) = go (b:bs) = case List.find (eqBlockBodyWith (eqBid subst) b) existing of
case List.find (eqBlockBodyWith dflags (eqBid subst) b) existing of -- This block is a duplicate. Drop it, and add it to the substitution
-- This block is a duplicate. Drop it, and add it to the substitution Just b' -> first (mapInsert (entryLabel b) (entryLabel b')) $ go bs
Just b' -> first (mapInsert (entryLabel b) (entryLabel b')) $ go bs -- This block is not a duplicate, keep it.
-- This block is not a duplicate, keep it. Nothing -> second (b:) $ go bs
Nothing -> second (b:) $ go bs
mergeBlockList :: Subst -> [DistinctBlocks] -> (Subst, DistinctBlocks)
mergeBlockList :: DynFlags -> Subst -> [DistinctBlocks] mergeBlockList _ [] = pprPanic "mergeBlockList" empty
-> (Subst, DistinctBlocks) mergeBlockList subst (b:bs) = go mapEmpty b bs
mergeBlockList _ _ [] = pprPanic "mergeBlockList" empty
mergeBlockList dflags subst (b:bs) = go mapEmpty b bs
where where
go !new_subst1 b [] = (new_subst1, b) go !new_subst1 b [] = (new_subst1, b)
go !new_subst1 b1 (b2:bs) = go new_subst b bs go !new_subst1 b1 (b2:bs) = go new_subst b bs
where where
(new_subst2, b) = mergeBlocks dflags subst b1 b2 (new_subst2, b) = mergeBlocks subst b1 b2
new_subst = new_subst1 `mapUnion` new_subst2 new_subst = new_subst1 `mapUnion` new_subst2
...@@ -132,110 +126,39 @@ mergeBlockList dflags subst (b:bs) = go mapEmpty b bs ...@@ -132,110 +126,39 @@ mergeBlockList dflags subst (b:bs) = go mapEmpty b bs
-- expensive. So include as much as possible in the hash. Ideally everything -- expensive. So include as much as possible in the hash. Ideally everything
-- that is compared with (==) in eqBlockBodyWith. -- that is compared with (==) in eqBlockBodyWith.
{-
Note [Equivalence up to local registers in CBE]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CBE treats two blocks which are equivalent up to alpha-renaming of locally-bound
local registers as equivalent. This was not always the case (see #14226) but is
quite important for effective CBE. For instance, consider the blocks,
c2VZ: // global
_c2Yd::I64 = _s2Se::I64 + 1;
_s2Sx::I64 = _c2Yd::I64;
_s2Se::I64 = _s2Sx::I64;
goto c2TE;
c2VY: // global
_c2Yb::I64 = _s2Se::I64 + 1;
_s2Sw::I64 = _c2Yb::I64;
_s2Se::I64 = _s2Sw::I64;
goto c2TE;
These clearly implement precisely the same logic, differing only register
naming. This happens quite often in the code produced by GHC.
This alpha-equivalence relation must be accounted for in two places:
1. the block hash function (hash_block), which we use for approximate "binning"
2. the exact block comparison function, which computes pair-wise equivalence
In (1) we maintain a de Bruijn numbering of each block's locally-bound local
registers and compute the hash relative to this numbering.
For (2) we maintain a substitution which maps the local registers of one block
onto those of the other. We then compare local registers modulo this
substitution.
-}
type HashCode = Int type HashCode = Int
type LocalRegEnv a = UniqFM a hash_block :: CmmBlock -> HashCode
type DeBruijn = Int hash_block block =
fromIntegral (foldBlockNodesB3 (hash_fst, hash_mid, hash_lst) block (0 :: Word32) .&. (0x7fffffff :: Word32))
-- | Maintains a de Bruijn numbering of local registers bound within a block. -- UniqFM doesn't like negative Ints
-- where hash_fst _ h = h
-- See Note [Equivalence up to local registers in CBE] hash_mid m h = hash_node m + h `shiftL` 1
data HashEnv = HashEnv { localRegHashEnv :: !(LocalRegEnv DeBruijn) hash_lst m h = hash_node m + h `shiftL` 1
, nextIndex :: !DeBruijn
} hash_node :: CmmNode O x -> Word32
hash_node n | dont_care n = 0 -- don't care
hash_block :: DynFlags -> CmmBlock -> HashCode hash_node (CmmAssign r e) = hash_reg r + hash_e e
hash_block dflags block = hash_node (CmmStore e e') = hash_e e + hash_e e'
--pprTrace "hash_block" (ppr (entryLabel block) $$ ppr hash) hash_node (CmmUnsafeForeignCall t _ as) = hash_tgt t + hash_list hash_e as
hash hash_node (CmmBranch _) = 23 -- NB. ignore the label
where hash_fst _ (env, h) = (env, h) hash_node (CmmCondBranch p _ _ _) = hash_e p
hash_mid m (env, h) = let (env', h') = hash_node env m hash_node (CmmCall e _ _ _ _ _) = hash_e e
in (env', h' + h `shiftL` 1) hash_node (CmmForeignCall t _ _ _ _ _ _) = hash_tgt t
hash_lst m (env, h) = let (env', h') = hash_node env m hash_node (CmmSwitch e _) = hash_e e
in (env', h' + h `shiftL` 1) hash_node _ = error "hash_node: unknown Cmm node!"
hash = hash_reg :: CmmReg -> Word32
let (_, raw_hash) = hash_reg (CmmLocal localReg) = hash_unique localReg -- important for performance, see #10397
foldBlockNodesF3 (hash_fst, hash_mid, hash_lst) hash_reg (CmmGlobal _) = 19
block
(emptyEnv, 0 :: Word32) hash_e :: CmmExpr -> Word32
emptyEnv = HashEnv mempty 0 hash_e (CmmLit l) = hash_lit l
in fromIntegral (raw_hash .&. (0x7fffffff :: Word32)) hash_e (CmmLoad e _) = 67 + hash_e e
-- UniqFM doesn't like negative Ints hash_e (CmmReg r) = hash_reg r
hash_e (CmmMachOp _ es) = hash_list hash_e es -- pessimal - no operator check
hash_node :: HashEnv -> CmmNode O x -> (HashEnv, Word32) hash_e (CmmRegOff r i) = hash_reg r + cvt i
hash_node env n = hash_e (CmmStackSlot _ _) = 13
(env', hash)
where
hash =
case n of
n | dont_care n -> 0 -- don't care
-- don't include register as it is a binding occurrence
CmmAssign (CmmLocal _) e -> hash_e env e
CmmAssign r e -> hash_reg env r + hash_e env e
CmmStore e e' -> hash_e env e + hash_e env e'
CmmUnsafeForeignCall t _ as
-> hash_tgt env t + hash_list (hash_e env) as
CmmBranch _ -> 23 -- NB. ignore the label
CmmCondBranch p _ _ _ -> hash_e env p
CmmCall e _ _ _ _ _ -> hash_e env e
CmmForeignCall t _ _ _ _ _ _ -> hash_tgt env t
CmmSwitch e _ -> hash_e env e
_ -> error "hash_node: unknown Cmm node!"
env' = foldLocalRegsDefd dflags (flip bind_local_reg) env n
hash_reg :: HashEnv -> CmmReg -> Word32
hash_reg env (CmmLocal localReg)
| Just idx <- lookupUFM (localRegHashEnv env) localReg
= fromIntegral idx
| otherwise
= hash_unique localReg -- important for performance, see #10397
hash_reg _ (CmmGlobal _) = 19
hash_e :: HashEnv -> CmmExpr -> Word32
hash_e _ (CmmLit l) = hash_lit l
hash_e env (CmmLoad e _) = 67 + hash_e env e
hash_e env (CmmReg r) = hash_reg env r
hash_e env (CmmMachOp _ es) = hash_list (hash_e env) es -- pessimal - no operator check
hash_e env (CmmRegOff r i) = hash_reg env r + cvt i
hash_e _ (CmmStackSlot _ _) = 13
hash_lit :: CmmLit -> Word32 hash_lit :: CmmLit -> Word32
hash_lit (CmmInt i _) = fromInteger i hash_lit (CmmInt i _) = fromInteger i
...@@ -247,21 +170,13 @@ hash_block dflags block = ...@@ -247,21 +170,13 @@ hash_block dflags block =
hash_lit (CmmBlock _) = 191 -- ugh hash_lit (CmmBlock _) = 191 -- ugh
hash_lit (CmmHighStackMark) = cvt 313 hash_lit (CmmHighStackMark) = cvt 313
hash_tgt :: HashEnv -> ForeignTarget -> Word32 hash_tgt (ForeignTarget e _) = hash_e e
hash_tgt env (ForeignTarget e _) = hash_e env e hash_tgt (PrimTarget _) = 31 -- lots of these
hash_tgt _ (PrimTarget _) = 31 -- lots of these
hash_list f = List.foldl' (\z x -> f x + z) (0::Word32) hash_list f = foldl (\z x -> f x + z) (0::Word32)
cvt = fromInteger . toInteger cvt = fromInteger . toInteger
bind_local_reg :: LocalReg -> HashEnv -> HashEnv
bind_local_reg reg env =
env { localRegHashEnv =
addToUFM (localRegHashEnv env) reg (nextIndex env)
, nextIndex = nextIndex env + 1
}
hash_unique :: Uniquable a => a -> Word32 hash_unique :: Uniquable a => a -> Word32
hash_unique = cvt . getKey . getUnique hash_unique = cvt . getKey . getUnique
...@@ -282,76 +197,34 @@ lookupBid subst bid = case mapLookup bid subst of ...@@ -282,76 +197,34 @@ lookupBid subst bid = case mapLookup bid subst of
Just bid -> lookupBid subst bid Just bid -> lookupBid subst bid
Nothing -> bid Nothing -> bid
-- | Maps the local registers of one block to those of another
--
-- See Note [Equivalence up to local registers in CBE]
type LocalRegMapping = LocalRegEnv LocalReg
-- Middle nodes and expressions can contain BlockIds, in particular in -- Middle nodes and expressions can contain BlockIds, in particular in
-- CmmStackSlot and CmmBlock, so we have to use a special equality for -- CmmStackSlot and CmmBlock, so we have to use a special equality for
-- these. -- these.
-- --
eqMiddleWith :: DynFlags eqMiddleWith :: (BlockId -> BlockId -> Bool)
-> (BlockId -> BlockId -> Bool) -> CmmNode O O -> CmmNode O O -> Bool
-> LocalRegMapping eqMiddleWith eqBid (CmmAssign r1 e1) (CmmAssign r2 e2)
-> CmmNode O O -> CmmNode O O = r1 == r2 && eqExprWith eqBid e1 e2
-> (LocalRegMapping, Bool) eqMiddleWith eqBid (CmmStore l1 r1) (CmmStore l2 r2)
eqMiddleWith dflags eqBid env a b = = eqExprWith eqBid l1 l2 && eqExprWith eqBid r1 r2
case (a, b) of eqMiddleWith eqBid (CmmUnsafeForeignCall t1 r1 a1)
-- registers aren't compared since they are binding occurrences (CmmUnsafeForeignCall t2 r2 a2)
(CmmAssign (CmmLocal _) e1, CmmAssign (CmmLocal _) e2) -> = t1 == t2 && r1 == r2 && eqListWith (eqExprWith eqBid) a1 a2
let eq = eqExprWith eqBid env e1 e2 eqMiddleWith _ _ _ = False
in (env', eq)
(CmmAssign r1 e1, CmmAssign r2 e2) ->
let eq = r1 == r2
&& eqExprWith eqBid env e1 e2
in (env', eq)
(CmmStore l1 r1, CmmStore l2 r2) ->
let eq = eqExprWith eqBid env l1 l2
&& eqExprWith eqBid env r1 r2
in (env', eq)
-- result registers aren't compared since they are binding occurrences
(CmmUnsafeForeignCall t1 _ a1, CmmUnsafeForeignCall t2 _ a2) ->
let eq = t1 == t2
&& eqLists (eqExprWith eqBid env) a1 a2
in (env', eq)
_ -> (env, False)
where
env' = List.foldl' (\acc (ra,rb) -> addToUFM acc ra rb) emptyUFM
$ List.zip defd_a defd_b
defd_a = foldLocalRegsDefd dflags (flip (:)) [] a
defd_b = foldLocalRegsDefd dflags (flip (:)) [] b
eqLists :: (a -> b -> Bool) -> [a] -> [b] -> Bool
eqLists f (a:as) (b:bs) = f a b && eqLists f as bs
eqLists _ [] [] = True
eqLists _ _ _ = False
eqExprWith :: (BlockId -> BlockId -> Bool) eqExprWith :: (BlockId -> BlockId -> Bool)
-> LocalRegMapping -> CmmExpr -> CmmExpr -> Bool
-> CmmExpr -> CmmExpr eqExprWith eqBid = eq
-> Bool
eqExprWith eqBid env = eq
where where
CmmLit l1 `eq` CmmLit l2 = eqLit l1 l2 CmmLit l1 `eq` CmmLit l2 = eqLit l1 l2
CmmLoad e1 _ `eq` CmmLoad e2 _ = e1 `eq` e2 CmmLoad e1 _ `eq` CmmLoad e2 _ = e1 `eq` e2
CmmReg r1 `eq` CmmReg r2 = r1 `eqReg` r2 CmmReg r1 `eq` CmmReg r2 = r1==r2
CmmRegOff r1 i1 `eq` CmmRegOff r2 i2 = r1 `eqReg` r2 && i1==i2 CmmRegOff r1 i1 `eq` CmmRegOff r2 i2 = r1==r2 && i1==i2
CmmMachOp op1 es1 `eq` CmmMachOp op2 es2 = op1==op2 && es1 `eqs` es2 CmmMachOp op1 es1 `eq` CmmMachOp op2 es2 = op1==op2 && es1 `eqs` es2
CmmStackSlot a1 i1 `eq` CmmStackSlot a2 i2 = eqArea a1 a2 && i1==i2 CmmStackSlot a1 i1 `eq` CmmStackSlot a2 i2 = eqArea a1 a2 && i1==i2
_e1 `eq` _e2 = False _e1 `eq` _e2 = False
xs `eqs` ys = eqLists eq xs ys xs `eqs` ys = eqListWith eq xs ys
-- See Note [Equivalence up to local registers in CBE]
CmmLocal a `eqReg` CmmLocal b
| Just a' <- lookupUFM env a
= a' == b
a `eqReg` b = a == b
eqLit (CmmBlock id1) (CmmBlock id2) = eqBid id1 id2 eqLit (CmmBlock id1) (CmmBlock id2) = eqBid id1 id2
eqLit l1 l2 = l1 == l2 eqLit l1 l2 = l1 == l2
...@@ -362,10 +235,8 @@ eqExprWith eqBid env = eq ...@@ -362,10 +235,8 @@ eqExprWith eqBid env = eq
-- Equality on the body of a block, modulo a function mapping block -- Equality on the body of a block, modulo a function mapping block
-- IDs to block IDs. -- IDs to block IDs.
eqBlockBodyWith :: DynFlags eqBlockBodyWith :: (BlockId -> BlockId -> Bool) -> CmmBlock -> CmmBlock -> Bool
-> (BlockId -> BlockId -> Bool) eqBlockBodyWith eqBid block block'
-> CmmBlock -> CmmBlock -> Bool
eqBlockBodyWith dflags eqBid block block'
{- {-
| equal = pprTrace "equal" (vcat [ppr block, ppr block']) True | equal = pprTrace "equal" (vcat [ppr block, ppr block']) True
| otherwise = pprTrace "not equal" (vcat [ppr block, ppr block']) False | otherwise = pprTrace "not equal" (vcat [ppr block, ppr block']) False
...@@ -376,46 +247,30 @@ eqBlockBodyWith dflags eqBid block block' ...@@ -376,46 +247,30 @@ eqBlockBodyWith dflags eqBid block block'
(_,m',l') = blockSplit block' (_,m',l') = blockSplit block'
nodes' = filter (not . dont_care) (blockToList m') nodes' = filter (not . dont_care) (blockToList m')
eqMids :: LocalRegMapping -> [CmmNode O O] -> [CmmNode O O] -> Bool equal = eqListWith (eqMiddleWith eqBid) nodes nodes' &&
eqMids env (a:as) (b:bs) eqLastWith eqBid l l'
| eq = eqMids env' as bs
where
(env', eq) = eqMiddleWith dflags eqBid env a b eqLastWith :: (BlockId -> BlockId -> Bool) -> CmmNode O C -> CmmNode O C -> Bool
eqMids env [] [] = eqLastWith eqBid env l l' eqLastWith eqBid (CmmBranch bid1) (CmmBranch bid2) = eqBid bid1 bid2
eqMids _ _ _ = False eqLastWith eqBid (CmmCondBranch c1 t1 f1 l1) (CmmCondBranch c2 t2 f2 l2) =
c1 == c2 && l1 == l2 && eqBid t1 t2 && eqBid f1 f2
equal = eqMids emptyUFM nodes nodes' eqLastWith eqBid (CmmCall t1 c1 g1 a1 r1 u1) (CmmCall t2 c2 g2 a2 r2 u2) =
t1 == t2 && eqMaybeWith eqBid c1 c2 && a1 == a2 && r1 == r2 && u1 == u2 && g1 == g2
eqLastWith eqBid (CmmSwitch e1 ids1) (CmmSwitch e2 ids2) =
eqLastWith :: (BlockId -> BlockId -> Bool) -> LocalRegMapping e1 == e2 && eqSwitchTargetWith eqBid ids1 ids2
-> CmmNode O C -> CmmNode O C -> Bool eqLastWith _ _ _ = False
eqLastWith eqBid env a b =
case (a, b) of
(CmmBranch bid1, CmmBranch bid2) -> eqBid bid1 bid2
(CmmCondBranch c1 t1 f1 l1, CmmCondBranch c2 t2 f2 l2) ->
eqExprWith eqBid env c1 c2 && l1 == l2 && eqBid t1 t2 && eqBid f1 f2
(CmmCall t1 c1 g1 a1 r1 u1, CmmCall t2 c2 g2 a2 r2 u2) ->
t1 == t2
&& eqMaybeWith eqBid c1 c2
&& a1 == a2 && r1 == r2 && u1 == u2 && g1 == g2
(CmmSwitch e1 ids1, CmmSwitch e2 ids2) ->
eqExprWith eqBid env e1 e2 && eqSwitchTargetWith eqBid ids1 ids2
-- result registers aren't compared since they are binding occurrences
(CmmForeignCall t1 _ a1 s1 ret_args1 ret_off1 intrbl1,
CmmForeignCall t2 _ a2 s2 ret_args2 ret_off2 intrbl2) ->
t1 == t2
&& eqLists (eqExprWith eqBid env) a1 a2
&& s1 == s2
&& ret_args1 == ret_args2
&& ret_off1 == ret_off2
&& intrbl1 == intrbl2
_ -> False
eqMaybeWith :: (a -> b -> Bool) -> Maybe a -> Maybe b -> Bool eqMaybeWith :: (a -> b -> Bool) -> Maybe a -> Maybe b -> Bool
eqMaybeWith eltEq (Just e) (Just e') = eltEq e e' eqMaybeWith eltEq (Just e) (Just e') = eltEq e e'
eqMaybeWith _ Nothing Nothing = True eqMaybeWith _ Nothing Nothing = True
eqMaybeWith _ _ _ = False eqMaybeWith _ _ _ = False
eqListWith :: (a -> b -> Bool) -> [a] -> [b] -> Bool
eqListWith f (a : as) (b : bs) = f a b && eqListWith f as bs
eqListWith _ [] [] = True
eqListWith _ _ _ = False
-- | Given a block map, ensure that all "target" blocks are covered by -- | Given a block map, ensure that all "target" blocks are covered by
-- the same ticks as the respective "source" blocks. This not only -- the same ticks as the respective "source" blocks. This not only
-- means copying ticks, but also adjusting tick scopes where -- means copying ticks, but also adjusting tick scopes where
......
...@@ -587,6 +587,8 @@ data CallishMachOp ...@@ -587,6 +587,8 @@ data CallishMachOp
| MO_Memcmp Int | MO_Memcmp Int
| MO_PopCnt Width | MO_PopCnt Width
| MO_Pdep Width
| MO_Pext Width
| MO_Clz Width | MO_Clz Width
| MO_Ctz Width | MO_Ctz Width
......
...@@ -1006,6 +1006,16 @@ callishMachOps = listToUFM $ ...@@ -1006,6 +1006,16 @@ callishMachOps = listToUFM $
( "popcnt32", (,) $ MO_PopCnt W32 ), ( "popcnt32", (,) $ MO_PopCnt W32 ),
( "popcnt64", (,) $ MO_PopCnt W64 ), ( "popcnt64", (,) $ MO_PopCnt W64 ),
( "pdep8", (,) $ MO_Pdep W8 ),
( "pdep16", (,) $ MO_Pdep W16 ),
( "pdep32", (,) $ MO_Pdep W32 ),
( "pdep64", (,) $ MO_Pdep W64 ),
( "pext8", (,) $ MO_Pext W8 ),
( "pext16", (,) $ MO_Pext W16 ),
( "pext32", (,) $ MO_Pext W32 ),
( "pext64", (,) $ MO_Pext W64 ),
( "cmpxchg8", (,) $ MO_Cmpxchg W8 ), ( "cmpxchg8", (,) $ MO_Cmpxchg W8 ),
( "cmpxchg16", (,) $ MO_Cmpxchg W16 ), ( "cmpxchg16", (,) $ MO_Cmpxchg W16 ),
( "cmpxchg32", (,) $ MO_Cmpxchg W32 ), ( "cmpxchg32", (,) $ MO_Cmpxchg W32 ),
......
...@@ -68,7 +68,7 @@ cpsTop hsc_env proc = ...@@ -68,7 +68,7 @@ cpsTop hsc_env proc =
----------- Eliminate common blocks ------------------------------------- ----------- Eliminate common blocks -------------------------------------
g <- {-# SCC "elimCommonBlocks" #-} g <- {-# SCC "elimCommonBlocks" #-}
condPass Opt_CmmElimCommonBlocks (elimCommonBlocks dflags) g condPass Opt_CmmElimCommonBlocks elimCommonBlocks g
Opt_D_dump_cmm_cbe "Post common block elimination" Opt_D_dump_cmm_cbe "Post common block elimination"
-- Any work storing block Labels must be performed _after_ -- Any work storing block Labels must be performed _after_
......
...@@ -24,7 +24,6 @@ module Hoopl.Block ...@@ -24,7 +24,6 @@ module Hoopl.Block
, foldBlockNodesB , foldBlockNodesB
, foldBlockNodesB3 , foldBlockNodesB3
, foldBlockNodesF , foldBlockNodesF
, foldBlockNodesF3
, isEmptyBlock , isEmptyBlock
, lastNode , lastNode
, mapBlock , mapBlock
......
...@@ -789,6 +789,8 @@ pprCallishMachOp_for_C mop ...@@ -789,6 +789,8 @@ pprCallishMachOp_for_C mop
MO_Memcmp _ -> text "memcmp" MO_Memcmp _ -> text "memcmp"
(MO_BSwap w) -> ptext (sLit $ bSwapLabel w) (MO_BSwap w) -> ptext (sLit $ bSwapLabel w)
(MO_PopCnt w) -> ptext (sLit $ popCntLabel w) (MO_PopCnt w) -> ptext (sLit $ popCntLabel w)
(MO_Pext w) -> ptext (sLit $ pextLabel w)
(MO_Pdep w) -> ptext (sLit $ pdepLabel w)
(MO_Clz w) -> ptext (sLit $ clzLabel w) (MO_Clz w) -> ptext (sLit $ clzLabel w)
(MO_Ctz w) -> ptext (sLit $ ctzLabel w) (MO_Ctz w) -> ptext (sLit $ ctzLabel w)
(MO_AtomicRMW w amop) -> ptext (sLit $ atomicRMWLabel w amop) (MO_AtomicRMW w amop) -> ptext (sLit $ atomicRMWLabel w amop)
......
...@@ -113,7 +113,8 @@ cgTopRhsClosure dflags rec id ccs _ upd_flag args body = ...@@ -113,7 +113,8 @@ cgTopRhsClosure dflags rec id ccs _ upd_flag args body =
-- BUILD THE OBJECT, AND GENERATE INFO TABLE (IF NECESSARY) -- BUILD THE OBJECT, AND GENERATE INFO TABLE (IF NECESSARY)
; emitDataLits closure_label closure_rep ; emitDataLits closure_label closure_rep
; let fv_details :: [(NonVoid Id, ByteOff)] ; let fv_details :: [(NonVoid Id, ByteOff)]
(_, _, fv_details) = mkVirtHeapOffsets dflags (isLFThunk lf_info) [] header = if isLFThunk lf_info then ThunkHeader else StdHeader
(_, _, fv_details) = mkVirtHeapOffsets dflags header []
-- Don't drop the non-void args until the closure info has been made -- Don't drop the non-void args until the closure info has been made
; forkClosureBody (closureCodeBody True id closure_info ccs ; forkClosureBody (closureCodeBody True id closure_info ccs
(nonVoidIds args) (length args) body fv_details) (nonVoidIds args) (length args) body fv_details)
...@@ -350,9 +351,9 @@ mkRhsClosure dflags bndr cc _ fvs upd_flag args body ...@@ -350,9 +351,9 @@ mkRhsClosure dflags bndr cc _ fvs upd_flag args body
; let name = idName bndr ; let name = idName bndr
descr = closureDescription dflags mod_name name descr = closureDescription dflags mod_name name
fv_details :: [(NonVoid Id, ByteOff)] fv_details :: [(NonVoid Id, ByteOff)]
header = if isLFThunk lf_info then ThunkHeader else StdHeader
(tot_wds, ptr_wds, fv_details) (tot_wds, ptr_wds, fv_details)
= mkVirtHeapOffsets dflags (isLFThunk lf_info) = mkVirtHeapOffsets dflags header (addIdReps reduced_fvs)
(addIdReps reduced_fvs)
closure_info = mkClosureInfo dflags False -- Not static closure_info = mkClosureInfo dflags False -- Not static
bndr lf_info tot_wds ptr_wds bndr lf_info tot_wds ptr_wds
descr descr
...@@ -395,9 +396,10 @@ cgRhsStdThunk bndr lf_info payload ...@@ -395,9 +396,10 @@ cgRhsStdThunk bndr lf_info payload
{ -- LAY OUT THE OBJECT { -- LAY OUT THE OBJECT
mod_name <- getModuleName mod_name <- getModuleName
; dflags <- getDynFlags ; dflags <- getDynFlags
; let (tot_wds, ptr_wds, payload_w_offsets) ; let header = if isLFThunk lf_info then ThunkHeader else StdHeader
= mkVirtHeapOffsets dflags (isLFThunk lf_info) (tot_wds, ptr_wds, payload_w_offsets)
(addArgReps (nonVoidStgArgs payload)) = mkVirtHeapOffsets dflags header
(addArgReps (nonVoidStgArgs payload))
descr = closureDescription dflags mod_name (idName bndr) descr = closureDescription dflags mod_name (idName bndr)
closure_info = mkClosureInfo dflags False -- Not static closure_info = mkClosureInfo dflags False -- Not static
......
...@@ -79,11 +79,10 @@ cgTopRhsCon dflags id con args = ...@@ -79,11 +79,10 @@ cgTopRhsCon dflags id con args =
-- LAY IT OUT -- LAY IT OUT
; let ; let
is_thunk = False
(tot_wds, -- #ptr_wds + #nonptr_wds (tot_wds, -- #ptr_wds + #nonptr_wds
ptr_wds, -- #ptr_wds ptr_wds, -- #ptr_wds
nv_args_w_offsets) = nv_args_w_offsets) =
mkVirtHeapOffsetsWithPadding dflags is_thunk (addArgReps args) mkVirtHeapOffsetsWithPadding dflags StdHeader (addArgReps args)
mk_payload (Padding len _) = return (CmmInt 0 (widthFromBytes len)) mk_payload (Padding len _) = return (CmmInt 0 (widthFromBytes len))
mk_payload (FieldOff arg _) = do mk_payload (FieldOff arg _) = do
......
...@@ -19,6 +19,7 @@ module StgCmmLayout ( ...@@ -19,6 +19,7 @@ module StgCmmLayout (
slowCall, directCall, slowCall, directCall,
FieldOffOrPadding(..), FieldOffOrPadding(..),
ClosureHeader(..),
mkVirtHeapOffsets, mkVirtHeapOffsets,
mkVirtHeapOffsetsWithPadding, mkVirtHeapOffsetsWithPadding,
mkVirtConstrOffsets, mkVirtConstrOffsets,
...@@ -399,9 +400,17 @@ data FieldOffOrPadding a ...@@ -399,9 +400,17 @@ data FieldOffOrPadding a
| Padding ByteOff -- Length of padding in bytes. | Padding ByteOff -- Length of padding in bytes.
ByteOff -- Offset in bytes. ByteOff -- Offset in bytes.
-- | Used to tell the various @mkVirtHeapOffsets@ functions what kind
-- of header the object has. This will be accounted for in the
-- offsets of the fields returned.
data ClosureHeader
= NoHeader
| StdHeader
| ThunkHeader
mkVirtHeapOffsetsWithPadding mkVirtHeapOffsetsWithPadding
:: DynFlags :: DynFlags
-> Bool -- True <=> is a thunk -> ClosureHeader -- What kind of header to account for
-> [NonVoid (PrimRep, a)] -- Things to make offsets for -> [NonVoid (PrimRep, a)] -- Things to make offsets for
-> ( WordOff -- Total number of words allocated -> ( WordOff -- Total number of words allocated
, WordOff -- Number of words allocated for *pointers* , WordOff -- Number of words allocated for *pointers*
...@@ -415,15 +424,17 @@ mkVirtHeapOffsetsWithPadding ...@@ -415,15 +424,17 @@ mkVirtHeapOffsetsWithPadding
-- mkVirtHeapOffsetsWithPadding always returns boxed things with smaller offsets -- mkVirtHeapOffsetsWithPadding always returns boxed things with smaller offsets
-- than the unboxed things -- than the unboxed things
mkVirtHeapOffsetsWithPadding dflags is_thunk things = mkVirtHeapOffsetsWithPadding dflags header things =
ASSERT(not (any (isVoidRep . fst . fromNonVoid) things)) ASSERT(not (any (isVoidRep . fst . fromNonVoid) things))
( tot_wds ( tot_wds
, bytesToWordsRoundUp dflags bytes_of_ptrs , bytesToWordsRoundUp dflags bytes_of_ptrs
, concat (ptrs_w_offsets ++ non_ptrs_w_offsets) ++ final_pad , concat (ptrs_w_offsets ++ non_ptrs_w_offsets) ++ final_pad
) )
where where
hdr_words | is_thunk = thunkHdrSize dflags hdr_words = case header of
| otherwise = fixedHdrSizeW dflags NoHeader -> 0
StdHeader -> fixedHdrSizeW dflags
ThunkHeader -> thunkHdrSize dflags
hdr_bytes = wordsToBytes dflags hdr_words hdr_bytes = wordsToBytes dflags hdr_words
(ptrs, non_ptrs) = partition (isGcPtrRep . fst . fromNonVoid) things (ptrs, non_ptrs) = partition (isGcPtrRep . fst . fromNonVoid) things
...@@ -472,25 +483,25 @@ mkVirtHeapOffsetsWithPadding dflags is_thunk things = ...@@ -472,25 +483,25 @@ mkVirtHeapOffsetsWithPadding dflags is_thunk things =
mkVirtHeapOffsets mkVirtHeapOffsets
:: DynFlags :: DynFlags
-> Bool -- True <=> is a thunk -> ClosureHeader -- What kind of header to account for
-> [NonVoid (PrimRep,a)] -- Things to make offsets for -> [NonVoid (PrimRep,a)] -- Things to make offsets for
-> (WordOff, -- _Total_ number of words allocated -> (WordOff, -- _Total_ number of words allocated
WordOff, -- Number of words allocated for *pointers* WordOff, -- Number of words allocated for *pointers*
[(NonVoid a, ByteOff)]) [(NonVoid a, ByteOff)])
mkVirtHeapOffsets dflags is_thunk things = mkVirtHeapOffsets dflags header things =
( tot_wds ( tot_wds
, ptr_wds , ptr_wds
, [ (field, offset) | (FieldOff field offset) <- things_offsets ] , [ (field, offset) | (FieldOff field offset) <- things_offsets ]
) )
where where
(tot_wds, ptr_wds, things_offsets) = (tot_wds, ptr_wds, things_offsets) =
mkVirtHeapOffsetsWithPadding dflags is_thunk things mkVirtHeapOffsetsWithPadding dflags header things
-- | Just like mkVirtHeapOffsets, but for constructors -- | Just like mkVirtHeapOffsets, but for constructors
mkVirtConstrOffsets mkVirtConstrOffsets
:: DynFlags -> [NonVoid (PrimRep, a)] :: DynFlags -> [NonVoid (PrimRep, a)]
-> (WordOff, WordOff, [(NonVoid a, ByteOff)]) -> (WordOff, WordOff, [(NonVoid a, ByteOff)])
mkVirtConstrOffsets dflags = mkVirtHeapOffsets dflags False mkVirtConstrOffsets dflags = mkVirtHeapOffsets dflags StdHeader
-- | Just like mkVirtConstrOffsets, but used when we don't have the actual -- | Just like mkVirtConstrOffsets, but used when we don't have the actual
-- arguments. Useful when e.g. generating info tables; we just need to know -- arguments. Useful when e.g. generating info tables; we just need to know
......
...@@ -584,6 +584,20 @@ emitPrimOp _ [res] PopCnt32Op [w] = emitPopCntCall res w W32 ...@@ -584,6 +584,20 @@ emitPrimOp _ [res] PopCnt32Op [w] = emitPopCntCall res w W32
emitPrimOp _ [res] PopCnt64Op [w] = emitPopCntCall res w W64 emitPrimOp _ [res] PopCnt64Op [w] = emitPopCntCall res w W64
emitPrimOp dflags [res] PopCntOp [w] = emitPopCntCall res w (wordWidth dflags) emitPrimOp dflags [res] PopCntOp [w] = emitPopCntCall res w (wordWidth dflags)
-- Parallel bit deposit
emitPrimOp _ [res] Pdep8Op [src, mask] = emitPdepCall res src mask W8
emitPrimOp _ [res] Pdep16Op [src, mask] = emitPdepCall res src mask W16
emitPrimOp _ [res] Pdep32Op [src, mask] = emitPdepCall res src mask W32
emitPrimOp _ [res] Pdep64Op [src, mask] = emitPdepCall res src mask W64
emitPrimOp dflags [res] PdepOp [src, mask] = emitPdepCall res src mask (wordWidth dflags)
-- Parallel bit extract
emitPrimOp _ [res] Pext8Op [src, mask] = emitPextCall res src mask W8
emitPrimOp _ [res] Pext16Op [src, mask] = emitPextCall res src mask W16
emitPrimOp _ [res] Pext32Op [src, mask] = emitPextCall res src mask W32
emitPrimOp _ [res] Pext64Op [src, mask] = emitPextCall res src mask W64
emitPrimOp dflags [res] PextOp [src, mask] = emitPextCall res src mask (wordWidth dflags)
-- count leading zeros -- count leading zeros
emitPrimOp _ [res] Clz8Op [w] = emitClzCall res w W8 emitPrimOp _ [res] Clz8Op [w] = emitClzCall res w W8
emitPrimOp _ [res] Clz16Op [w] = emitClzCall res w W16 emitPrimOp _ [res] Clz16Op [w] = emitClzCall res w W16
...@@ -1732,8 +1746,51 @@ doCompareByteArraysOp res ba1 ba1_off ba2 ba2_off n = do ...@@ -1732,8 +1746,51 @@ doCompareByteArraysOp res ba1 ba1_off ba2 ba2_off n = do
dflags <- getDynFlags dflags <- getDynFlags
ba1_p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags ba1 (arrWordsHdrSize dflags)) ba1_off ba1_p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags ba1 (arrWordsHdrSize dflags)) ba1_off
ba2_p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags ba2 (arrWordsHdrSize dflags)) ba2_off ba2_p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags ba2 (arrWordsHdrSize dflags)) ba2_off
-- short-cut in case of equal pointers avoiding a costly
-- subroutine call to the memcmp(3) routine; the Cmm logic below
-- results in assembly code being generated for
--
-- cmpPrefix10 :: ByteArray# -> ByteArray# -> Int#
-- cmpPrefix10 ba1 ba2 = compareByteArrays# ba1 0# ba2 0# 10#
--
-- that looks like
--
-- leaq 16(%r14),%rax
-- leaq 16(%rsi),%rbx
-- xorl %ecx,%ecx
-- cmpq %rbx,%rax
-- je l_ptr_eq
--
-- ; NB: the common case (unequal pointers) falls-through
-- ; the conditional jump, and therefore matches the
-- ; usual static branch prediction convention of modern cpus
--
-- subq $8,%rsp
-- movq %rbx,%rsi
-- movq %rax,%rdi
-- movl $10,%edx
-- xorl %eax,%eax
-- call memcmp
-- addq $8,%rsp
-- movslq %eax,%rax
-- movq %rax,%rcx
-- l_ptr_eq:
-- movq %rcx,%rbx
-- jmp *(%rbp)
l_ptr_eq <- newBlockId
l_ptr_ne <- newBlockId
emit (mkAssign (CmmLocal res) (zeroExpr dflags))
emit (mkCbranch (cmmEqWord dflags ba1_p ba2_p)
l_ptr_eq l_ptr_ne (Just False))
emitLabel l_ptr_ne
emitMemcmpCall res ba1_p ba2_p n 1 emitMemcmpCall res ba1_p ba2_p n 1
emitLabel l_ptr_eq
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
-- Copying byte arrays -- Copying byte arrays
...@@ -2266,6 +2323,20 @@ emitPopCntCall res x width = do ...@@ -2266,6 +2323,20 @@ emitPopCntCall res x width = do
(MO_PopCnt width) (MO_PopCnt width)
[ x ] [ x ]
emitPdepCall :: LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPdepCall res x y width = do
emitPrimCall
[ res ]
(MO_Pdep width)
[ x, y ]
emitPextCall :: LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPextCall res x y width = do
emitPrimCall
[ res ]
(MO_Pext width)
[ x, y ]
emitClzCall :: LocalReg -> CmmExpr -> Width -> FCode () emitClzCall :: LocalReg -> CmmExpr -> Width -> FCode ()
emitClzCall res x width = do emitClzCall res x width = do
emitPrimCall emitPrimCall
......
...@@ -209,7 +209,7 @@ ifProfilingL dflags xs ...@@ -209,7 +209,7 @@ ifProfilingL dflags xs
initCostCentres :: CollectedCCs -> FCode () initCostCentres :: CollectedCCs -> FCode ()
-- Emit the declarations -- Emit the declarations
initCostCentres (local_CCs, ___extern_CCs, singleton_CCSs) initCostCentres (local_CCs, singleton_CCSs)
= do dflags <- getDynFlags = do dflags <- getDynFlags
when (gopt Opt_SccProfilingOn dflags) $ when (gopt Opt_SccProfilingOn dflags) $
do mapM_ emitCostCentreDecl local_CCs do mapM_ emitCostCentreDecl local_CCs
......
...@@ -386,13 +386,13 @@ orphNamesOfCo (CoherenceCo co1 co2) = orphNamesOfCo co1 `unionNameSet` orphNames ...@@ -386,13 +386,13 @@ orphNamesOfCo (CoherenceCo co1 co2) = orphNamesOfCo co1 `unionNameSet` orphNames
orphNamesOfCo (KindCo co) = orphNamesOfCo co orphNamesOfCo (KindCo co) = orphNamesOfCo co
orphNamesOfCo (SubCo co) = orphNamesOfCo co orphNamesOfCo (SubCo co) = orphNamesOfCo co
orphNamesOfCo (AxiomRuleCo _ cs) = orphNamesOfCos cs orphNamesOfCo (AxiomRuleCo _ cs) = orphNamesOfCos cs
orphNamesOfCo (HoleCo _) = emptyNameSet
orphNamesOfProv :: UnivCoProvenance -> NameSet orphNamesOfProv :: UnivCoProvenance -> NameSet
orphNamesOfProv UnsafeCoerceProv = emptyNameSet orphNamesOfProv UnsafeCoerceProv = emptyNameSet
orphNamesOfProv (PhantomProv co) = orphNamesOfCo co orphNamesOfProv (PhantomProv co) = orphNamesOfCo co
orphNamesOfProv (ProofIrrelProv co) = orphNamesOfCo co orphNamesOfProv (ProofIrrelProv co) = orphNamesOfCo co
orphNamesOfProv (PluginProv _) = emptyNameSet orphNamesOfProv (PluginProv _) = emptyNameSet
orphNamesOfProv (HoleProv _) = emptyNameSet
orphNamesOfCos :: [Coercion] -> NameSet orphNamesOfCos :: [Coercion] -> NameSet
orphNamesOfCos = orphNamesOfThings orphNamesOfCo orphNamesOfCos = orphNamesOfThings orphNamesOfCo
......
...@@ -531,7 +531,7 @@ lintSingleBinding top_lvl_flag rec_flag (binder,rhs) ...@@ -531,7 +531,7 @@ lintSingleBinding top_lvl_flag rec_flag (binder,rhs)
; checkL ( isJoinId binder ; checkL ( isJoinId binder
|| not (isUnliftedType binder_ty) || not (isUnliftedType binder_ty)
|| (isNonRec rec_flag && exprOkForSpeculation rhs) || (isNonRec rec_flag && exprOkForSpeculation rhs)
|| exprIsLiteralString rhs) || exprIsTickedString rhs)
(badBndrTyMsg binder (text "unlifted")) (badBndrTyMsg binder (text "unlifted"))
-- Check that if the binder is top-level or recursive, it's not -- Check that if the binder is top-level or recursive, it's not
...@@ -539,14 +539,14 @@ lintSingleBinding top_lvl_flag rec_flag (binder,rhs) ...@@ -539,14 +539,14 @@ lintSingleBinding top_lvl_flag rec_flag (binder,rhs)
-- computation to perform, see Note [CoreSyn top-level string literals]. -- computation to perform, see Note [CoreSyn top-level string literals].
; checkL (not (isStrictId binder) ; checkL (not (isStrictId binder)
|| (isNonRec rec_flag && not (isTopLevel top_lvl_flag)) || (isNonRec rec_flag && not (isTopLevel top_lvl_flag))
|| exprIsLiteralString rhs) || exprIsTickedString rhs)
(mkStrictMsg binder) (mkStrictMsg binder)
-- Check that if the binder is at the top level and has type Addr#, -- Check that if the binder is at the top level and has type Addr#,
-- that it is a string literal, see -- that it is a string literal, see
-- Note [CoreSyn top-level string literals]. -- Note [CoreSyn top-level string literals].
; checkL (not (isTopLevel top_lvl_flag && binder_ty `eqType` addrPrimTy) ; checkL (not (isTopLevel top_lvl_flag && binder_ty `eqType` addrPrimTy)
|| exprIsLiteralString rhs) || exprIsTickedString rhs)
(mkTopNonLitStrMsg binder) (mkTopNonLitStrMsg binder)
; flags <- getLintFlags ; flags <- getLintFlags
...@@ -1123,7 +1123,7 @@ checkCaseAlts e ty alts = ...@@ -1123,7 +1123,7 @@ checkCaseAlts e ty alts =
where where
(con_alts, maybe_deflt) = findDefault alts (con_alts, maybe_deflt) = findDefault alts
-- Check that successive alternatives have increasing tags -- Check that successive alternatives have strictly increasing tags
increasing_tag (alt1 : rest@( alt2 : _)) = alt1 `ltAlt` alt2 && increasing_tag rest increasing_tag (alt1 : rest@( alt2 : _)) = alt1 `ltAlt` alt2 && increasing_tag rest
increasing_tag _ = True increasing_tag _ = True
...@@ -1666,8 +1666,6 @@ lintCoercion co@(UnivCo prov r ty1 ty2) ...@@ -1666,8 +1666,6 @@ lintCoercion co@(UnivCo prov r ty1 ty2)
; check_kinds kco k1 k2 } ; check_kinds kco k1 k2 }
PluginProv _ -> return () -- no extra checks PluginProv _ -> return () -- no extra checks
HoleProv h -> addErrL $
text "Unfilled coercion hole:" <+> ppr h
; when (r /= Phantom && classifiesTypeWithValues k1 ; when (r /= Phantom && classifiesTypeWithValues k1
&& classifiesTypeWithValues k2) && classifiesTypeWithValues k2)
...@@ -1874,6 +1872,11 @@ lintCoercion this@(AxiomRuleCo co cs) ...@@ -1874,6 +1872,11 @@ lintCoercion this@(AxiomRuleCo co cs)
[ text "Expected:" <+> int (n + length es) [ text "Expected:" <+> int (n + length es)
, text "Provided:" <+> int n ] , text "Provided:" <+> int n ]
lintCoercion (HoleCo h)
= do { addErrL $ text "Unfilled coercion hole:" <+> ppr h
; lintCoercion (CoVarCo (coHoleCoVar h)) }
---------- ----------
lintUnliftedCoVar :: CoVar -> LintM () lintUnliftedCoVar :: CoVar -> LintM ()
lintUnliftedCoVar cv lintUnliftedCoVar cv
......
...@@ -22,7 +22,7 @@ module CoreOpt ( ...@@ -22,7 +22,7 @@ module CoreOpt (
import GhcPrelude import GhcPrelude
import CoreArity( joinRhsArity, etaExpandToJoinPoint ) import CoreArity( etaExpandToJoinPoint )
import CoreSyn import CoreSyn
import CoreSubst import CoreSubst
...@@ -644,58 +644,18 @@ joinPointBinding_maybe bndr rhs ...@@ -644,58 +644,18 @@ joinPointBinding_maybe bndr rhs
= Just (bndr, rhs) = Just (bndr, rhs)
| AlwaysTailCalled join_arity <- tailCallInfo (idOccInfo bndr) | AlwaysTailCalled join_arity <- tailCallInfo (idOccInfo bndr)
, not (bad_unfolding join_arity (idUnfolding bndr))
, (bndrs, body) <- etaExpandToJoinPoint join_arity rhs , (bndrs, body) <- etaExpandToJoinPoint join_arity rhs
= Just (bndr `asJoinId` join_arity, mkLams bndrs body) = Just (bndr `asJoinId` join_arity, mkLams bndrs body)
| otherwise | otherwise
= Nothing = Nothing
where
-- bad_unfolding returns True if we should /not/ convert a non-join-id
-- into a join-id, even though it is AlwaysTailCalled
-- See Note [Join points and INLINE pragmas]
bad_unfolding join_arity (CoreUnfolding { uf_src = src, uf_tmpl = rhs })
= isStableSource src && join_arity > joinRhsArity rhs
bad_unfolding _ (DFunUnfolding {})
= True
bad_unfolding _ _
= False
joinPointBindings_maybe :: [(InBndr, InExpr)] -> Maybe [(InBndr, InExpr)] joinPointBindings_maybe :: [(InBndr, InExpr)] -> Maybe [(InBndr, InExpr)]
joinPointBindings_maybe bndrs joinPointBindings_maybe bndrs
= mapM (uncurry joinPointBinding_maybe) bndrs = mapM (uncurry joinPointBinding_maybe) bndrs
{- Note [Join points and INLINE pragmas] {- *********************************************************************
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
f x = let g = \x. not -- Arity 1
{-# INLINE g #-}
in case x of
A -> g True True
B -> g True False
C -> blah2
Here 'g' is always tail-called applied to 2 args, but the stable
unfolding captured by the INLINE pragma has arity 1. If we try to
convert g to be a join point, its unfolding will still have arity 1
(since it is stable, and we don't meddle with stable unfoldings), and
Lint will complain (see Note [Invariants on join points], (2a), in
CoreSyn. Trac #13413.
Moreover, since g is going to be inlined anyway, there is no benefit
from making it a join point.
If it is recursive, and uselessly marked INLINE, this will stop us
making it a join point, which is annoying. But occasionally
(notably in class methods; see Note [Instances and loop breakers] in
TcInstDcls) we mark recursive things as INLINE but the recursion
unravels; so ignoring INLINE pragmas on recursive things isn't good
either.
************************************************************************
* * * *
exprIsConApp_maybe exprIsConApp_maybe
* * * *
......
...@@ -60,12 +60,14 @@ import Name ( NamedThing(..), nameSrcSpan ) ...@@ -60,12 +60,14 @@ import Name ( NamedThing(..), nameSrcSpan )
import SrcLoc ( SrcSpan(..), realSrcLocSpan, mkRealSrcLoc ) import SrcLoc ( SrcSpan(..), realSrcLocSpan, mkRealSrcLoc )
import Data.Bits import Data.Bits
import MonadUtils ( mapAccumLM ) import MonadUtils ( mapAccumLM )
import Data.List ( mapAccumL ) import Data.List ( mapAccumL, foldl' )
import Control.Monad import Control.Monad
import CostCentre ( CostCentre, ccFromThisModule )
import qualified Data.Set as S
{- {-
-- --------------------------------------------------------------------------- -- ---------------------------------------------------------------------------
-- Overview -- Note [CorePrep Overview]
-- --------------------------------------------------------------------------- -- ---------------------------------------------------------------------------
The goal of this pass is to prepare for code generation. The goal of this pass is to prepare for code generation.
...@@ -124,6 +126,10 @@ The goal of this pass is to prepare for code generation. ...@@ -124,6 +126,10 @@ The goal of this pass is to prepare for code generation.
(non-type) applications where we can, and make sure that we (non-type) applications where we can, and make sure that we
annotate according to scoping rules when floating. annotate according to scoping rules when floating.
12. Collect cost centres (including cost centres in unfoldings) if we're in
profiling mode. We have to do this here beucase we won't have unfoldings
after this pass (see `zapUnfolding` and Note [Drop unfoldings and rules].
This is all done modulo type applications and abstractions, so that This is all done modulo type applications and abstractions, so that
when type erasure is done for conversion to STG, we don't end up with when type erasure is done for conversion to STG, we don't end up with
any trivial or useless bindings. any trivial or useless bindings.
...@@ -169,7 +175,7 @@ type CpeRhs = CoreExpr -- Non-terminal 'rhs' ...@@ -169,7 +175,7 @@ type CpeRhs = CoreExpr -- Non-terminal 'rhs'
-} -}
corePrepPgm :: HscEnv -> Module -> ModLocation -> CoreProgram -> [TyCon] corePrepPgm :: HscEnv -> Module -> ModLocation -> CoreProgram -> [TyCon]
-> IO CoreProgram -> IO (CoreProgram, S.Set CostCentre)
corePrepPgm hsc_env this_mod mod_loc binds data_tycons = corePrepPgm hsc_env this_mod mod_loc binds data_tycons =
withTiming (pure dflags) withTiming (pure dflags)
(text "CorePrep"<+>brackets (ppr this_mod)) (text "CorePrep"<+>brackets (ppr this_mod))
...@@ -177,7 +183,13 @@ corePrepPgm hsc_env this_mod mod_loc binds data_tycons = ...@@ -177,7 +183,13 @@ corePrepPgm hsc_env this_mod mod_loc binds data_tycons =
us <- mkSplitUniqSupply 's' us <- mkSplitUniqSupply 's'
initialCorePrepEnv <- mkInitialCorePrepEnv dflags hsc_env initialCorePrepEnv <- mkInitialCorePrepEnv dflags hsc_env
let implicit_binds = mkDataConWorkers dflags mod_loc data_tycons let cost_centres
| WayProf `elem` ways dflags
= collectCostCentres this_mod binds
| otherwise
= S.empty
implicit_binds = mkDataConWorkers dflags mod_loc data_tycons
-- NB: we must feed mkImplicitBinds through corePrep too -- NB: we must feed mkImplicitBinds through corePrep too
-- so that they are suitably cloned and eta-expanded -- so that they are suitably cloned and eta-expanded
...@@ -187,7 +199,7 @@ corePrepPgm hsc_env this_mod mod_loc binds data_tycons = ...@@ -187,7 +199,7 @@ corePrepPgm hsc_env this_mod mod_loc binds data_tycons =
return (deFloatTop (floats1 `appendFloats` floats2)) return (deFloatTop (floats1 `appendFloats` floats2))
endPassIO hsc_env alwaysQualify CorePrep binds_out [] endPassIO hsc_env alwaysQualify CorePrep binds_out []
return binds_out return (binds_out, cost_centres)
where where
dflags = hsc_dflags hsc_env dflags = hsc_dflags hsc_env
...@@ -1600,3 +1612,39 @@ wrapTicks (Floats flag floats0) expr = ...@@ -1600,3 +1612,39 @@ wrapTicks (Floats flag floats0) expr =
(ppr other) (ppr other)
wrapBind t (NonRec binder rhs) = NonRec binder (mkTick t rhs) wrapBind t (NonRec binder rhs) = NonRec binder (mkTick t rhs)
wrapBind t (Rec pairs) = Rec (mapSnd (mkTick t) pairs) wrapBind t (Rec pairs) = Rec (mapSnd (mkTick t) pairs)
------------------------------------------------------------------------------
-- Collecting cost centres
-- ---------------------------------------------------------------------------
-- | Collect cost centres defined in the current module, including those in
-- unfoldings.
collectCostCentres :: Module -> CoreProgram -> S.Set CostCentre
collectCostCentres mod_name
= foldl' go_bind S.empty
where
go cs e = case e of
Var{} -> cs
Lit{} -> cs
App e1 e2 -> go (go cs e1) e2
Lam _ e -> go cs e
Let b e -> go (go_bind cs b) e
Case scrt _ _ alts -> go_alts (go cs scrt) alts
Cast e _ -> go cs e
Tick (ProfNote cc _ _) e ->
go (if ccFromThisModule cc mod_name then S.insert cc cs else cs) e
Tick _ e -> go cs e
Type{} -> cs
Coercion{} -> cs
go_alts = foldl' (\cs (_con, _bndrs, e) -> go cs e)
go_bind :: S.Set CostCentre -> CoreBind -> S.Set CostCentre
go_bind cs (NonRec b e) =
go (maybe cs (go cs) (get_unf b)) e
go_bind cs (Rec bs) =
foldl' (\cs' (b, e) -> go (maybe cs' (go cs') (get_unf b)) e) cs bs
-- Unfoldings may have cost centres that in the original definion are
-- optimized away, see #5889.
get_unf = maybeUnfoldingTemplate . realIdUnfolding
...@@ -401,10 +401,10 @@ The solution is simply to allow top-level unlifted binders. We can't allow ...@@ -401,10 +401,10 @@ The solution is simply to allow top-level unlifted binders. We can't allow
arbitrary unlifted expression at the top-level though, unlifted binders cannot arbitrary unlifted expression at the top-level though, unlifted binders cannot
be thunks, so we just allow string literals. be thunks, so we just allow string literals.
It is important to note that top-level primitive string literals cannot be We allow the top-level primitive string literals to be wrapped in Ticks
wrapped in Ticks, as is otherwise done with lifted bindings. CoreToStg expects in the same way they can be wrapped when nested in an expression.
to see just a plain (Lit (MachStr ...)) expression on the RHS of primitive CoreToSTG currently discards Ticks around top-level primitive string literals.
string bindings; anything else and things break. CoreLint checks this invariant. See Trac #14779.
Also see Note [Compilation plan for top-level string literals]. Also see Note [Compilation plan for top-level string literals].
...@@ -414,7 +414,7 @@ Here is a summary on how top-level string literals are handled by various ...@@ -414,7 +414,7 @@ Here is a summary on how top-level string literals are handled by various
parts of the compilation pipeline. parts of the compilation pipeline.
* In the source language, there is no way to bind a primitive string literal * In the source language, there is no way to bind a primitive string literal
at the top leve. at the top level.
* In Core, we have a special rule that permits top-level Addr# bindings. See * In Core, we have a special rule that permits top-level Addr# bindings. See
Note [CoreSyn top-level string literals]. Core-to-core passes may introduce Note [CoreSyn top-level string literals]. Core-to-core passes may introduce
......