Index: llvm/trunk/include/llvm/IR/Instructions.h =================================================================== --- llvm/trunk/include/llvm/IR/Instructions.h +++ llvm/trunk/include/llvm/IR/Instructions.h @@ -2261,6 +2261,19 @@ return Mask; } + /// Change values in a shuffle permute mask assuming the two vector operands + /// of length InVecNumElts have swapped position. + static void commuteShuffleMask(MutableArrayRef Mask, + unsigned InVecNumElts) { + for (int &Idx : Mask) { + if (Idx == -1) + continue; + Idx = Idx < (int)InVecNumElts ? Idx + InVecNumElts : Idx - InVecNumElts; + assert(Idx >= 0 && Idx < (int)InVecNumElts * 2 && + "shufflevector mask index out of range"); + } + } + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::ShuffleVector; Index: llvm/trunk/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/trunk/lib/Analysis/InstructionSimplify.cpp +++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp @@ -4126,13 +4126,7 @@ // second one. if (Op0Const && !Op1Const) { std::swap(Op0, Op1); - for (int &Idx : Indices) { - if (Idx == -1) - continue; - Idx = Idx < (int)InVecNumElts ? Idx + InVecNumElts : Idx - InVecNumElts; - assert(Idx >= 0 && Idx < (int)InVecNumElts * 2 && - "shufflevector mask index out of range"); - } + ShuffleVectorInst::commuteShuffleMask(Indices, InVecNumElts); Mask = ConstantDataVector::get( Mask->getContext(), makeArrayRef(reinterpret_cast(Indices.data()), Index: llvm/trunk/unittests/IR/InstructionsTest.cpp =================================================================== --- llvm/trunk/unittests/IR/InstructionsTest.cpp +++ llvm/trunk/unittests/IR/InstructionsTest.cpp @@ -21,6 +21,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/NoFolder.h" #include "llvm/IR/Operator.h" +#include "gmock/gmock-matchers.h" #include "gtest/gtest.h" #include @@ -740,5 +741,11 @@ EXPECT_EQ(BB1.get(), Handle.getCaseSuccessor()); } +TEST(InstructionsTest, CommuteShuffleMask) { + SmallVector Indices({-1, 0, 7}); + ShuffleVectorInst::commuteShuffleMask(Indices, 4); + EXPECT_THAT(Indices, testing::ContainerEq(ArrayRef({-1, 4, 3}))); +} + } // end anonymous namespace } // end namespace llvm