Skip to content

globalRegMaybe inconsistencies on aarch64

CmmSink claims in one place globalRegMaybe isn't available on ARM:

isTrivial :: Platform -> CmmExpr -> Bool
isTrivial _ (CmmReg (CmmLocal _)) = True
isTrivial platform (CmmReg (CmmGlobal (GlobalRegUse r _))) = -- see Note [Inline GlobalRegs?]
  if isARM (platformArch platform)
  then True -- CodeGen.Platform.ARM does not have globalRegMaybe
  else isJust (globalRegMaybe platform r)
  -- GlobalRegs that are loads from BaseReg are not trivial
isTrivial _ (CmmLit _) = True
isTrivial _ _          = False

However CmmSink also has unguarded calls to globalRegMaybe which should be reachable on ARM in the conflicts function:

  -- (6) suspendThread clobbers every global register not backed by a real
  -- register. It also clobbers heap and stack but this is handled by (5)
  | CmmUnsafeForeignCall (PrimTarget MO_SuspendThread) _ _ <- node
  , foldRegsUsed platform (\b g -> globalRegMaybe platform g == Nothing || b) False rhs
  = True

So if this were true I would expect this to fail.

Indeed in CodeGen.Platform.h we have:

globalRegMaybe :: GlobalReg -> Maybe RealReg
#if defined(MACHREGS_i386) || defined(MACHREGS_x86_64) \
    || defined(MACHREGS_powerpc) \
    || defined(MACHREGS_arm) || defined(MACHREGS_aarch64) \
    || defined(MACHREGS_s390x) || defined(MACHREGS_riscv64) \
    || defined(MACHREGS_wasm32) \
    || defined(MACHREGS_loongarch64)

# if defined(REG_Base)
globalRegMaybe BaseReg                  = Just (RealRegSingle REG_Base)
# endif
# if defined(REG_R1)
globalRegMaybe (VanillaReg 1)           = Just (RealRegSingle REG_R1)
# endif
# if defined(REG_R2)
globalRegMaybe (VanillaReg 2)           = Just (RealRegSingle REG_R2)
# endif
...

Which should work for aarch64 just fine. So I think this is no longer the case and the special casing can be removed.

Edited by sheaf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information