[InstCombine] canonicalize select shuffles by commuting
In PR41304:
https://bugs.llvm.org/show_bug.cgi?id=41304
...we have a case where we want to fold a binop of select-shuffle (blended) values.
Rather than try to match commuted variants of the pattern, we can canonicalize the
shuffles and check for mask equality with commuted operands.
We don't produce arbitrary shuffle masks in instcombine, but select-shuffles are a
special case that the backend is required to handle because we already canonicalize
vector select to this shuffle form.
So there should be no codegen difference from this change. It's possible that this
improves CSE in IR though.
Differential Revision: https://reviews.llvm.org/D60016
llvm-svn: 357366
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 09d4395..d65c61c 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -1750,6 +1750,25 @@
setName(Name);
}
+void ShuffleVectorInst::commute() {
+ int NumOpElts = Op<0>()->getType()->getVectorNumElements();
+ int NumMaskElts = getMask()->getType()->getVectorNumElements();
+ SmallVector<Constant*, 16> NewMask(NumMaskElts);
+ Type *Int32Ty = Type::getInt32Ty(getContext());
+ for (int i = 0; i != NumMaskElts; ++i) {
+ int MaskElt = getMaskValue(i);
+ if (MaskElt == -1) {
+ NewMask[i] = UndefValue::get(Int32Ty);
+ continue;
+ }
+ assert(MaskElt >= 0 && MaskElt < 2 * NumOpElts && "Out-of-range mask");
+ MaskElt = (MaskElt < NumOpElts) ? MaskElt + NumOpElts : MaskElt - NumOpElts;
+ NewMask[i] = ConstantInt::get(Int32Ty, MaskElt);
+ }
+ Op<2>() = ConstantVector::get(NewMask);
+ Op<0>().swap(Op<1>());
+}
+
bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2,
const Value *Mask) {
// V1 and V2 must be vectors of the same type.