You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GHC 9.4.4同时使用-fllvm与-O2编译Haskell代码出错咨询

GHC 9.4.4 同时使用 -fllvm 和 -O2 编译报错的解决方法

问题现象

使用GHC 9.4.4编译Haskell代码时,同时指定-fllvm和-O2参数会触发LLVM优化器错误:

$ ~/.ghcup/ghc/9.4.4/bin/ghc --make -fllvm -O2 test.hs
Loaded package environment from /home/dunham/.ghc/x86_64-linux-9.4.4/environments/default
[1 of 2] Compiling Main             ( test.hs, test.o )
Cannot specify -O# and --passes=/--foo-pass, use -passes='default<O#>,other-pass'

<no location info>: error:
    `opt' failed in phase `LLVM Optimiser'. (Exit code: 1)

但单独使用-fllvm或-O2参数时,编译均能成功:
仅用-fllvm:

$ ~/.ghcup/ghc/9.4.4/bin/ghc --make -fllvm test.hs
Loaded package environment from /home/dunham/.ghc/x86_64-linux-9.4.4/environments/default
[1 of 2] Compiling Main             ( test.hs, test.o )
[2 of 2] Linking test

仅用-O2:

$ ~/.ghcup/ghc/9.4.4/bin/ghc --make -O2 test.hs
Loaded package environment from /home/dunham/.ghc/x86_64-linux-9.4.4/environments/default
[1 of 2] Compiling Main             ( test.hs, test.o )
[2 of 2] Linking test

涉及的test.hs代码如下:

import Data.Array.Base
import System.Environment
import Numeric

main = do 
        [arg] <- getArgs
        let n = (read arg) - 1 
        let init = listArray (0,n) (repeat 1.0)
        let (v:u:rest) = drop 19 $ iterate (eval_AtA_times_u n) init
        let vBv = sum [(u!i)*(v!i) |i<-[0..n]]
        let vv  = sum [(v!i)*(v!i) |i<-[0..n]]
        putStrLn $ showFFloat (Just 9) (sqrt (vBv/vv)) ""

eval_AtA_times_u n u = eval_At_times_u n v
    where v = eval_A_times_u n u

eval_A x y = 1.0/((i+j)*(i+j+1)/2+i+1)
    where i = fromIntegral x
          j = fromIntegral y

eval_A_times_u :: Int -> UArray Int Double -> UArray Int Double
eval_A_times_u n u = unsafeAccumArray (+) 0 (0,n) 
                     [(i,(eval_A i j) * u!j)|i<-[0..n], j<-[0..n]]
   
eval_At_times_u :: Int -> UArray Int Double -> UArray Int Double
eval_At_times_u n u = unsafeAccumArray (+) 0 (0,n) 
                      [(i,(eval_A j i) * u!j)|i<-[0..n], j<-[0..n]]

错误原因

这是GHC 9.4.4版本的已知问题:当同时启用-fllvm和-O2时,GHC会错误地向LLVM的opt工具同时传递-O2参数和自定义pass配置,而LLVM不允许这种混合传递方式,必须通过-passes参数统一指定优化级别和额外pass。

解决方案

方案1:显式指定LLVM优化pass

用-fllvm-passes参数替代直接的-O2,明确告诉LLVM使用O2级别的默认优化pass:

$ ~/.ghcup/ghc/9.4.4/bin/ghc --make -fllvm -fllvm-passes="default<O2>" test.hs

方案2:升级GHC版本

该bug在GHC 9.4.5及更高版本中已被修复,通过ghcup升级到新版本即可解决:

$ ghcup upgrade ghc 9.4.5
# 或直接升级到最新稳定版
$ ghcup install ghc latest
$ ghcup set ghc latest

方案3:临时降级优化级别(不推荐)

如果暂时无法升级,可尝试用-O1结合-fllvm,虽优化级别稍低,但能避免参数冲突:

$ ~/.ghcup/ghc/9.4.4/bin/ghc --make -fllvm -O1 test.hs

内容的提问来源于stack exchange,提问作者igouy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 17:31:00