Skip to content

Missed opportunity for SpecConstr

Look at perf/should_run/T4830. After SpecConstr and optimisation we finally get

Rec {
Main.foo_$s$wfoo1 [Occ=LoopBreaker]
  :: Int# -> Double -> Double -> Double#
[GblId, Arity=3, Caf=NoCafRefs, Str=DmdType <L,1*U><L,U><L,U>]
Main.foo_$s$wfoo1 =
  \ (sc_s4eN :: Int#) (sc1_s4eO :: Double) (sc2_s4eP :: Double) ->
    case sc_s4eN of ds_X1SR {
      __DEFAULT ->
        case sc1_s4eO of wild_a1Tf { D# x_a1Th ->
        case sc2_s4eP of wild1_a1Tj { D# y_a1Tl ->
        case tagToEnum# @ Bool (<=## x_a1Th y_a1Tl) of _ [Occ=Dead] {
          False -> Main.foo_$s$wfoo1 (-# ds_X1SR 1#) wild1_a1Tj wild_a1Tf;
          True -> Main.foo_$s$wfoo1 (-# ds_X1SR 1#) wild_a1Tf wild1_a1Tj
        }
        }
        };
      0# ->
        case sc1_s4eO of _ [Occ=Dead] { D# x_a1UL ->
        case sc2_s4eP of _ [Occ=Dead] { D# y_a1UP -> +## x_a1UL y_a1UP }
        }
    }
end Rec }

If we ran SpecConstr again we'd specialise this function, because the recursive calls both have boxed arguments.

I looked into why SpecConstr didn't catch it, and it's because SpecConstr's input looks like this

            case case tagToEnum# @ Bool (<=## x_a1Th y_a1Tl) of _ [Occ=Dead] {
                   False -> (wild1_a1Tj, wild_a1Tf);
                   True -> wild_X8
                 }
            of r_s4e0 { (ipv_s4e1, ipv_s4e2) ->
            $wfoo_s4db (I# (-# ds_X1SR 1#)) (Just @ (Double, Double) r_s4e0)

Notice the case-of-case which doesn't expose the Double boxes of arguments to $wfoo.

Why is that case-of-case still there? Because of Note [Single-alternative cases] in Simplify. Which is clearly a delicate spot so I don't want to meddle with it today. But it's intriguing. Maybe Sequent Core will do better.

Note that late demand analysis also catches this case, yielding the (rather good)

Rec {
Main.$w$s$wfoo [InlPrag=[0], Occ=LoopBreaker]
  :: Int# -> Double# -> Double# -> Double#
[GblId, Arity=3, Caf=NoCafRefs, Str=DmdType <S,1*U><L,U><L,U>]
Main.$w$s$wfoo =
  \ (w_s4gW :: Int#) (ww_s4h1 :: Double#) (ww1_s4h5 :: Double#) ->
    case w_s4gW of ds_X1SW {
      __DEFAULT ->
        case tagToEnum# @ Bool (<=## ww_s4h1 ww1_s4h5) of _ [Occ=Dead] {
          False -> Main.$w$s$wfoo (-# ds_X1SW 1#) ww1_s4h5 ww_s4h1;
          True -> Main.$w$s$wfoo (-# ds_X1SW 1#) ww_s4h1 ww1_s4h5
        };
      0# -> +## ww_s4h1 ww1_s4h5
    }
end Rec }

I'm pretty sure that late-demand-analysis should be on with -O2 but someone should do a nofib run to check.

Trac metadata
Trac field Value
Version 7.10.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
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