Skip to content

NCG doesn't realise shift instructions trash shifted input?

It looks like the NCG on amd64/Linux doesn't realise that shifting instructions trash the shifted input (spotted due to arith011). With this input file:

module Main where

import Data.Bits
import GHC.Exts

main = print ((2 :: Int) `qrotate` 1)

{-# NOINLINE qrotate #-}
(I# x#) `qrotate` (I# i#) =
    (I# (word2Int# (a# `or#` b#)), W# a#, W# b#)
    where
    x'# = int2Word# x#
    i'# = word2Int# (int2Word# i# `and#` int2Word# (wsib -# 1#))
    a# = x'# `uncheckedShiftL#` i'#
    b# = x'# `uncheckedShiftRL#` (wsib -# i'#)

    wsib = 64#

compiling with -O -fglasgow-exts -v9 if I merge the Cmm and Asm output I get:

R2 == rsi
R3 == rdi

_sTh = R3;            movq %rdi,%rax  rax=_sTh
_sTj = _sTh & 63;     andq $63,%rax   rax=_sTj
_sTl = _sTj;          rax=_sTl
_sTp = R2;            movq %rsi,%rcx  rcx=_sTp
                      movq %rcx,64(%rsp)
_sTs = 64 - _sTl;     movl $64,%ecx
                      subq %rax,%rcx
                      movq 64(%rsp),%rdx
_sTu = _sTp >> _sTs;  shrq %cl,%rdx
                      movq %rdx,%rcx     \ 
                      movq %rcx,72(%rsp) / why?
                      movq %rax,%rcx
_sTx = _sTp << _sTl;  shlq %cl,%rdx   but rdx contains _sTp >> _sTs!
I64[Hp + (-40)] = base_GHCziWord_Wzh_con_info;
I64[Hp + (-32)] = _sTu;
I64[Hp + (-24)] = base_GHCziWord_Wzh_con_info;
I64[Hp + (-16)] = _sTx;
_sTz = _sTx | _sTu;
_sTB = _sTz;
I64[Hp + (-8)] = base_GHCziBase_Izh_con_info;
I64[Hp + 0] = _sTB;
R1 = Hp + (-8);
R2 = Hp + (-24);
R3 = Hp + (-40);
jump (I64[Sp + 0]);

Thanks Ian

Trac metadata
Trac field Value
Version 6.6
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler (NCG)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information