Index: include/llvm/CodeGen/MachineInstrBuilder.h =================================================================== --- include/llvm/CodeGen/MachineInstrBuilder.h +++ include/llvm/CodeGen/MachineInstrBuilder.h @@ -250,6 +250,11 @@ return *this; } + const MachineInstrBuilder &addShuffleMask(const Constant *Val) const { + MI->addOperand(*MF, MachineOperand::CreateShuffleMask(Val)); + return *this; + } + const MachineInstrBuilder &addSym(MCSymbol *Sym, unsigned char TargetFlags = 0) const { MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym, TargetFlags)); Index: include/llvm/CodeGen/MachineOperand.h =================================================================== --- include/llvm/CodeGen/MachineOperand.h +++ include/llvm/CodeGen/MachineOperand.h @@ -23,6 +23,7 @@ namespace llvm { class BlockAddress; +class Constant; class ConstantFP; class ConstantInt; class GlobalValue; @@ -68,7 +69,8 @@ MO_CFIIndex, ///< MCCFIInstruction index. MO_IntrinsicID, ///< Intrinsic ID for ISel MO_Predicate, ///< Generic predicate for ISel - MO_Last = MO_Predicate, + MO_ShuffleMask, ///< Other IR Constant for ISel (shuffle masks) + MO_Last = MO_ShuffleMask }; private: @@ -172,6 +174,7 @@ unsigned CFIIndex; // For MO_CFI. Intrinsic::ID IntrinsicID; // For MO_IntrinsicID. unsigned Pred; // For MO_Predicate + const Constant *ShuffleMask; // For MO_ShuffleMask struct { // For MO_Register. // Register number is in SmallContents.RegNo. @@ -341,6 +344,7 @@ bool isCFIIndex() const { return OpKind == MO_CFIIndex; } bool isIntrinsicID() const { return OpKind == MO_IntrinsicID; } bool isPredicate() const { return OpKind == MO_Predicate; } + bool isShuffleMask() const { return OpKind == MO_ShuffleMask; } //===--------------------------------------------------------------------===// // Accessors for Register Operands //===--------------------------------------------------------------------===// @@ -579,6 +583,11 @@ return Contents.Pred; } + const Constant *getShuffleMask() const { + assert(isShuffleMask() && "Wrong MachineOperand accessor"); + return Contents.ShuffleMask; + } + /// Return the offset from the symbol in this operand. This always returns 0 /// for ExternalSymbol operands. int64_t getOffset() const { @@ -902,6 +911,12 @@ return Op; } + static MachineOperand CreateShuffleMask(const Constant *C) { + MachineOperand Op(MachineOperand::MO_ShuffleMask); + Op.Contents.ShuffleMask = C; + return Op; + } + friend class MachineInstr; friend class MachineRegisterInfo; Index: include/llvm/Target/GenericOpcodes.td =================================================================== --- include/llvm/Target/GenericOpcodes.td +++ include/llvm/Target/GenericOpcodes.td @@ -969,7 +969,7 @@ // Generic shufflevector. def G_SHUFFLE_VECTOR: GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$v1, type1:$v2, type2:$mask); + let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask); let hasSideEffects = 0; } Index: lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- lib/CodeGen/GlobalISel/IRTranslator.cpp +++ lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1902,7 +1902,7 @@ .addDef(getOrCreateVReg(U)) .addUse(getOrCreateVReg(*U.getOperand(0))) .addUse(getOrCreateVReg(*U.getOperand(1))) - .addUse(getOrCreateVReg(*U.getOperand(2))); + .addShuffleMask(cast(U.getOperand(2))); return true; } Index: lib/CodeGen/MIRParser/MILexer.h =================================================================== --- lib/CodeGen/MIRParser/MILexer.h +++ lib/CodeGen/MIRParser/MILexer.h @@ -117,6 +117,7 @@ kw_successors, kw_floatpred, kw_intpred, + kw_shufflemask, kw_pre_instr_symbol, kw_post_instr_symbol, kw_unknown_size, @@ -146,6 +147,7 @@ IntegerLiteral, FloatingPointLiteral, HexLiteral, + VectorLiteral, VirtualRegister, ConstantPoolItem, JumpTableIndex, Index: lib/CodeGen/MIRParser/MILexer.cpp =================================================================== --- lib/CodeGen/MIRParser/MILexer.cpp +++ lib/CodeGen/MIRParser/MILexer.cpp @@ -249,6 +249,7 @@ .Case("successors", MIToken::kw_successors) .Case("floatpred", MIToken::kw_floatpred) .Case("intpred", MIToken::kw_intpred) + .Case("shufflemask", MIToken::kw_shufflemask) .Case("pre-instr-symbol", MIToken::kw_pre_instr_symbol) .Case("post-instr-symbol", MIToken::kw_post_instr_symbol) .Case("unknown-size", MIToken::kw_unknown_size) Index: lib/CodeGen/MIRParser/MIParser.cpp =================================================================== --- lib/CodeGen/MIRParser/MIParser.cpp +++ lib/CodeGen/MIRParser/MIParser.cpp @@ -451,6 +451,7 @@ bool parseBlockAddressOperand(MachineOperand &Dest); bool parseIntrinsicOperand(MachineOperand &Dest); bool parsePredicateOperand(MachineOperand &Dest); + bool parseShuffleMaskOperand(MachineOperand &Dest); bool parseTargetIndexOperand(MachineOperand &Dest); bool parseCustomRegisterMaskOperand(MachineOperand &Dest); bool parseLiveoutRegisterMaskOperand(MachineOperand &Dest); @@ -2285,6 +2286,49 @@ return false; } +bool MIParser::parseShuffleMaskOperand(MachineOperand &Dest) { + assert(Token.is(MIToken::kw_shufflemask)); + + lex(); + if (expectAndConsume(MIToken::lparen)) + return error("expected syntax shufflemask(, ...)"); + + SmallVector ShufMask; + LLVMContext &Ctx = MF.getFunction().getContext(); + Type *I32Ty = Type::getInt32Ty(Ctx); + + bool AllZero = true; + bool AllUndef = true; + + do { + if (Token.is(MIToken::kw_undef)) { + ShufMask.push_back(UndefValue::get(I32Ty)); + AllZero = false; + } else if (Token.is(MIToken::IntegerLiteral)) { + AllUndef = false; + const APSInt &Int = Token.integerValue(); + if (!Int.isNullValue()) + AllZero = false; + ShufMask.push_back(ConstantInt::get(I32Ty, Int.getExtValue())); + } else + return error("expected integer constant"); + + lex(); + } while (consumeIfPresent(MIToken::comma)); + + if (expectAndConsume(MIToken::rparen)) + return error("shufflemask should be terminated by ')'."); + + if (AllZero || AllUndef) { + VectorType *VT = VectorType::get(I32Ty, ShufMask.size()); + Constant *C = AllZero ? Constant::getNullValue(VT) : UndefValue::get(VT); + Dest = MachineOperand::CreateShuffleMask(C); + } else + Dest = MachineOperand::CreateShuffleMask(ConstantVector::get(ShufMask)); + + return false; +} + bool MIParser::parseTargetIndexOperand(MachineOperand &Dest) { assert(Token.is(MIToken::kw_target_index)); lex(); @@ -2432,6 +2476,8 @@ case MIToken::kw_floatpred: case MIToken::kw_intpred: return parsePredicateOperand(Dest); + case MIToken::kw_shufflemask: + return parseShuffleMaskOperand(Dest); case MIToken::Error: return true; case MIToken::Identifier: Index: lib/CodeGen/MIRPrinter.cpp =================================================================== --- lib/CodeGen/MIRPrinter.cpp +++ lib/CodeGen/MIRPrinter.cpp @@ -842,7 +842,8 @@ case MachineOperand::MO_CFIIndex: case MachineOperand::MO_IntrinsicID: case MachineOperand::MO_Predicate: - case MachineOperand::MO_BlockAddress: { + case MachineOperand::MO_BlockAddress: + case MachineOperand::MO_ShuffleMask: { unsigned TiedOperandIdx = 0; if (ShouldPrintRegisterTies && Op.isReg() && Op.isTied() && !Op.isDef()) TiedOperandIdx = Op.getParent()->findTiedOperandIdx(OpIdx); Index: lib/CodeGen/MachineOperand.cpp =================================================================== --- lib/CodeGen/MachineOperand.cpp +++ lib/CodeGen/MachineOperand.cpp @@ -333,6 +333,8 @@ return getIntrinsicID() == Other.getIntrinsicID(); case MachineOperand::MO_Predicate: return getPredicate() == Other.getPredicate(); + case MachineOperand::MO_ShuffleMask: + return getShuffleMask() == Other.getShuffleMask(); } llvm_unreachable("Invalid machine operand type"); } @@ -381,6 +383,8 @@ return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID()); case MachineOperand::MO_Predicate: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate()); + case MachineOperand::MO_ShuffleMask: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getShuffleMask()); } llvm_unreachable("Invalid machine operand type"); } @@ -936,6 +940,20 @@ << CmpInst::getPredicateName(Pred) << ')'; break; } + case MachineOperand::MO_ShuffleMask: + OS << "shufflemask("; + const Constant* C = getShuffleMask(); + const int NumElts = C->getType()->getVectorNumElements(); + + StringRef Separator; + for (int I = 0; I != NumElts; ++I) { + OS << Separator; + C->getAggregateElement(I)->printAsOperand(OS, false, MST); + Separator = ", "; + } + + OS << ')'; + break; } } Index: lib/CodeGen/MachineVerifier.cpp =================================================================== --- lib/CodeGen/MachineVerifier.cpp +++ lib/CodeGen/MachineVerifier.cpp @@ -1387,6 +1387,22 @@ report("G_SEXT_INREG size must be less than source bit width", MI); break; } + case TargetOpcode::G_SHUFFLE_VECTOR: { + const MachineOperand &MaskOp = MI->getOperand(3); + if (!MaskOp.isShuffleMask()) { + report("Incorrect mask operand type for G_SHUFFLE_VECTOR", MI); + break; + } + + const Constant *Mask = MaskOp.getShuffleMask(); + if (!Mask->getAggregateElement(0u)) { + report("Invalid shufflemask constant type", MI); + break; + } + + // TODO: Verify element numbers consistent + break; + } default: break; } Index: lib/Target/AArch64/AArch64InstructionSelector.cpp =================================================================== --- lib/Target/AArch64/AArch64InstructionSelector.cpp +++ lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -106,8 +106,6 @@ bool selectMergeValues(MachineInstr &I, MachineRegisterInfo &MRI) const; bool selectUnmergeValues(MachineInstr &I, MachineRegisterInfo &MRI) const; - void collectShuffleMaskIndices(MachineInstr &I, MachineRegisterInfo &MRI, - SmallVectorImpl> &Idxs) const; bool selectShuffleVector(MachineInstr &I, MachineRegisterInfo &MRI) const; bool selectExtractElt(MachineInstr &I, MachineRegisterInfo &MRI) const; bool selectConcatVectors(MachineInstr &I, MachineRegisterInfo &MRI) const; @@ -3054,29 +3052,6 @@ return true; } -void AArch64InstructionSelector::collectShuffleMaskIndices( - MachineInstr &I, MachineRegisterInfo &MRI, - SmallVectorImpl> &Idxs) const { - MachineInstr *MaskDef = MRI.getVRegDef(I.getOperand(3).getReg()); - assert( - MaskDef->getOpcode() == TargetOpcode::G_BUILD_VECTOR && - "G_SHUFFLE_VECTOR should have a constant mask operand as G_BUILD_VECTOR"); - // Find the constant indices. - for (unsigned i = 1, e = MaskDef->getNumOperands(); i < e; ++i) { - // Look through copies. - MachineInstr *ScalarDef = - getDefIgnoringCopies(MaskDef->getOperand(i).getReg(), MRI); - assert(ScalarDef && "Could not find vreg def of shufflevec index op"); - if (ScalarDef->getOpcode() != TargetOpcode::G_CONSTANT) { - // This be an undef if not a constant. - assert(ScalarDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF); - Idxs.push_back(None); - } else { - Idxs.push_back(ScalarDef->getOperand(1).getCImm()->getSExtValue()); - } - } -} - unsigned AArch64InstructionSelector::emitConstantPoolEntry(Constant *CPVal, MachineFunction &MF) const { @@ -3619,16 +3594,9 @@ return false; // The shuffle's second operand doesn't matter if the mask is all zero. - auto *ZeroVec = getOpcodeDef(G_BUILD_VECTOR, I.getOperand(3).getReg(), MRI); - if (!ZeroVec) + const Constant *Mask = I.getOperand(3).getShuffleMask(); + if (!isa(Mask)) return false; - int64_t Zero = 0; - if (!mi_match(ZeroVec->getOperand(1).getReg(), MRI, m_ICst(Zero)) || Zero) - return false; - for (unsigned i = 1, e = ZeroVec->getNumOperands(); i < e; ++i) { - if (ZeroVec->getOperand(i).getReg() != ZeroVec->getOperand(1).getReg()) - return false; // This wasn't an all zeros vector. - } // We're done, now find out what kind of splat we need. LLT VecTy = MRI.getType(I.getOperand(0).getReg()); @@ -3676,19 +3644,14 @@ const LLT Src1Ty = MRI.getType(Src1Reg); Register Src2Reg = I.getOperand(2).getReg(); const LLT Src2Ty = MRI.getType(Src2Reg); + const Constant *ShuffleMask = I.getOperand(3).getShuffleMask(); MachineBasicBlock &MBB = *I.getParent(); MachineFunction &MF = *MBB.getParent(); LLVMContext &Ctx = MF.getFunction().getContext(); - // G_SHUFFLE_VECTOR doesn't really have a strictly enforced constant mask - // operand, it comes in as a normal vector value which we have to analyze to - // find the mask indices. If the mask element is undef, then - // collectShuffleMaskIndices() will add a None entry for that index into - // the list. - SmallVector, 8> Mask; - collectShuffleMaskIndices(I, MRI, Mask); - assert(!Mask.empty() && "Expected to find mask indices"); + SmallVector Mask; + ShuffleVectorInst::getShuffleMask(ShuffleMask, Mask); // G_SHUFFLE_VECTOR is weird in that the source operands can be scalars, if // it's originated from a <1 x T> type. Those should have been lowered into @@ -3701,10 +3664,10 @@ unsigned BytesPerElt = DstTy.getElementType().getSizeInBits() / 8; SmallVector CstIdxs; - for (auto &MaybeVal : Mask) { + for (int Val : Mask) { // For now, any undef indexes we'll just assume to be 0. This should be // optimized in future, e.g. to select DUP etc. - int Val = MaybeVal.hasValue() ? *MaybeVal : 0; + Val = Val < 0 ? 0 : Val; for (unsigned Byte = 0; Byte < BytesPerElt; ++Byte) { unsigned Offset = Byte + Val * BytesPerElt; CstIdxs.emplace_back(ConstantInt::get(Type::getInt8Ty(Ctx), Offset)); Index: lib/Target/ARM/ARMExpandPseudoInsts.cpp =================================================================== --- lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -789,6 +789,7 @@ case MachineOperand::MO_Immediate: case MachineOperand::MO_CImmediate: case MachineOperand::MO_FPImmediate: + case MachineOperand::MO_ShuffleMask: return false; case MachineOperand::MO_MachineBasicBlock: return true; Index: test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll =================================================================== --- test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -1622,9 +1622,7 @@ ; CHECK-LABEL: name: test_shufflevector_s32_v2s32 ; CHECK: [[ARG:%[0-9]+]]:_(s32) = COPY $w0 ; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF -; CHECK-DAG: [[C0:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 -; CHECK-DAG: [[MASK:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[C0]](s32), [[C0]](s32) -; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](s32), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](s32), [[UNDEF]], shufflemask(0, 0) ; CHECK: $d0 = COPY [[VEC]](<2 x s32>) %vec = insertelement <1 x i32> undef, i32 %arg, i32 0 %res = shufflevector <1 x i32> %vec, <1 x i32> undef, <2 x i32> zeroinitializer @@ -1634,25 +1632,40 @@ define i32 @test_shufflevector_v2s32_s32(<2 x i32> %arg) { ; CHECK-LABEL: name: test_shufflevector_v2s32_s32 ; CHECK: [[ARG:%[0-9]+]]:_(<2 x s32>) = COPY $d0 -; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF -; CHECK-DAG: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 -; CHECK: [[RES:%[0-9]+]]:_(s32) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], [[C1]](s32) +; CHECK: [[RES:%[0-9]+]]:_(s32) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], shufflemask(1) ; CHECK: $w0 = COPY [[RES]](s32) %vec = shufflevector <2 x i32> %arg, <2 x i32> undef, <1 x i32> %res = extractelement <1 x i32> %vec, i32 0 ret i32 %res } -define <2 x i32> @test_shufflevector_v2s32_v2s32(<2 x i32> %arg) { -; CHECK-LABEL: name: test_shufflevector_v2s32_v2s32 +define <2 x i32> @test_shufflevector_v2s32_v2s32_undef(<2 x i32> %arg) { +; CHECK-LABEL: name: test_shufflevector_v2s32_v2s32_undef +; CHECK: [[ARG:%[0-9]+]]:_(<2 x s32>) = COPY $d0 +; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF +; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], shufflemask(undef, undef) +; CHECK: $d0 = COPY [[VEC]](<2 x s32>) + %res = shufflevector <2 x i32> %arg, <2 x i32> undef, <2 x i32> undef + ret <2 x i32> %res +} + +define <2 x i32> @test_shufflevector_v2s32_v2s32_undef_0(<2 x i32> %arg) { +; CHECK-LABEL: name: test_shufflevector_v2s32_v2s32_undef_0 +; CHECK: [[ARG:%[0-9]+]]:_(<2 x s32>) = COPY $d0 +; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF +; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], shufflemask(undef, 0) +; CHECK: $d0 = COPY [[VEC]](<2 x s32>) + %res = shufflevector <2 x i32> %arg, <2 x i32> undef, <2 x i32> + ret <2 x i32> %res +} + +define <2 x i32> @test_shufflevector_v2s32_v2s32_0_undef(<2 x i32> %arg) { +; CHECK-LABEL: name: test_shufflevector_v2s32_v2s32_0_undef ; CHECK: [[ARG:%[0-9]+]]:_(<2 x s32>) = COPY $d0 ; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF -; CHECK-DAG: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 -; CHECK-DAG: [[C0:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 -; CHECK-DAG: [[MASK:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C0]](s32) -; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], shufflemask(0, undef) ; CHECK: $d0 = COPY [[VEC]](<2 x s32>) - %res = shufflevector <2 x i32> %arg, <2 x i32> undef, <2 x i32> + %res = shufflevector <2 x i32> %arg, <2 x i32> undef, <2 x i32> ret <2 x i32> %res } @@ -1660,10 +1673,7 @@ ; CHECK-LABEL: name: test_shufflevector_v2s32_v3s32 ; CHECK: [[ARG:%[0-9]+]]:_(<2 x s32>) = COPY $d0 ; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF -; CHECK-DAG: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 -; CHECK-DAG: [[C0:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 -; CHECK-DAG: [[MASK:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C0]](s32), [[C1]](s32) -; CHECK: [[VEC:%[0-9]+]]:_(<3 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], [[MASK]](<3 x s32>) +; CHECK: [[VEC:%[0-9]+]]:_(<3 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], shufflemask(1, 0, 1) ; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<3 x s32>) %vec = shufflevector <2 x i32> %arg, <2 x i32> undef, <3 x i32> %res = extractelement <3 x i32> %vec, i32 0 @@ -1674,12 +1684,7 @@ ; CHECK-LABEL: name: test_shufflevector_v2s32_v4s32 ; CHECK: [[ARG1:%[0-9]+]]:_(<2 x s32>) = COPY $d0 ; CHECK: [[ARG2:%[0-9]+]]:_(<2 x s32>) = COPY $d1 -; CHECK: [[C0:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 -; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 -; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 -; CHECK: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 -; CHECK: [[MASK:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C0]](s32), [[C1]](s32), [[C2]](s32), [[C3]](s32) -; CHECK: [[VEC:%[0-9]+]]:_(<4 x s32>) = G_SHUFFLE_VECTOR [[ARG1]](<2 x s32>), [[ARG2]], [[MASK]](<4 x s32>) +; CHECK: [[VEC:%[0-9]+]]:_(<4 x s32>) = G_SHUFFLE_VECTOR [[ARG1]](<2 x s32>), [[ARG2]], shufflemask(0, 1, 2, 3) ; CHECK: $q0 = COPY [[VEC]](<4 x s32>) %res = shufflevector <2 x i32> %arg1, <2 x i32> %arg2, <4 x i32> ret <4 x i32> %res @@ -1689,10 +1694,7 @@ ; CHECK-LABEL: name: test_shufflevector_v4s32_v2s32 ; CHECK: [[ARG:%[0-9]+]]:_(<4 x s32>) = COPY $q0 ; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<4 x s32>) = G_IMPLICIT_DEF -; CHECK-DAG: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 -; CHECK-DAG: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 -; CHECK-DAG: [[MASK:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C3]](s32) -; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<4 x s32>), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<4 x s32>), [[UNDEF]], shufflemask(1, 3) ; CHECK: $d0 = COPY [[VEC]](<2 x s32>) %res = shufflevector <4 x i32> %arg, <4 x i32> undef, <2 x i32> ret <2 x i32> %res @@ -1703,24 +1705,7 @@ ; CHECK-LABEL: name: test_shufflevector_v8s8_v16s8 ; CHECK: [[ARG1:%[0-9]+]]:_(<8 x s8>) = COPY $d0 ; CHECK: [[ARG2:%[0-9]+]]:_(<8 x s8>) = COPY $d1 -; CHECK: [[C0:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 -; CHECK: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 -; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 -; CHECK: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 9 -; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 -; CHECK: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 10 -; CHECK: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 -; CHECK: [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 11 -; CHECK: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 -; CHECK: [[C12:%[0-9]+]]:_(s32) = G_CONSTANT i32 12 -; CHECK: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 5 -; CHECK: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 13 -; CHECK: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 6 -; CHECK: [[C14:%[0-9]+]]:_(s32) = G_CONSTANT i32 14 -; CHECK: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 7 -; CHECK: [[C15:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 -; CHECK: [[MASK:%[0-9]+]]:_(<16 x s32>) = G_BUILD_VECTOR [[C0]](s32), [[C8]](s32), [[C1]](s32), [[C9]](s32), [[C2]](s32), [[C10]](s32), [[C3]](s32), [[C11]](s32), [[C4]](s32), [[C12]](s32), [[C5]](s32), [[C13]](s32), [[C6]](s32), [[C14]](s32), [[C7]](s32), [[C15]](s32) -; CHECK: [[VEC:%[0-9]+]]:_(<16 x s8>) = G_SHUFFLE_VECTOR [[ARG1]](<8 x s8>), [[ARG2]], [[MASK]](<16 x s32>) +; CHECK: [[VEC:%[0-9]+]]:_(<16 x s8>) = G_SHUFFLE_VECTOR [[ARG1]](<8 x s8>), [[ARG2]], shufflemask(0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15) ; CHECK: $q0 = COPY [[VEC]](<16 x s8>) %res = shufflevector <8 x i8> %arg1, <8 x i8> %arg2, <16 x i32> ret <16 x i8> %res Index: test/CodeGen/AArch64/GlobalISel/legalize-shuffle-vector.mir =================================================================== --- test/CodeGen/AArch64/GlobalISel/legalize-shuffle-vector.mir +++ test/CodeGen/AArch64/GlobalISel/legalize-shuffle-vector.mir @@ -12,16 +12,12 @@ ; CHECK: liveins: $q0, $q1 ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0 ; CHECK: [[COPY1:%[0-9]+]]:_(<4 x s32>) = COPY $q1 - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 - ; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) - ; CHECK: [[SHUF:%[0-9]+]]:_(<4 x s32>) = G_SHUFFLE_VECTOR [[COPY]](<4 x s32>), [[COPY1]], [[BUILD_VECTOR]](<4 x s32>) + ; CHECK: [[SHUF:%[0-9]+]]:_(<4 x s32>) = G_SHUFFLE_VECTOR [[COPY]](<4 x s32>), [[COPY1]], shufflemask(0, 0, 0, 0) ; CHECK: $q0 = COPY [[SHUF]](<4 x s32>) ; CHECK: RET_ReallyLR implicit $q0 %0:_(<4 x s32>) = COPY $q0 %1:_(<4 x s32>) = COPY $q1 - %4:_(s32) = G_CONSTANT i32 0 - %3:_(<4 x s32>) = G_BUILD_VECTOR %4(s32), %4(s32), %4(s32), %4(s32) - %2:_(<4 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1, %3(<4 x s32>) + %2:_(<4 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1, shufflemask(0, 0, 0, 0) $q0 = COPY %2(<4 x s32>) RET_ReallyLR implicit $q0 @@ -38,16 +34,12 @@ ; CHECK: liveins: $q0, $q1 ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0 ; CHECK: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1 - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 - ; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32) - ; CHECK: [[SHUF:%[0-9]+]]:_(<2 x s64>) = G_SHUFFLE_VECTOR [[COPY]](<2 x s64>), [[COPY1]], [[BUILD_VECTOR]](<2 x s32>) + ; CHECK: [[SHUF:%[0-9]+]]:_(<2 x s64>) = G_SHUFFLE_VECTOR [[COPY]](<2 x s64>), [[COPY1]], shufflemask(0, 0) ; CHECK: $q0 = COPY [[SHUF]](<2 x s64>) ; CHECK: RET_ReallyLR implicit $q0 %0:_(<2 x s64>) = COPY $q0 %1:_(<2 x s64>) = COPY $q1 - %4:_(s32) = G_CONSTANT i32 0 - %3:_(<2 x s32>) = G_BUILD_VECTOR %4(s32), %4(s32) - %2:_(<2 x s64>) = G_SHUFFLE_VECTOR %0(<2 x s64>), %1, %3(<2 x s32>) + %2:_(<2 x s64>) = G_SHUFFLE_VECTOR %0(<2 x s64>), %1, shufflemask(0, 0) $q0 = COPY %2(<2 x s64>) RET_ReallyLR implicit $q0 Index: test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir =================================================================== --- test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -424,7 +424,7 @@ # DEBUG-NEXT: G_EXTRACT_VECTOR_ELT (opcode {{[0-9]+}}): 3 type indices, 0 imm indices # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected -# DEBUG-NEXT: G_SHUFFLE_VECTOR (opcode {{[0-9]+}}): 3 type indices, 0 imm indices +# DEBUG-NEXT: G_SHUFFLE_VECTOR (opcode {{[0-9]+}}): 2 type indices, 0 imm indices # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: G_CTTZ (opcode {{[0-9]+}}): 2 type indices, 0 imm indices Index: test/CodeGen/AArch64/GlobalISel/opt-shuffle-splat.mir =================================================================== --- test/CodeGen/AArch64/GlobalISel/opt-shuffle-splat.mir +++ test/CodeGen/AArch64/GlobalISel/opt-shuffle-splat.mir @@ -19,9 +19,8 @@ %0:gpr(s32) = COPY $w0 %2:fpr(<4 x s32>) = G_IMPLICIT_DEF %3:gpr(s32) = G_CONSTANT i32 0 - %5:fpr(<4 x s32>) = G_BUILD_VECTOR %3(s32), %3(s32), %3(s32), %3(s32) %1:fpr(<4 x s32>) = G_INSERT_VECTOR_ELT %2, %0(s32), %3(s32) - %4:fpr(<4 x s32>) = G_SHUFFLE_VECTOR %1(<4 x s32>), %2, %5(<4 x s32>) + %4:fpr(<4 x s32>) = G_SHUFFLE_VECTOR %1(<4 x s32>), %2, shufflemask(0, 0, 0, 0) $q0 = COPY %4(<4 x s32>) RET_ReallyLR implicit $q0 @@ -45,9 +44,8 @@ %0:gpr(s64) = COPY $x0 %2:fpr(<2 x s64>) = G_IMPLICIT_DEF %3:gpr(s32) = G_CONSTANT i32 0 - %5:fpr(<2 x s32>) = G_BUILD_VECTOR %3(s32), %3(s32) %1:fpr(<2 x s64>) = G_INSERT_VECTOR_ELT %2, %0(s64), %3(s32) - %4:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %1(<2 x s64>), %2, %5(<2 x s32>) + %4:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %1(<2 x s64>), %2, shufflemask(0, 0) $q0 = COPY %4(<2 x s64>) RET_ReallyLR implicit $q0 @@ -73,9 +71,8 @@ %0:fpr(s32) = COPY $s0 %2:fpr(<4 x s32>) = G_IMPLICIT_DEF %3:gpr(s32) = G_CONSTANT i32 0 - %5:fpr(<4 x s32>) = G_BUILD_VECTOR %3(s32), %3(s32), %3(s32), %3(s32) %1:fpr(<4 x s32>) = G_INSERT_VECTOR_ELT %2, %0(s32), %3(s32) - %4:fpr(<4 x s32>) = G_SHUFFLE_VECTOR %1(<4 x s32>), %2, %5(<4 x s32>) + %4:fpr(<4 x s32>) = G_SHUFFLE_VECTOR %1(<4 x s32>), %2, shufflemask(0, 0, 0, 0) $q0 = COPY %4(<4 x s32>) RET_ReallyLR implicit $q0 @@ -101,9 +98,8 @@ %0:fpr(s64) = COPY $d0 %2:fpr(<2 x s64>) = G_IMPLICIT_DEF %3:gpr(s32) = G_CONSTANT i32 0 - %5:fpr(<2 x s32>) = G_BUILD_VECTOR %3(s32), %3(s32) %1:fpr(<2 x s64>) = G_INSERT_VECTOR_ELT %2, %0(s64), %3(s32) - %4:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %1(<2 x s64>), %2, %5(<2 x s32>) + %4:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %1(<2 x s64>), %2, shufflemask(0, 0) $q0 = COPY %4(<2 x s64>) RET_ReallyLR implicit $q0 @@ -132,10 +128,9 @@ %2:fpr(<2 x s64>) = G_IMPLICIT_DEF %6:fpr(<2 x s64>) = COPY %2 %3:gpr(s32) = G_CONSTANT i32 0 - %5:fpr(<2 x s32>) = G_BUILD_VECTOR %3(s32), %3(s32) %1:fpr(<2 x s64>) = G_INSERT_VECTOR_ELT %6, %0(s64), %3(s32) %7:fpr(<2 x s64>) = COPY %1 - %4:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %7(<2 x s64>), %2, %5(<2 x s32>) + %4:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %7(<2 x s64>), %2, shufflemask(0, 0) $q0 = COPY %4(<2 x s64>) RET_ReallyLR implicit $q0 @@ -164,9 +159,7 @@ %0:gpr(s64) = COPY $x0 %2:fpr(<2 x s64>) = G_IMPLICIT_DEF %3:gpr(s32) = G_CONSTANT i32 0 - %6:gpr(s32) = G_CONSTANT i32 1 - %5:fpr(<2 x s32>) = G_BUILD_VECTOR %3(s32), %6(s32) %1:fpr(<2 x s64>) = G_INSERT_VECTOR_ELT %2, %0(s64), %3(s32) - %4:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %1(<2 x s64>), %2, %5(<2 x s32>) + %4:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %1(<2 x s64>), %2, shufflemask(0, 1) $q0 = COPY %4(<2 x s64>) RET_ReallyLR implicit $q0 Index: test/CodeGen/AArch64/GlobalISel/select-shuffle-vector.mir =================================================================== --- test/CodeGen/AArch64/GlobalISel/select-shuffle-vector.mir +++ test/CodeGen/AArch64/GlobalISel/select-shuffle-vector.mir @@ -61,10 +61,7 @@ ; CHECK: RET_ReallyLR implicit $d0 %0:fpr(<2 x s32>) = COPY $d0 %1:fpr(<2 x s32>) = COPY $d1 - %4:gpr(s32) = G_CONSTANT i32 1 - %5:gpr(s32) = G_CONSTANT i32 0 - %3:fpr(<2 x s32>) = G_BUILD_VECTOR %4(s32), %5(s32) - %2:fpr(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %1, %3(<2 x s32>) + %2:fpr(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %1, shufflemask(1, 0) $d0 = COPY %2(<2 x s32>) RET_ReallyLR implicit $d0 @@ -95,11 +92,7 @@ ; CHECK: RET_ReallyLR implicit $q0 %0:fpr(<4 x s32>) = COPY $q0 %1:fpr(<4 x s32>) = COPY $q1 - %4:gpr(s32) = G_CONSTANT i32 0 - %5:gpr(s32) = G_CONSTANT i32 1 - %6:gpr(s32) = G_CONSTANT i32 3 - %3:fpr(<4 x s32>) = G_BUILD_VECTOR %4(s32), %5(s32), %6(s32), %4(s32) - %2:fpr(<4 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1, %3(<4 x s32>) + %2:fpr(<4 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1, shufflemask(0, 1, 3, 0) $q0 = COPY %2(<4 x s32>) RET_ReallyLR implicit $q0 @@ -130,12 +123,7 @@ ; CHECK: RET_ReallyLR implicit $q0 %0:fpr(<4 x s32>) = COPY $q0 %1:fpr(<4 x s32>) = COPY $q1 - %4:gpr(s32) = G_CONSTANT i32 5 - %5:gpr(s32) = G_CONSTANT i32 7 - %6:gpr(s32) = G_CONSTANT i32 1 - %7:gpr(s32) = G_CONSTANT i32 0 - %3:fpr(<4 x s32>) = G_BUILD_VECTOR %4(s32), %5(s32), %6(s32), %7(s32) - %2:fpr(<4 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1, %3(<4 x s32>) + %2:fpr(<4 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1, shufflemask(5, 7, 1, 0) $q0 = COPY %2(<4 x s32>) RET_ReallyLR implicit $q0 @@ -166,9 +154,7 @@ ; CHECK: RET_ReallyLR implicit $q0 %0:fpr(<2 x s64>) = COPY $q0 %1:fpr(<2 x s64>) = COPY $q1 - %4:gpr(s32) = G_CONSTANT i32 0 - %3:fpr(<2 x s32>) = G_BUILD_VECTOR %4(s32), %4(s32) - %2:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %0(<2 x s64>), %1, %3(<2 x s32>) + %2:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %0(<2 x s64>), %1, shufflemask(0, 0) $q0 = COPY %2(<2 x s64>) RET_ReallyLR implicit $q0 Index: test/CodeGen/AArch64/GlobalISel/select-shufflevec-undef-mask-elt.mir =================================================================== --- test/CodeGen/AArch64/GlobalISel/select-shufflevec-undef-mask-elt.mir +++ test/CodeGen/AArch64/GlobalISel/select-shufflevec-undef-mask-elt.mir @@ -41,10 +41,7 @@ %6:gpr(s32) = G_IMPLICIT_DEF %7:gpr(s32) = G_IMPLICIT_DEF %2:fpr(<2 x s32>) = G_BUILD_VECTOR %6(s32), %7(s32) - %4:gpr(s32) = G_CONSTANT i32 1 - %5:gpr(s32) = G_IMPLICIT_DEF - %3:fpr(<2 x s32>) = G_BUILD_VECTOR %4(s32), %5(s32) - %1:fpr(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, %3(<2 x s32>) + %1:fpr(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(1, undef) $d0 = COPY %1(<2 x s32>) RET_ReallyLR implicit $d0 Index: test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll =================================================================== --- test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll +++ test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll @@ -438,9 +438,7 @@ ; CHECK-LABEL: name: test_shufflevector_s32_v2s32 ; CHECK: [[ARG:%[0-9]+]]:_(s32) = COPY $r0 ; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF -; CHECK-DAG: [[C0:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 -; CHECK-DAG: [[MASK:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[C0]](s32), [[C0]](s32) -; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](s32), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](s32), [[UNDEF]], shufflemask(0, 0) ; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<2 x s32>) %vec = insertelement <1 x i32> undef, i32 %arg, i32 0 %shuffle = shufflevector <1 x i32> %vec, <1 x i32> undef, <2 x i32> zeroinitializer @@ -455,10 +453,9 @@ ; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF ; CHECK-DAG: [[C0:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 ; CHECK-DAG: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 -; CHECK-DAG: [[MASK:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C0]](s32), [[C1]](s32) ; CHECK-DAG: [[V1:%[0-9]+]]:_(<2 x s32>) = G_INSERT_VECTOR_ELT [[UNDEF]], [[ARG1]](s32), [[C0]](s32) ; CHECK-DAG: [[V2:%[0-9]+]]:_(<2 x s32>) = G_INSERT_VECTOR_ELT [[V1]], [[ARG2]](s32), [[C1]](s32) -; CHECK: [[VEC:%[0-9]+]]:_(<3 x s32>) = G_SHUFFLE_VECTOR [[V2]](<2 x s32>), [[UNDEF]], [[MASK]](<3 x s32>) +; CHECK: [[VEC:%[0-9]+]]:_(<3 x s32>) = G_SHUFFLE_VECTOR [[V2]](<2 x s32>), [[UNDEF]], shufflemask(1, 0, 1) ; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<3 x s32>) %v1 = insertelement <2 x i32> undef, i32 %arg1, i32 0 %v2 = insertelement <2 x i32> %v1, i32 %arg2, i32 1 @@ -475,10 +472,9 @@ ; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF ; CHECK-DAG: [[C0:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 ; CHECK-DAG: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 -; CHECK-DAG: [[MASK:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C0]](s32), [[C0]](s32), [[C0]](s32), [[C0]](s32) ; CHECK-DAG: [[V1:%[0-9]+]]:_(<2 x s32>) = G_INSERT_VECTOR_ELT [[UNDEF]], [[ARG1]](s32), [[C0]](s32) ; CHECK-DAG: [[V2:%[0-9]+]]:_(<2 x s32>) = G_INSERT_VECTOR_ELT [[V1]], [[ARG2]](s32), [[C1]](s32) -; CHECK: [[VEC:%[0-9]+]]:_(<4 x s32>) = G_SHUFFLE_VECTOR [[V2]](<2 x s32>), [[UNDEF]], [[MASK]](<4 x s32>) +; CHECK: [[VEC:%[0-9]+]]:_(<4 x s32>) = G_SHUFFLE_VECTOR [[V2]](<2 x s32>), [[UNDEF]], shufflemask(0, 0, 0, 0) ; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<4 x s32>) %v1 = insertelement <2 x i32> undef, i32 %arg1, i32 0 %v2 = insertelement <2 x i32> %v1, i32 %arg2, i32 1 @@ -498,12 +494,11 @@ ; CHECK-DAG: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; CHECK-DAG: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 ; CHECK-DAG: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 -; CHECK-DAG: [[MASK:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C3]](s32) ; CHECK-DAG: [[V1:%[0-9]+]]:_(<4 x s32>) = G_INSERT_VECTOR_ELT [[UNDEF]], [[ARG1]](s32), [[C0]](s32) ; CHECK-DAG: [[V2:%[0-9]+]]:_(<4 x s32>) = G_INSERT_VECTOR_ELT [[V1]], [[ARG2]](s32), [[C1]](s32) ; CHECK-DAG: [[V3:%[0-9]+]]:_(<4 x s32>) = G_INSERT_VECTOR_ELT [[V2]], [[ARG3]](s32), [[C2]](s32) ; CHECK-DAG: [[V4:%[0-9]+]]:_(<4 x s32>) = G_INSERT_VECTOR_ELT [[V3]], [[ARG4]](s32), [[C3]](s32) -; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[V4]](<4 x s32>), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[V4]](<4 x s32>), [[UNDEF]], shufflemask(1, 3) ; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<2 x s32>) %v1 = insertelement <4 x i32> undef, i32 %arg1, i32 0 %v2 = insertelement <4 x i32> %v1, i32 %arg2, i32 1 Index: test/CodeGen/MIR/AArch64/parse-shufflemask-invalid0.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/AArch64/parse-shufflemask-invalid0.mir @@ -0,0 +1,19 @@ +# RUN: not llc -mtriple=aarch64-- -run-pass=none -o /dev/null %s 2>&1 | FileCheck %s + +--- +name: test_missing_comma +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + + ; FIXME: Not ideal error + ; CHECK: [[@LINE+1]]:73: shufflemask should be terminated by ')'. + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(1 0) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... Index: test/CodeGen/MIR/AArch64/parse-shufflemask-invalid1.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/AArch64/parse-shufflemask-invalid1.mir @@ -0,0 +1,18 @@ +# RUN: not llc -mtriple=aarch64-- -run-pass=none -o /dev/null %s 2>&1 | FileCheck %s + +--- +name: test_missing_lparen +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + + ; CHECK: [[@LINE+1]]:71: expected syntax shufflemask(, ...) + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask 1, 0) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... Index: test/CodeGen/MIR/AArch64/parse-shufflemask-invalid2.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/AArch64/parse-shufflemask-invalid2.mir @@ -0,0 +1,18 @@ +# RUN: not llc -mtriple=aarch64-- -run-pass=none -o /dev/null %s 2>&1 | FileCheck %s + +--- +name: test_missing_rparen +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + + ; CHECK: [[@LINE+1]]:75: shufflemask should be terminated by ')'. + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(1, 0 + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... Index: test/CodeGen/MIR/AArch64/parse-shufflemask-invalid3.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/AArch64/parse-shufflemask-invalid3.mir @@ -0,0 +1,18 @@ +# RUN: not llc -mtriple=aarch64-- -run-pass=none -o /dev/null %s 2>&1 | FileCheck %s + +--- +name: test_not_integer +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + + ; CHECK: [[@LINE+1]]:74: expected integer constant + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(1, arst) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... Index: test/CodeGen/MIR/AArch64/parse-shufflemask.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/AArch64/parse-shufflemask.mir @@ -0,0 +1,175 @@ +# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass none -o - %s | FileCheck %s +# This test ensures that the MIR parser parses shufflemask correctly + +# CHECK-LABEL: name: test_shuffle_1_0 +# CHECK: G_SHUFFLE_VECTOR %0(<2 x s32>), %1, shufflemask(1, 0) +--- +name: test_shuffle_1_0 +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(1, 0) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... + +# CHECK-LABEL: name: test_shuffle_nospace +# CHECK: G_SHUFFLE_VECTOR %0(<2 x s32>), %1, shufflemask(1, 0) +--- +name: test_shuffle_nospace +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(1,0) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... + +# CHECK-LABEL: name: test_shuffle_0_0 +# CHECK: G_SHUFFLE_VECTOR %0(<2 x s32>), %1, shufflemask(0, 0) +--- +name: test_shuffle_0_0 +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(0, 0) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... + +# CHECK-LABEL: name: test_shuffle_1_1 +# CHECK: G_SHUFFLE_VECTOR %0(<2 x s32>), %1, shufflemask(1, 1) +--- +name: test_shuffle_1_1 +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(1, 1) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... + +# CHECK-LABEL: name: test_shuffle_undef_undef +# CHECK: G_SHUFFLE_VECTOR %0(<2 x s32>), %1, shufflemask(undef, undef) + +--- +name: test_shuffle_undef_undef +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(undef, undef) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... + +# CHECK-LABEL: name: test_shuffle_undef_0 +# CHECK: G_SHUFFLE_VECTOR %0(<2 x s32>), %1, shufflemask(undef, 0) + +--- +name: test_shuffle_undef_0 +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(undef, 0) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... + +# CHECK-LABEL: name: test_shuffle_0_undef +# CHECK: G_SHUFFLE_VECTOR %0(<2 x s32>), %1, shufflemask(0, undef) + +--- +name: test_shuffle_0_undef +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(0, undef) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... + +# CHECK-LABEL: name: test_shuffle_0 +# CHECK: G_SHUFFLE_VECTOR %0(<2 x s32>), %1, shufflemask(0) +--- +name: test_shuffle_0 +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(0) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... + +# CHECK-LABEL: name: test_shuffle_1 +# CHECK: G_SHUFFLE_VECTOR %0(<2 x s32>), %1, shufflemask(1) +--- +name: test_shuffle_1 +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(1) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... + +# CHECK-LABEL: name: test_shuffle_undef +# CHECK: G_SHUFFLE_VECTOR %0(<2 x s32>), %1, shufflemask(undef) +--- +name: test_shuffle_undef +tracksRegLiveness: true +body: | + bb.0: + liveins: $d0 + + %0:_(<2 x s32>) = COPY $d0 + %2:_(<2 x s32>) = G_IMPLICIT_DEF + %1:_(<2 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %2, shufflemask(undef) + $d0 = COPY %1(<2 x s32>) + RET_ReallyLR implicit $d0 + +... Index: test/MachineVerifier/test_g_shuffle_vector.mir =================================================================== --- /dev/null +++ test/MachineVerifier/test_g_shuffle_vector.mir @@ -0,0 +1,29 @@ +# RUN: not llc -o - -march=arm64 -global-isel -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s +# REQUIRES: aarch64-registered-target +--- +name: g_shuffle_vector +tracksRegLiveness: true +liveins: +body: | + bb.0: + %0:_(<2 x s32>) = G_IMPLICIT_DEF + %1:_(<2 x s32>) = G_IMPLICIT_DEF + %2:_(<4 x s32>) = G_IMPLICIT_DEF + + %3:_(s32) = G_CONSTANT i32 0 + %4:_(s32) = G_CONSTANT i32 1 + %5:_(<2 x s32>) = G_BUILD_VECTOR %3, %4 + + ; CHECK: Bad machine code: Incorrect mask operand type for G_SHUFFLE_VECTOR + %6:_(<4 x s32>) = G_SHUFFLE_VECTOR %0, %1, %2 + + ; CHECK: Bad machine code: Incorrect mask operand type for G_SHUFFLE_VECTOR + %7:_(<4 x s32>) = G_SHUFFLE_VECTOR %0, %1, %5 + + ; CHECK: Bad machine code: Incorrect mask operand type for G_SHUFFLE_VECTOR + %8:_(<4 x s32>) = G_SHUFFLE_VECTOR %0, %1, 0 + + ; CHECK: Bad machine code: Incorrect mask operand type for G_SHUFFLE_VECTOR + %9:_(<4 x s32>) = G_SHUFFLE_VECTOR %0, %1, i32 0 + +...