MachineInstrBuilder buildStore(LLT VTy, LLT PTy, unsigned Val, unsigned Addr,
MachineMemOperand &MMO);
- /// Build and insert `Res0<def>, ... = G_EXTRACT Ty Src, Idx0, ...`.
+ /// Build and insert `Res0<def>, ... = G_EXTRACT { ResTys, SrcTy } Src, Idx0,
+ /// ...`.
///
- /// If \p Ty has size N bits, G_EXTRACT sets \p Res[0] to bits `[Idxs[0],
+ /// If \p SrcTy has size N bits, G_EXTRACT sets \p Res[0] to bits `[Idxs[0],
/// Idxs[0] + N)` of \p Src and similarly for subsequent bit-indexes.
///
/// \pre setBasicBlock or setMI must have been called.
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildExtract(LLT Ty, ArrayRef<unsigned> Results,
- unsigned Src, ArrayRef<uint64_t> Indexes);
+ MachineInstrBuilder buildExtract(ArrayRef<LLT> ResTys,
+ ArrayRef<unsigned> Results,
+ ArrayRef<uint64_t> Indices, LLT SrcTy,
+ unsigned Src);
- /// Build and insert \p Res<def> = G_SEQUENCE \p Ty \p Op0, \p Idx0...
+ /// Build and insert \p Res<def> = G_SEQUENCE \p { \pResTy, \p Op0Ty, ... }
+ /// \p Op0, \p Idx0...
///
/// G_SEQUENCE inserts each element of Ops into an IMPLICIT_DEF register,
- /// where each entry starts at the bit-index specified by \p Indexes.
+ /// where each entry starts at the bit-index specified by \p Indices.
///
/// \pre setBasicBlock or setMI must have been called.
/// \pre The final element of the sequence must not extend past the end of the
/// destination register.
/// \pre The bits defined by each Op (derived from index and scalar size) must
/// not overlap.
+ /// \pre Each source operand must have a
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildSequence(LLT Ty, unsigned Res,
+ MachineInstrBuilder buildSequence(LLT ResTy, unsigned Res,
+ ArrayRef<LLT> OpTys,
ArrayRef<unsigned> Ops,
- ArrayRef<unsigned> Indexes);
+ ArrayRef<unsigned> Indices);
- void addUsesWithIndexes(MachineInstrBuilder MIB) {}
+ void addUsesWithIndices(MachineInstrBuilder MIB) {}
template <typename... ArgTys>
- void addUsesWithIndexes(MachineInstrBuilder MIB, unsigned Reg,
+ void addUsesWithIndices(MachineInstrBuilder MIB, LLT Ty, unsigned Reg,
unsigned BitIndex, ArgTys... Args) {
MIB.addUse(Reg).addImm(BitIndex);
- addUsesWithIndexes(MIB, Args...);
+ MIB->setType(Ty, MIB->getNumTypes());
+
+ addUsesWithIndices(MIB, Args...);
}
template <typename... ArgTys>
- MachineInstrBuilder buildSequence(LLT Ty, unsigned Res, unsigned Op,
+ MachineInstrBuilder buildSequence(LLT Ty, unsigned Res, LLT OpTy, unsigned Op,
unsigned Index, ArgTys... Args) {
MachineInstrBuilder MIB =
buildInstr(TargetOpcode::G_SEQUENCE, Ty).addDef(Res);
- addUsesWithIndexes(MIB, Op, Index, Args...);
+ addUsesWithIndices(MIB, OpTy, Op, Index, Args...);
return MIB;
}
uint64_t Offset = 8 * DL->getIndexedOffsetInType(Src->getType(), Indices);
unsigned Res = getOrCreateVReg(EVI);
- MIRBuilder.buildExtract(LLT{*EVI.getType(), DL}, Res, getOrCreateVReg(*Src),
- Offset);
+ MIRBuilder.buildExtract(LLT{*EVI.getType(), DL}, Res, Offset,
+ LLT{*Src->getType(), DL}, getOrCreateVReg(*Src));
return true;
}
MIB.addUse(Zero);
}
- MIRBuilder.buildSequence(LLT{*CI.getType(), DL}, getOrCreateVReg(CI), Res, 0,
- Overflow, Width);
+ MIRBuilder.buildSequence(LLT{*CI.getType(), DL}, getOrCreateVReg(CI), Ty, Res,
+ 0, s1, Overflow, Width);
return true;
}
return buildInstr(TargetOpcode::G_ANYEXTEND, Ty).addDef(Res).addUse(Op);
}
-MachineInstrBuilder
-MachineIRBuilder::buildExtract(LLT Ty, ArrayRef<unsigned> Results, unsigned Src,
- ArrayRef<uint64_t> Indexes) {
- assert(Results.size() == Indexes.size() && "inconsistent number of regs");
+MachineInstrBuilder MachineIRBuilder::buildExtract(ArrayRef<LLT> ResTys,
+ ArrayRef<unsigned> Results,
+ ArrayRef<uint64_t> Indices,
+ LLT SrcTy, unsigned Src) {
+ assert(ResTys.size() == Results.size() && Results.size() == Indices.size() &&
+ "inconsistent number of regs");
+ assert(!Results.empty() && "invalid trivial extract");
+
+ auto MIB = BuildMI(getMF(), DL, getTII().get(TargetOpcode::G_EXTRACT));
+ for (unsigned i = 0; i < ResTys.size(); ++i)
+ MIB->setType(LLT::scalar(ResTys[i].getSizeInBits()), i);
+ MIB->setType(LLT::scalar(SrcTy.getSizeInBits()), ResTys.size());
- MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_EXTRACT, Ty);
for (auto Res : Results)
MIB.addDef(Res);
MIB.addUse(Src);
- for (auto Idx : Indexes)
+ for (auto Idx : Indices)
MIB.addImm(Idx);
+
+ getMBB().insert(getInsertPt(), MIB);
+
return MIB;
}
MachineInstrBuilder
-MachineIRBuilder::buildSequence(LLT Ty, unsigned Res,
+MachineIRBuilder::buildSequence(LLT ResTy, unsigned Res,
+ ArrayRef<LLT> OpTys,
ArrayRef<unsigned> Ops,
- ArrayRef<unsigned> Indexes) {
- assert(Ops.size() == Indexes.size() && "incompatible args");
+ ArrayRef<unsigned> Indices) {
+ assert(OpTys.size() == Ops.size() && Ops.size() == Indices.size() &&
+ "incompatible args");
+ assert(!Ops.empty() && "invalid trivial sequence");
- MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_SEQUENCE, Ty);
+ MachineInstrBuilder MIB =
+ buildInstr(TargetOpcode::G_SEQUENCE, LLT::scalar(ResTy.getSizeInBits()));
MIB.addDef(Res);
for (unsigned i = 0; i < Ops.size(); ++i) {
MIB.addUse(Ops[i]);
- MIB.addImm(Indexes[i]);
+ MIB.addImm(Indices[i]);
+ MIB->setType(LLT::scalar(OpTys[i].getSizeInBits()), MIB->getNumTypes());
}
return MIB;
}
SmallVectorImpl<unsigned> &VRegs) {
unsigned Size = Ty.getSizeInBits();
SmallVector<uint64_t, 4> Indexes;
+ SmallVector<LLT, 4> ResTys;
for (int i = 0; i < NumParts; ++i) {
VRegs.push_back(MRI.createGenericVirtualRegister(Size));
Indexes.push_back(i * Size);
+ ResTys.push_back(Ty);
}
- MIRBuilder.buildExtract(Ty, VRegs, Reg, Indexes);
+ MIRBuilder.buildExtract(ResTys, VRegs, Indexes,
+ LLT::scalar(Ty.getSizeInBits() * NumParts), Reg);
}
MachineLegalizeHelper::LegalizeResult
unsigned CarryIn = MRI.createGenericVirtualRegister(1);
MIRBuilder.buildConstant(LLT::scalar(1), CarryIn, 0);
+ SmallVector<LLT, 2> DstTys;
for (int i = 0; i < NumParts; ++i) {
unsigned DstReg = MRI.createGenericVirtualRegister(NarrowSize);
unsigned CarryOut = MRI.createGenericVirtualRegister(1);
MIRBuilder.buildUAdde(NarrowTy, DstReg, CarryOut, Src1Regs[i],
Src2Regs[i], CarryIn);
+ DstTys.push_back(NarrowTy);
DstRegs.push_back(DstReg);
Indexes.push_back(i * NarrowSize);
CarryIn = CarryOut;
}
- MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstRegs,
- Indexes);
+ MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstTys,
+ DstRegs, Indexes);
MI.eraseFromParent();
return Legalized;
}
extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
+ SmallVector<LLT, 2> DstTys;
for (int i = 0; i < NumParts; ++i) {
unsigned DstReg = MRI.createGenericVirtualRegister(NarrowSize);
MIRBuilder.buildAdd(NarrowTy, DstReg, Src1Regs[i], Src2Regs[i]);
+ DstTys.push_back(NarrowTy);
DstRegs.push_back(DstReg);
Indexes.push_back(i * NarrowSize);
}
- MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstRegs,
- Indexes);
+ MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstTys,
+ DstRegs, Indexes);
MI.eraseFromParent();
return Legalized;
}
; CHECK: [[RHS:%[0-9]+]](32) = COPY %w1
; CHECK: [[ADDR:%[0-9]+]](64) = COPY %x2
; CHECK: [[VAL:%[0-9]+]](32), [[OVERFLOW:%[0-9]+]](1) = G_SADDO { s32, s1 } [[LHS]], [[RHS]]
-; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE s64 [[VAL]], 0, [[OVERFLOW]], 32
+; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE { s64, s32, s1 } [[VAL]], 0, [[OVERFLOW]], 32
; CHECK: G_STORE { s64, p0 } [[RES]], [[ADDR]]
declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32)
define void @test_sadd_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
; CHECK: [[ADDR:%[0-9]+]](64) = COPY %x2
; CHECK: [[ZERO:%[0-9]+]](1) = G_CONSTANT s1 0
; CHECK: [[VAL:%[0-9]+]](32), [[OVERFLOW:%[0-9]+]](1) = G_UADDE { s32, s1 } [[LHS]], [[RHS]], [[ZERO]]
-; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE s64 [[VAL]], 0, [[OVERFLOW]], 32
+; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE { s64, s32, s1 } [[VAL]], 0, [[OVERFLOW]], 32
; CHECK: G_STORE { s64, p0 } [[RES]], [[ADDR]]
declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32)
define void @test_uadd_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
; CHECK: [[RHS:%[0-9]+]](32) = COPY %w1
; CHECK: [[SUBR:%[0-9]+]](64) = COPY %x2
; CHECK: [[VAL:%[0-9]+]](32), [[OVERFLOW:%[0-9]+]](1) = G_SSUBO { s32, s1 } [[LHS]], [[RHS]]
-; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE s64 [[VAL]], 0, [[OVERFLOW]], 32
+; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE { s64, s32, s1 } [[VAL]], 0, [[OVERFLOW]], 32
; CHECK: G_STORE { s64, p0 } [[RES]], [[SUBR]]
declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32)
define void @test_ssub_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %subr) {
; CHECK: [[SUBR:%[0-9]+]](64) = COPY %x2
; CHECK: [[ZERO:%[0-9]+]](1) = G_CONSTANT s1 0
; CHECK: [[VAL:%[0-9]+]](32), [[OVERFLOW:%[0-9]+]](1) = G_USUBE { s32, s1 } [[LHS]], [[RHS]], [[ZERO]]
-; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE s64 [[VAL]], 0, [[OVERFLOW]], 32
+; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE { s64, s32, s1 } [[VAL]], 0, [[OVERFLOW]], 32
; CHECK: G_STORE { s64, p0 } [[RES]], [[SUBR]]
declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32)
define void @test_usub_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %subr) {
; CHECK: [[RHS:%[0-9]+]](32) = COPY %w1
; CHECK: [[ADDR:%[0-9]+]](64) = COPY %x2
; CHECK: [[VAL:%[0-9]+]](32), [[OVERFLOW:%[0-9]+]](1) = G_SMULO { s32, s1 } [[LHS]], [[RHS]]
-; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE s64 [[VAL]], 0, [[OVERFLOW]], 32
+; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE { s64, s32, s1 } [[VAL]], 0, [[OVERFLOW]], 32
; CHECK: G_STORE { s64, p0 } [[RES]], [[ADDR]]
declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32)
define void @test_smul_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
; CHECK: [[RHS:%[0-9]+]](32) = COPY %w1
; CHECK: [[ADDR:%[0-9]+]](64) = COPY %x2
; CHECK: [[VAL:%[0-9]+]](32), [[OVERFLOW:%[0-9]+]](1) = G_UMULO { s32, s1 } [[LHS]], [[RHS]]
-; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE s64 [[VAL]], 0, [[OVERFLOW]], 32
+; CHECK: [[RES:%[0-9]+]](64) = G_SEQUENCE { s64, s32, s1 } [[VAL]], 0, [[OVERFLOW]], 32
; CHECK: G_STORE { s64, p0 } [[RES]], [[ADDR]]
declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32)
define void @test_umul_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
; CHECK-LABEL: name: test_extractvalue
; CHECK: [[STRUCT:%[0-9]+]](128) = G_LOAD { s128, p0 }
-; CHECK: [[RES:%[0-9]+]](32) = G_EXTRACT s32 [[STRUCT]], 64
+; CHECK: [[RES:%[0-9]+]](32) = G_EXTRACT { s32, s128 } [[STRUCT]], 64
; CHECK: %w0 = COPY [[RES]]
%struct.nested = type {i8, { i8, i32 }, i32}
define i32 @test_extractvalue(%struct.nested* %addr) {
; CHECK-LABEL: name: test_extractvalue_agg
; CHECK: [[STRUCT:%[0-9]+]](128) = G_LOAD { s128, p0 }
-; CHECK: [[RES:%[0-9]+]](64) = G_EXTRACT s64 [[STRUCT]], 32
+; CHECK: [[RES:%[0-9]+]](64) = G_EXTRACT { s64, s128 } [[STRUCT]], 32
; CHECK: G_STORE { s64, p0 } [[RES]]
define void @test_extractvalue_agg(%struct.nested* %addr, {i8, i32}* %addr2) {
%struct = load %struct.nested, %struct.nested* %addr
bb.0.entry:
liveins: %x0, %x1, %x2, %x3
; CHECK-LABEL: name: test_scalar_add_big
- ; CHECK-DAG: [[LHS_LO:%.*]](64), [[LHS_HI:%.*]](64) = G_EXTRACT s64 %0, 0, 64
- ; CHECK-DAG: [[RHS_LO:%.*]](64), [[RHS_HI:%.*]](64) = G_EXTRACT s64 %1, 0, 64
+ ; CHECK-DAG: [[LHS_LO:%.*]](64), [[LHS_HI:%.*]](64) = G_EXTRACT { s64, s64, s128 } %0, 0, 64
+ ; CHECK-DAG: [[RHS_LO:%.*]](64), [[RHS_HI:%.*]](64) = G_EXTRACT { s64, s64, s128 } %1, 0, 64
; CHECK-DAG: [[CARRY0:%.*]](1) = G_CONSTANT s1 0
; CHECK: [[RES_LO:%.*]](64), [[CARRY:%.*]](1) = G_UADDE s64 [[LHS_LO]], [[RHS_LO]], [[CARRY0]]
; CHECK: [[RES_HI:%.*]](64), {{%.*}}(1) = G_UADDE s64 [[LHS_HI]], [[RHS_HI]], [[CARRY]]
- ; CHECK: %2(128) = G_SEQUENCE s128 [[RES_LO]], 0, [[RES_HI]], 64
+ ; CHECK: %2(128) = G_SEQUENCE { s128, s64, s64 } [[RES_LO]], 0, [[RES_HI]], 64
- %0(128) = G_SEQUENCE s128 %x0, 0, %x1, 64
- %1(128) = G_SEQUENCE s128 %x2, 0, %x3, 64
+ %0(128) = G_SEQUENCE { s128, s64, s64 } %x0, 0, %x1, 64
+ %1(128) = G_SEQUENCE { s128, s64, s64 } %x2, 0, %x3, 64
%2(128) = G_ADD s128 %0, %1
- %x0, %x1 = G_EXTRACT s64 %2, 0, 64
+ %x0, %x1 = G_EXTRACT { s64, s64, s128 } %2, 0, 64
...
---
bb.0.entry:
liveins: %q0, %q1, %q2, %q3
; CHECK-LABEL: name: test_vector_add
- ; CHECK-DAG: [[LHS_LO:%.*]](128), [[LHS_HI:%.*]](128) = G_EXTRACT <2 x s64> %0, 0, 128
- ; CHECK-DAG: [[RHS_LO:%.*]](128), [[RHS_HI:%.*]](128) = G_EXTRACT <2 x s64> %1, 0, 128
+ ; CHECK-DAG: [[LHS_LO:%.*]](128), [[LHS_HI:%.*]](128) = G_EXTRACT { s128, s128, s256 } %0, 0, 128
+ ; CHECK-DAG: [[RHS_LO:%.*]](128), [[RHS_HI:%.*]](128) = G_EXTRACT { s128, s128, s256 } %1, 0, 128
; CHECK: [[RES_LO:%.*]](128) = G_ADD <2 x s64> [[LHS_LO]], [[RHS_LO]]
; CHECK: [[RES_HI:%.*]](128) = G_ADD <2 x s64> [[LHS_HI]], [[RHS_HI]]
- ; CHECK: %2(256) = G_SEQUENCE <4 x s64> [[RES_LO]], 0, [[RES_HI]], 128
+ ; CHECK: %2(256) = G_SEQUENCE { s256, s128, s128 } [[RES_LO]], 0, [[RES_HI]], 128
- %0(256) = G_SEQUENCE <4 x s64> %q0, 0, %q1, 128
- %1(256) = G_SEQUENCE <4 x s64> %q2, 0, %q3, 128
+ %0(256) = G_SEQUENCE { s256, s128, s128 } %q0, 0, %q1, 128
+ %1(256) = G_SEQUENCE { s256, s128, s128 } %q2, 0, %q3, 128
%2(256) = G_ADD <4 x s64> %0, %1
- %q0, %q1 = G_EXTRACT <2 x s64> %2, 0, 128
+ %q0, %q1 = G_EXTRACT { s128, s128, s256 } %2, 0, 128
...