summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2017-03-06 18:23:04 +0000
committerTim Northover <tnorthover@apple.com>2017-03-06 18:23:04 +0000
commit75e0b91e597f97ee8f32f56984988ab55fbfa067 (patch)
treea9bd7d90fb4cdfcca0c759dccad7355076a3f915 /llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
parentc494239bd85d909c7a0a7030a05a9221046db1ef (diff)
downloadbcm5719-llvm-75e0b91e597f97ee8f32f56984988ab55fbfa067.tar.gz
bcm5719-llvm-75e0b91e597f97ee8f32f56984988ab55fbfa067.zip
GlobalISel: refactor legalization of G_INSERT.
Now that G_INSERT instructions can only insert one register, this code was overly general. In another direction it didn't handle registers that crossed split boundaries properly, which needed to be fixed. llvm-svn: 297042
Diffstat (limited to 'llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp')
-rw-r--r--llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp60
1 files changed, 23 insertions, 37 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 2d28a42c797..a8bc694dc17 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -127,17 +127,6 @@ LegalizerHelper::libcall(MachineInstr &MI) {
}
}
-void LegalizerHelper::findInsertionsForRange(
- int64_t DstStart, int64_t DstEnd, MachineInstr::mop_iterator &CurOp,
- MachineInstr::mop_iterator &EndOp, MachineInstr &MI) {
- while (CurOp != MI.operands_end() && std::next(CurOp)->getImm() < DstStart)
- CurOp += 2;
-
- EndOp = CurOp;
- while (EndOp != MI.operands_end() && std::next(EndOp)->getImm() < DstEnd)
- EndOp += 2;
-}
-
LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
unsigned TypeIdx,
LLT NarrowTy) {
@@ -181,7 +170,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
if (TypeIdx != 0)
return UnableToLegalize;
- unsigned NarrowSize = NarrowTy.getSizeInBits();
+ int64_t NarrowSize = NarrowTy.getSizeInBits();
int NumParts =
MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
@@ -189,44 +178,41 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
SmallVector<uint64_t, 2> Indexes;
extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
- MachineInstr::mop_iterator CurOp = MI.operands_begin() + 2, EndOp;
+ unsigned OpReg = MI.getOperand(2).getReg();
+ int64_t OpStart = MI.getOperand(3).getImm();
+ int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
for (int i = 0; i < NumParts; ++i) {
unsigned DstStart = i * NarrowSize;
- unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
-
- findInsertionsForRange(DstStart, DstStart + NarrowSize, CurOp, EndOp, MI);
- if (CurOp == EndOp) {
+ if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
// No part of the insert affects this subregister, forward the original.
DstRegs.push_back(SrcRegs[i]);
continue;
- } else if (MRI.getType(CurOp->getReg()) == NarrowTy &&
- std::next(CurOp)->getImm() == DstStart) {
+ } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
// The entire subregister is defined by this insert, forward the new
// value.
- DstRegs.push_back(CurOp->getReg());
+ DstRegs.push_back(OpReg);
continue;
}
- auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_INSERT)
- .addDef(DstReg)
- .addUse(SrcRegs[i]);
-
- for (; CurOp != EndOp; CurOp += 2) {
- unsigned Reg = CurOp->getReg();
- uint64_t Offset = std::next(CurOp)->getImm() - DstStart;
-
- // Make sure we don't have a cross-register insert.
- if (Offset + MRI.getType(Reg).getSizeInBits() > NarrowSize) {
- // FIXME: we should handle this case, though it's unlikely to be
- // common given ABI-related layout restrictions.
- return UnableToLegalize;
- }
-
- MIB.addUse(Reg);
- MIB.addImm(Offset);
+ int64_t OpSegStart = DstStart - OpStart;
+ int64_t OpSegSize =
+ std::min(NarrowSize - OpSegStart, OpSegStart + OpSize);
+ unsigned OpSegReg = OpReg;
+ if (OpSegSize != OpSize) {
+ // A genuine extract is needed.
+ OpSegReg = MRI.createGenericVirtualRegister(LLT::scalar(OpSegSize));
+ MIRBuilder.buildExtract(OpSegReg, std::max(OpSegStart, (int64_t)0),
+ OpReg);
}
+ unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
+ MIRBuilder.buildInstr(TargetOpcode::G_INSERT)
+ .addDef(DstReg)
+ .addUse(SrcRegs[i])
+ .addUse(OpSegReg)
+ .addImm(std::max((int64_t)0, -OpSegStart));
+
DstRegs.push_back(DstReg);
}
OpenPOWER on IntegriCloud