summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcello Maggioni <hayarms@gmail.com>2016-02-03 00:22:32 +0000
committerMarcello Maggioni <hayarms@gmail.com>2016-02-03 00:22:32 +0000
commitbfe87568aa4d4518e2665efd57dc27664a5dd364 (patch)
treebcee9ff5f0cded88305c331c3f8968ef51defe1b
parent512c61df1c28a5b1bfaa58d8cc8d3a215f5cfc8c (diff)
downloadbcm5719-llvm-bfe87568aa4d4518e2665efd57dc27664a5dd364.tar.gz
bcm5719-llvm-bfe87568aa4d4518e2665efd57dc27664a5dd364.zip
RegCoalescer: Making sure re-materialization defines all subranges
The register coalescer can rematerialize constants that define more of a register than the copy it is going to replace was going to do. This is valid in the case the register was undef before the copy happened. This patch makes sure that all the subranges defined by the new rematerialization instructions have at least a dead def. Review: http://reviews.llvm.org/D16693 llvm-svn: 259614
-rw-r--r--llvm/lib/CodeGen/RegisterCoalescer.cpp30
1 files changed, 30 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp
index 95c772357c3..e8793c368b2 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -1001,6 +1001,36 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
updateRegDefsUses(DstReg, DstReg, DstIdx);
NewMI->getOperand(0).setSubReg(NewIdx);
+ // Add dead subregister definitions if we are defining the whole register
+ // but only part of it is live.
+ // This could happen if the rematerialization instruction is rematerializing
+ // more than actually is used in the register.
+ // An example would be:
+ // vreg1 = LOAD CONSTANTS 5, 8 ; Loading both 5 and 8 in different subregs
+ // ; Copying only part of the register here, but the rest is undef.
+ // vreg2:sub_16bit<def, read-undef> = COPY vreg1:sub_16bit
+ // ==>
+ // ; Materialize all the constants but only using one
+ // vreg2 = LOAD_CONSTANTS 5, 8
+ //
+ // at this point for the part that wasn't defined before we could have
+ // subranges missing the definition.
+ LiveInterval &DstInt = LIS->getInterval(DstReg);
+ if (NewIdx == 0 && DstInt.hasSubRanges()) {
+ SlotIndex CurrIdx = LIS->getInstructionIndex(NewMI);
+ SlotIndex DefIndex = CurrIdx.getRegSlot(NewMI->getOperand(0).isEarlyClobber());
+ LaneBitmask MaxMask = MRI->getMaxLaneMaskForVReg(DstReg);
+ VNInfo::Allocator& Alloc = LIS->getVNInfoAllocator();
+ for (LiveInterval::SubRange &SR : DstInt.subranges()) {
+ if (!SR.liveAt(DefIndex))
+ SR.createDeadDef(DefIndex, Alloc);
+ MaxMask &= ~SR.LaneMask;
+ }
+ if (MaxMask != 0) {
+ LiveInterval::SubRange *SR = DstInt.createSubRange(Alloc, MaxMask);
+ SR->createDeadDef(DefIndex, Alloc);
+ }
+ }
} else if (NewMI->getOperand(0).getReg() != CopyDstReg) {
// The New instruction may be defining a sub-register of what's actually
// been asked for. If so it must implicitly define the whole thing.
OpenPOWER on IntegriCloud