[DAGCombiner] fold shift-trunc-shift to shift-mask-trunc (2nd try)
authorSanjay Patel <spatel@rotateright.com>
Fri, 13 Dec 2019 14:40:33 +0000 (09:40 -0500)
committerSanjay Patel <spatel@rotateright.com>
Fri, 13 Dec 2019 19:03:54 +0000 (14:03 -0500)
commit2f0c7fd2dbd06ae5f25b0c72b2b8f2a1c5baeb72
tree05694975281fbc7378ff5b8849ef90a8cd0db81d
parented50e6060b1c51ec4a5dad6c01a64a5f1526cdb5
[DAGCombiner] fold shift-trunc-shift to shift-mask-trunc (2nd try)

The initial attempt (rG89633320) botched the logic by reversing
the source/dest types. Added x86 tests for additional coverage.
The vector tests show a potential improvement (fold vector load
instead of broadcasting), but that's a known/existing problem.

This fold is done in IR by instcombine, and we have a special
form of it already here in DAGCombiner, but we want the more
general transform too:
https://rise4fun.com/Alive/3jZm

Name: general
Pre: (C1 + zext(C2) < 64)
%s = lshr i64 %x, C1
%t = trunc i64 %s to i16
%r = lshr i16 %t, C2
=>
%s2 = lshr i64 %x, C1 + zext(C2)
%a = and i64 %s2, zext((1 << (16 - C2)) - 1)
%r = trunc %a to i16

Name: special
Pre: C1 == 48
%s = lshr i64 %x, C1
%t = trunc i64 %s to i16
%r = lshr i16 %t, C2
=>
%s2 = lshr i64 %x, C1 + zext(C2)
%r = trunc %s2 to i16

...because D58017 exposes a regression without this fold.
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/test/CodeGen/AArch64/shift-amount-mod.ll
llvm/test/CodeGen/PowerPC/trunc-srl-load.ll
llvm/test/CodeGen/X86/shift-amount-mod.ll
llvm/test/CodeGen/X86/vector-shift-lshr-256.ll