diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2015-05-28 20:02:45 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2015-05-28 20:02:45 +0000 |
commit | 450fbee6b2dc44e4c82b064743f84af0ee0b8573 (patch) | |
tree | c1229bd506b88568fc2b80d55e080c4cb5c0d194 /llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | |
parent | e2e57faa7d4326f482aea8050c0cf0d6ce72f4a3 (diff) | |
download | bcm5719-llvm-450fbee6b2dc44e4c82b064743f84af0ee0b8573.tar.gz bcm5719-llvm-450fbee6b2dc44e4c82b064743f84af0ee0b8573.zip |
Thumb2: Modify codegen for memcpy intrinsic to prefer LDM/STM.
We were previously codegen'ing these as regular load/store operations and
hoping that the register allocator would allocate registers in ascending order
so that we could apply an LDM/STM combine after register allocation. According
to the commit that first introduced this code (r37179), we planned to teach
the register allocator to allocate the registers in ascending order. This
never got implemented, and up to now we've been stuck with very poor codegen.
A much simpler approach for achiveing better codegen is to create LDM/STM
instructions with identical sets of virtual registers, let the register
allocator pick arbitrary registers and order register lists when printing an
MCInst. This approach also avoids the need to repeatedly calculate offsets
which ultimately ought to be eliminated pre-RA in order to decrease register
pressure.
This is implemented by lowering the memcpy intrinsic to a series of SD-only
MCOPY pseudo-instructions which performs a memory copy using a given number
of registers. During SD->MI lowering, we lower MCOPY to LDM/STM. This is a
little unusual, but it avoids the need to encode register lists in the SD,
and we can take advantage of SD use lists to decide whether to use the _UPD
variant of the instructions.
Fixes PR9199.
Differential Revision: http://reviews.llvm.org/D9508
llvm-svn: 238473
Diffstat (limited to 'llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 2d36c302001..b7642b1ba98 100644 --- a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -744,10 +744,21 @@ void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O) { O << "{"; - for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { - if (i != OpNum) + + // The backend may have given us a register list in non-ascending order. Sort + // it now. + std::vector<MCOperand> RegOps(MI->size() - OpNum); + std::copy(MI->begin() + OpNum, MI->end(), RegOps.begin()); + std::sort(RegOps.begin(), RegOps.end(), + [this](const MCOperand &O1, const MCOperand &O2) -> bool { + return MRI.getEncodingValue(O1.getReg()) < + MRI.getEncodingValue(O2.getReg()); + }); + + for (unsigned i = 0, e = RegOps.size(); i != e; ++i) { + if (i != 0) O << ", "; - printRegName(O, MI->getOperand(i).getReg()); + printRegName(O, RegOps[i].getReg()); } O << "}"; } |