aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolkan Keles <vkeles@apple.com>2017-03-10 19:08:28 +0000
committerVolkan Keles <vkeles@apple.com>2017-03-10 19:08:28 +0000
commit04cb08cc83032168f3f7a1a5a6c8f11bbf8aa16c (patch)
tree1b1d947cd45ed34b3819495fd4320ac2714760bc
parent5c338ff7a3f56800989c8c2b0a3fe544e57d12c0 (diff)
downloadllvm-04cb08cc83032168f3f7a1a5a6c8f11bbf8aa16c.zip
llvm-04cb08cc83032168f3f7a1a5a6c8f11bbf8aa16c.tar.gz
llvm-04cb08cc83032168f3f7a1a5a6c8f11bbf8aa16c.tar.bz2
[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 llvm-svn: 297495
-rw-r--r--llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h10
-rw-r--r--llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h24
-rw-r--r--llvm/include/llvm/Target/GenericOpcodes.td18
-rw-r--r--llvm/include/llvm/Target/TargetOpcodes.def6
-rw-r--r--llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp30
-rw-r--r--llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp40
-rw-r--r--llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll32
7 files changed, 154 insertions, 6 deletions
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index 174443d..104a444 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/llvm/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/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 0c37a0e..472f505 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/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<def> = 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<def> = 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/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index cb0ab8d..64f4ec8 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/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/llvm/include/llvm/Target/TargetOpcodes.def b/llvm/include/llvm/Target/TargetOpcodes.def
index a39fa3f..6253a34 100644
--- a/llvm/include/llvm/Target/TargetOpcodes.def
+++ b/llvm/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/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index b8bb71d..5a4f950 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/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<PHINode>(U);
auto MIB = MIRBuilder.buildInstr(TargetOpcode::PHI);
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 9745340..8d1a263 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/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/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
index 21ce631..9d97ade 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
+++ b/llvm/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
+}