summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Paulsson <paulsson@linux.vnet.ibm.com>2018-11-08 15:29:48 +0000
committerJonas Paulsson <paulsson@linux.vnet.ibm.com>2018-11-08 15:29:48 +0000
commit1993894c0300c2f900e53d38196b948f36d566ff (patch)
tree460d06c80f954337fd91e2a54e2394bc2e358b35
parent4c4556186e1b0e0380c0af934982e4f21eb8040c (diff)
downloadbcm5719-llvm-1993894c0300c2f900e53d38196b948f36d566ff.tar.gz
bcm5719-llvm-1993894c0300c2f900e53d38196b948f36d566ff.zip
[SystemZ] Bugfix in shouldCoalesce()
It was discovered in randomized testing that the SystemZ implementation of shouldCoalesce() could be caused to crash when subreg liveness was enabled. This was because an undef use of the virtual register was copied outside current MBB at the point of shouldCoalesce() being called. For more details, see https://bugs.llvm.org/show_bug.cgi?id=39276. This patch changes the check for MBB locality from livein/liveout checks to do checks for all instructions of both intervals being inside MBB. This avoids the cases with dead defs / undef uses outside MBB, which are not affecting liveness in/out of MBB. The original test case included as a reduced .mir test case. Review: Ulrich Weigand https://reviews.llvm.org/D54197 llvm-svn: 346406
-rw-r--r--llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp25
-rw-r--r--llvm/test/CodeGen/SystemZ/regalloc-GR128-02.mir68
2 files changed, 83 insertions, 10 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
index 76ed6f80ba5..23338dfec35 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
@@ -270,25 +270,30 @@ bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI,
// Check that the two virtual registers are local to MBB.
MachineBasicBlock *MBB = MI->getParent();
- if (LIS.isLiveInToMBB(IntGR128, MBB) || LIS.isLiveOutOfMBB(IntGR128, MBB) ||
- LIS.isLiveInToMBB(IntGRNar, MBB) || LIS.isLiveOutOfMBB(IntGRNar, MBB))
+ MachineInstr *FirstMI_GR128 =
+ LIS.getInstructionFromIndex(IntGR128.beginIndex());
+ MachineInstr *FirstMI_GRNar =
+ LIS.getInstructionFromIndex(IntGRNar.beginIndex());
+ MachineInstr *LastMI_GR128 = LIS.getInstructionFromIndex(IntGR128.endIndex());
+ MachineInstr *LastMI_GRNar = LIS.getInstructionFromIndex(IntGRNar.endIndex());
+ if ((!FirstMI_GR128 || FirstMI_GR128->getParent() != MBB) ||
+ (!FirstMI_GRNar || FirstMI_GRNar->getParent() != MBB) ||
+ (!LastMI_GR128 || LastMI_GR128->getParent() != MBB) ||
+ (!LastMI_GRNar || LastMI_GRNar->getParent() != MBB))
return false;
- // Find the first and last MIs of the registers.
- MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
+ MachineBasicBlock::iterator MII = nullptr, MEE = nullptr;
if (WideOpNo == 1) {
- FirstMI = LIS.getInstructionFromIndex(IntGR128.beginIndex());
- LastMI = LIS.getInstructionFromIndex(IntGRNar.endIndex());
+ MII = FirstMI_GR128;
+ MEE = LastMI_GRNar;
} else {
- FirstMI = LIS.getInstructionFromIndex(IntGRNar.beginIndex());
- LastMI = LIS.getInstructionFromIndex(IntGR128.endIndex());
+ MII = FirstMI_GRNar;
+ MEE = LastMI_GR128;
}
- assert (FirstMI && LastMI && "No instruction from index?");
// Check if coalescing seems safe by finding the set of clobbered physreg
// pairs in the region.
BitVector PhysClobbered(getNumRegs());
- MachineBasicBlock::iterator MII = FirstMI, MEE = LastMI;
MEE++;
for (; MII != MEE; ++MII) {
for (const MachineOperand &MO : MII->operands())
diff --git a/llvm/test/CodeGen/SystemZ/regalloc-GR128-02.mir b/llvm/test/CodeGen/SystemZ/regalloc-GR128-02.mir
new file mode 100644
index 00000000000..65758bea4fd
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/regalloc-GR128-02.mir
@@ -0,0 +1,68 @@
+# RUN: llc %s -mtriple=s390x-linux-gnu -mcpu=z13 \
+# RUN: -start-before=simple-register-coalescing -o - 2>&1 > /dev/null
+
+# Test that the SystemZ shouldCoalesce() implementation does not crash in
+# case of an undef use in another MBB. This was discovered in testing with
+# -systemz-subreg-liveness.
+
+--- |
+ @g_74 = external dso_local unnamed_addr global i32, align 4
+ @g_193 = external dso_local unnamed_addr global i32, align 4
+
+ define dso_local void @main() local_unnamed_addr {
+ %1 = load i32, i32* @g_193
+ %2 = or i32 %1, -1395153718
+ %3 = sdiv i32 -1395153718, %2
+ br i1 undef, label %5, label %4
+
+ ; <label>:4: ; preds = %0
+ store i32 %3, i32* @g_74
+ store i32 -9, i32* @g_74
+ ret void
+
+ ; <label>:5: ; preds = %0
+ unreachable
+ }
+
+...
+---
+name: main
+alignment: 4
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: grx32bit }
+ - { id: 1, class: addr64bit }
+ - { id: 2, class: gr32bit }
+ - { id: 3, class: gr32bit }
+ - { id: 4, class: gr64bit }
+ - { id: 5, class: gr128bit }
+ - { id: 6, class: gr128bit }
+ - { id: 7, class: grx32bit }
+ - { id: 8, class: gr32bit }
+ - { id: 9, class: gr128bit }
+body: |
+ bb.0 (%ir-block.0):
+ successors: %bb.2(0x00000001), %bb.1(0x7fffffff)
+
+ %1:addr64bit = LARL @g_193
+ %2:gr32bit = IIFMux 2899813578
+ %3:gr32bit = COPY killed %2
+ %3:gr32bit = O %3, killed %1, 0, $noreg, implicit-def dead $cc :: (dereferenceable load 4 from @g_193)
+ %4:gr64bit = LGFI -1395153718
+ undef %5.subreg_l64:gr128bit = COPY killed %4
+ %6:gr128bit = COPY killed %5
+ dead %6:gr128bit = DSGFR %6, killed %3
+ %7:grx32bit = LHIMux 0
+ CHIMux killed %7, 0, implicit-def $cc
+ BRC 14, 6, %bb.2, implicit killed $cc
+ J %bb.1
+
+ bb.1 (%ir-block.4):
+ %8:gr32bit = LHIMux -9
+ STRL killed %8, @g_74 :: (store 4 into @g_74)
+ Return
+
+ bb.2 (%ir-block.5):
+ dead %0:grx32bit = COPY undef %6.subreg_l32
+
+...
OpenPOWER on IntegriCloud