Add a simplification:
shuffle (splat-shuffle), undef, M --> splat-shuffle
Fixes pr32449
Patch by Sanjay Patel
Differential D31426
[DAGCombine] A shuffle of a splat is always the splat itself zvi on Mar 28 2017, 10:19 AM. Authored by
Details Add a simplification: Fixes pr32449 Patch by Sanjay Patel
Diff Detail
Event TimelineComment Actions This seems unnecessarily complicated. Why can't we just match any shuffle of a splat before we get here and simplify it? Also, would you be interested in fixing this in IR? :) $ ./opt -instsimplify shufsplat.ll -S define <4 x i32> @foo(<4 x i32> %x) { %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer %shuf = shufflevector <4 x i32> %splat, <4 x i32> undef, <4 x i32> <i32 0, i32 3, i32 2, i32 1> ret <4 x i32> %shuf } This example is handled by instcombine...but in a very inefficient way. Comment Actions I initially tried handling all cases of shuffle of shuffle-splat but the improvements from D27793 regressed, so this is what i came up with. About doing this in instcombine, yes, i plan to look into that too, but the pattern optimized by this patch is born out of thin air in another patch I'm working on that improves the combine of BUILD_VECTOR into composed shuffles. Comment Actions I think D27793 overstepped what it was trying to protect against. In the case where N1 is undef, we probably still want to do more combining? But that doesn't solve the tests here. I haven't looked at what is happening below that check. But the transform you want is a "simplify" not a "combine" (we're returning an existing node), so we shouldn't need to check uses, legality, or anything else. This diff solves the tests in this patch with no regressions on other tests: Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp (revision 298954) +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp (working copy) @@ -14646,6 +14646,12 @@ return DAG.getVectorShuffle(VT, SDLoc(N), N0, N1, NewMask); } + // A shuffle of a splat is always the splat itself: + // shuffle (splat-shuffle), undef, M --> splat-shuffle + if (auto *N0Shuf = dyn_cast<ShuffleVectorSDNode>(N0)) + if (N1.isUndef() && N0Shuf->isSplat()) + return N0; + // If it is a splat, check if the argument vector is another splat or a // build_vector. if (SVN->isSplat() && SVN->getSplatIndex() < (int)NumElts) { Comment Actions Thanks, Sanjay, for suggesting this superior patch. I will use it for the next revision. Comment Actions LGTM of course. :) |