This is an archive of the discontinued LLVM Phabricator instance.

[DAGCombiner] try to convert opposing shifts to casts
ClosedPublic

Authored by spatel on Aug 1 2019, 2:22 PM.

Details

Summary

This reverses a questionable IR canonicalization when a truncate is free:

sra (add (shl X, N1C), AddC), N1C -->
sext (add (trunc X to (width - N1C)), AddC')

https://rise4fun.com/Alive/slRC

More details in PR42644:
https://bugs.llvm.org/show_bug.cgi?id=42644

I limited this to pre-legalization for code simplicity because that should be enough to reverse the IR patterns. I don't have any evidence (no regression test diffs) that we need to try this later.

Diff Detail

Repository
rL LLVM

Event Timeline

spatel created this revision.Aug 1 2019, 2:22 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 1 2019, 2:22 PM

Looks good.

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
7624 ↗(On Diff #212904)

Don't we also need for N0 to be one-use?

Thanks for fixing this!

spatel marked an inline comment as done.Aug 2 2019, 4:58 AM
spatel added inline comments.
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
7624 ↗(On Diff #212904)

Good catch. I was assuming that the free truncate wasn't a real instruction (and lazily didn't include extra-use tests), so that case would be ok. But that's not true. If either operand has extra uses, this transform can result in an extra x86 instruction, so it's unlikely to be profitable.

spatel updated this revision to Diff 213019.Aug 2 2019, 5:00 AM

Patch updated:

  1. Added 1 more one-use restriction.
  2. Added extra-use tests (not changed here - baseline rL367677).
This revision is now accepted and ready to land.Aug 2 2019, 5:05 AM
This revision was automatically updated to reflect the committed changes.

This caused failed asserts ("Unexpected illegal type!" in LegalizeDAG) when building Qt, with https://martin.st/temp/qpainterpath-preproc.cpp, built with clang++ -target i686-w64-mingw32 -c -O3 -std=c++17 qpainterpath-preproc.cpp. Will file a full proper bug later if necessary.

This caused failed asserts ("Unexpected illegal type!" in LegalizeDAG) when building Qt, with https://martin.st/temp/qpainterpath-preproc.cpp, built with clang++ -target i686-w64-mingw32 -c -O3 -std=c++17 qpainterpath-preproc.cpp. Will file a full proper bug later if necessary.

Would be good to have a reproducer, even just N->dumprFull() may shed some light.

This caused failed asserts ("Unexpected illegal type!" in LegalizeDAG) when building Qt, with https://martin.st/temp/qpainterpath-preproc.cpp, built with clang++ -target i686-w64-mingw32 -c -O3 -std=c++17 qpainterpath-preproc.cpp. Will file a full proper bug later if necessary.

Would be good to have a reproducer, even just N->dumprFull() may shed some light.

Node->dumprFull(); for the failed assert prints

t51: i32 = sign_extend t50
  t50: i29 = add t48, Constant:i29<-3>
    t48: i29 = truncate t46
      t46: i32 = <<Unknown Node #438>> t8, Constant:i32<3>
        t8: i32,ch = CopyFromReg t0, Register:i32 %13
          t7: i32 = Register %13
        t45: i32 = Constant<3>
    t49: i29 = Constant<-3>
spatel added a comment.Aug 3 2019, 4:02 AM

This caused failed asserts ("Unexpected illegal type!" in LegalizeDAG) when building Qt, with https://martin.st/temp/qpainterpath-preproc.cpp, built with clang++ -target i686-w64-mingw32 -c -O3 -std=c++17 qpainterpath-preproc.cpp. Will file a full proper bug later if necessary.

Would be good to have a reproducer, even just N->dumprFull() may shed some light.

Node->dumprFull(); for the failed assert prints

t51: i32 = sign_extend t50
  t50: i29 = add t48, Constant:i29<-3>
    t48: i29 = truncate t46
      t46: i32 = <<Unknown Node #438>> t8, Constant:i32<3>
        t8: i32,ch = CopyFromReg t0, Register:i32 %13
          t7: i32 = Register %13
        t45: i32 = Constant<3>
    t49: i29 = Constant<-3>

I can guess how we should limit this transform, but my translation of that DAG to IR does not crash for me:

define i32 @trunc29(i32 %x) nounwind {
  %u2 = trunc i32 %x to i29
  %u3 = add i29 %u2, -3
  %r = sext i29 %u3 to i32
  ret i32 %r
}

...so I need more info.

This caused failed asserts ("Unexpected illegal type!" in LegalizeDAG) when building Qt, with https://martin.st/temp/qpainterpath-preproc.cpp, built with clang++ -target i686-w64-mingw32 -c -O3 -std=c++17 qpainterpath-preproc.cpp. Will file a full proper bug later if necessary.

Would be good to have a reproducer, even just N->dumprFull() may shed some light.

Node->dumprFull(); for the failed assert prints

t51: i32 = sign_extend t50
  t50: i29 = add t48, Constant:i29<-3>
    t48: i29 = truncate t46
      t46: i32 = <<Unknown Node #438>> t8, Constant:i32<3>
        t8: i32,ch = CopyFromReg t0, Register:i32 %13
          t7: i32 = Register %13
        t45: i32 = Constant<3>
    t49: i29 = Constant<-3>

I can guess how we should limit this transform, but my translation of that DAG to IR does not crash for me:

define i32 @trunc29(i32 %x) nounwind {
  %u2 = trunc i32 %x to i29
  %u3 = add i29 %u2, -3
  %r = sext i29 %u3 to i32
  ret i32 %r
}

...so I need more info.

The original standalone preprocessed C++ code I linked before was reproducible on its own already, but I went ahead and made a reduced IR reproducer out of it, and filed a bug for it at https://bugs.llvm.org/show_bug.cgi?id=42880.

spatel added a comment.Aug 3 2019, 2:50 PM

This caused failed asserts ("Unexpected illegal type!" in LegalizeDAG) when building Qt, with https://martin.st/temp/qpainterpath-preproc.cpp, built with clang++ -target i686-w64-mingw32 -c -O3 -std=c++17 qpainterpath-preproc.cpp. Will file a full proper bug later if necessary.

Would be good to have a reproducer, even just N->dumprFull() may shed some light.

Node->dumprFull(); for the failed assert prints

t51: i32 = sign_extend t50
  t50: i29 = add t48, Constant:i29<-3>
    t48: i29 = truncate t46
      t46: i32 = <<Unknown Node #438>> t8, Constant:i32<3>
        t8: i32,ch = CopyFromReg t0, Register:i32 %13
          t7: i32 = Register %13
        t45: i32 = Constant<3>
    t49: i29 = Constant<-3>

I can guess how we should limit this transform, but my translation of that DAG to IR does not crash for me:

define i32 @trunc29(i32 %x) nounwind {
  %u2 = trunc i32 %x to i29
  %u3 = add i29 %u2, -3
  %r = sext i29 %u3 to i32
  ret i32 %r
}

...so I need more info.

The original standalone preprocessed C++ code I linked before was reproducible on its own already, but I went ahead and made a reduced IR reproducer out of it, and filed a bug for it at https://bugs.llvm.org/show_bug.cgi?id=42880.

Thank you for reducing that! I submitted:
rL367766
...as an immediate fix, but I'm still not sure what happens later to cause the assert.