forked from OSchip/llvm-project
[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
This commit is contained in:
parent
5c338ff7a3
commit
04cb08cc83
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue