Simon Jakobi pushed to branch wip/sjakobi/T25233 at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • compiler/GHC/CmmToAsm/X86/CodeGen.hs
    ... ... @@ -1480,6 +1480,23 @@ getRegister' platform is32Bit (CmmMachOp (MO_Xor w) [x, CmmLit lit@(CmmInt m _)]
    1480 1480
       , not (is32BitLit platform lit)
    
    1481 1481
       = genBitTestImmCode (intFormat w) BTC x i
    
    1482 1482
     
    
    1483
    +-- Mirrored versions with the literal mask on the left. Constant folding
    
    1484
    +-- canonicalizes constants to the right (see GHC.Cmm.Opt.cmmMachOpFoldM), so
    
    1485
    +-- these only fire on Cmm that reaches the NCG unfolded, e.g. hand-written
    
    1486
    +-- .cmm code.
    
    1487
    +getRegister' platform is32Bit (CmmMachOp (MO_And w) [CmmLit lit@(CmmInt m _), x])
    
    1488
    +  | Just i <- clearBitLit_maybe w m, bitTestOpWidthOK is32Bit w
    
    1489
    +  , not (is32BitLit platform lit)
    
    1490
    +  = genBitTestImmCode (intFormat w) BTR x i
    
    1491
    +getRegister' platform is32Bit (CmmMachOp (MO_Or w) [CmmLit lit@(CmmInt m _), x])
    
    1492
    +  | Just i <- setBitLit_maybe w m, bitTestOpWidthOK is32Bit w
    
    1493
    +  , not (is32BitLit platform lit)
    
    1494
    +  = genBitTestImmCode (intFormat w) BTS x i
    
    1495
    +getRegister' platform is32Bit (CmmMachOp (MO_Xor w) [CmmLit lit@(CmmInt m _), x])
    
    1496
    +  | Just i <- setBitLit_maybe w m, bitTestOpWidthOK is32Bit w
    
    1497
    +  , not (is32BitLit platform lit)
    
    1498
    +  = genBitTestImmCode (intFormat w) BTC x i
    
    1499
    +
    
    1483 1500
     getRegister' platform is32Bit (CmmMachOp mop [x, y]) = do -- dyadic MachOps
    
    1484 1501
       sse4_1 <- sse4_1Enabled
    
    1485 1502
       sse4_2 <- sse4_2Enabled
    
    ... ... @@ -5938,11 +5955,14 @@ in any case undefined).
    5938 5955
     The bit-offset operand of these instructions must be an immediate or a
    
    5939 5956
     register.  When the bit index is a literal, no shift reaches the NCG:
    
    5940 5957
     constant folding has already turned the whole mask into a literal.  If that
    
    5941
    -mask fits in an imm32, an ordinary and/or/xor with an immediate is at least
    
    5942
    -as good; but a W64 mask touching the upper bits, e.g. ~(1 << 40), would have
    
    5943
    -to be moved into a register first.  For such masks we recognise the folded
    
    5944
    -literal itself (exactly one bit clear resp. set) and emit btr/bts/btc with
    
    5945
    -an immediate bit offset.
    
    5958
    +mask fits in an imm32, we keep the ordinary and/or/xor with an immediate:
    
    5959
    +it has the same latency and better throughput (more execution ports) than
    
    5960
    +the bit-test instructions,  and at worst two bytes of extra code size for bit
    
    5961
    +indices 7..30.
    
    5962
    +But a W64 mask touching the upper bits, e.g. ~(1 << 40), would have to be moved
    
    5963
    +into a register first.  For such masks we recognise the folded literal itself
    
    5964
    +(exactly one bit clear resp. set) and emit btr/bts/btc with an immediate
    
    5965
    +bit offset.
    
    5946 5966
     
    
    5947 5967
     We restrict the pattern to W32 and native-width W64: the instructions do not
    
    5948 5968
     exist at width 8, and sub-word Cmm operations at W8/W16 are rare enough that
    

  • testsuite/tests/codeGen/should_gen_asm/T25233b.asm
    1
    +btrq $40,
    
    2
    +btsq $40,
    
    3
    +btcq $40,

  • testsuite/tests/codeGen/should_gen_asm/T25233b.cmm
    1
    +#include "Cmm.h"
    
    2
    +
    
    3
    +// Single-bit literal masks written on the left of the operator. Constant
    
    4
    +// folding canonicalizes literals to the right, so these shapes only reach
    
    5
    +// the NCG from hand-written Cmm like this (#25233).
    
    6
    +
    
    7
    +clearBit40 (W_ x) {
    
    8
    +    return ((0xFFFFFEFFFFFFFFFF :: bits64) & x);
    
    9
    +}
    
    10
    +
    
    11
    +setBit40 (W_ x) {
    
    12
    +    return ((0x10000000000 :: bits64) | x);
    
    13
    +}
    
    14
    +
    
    15
    +complementBit40 (W_ x) {
    
    16
    +    return ((0x10000000000 :: bits64) ^ x);
    
    17
    +}

  • testsuite/tests/codeGen/should_gen_asm/all.T
    ... ... @@ -25,6 +25,8 @@ test('avx512-word64-minmax', [unless(arch('x86_64'), skip),
    25 25
                                   when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-mavx512vl'])
    
    26 26
     test('T25233', [unless(arch('x86_64'), skip),
    
    27 27
                     when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-O'])
    
    28
    +test('T25233b', [unless(arch('x86_64'), skip),
    
    29
    +                 when(unregisterised(), skip)], compile_grep_asm, ['cmm', True, ''])
    
    28 30
     is_aarch64_codegen = [
    
    29 31
         unless(arch('aarch64'), skip),
    
    30 32
         when(unregisterised(), skip),