From 27b5bfd0d0ff02dffc4b66ed074412454cc6294c Mon Sep 17 00:00:00 2001 From: Volkan Keles Date: Fri, 10 Mar 2017 19:08:28 +0000 Subject: [PATCH] [GlobalISel] Translate insertelement and extractelement Reviewers: qcolombet, aditya_nandakumar, dsanders, ab, t.p.northover, javed.absar Reviewed By: qcolombet Subscribers: dberris, rovka, llvm-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D30761 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297495 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../llvm/CodeGen/GlobalISel/IRTranslator.h | 10 ++--- .../CodeGen/GlobalISel/MachineIRBuilder.h | 24 +++++++++++ include/llvm/Target/GenericOpcodes.td | 18 +++++++++ include/llvm/Target/TargetOpcodes.def | 6 +++ lib/CodeGen/GlobalISel/IRTranslator.cpp | 30 ++++++++++++++ lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | 40 +++++++++++++++++++ .../AArch64/GlobalISel/arm64-irtranslator.ll | 32 +++++++++++++++ 7 files changed, 154 insertions(+), 6 deletions(-) diff --git a/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 174443d47a5..104a444f5b2 100644 --- a/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -304,6 +304,10 @@ private: bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder); + bool translateInsertElement(const User &U, MachineIRBuilder &MIRBuilder); + + bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder); + // Stubs to keep the compiler happy while we implement the rest of the // translation. bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) { @@ -342,12 +346,6 @@ private: bool translateUserOp2(const User &U, MachineIRBuilder &MIRBuilder) { return false; } - bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateInsertElement(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder) { return false; } diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 0c37a0e9cfe..472f50576d9 100644 --- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -594,6 +594,30 @@ public: /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildSelect(unsigned Res, unsigned Tst, unsigned Op0, unsigned Op1); + + /// Build and insert \p Res = G_INSERT_VECTOR_ELT \p Val, + /// \p Elt, \p Idx + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res and \p Val must be a generic virtual register + // with the same vector type. + /// \pre \p Elt and \p Idx must be a generic virtual register + /// with scalar type. + /// + /// \return The newly created instruction. + MachineInstrBuilder buildInsertVectorElement(unsigned Res, unsigned Val, + unsigned Elt, unsigned Idx); + + /// Build and insert \p Res = G_EXTRACT_VECTOR_ELT \p Val, \p Idx + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res must be a generic virtual register with scalar type. + /// \pre \p Val must be a generic virtual register with vector type. + /// \pre \p Idx must be a generic virtual register with scalar type. + /// + /// \return The newly created instruction. + MachineInstrBuilder buildExtractVectorElement(unsigned Res, unsigned Val, + unsigned Idx); }; } // End namespace llvm. diff --git a/include/llvm/Target/GenericOpcodes.td b/include/llvm/Target/GenericOpcodes.td index cb0ab8d7e95..64f4ec8dd44 100644 --- a/include/llvm/Target/GenericOpcodes.td +++ b/include/llvm/Target/GenericOpcodes.td @@ -519,4 +519,22 @@ def G_BRINDIRECT : Instruction { let isTerminator = 1; } +//------------------------------------------------------------------------------ +// Vector ops +//------------------------------------------------------------------------------ + +// Generic insertelement. +def G_INSERT_VECTOR_ELT : Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src, type1:$elt, type2:$idx); + let hasSideEffects = 0; +} + +// Generic extractelement. +def G_EXTRACT_VECTOR_ELT : Instruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src, type2:$idx); + let hasSideEffects = 0; +} + // TODO: Add the other generic opcodes. diff --git a/include/llvm/Target/TargetOpcodes.def b/include/llvm/Target/TargetOpcodes.def index a39fa3f7739..6253a34c16b 100644 --- a/include/llvm/Target/TargetOpcodes.def +++ b/include/llvm/Target/TargetOpcodes.def @@ -395,6 +395,12 @@ HANDLE_TARGET_OPCODE(G_PTR_MASK) /// Generic BRANCH instruction. This is an unconditional branch. HANDLE_TARGET_OPCODE(G_BR) +/// Generic insertelement. +HANDLE_TARGET_OPCODE(G_INSERT_VECTOR_ELT) + +/// Generic extractelement. +HANDLE_TARGET_OPCODE(G_EXTRACT_VECTOR_ELT) + // TODO: Add more generic opcodes as we move along. /// Marker for the end of the generic opcode. diff --git a/lib/CodeGen/GlobalISel/IRTranslator.cpp b/lib/CodeGen/GlobalISel/IRTranslator.cpp index b8bb71dcc2c..5a4f950776f 100644 --- a/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -976,6 +976,36 @@ bool IRTranslator::translateVAArg(const User &U, MachineIRBuilder &MIRBuilder) { return true; } +bool IRTranslator::translateInsertElement(const User &U, + MachineIRBuilder &MIRBuilder) { + // If it is a <1 x Ty> vector, use the scalar as it is + // not a legal vector type in LLT. + if (U.getType()->getVectorNumElements() == 1) { + unsigned Elt = getOrCreateVReg(*U.getOperand(1)); + ValToVReg[&U] = Elt; + return true; + } + MIRBuilder.buildInsertVectorElement( + getOrCreateVReg(U), getOrCreateVReg(*U.getOperand(0)), + getOrCreateVReg(*U.getOperand(1)), getOrCreateVReg(*U.getOperand(2))); + return true; +} + +bool IRTranslator::translateExtractElement(const User &U, + MachineIRBuilder &MIRBuilder) { + // If it is a <1 x Ty> vector, use the scalar as it is + // not a legal vector type in LLT. + if (U.getOperand(0)->getType()->getVectorNumElements() == 1) { + unsigned Elt = getOrCreateVReg(*U.getOperand(0)); + ValToVReg[&U] = Elt; + return true; + } + MIRBuilder.buildExtractVectorElement(getOrCreateVReg(U), + getOrCreateVReg(*U.getOperand(0)), + getOrCreateVReg(*U.getOperand(1))); + return true; +} + bool IRTranslator::translatePHI(const User &U, MachineIRBuilder &MIRBuilder) { const PHINode &PI = cast(U); auto MIB = MIRBuilder.buildInstr(TargetOpcode::PHI); diff --git a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 9745340a05a..8d1a263395a 100644 --- a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -582,6 +582,46 @@ MachineInstrBuilder MachineIRBuilder::buildSelect(unsigned Res, unsigned Tst, .addUse(Op1); } +MachineInstrBuilder MachineIRBuilder::buildInsertVectorElement(unsigned Res, + unsigned Val, + unsigned Elt, + unsigned Idx) { +#ifndef NDEBUG + LLT ResTy = MRI->getType(Res); + LLT ValTy = MRI->getType(Val); + LLT EltTy = MRI->getType(Elt); + LLT IdxTy = MRI->getType(Idx); + assert(ResTy.isVector() && ValTy.isVector() && "invalid operand type"); + assert(EltTy.isScalar() && IdxTy.isScalar() && "invalid operand type"); + assert(ResTy.getNumElements() == ValTy.getNumElements() && "type mismatch"); + assert(ResTy.getElementType() == EltTy && "type mismatch"); +#endif + + return buildInstr(TargetOpcode::G_INSERT_VECTOR_ELT) + .addDef(Res) + .addUse(Val) + .addUse(Elt) + .addUse(Idx); +} + +MachineInstrBuilder MachineIRBuilder::buildExtractVectorElement(unsigned Res, + unsigned Val, + unsigned Idx) { +#ifndef NDEBUG + LLT ResTy = MRI->getType(Res); + LLT ValTy = MRI->getType(Val); + LLT IdxTy = MRI->getType(Idx); + assert(ValTy.isVector() && "invalid operand type"); + assert(ResTy.isScalar() && IdxTy.isScalar() && "invalid operand type"); + assert(ValTy.getElementType() == ResTy && "type mismatch"); +#endif + + return buildInstr(TargetOpcode::G_EXTRACT_VECTOR_ELT) + .addDef(Res) + .addUse(Val) + .addUse(Idx); +} + void MachineIRBuilder::validateTruncExt(unsigned Dst, unsigned Src, bool IsExtend) { #ifndef NDEBUG diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll index 21ce631cca3..9d97ade874e 100644 --- a/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -1271,3 +1271,35 @@ define void @test_trivial_inlineasm() { call void asm "wibble", ""() ret void } + +define <2 x i32> @test_insertelement(<2 x i32> %vec, i32 %elt, i32 %idx){ +; CHECK-LABEL: name: test_insertelement +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK: [[ELT:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[IDX:%[0-9]+]](s32) = COPY %w1 +; CHECK: [[RES:%[0-9]+]](<2 x s32>) = G_INSERT_VECTOR_ELT [[VEC]], [[ELT]](s32), [[IDX]](s32) +; CHECK: %d0 = COPY [[RES]](<2 x s32>) + %res = insertelement <2 x i32> %vec, i32 %elt, i32 %idx + ret <2 x i32> %res +} + +define i32 @test_extractelement(<2 x i32> %vec, i32 %idx) { +; CHECK-LABEL: name: test_extractelement +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK: [[IDX:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[RES:%[0-9]+]](s32) = G_EXTRACT_VECTOR_ELT [[VEC]](<2 x s32>), [[IDX]](s32) +; CHECK: %w0 = COPY [[RES]](s32) + %res = extractelement <2 x i32> %vec, i32 %idx + ret i32 %res +} + +define i32 @test_singleelementvector(i32 %elt){ +; CHECK-LABEL: name: test_singleelementvector +; CHECK: [[ELT:%[0-9]+]](s32) = COPY %w0 +; CHECK-NOT: G_INSERT_VECTOR_ELT +; CHECK-NOT: G_EXTRACT_VECTOR_ELT +; CHECK: %w0 = COPY [[ELT]](s32) + %vec = insertelement <1 x i32> undef, i32 %elt, i32 0 + %res = extractelement <1 x i32> %vec, i32 0 + ret i32 %res +} -- 2.50.1