Do not use MRI::getMaxLaneMaskForVReg as a mask covering whole register
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>
Mon, 29 Aug 2016 13:15:35 +0000 (13:15 +0000)
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>
Mon, 29 Aug 2016 13:15:35 +0000 (13:15 +0000)
MRI::getMaxLaneMaskForVReg does not always cover the whole register.
For example, on X86 the upper 16 bits of EAX cannot be accessed via
any subregister. Consequently, there is no lane mask that only covers
that part of EAX. The getMaxLaneMaskForVReg will return the union of
the lane masks for all subregisters, and in case of EAX, that union
will not cover the upper 16 bits.

This fixes https://llvm.org/bugs/show_bug.cgi?id=29132

llvm-svn: 279969

llvm/lib/CodeGen/LiveRangeCalc.cpp
llvm/lib/CodeGen/MachineVerifier.cpp
llvm/test/CodeGen/X86/live-range-nosubreg.ll [new file with mode: 0644]

index b480747..25d22a0 100644 (file)
@@ -66,9 +66,8 @@ void LiveRangeCalc::calculate(LiveInterval &LI, bool TrackSubRegs) {
 
     unsigned SubReg = MO.getSubReg();
     if (LI.hasSubRanges() || (SubReg != 0 && TrackSubRegs)) {
-      LaneBitmask WholeMask = MRI->getMaxLaneMaskForVReg(Reg);
       LaneBitmask SubMask = SubReg != 0 ? TRI.getSubRegIndexLaneMask(SubReg)
-                                        : WholeMask;
+                                        : MRI->getMaxLaneMaskForVReg(Reg);
       // If this is the first time we see a subregister def, initialize
       // subranges by creating a copy of the main range.
       if (!LI.hasSubRanges() && !LI.empty()) {
@@ -177,8 +176,8 @@ void LiveRangeCalc::extendToUses(LiveRange &LR, unsigned Reg, LaneBitmask Mask,
     if (SubReg != 0) {
       LaneBitmask SLM = TRI.getSubRegIndexLaneMask(SubReg);
       if (MO.isDef())
-        SLM = MRI->getMaxLaneMaskForVReg(Reg) & ~SLM;
-      // Ignore uses not covering the current subrange.
+        SLM = ~SLM;
+      // Ignore uses not reading the current (sub)range.
       if ((SLM & Mask) == 0)
         continue;
     }
index f0ab4c3..34d4c57 100644 (file)
@@ -1810,19 +1810,18 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR,
     bool hasRead = false;
     bool hasSubRegDef = false;
     bool hasDeadDef = false;
-    LaneBitmask RLM = MRI->getMaxLaneMaskForVReg(Reg);
     for (ConstMIBundleOperands MOI(*MI); MOI.isValid(); ++MOI) {
       if (!MOI->isReg() || MOI->getReg() != Reg)
         continue;
       unsigned Sub = MOI->getSubReg();
-      LaneBitmask SLM = Sub != 0 ? TRI->getSubRegIndexLaneMask(Sub) : RLM;
+      LaneBitmask SLM = Sub != 0 ? TRI->getSubRegIndexLaneMask(Sub) : ~0U;
       if (MOI->isDef()) {
         if (Sub != 0) {
           hasSubRegDef = true;
           // An operand vreg0:sub0<def> reads vreg0:sub1..n. Invert the lane
           // mask for subregister defs. Read-undef defs will be handled by
           // readsReg below.
-          SLM = ~SLM & RLM;
+          SLM = ~SLM;
         }
         if (MOI->isDead())
           hasDeadDef = true;
diff --git a/llvm/test/CodeGen/X86/live-range-nosubreg.ll b/llvm/test/CodeGen/X86/live-range-nosubreg.ll
new file mode 100644 (file)
index 0000000..f28d592
--- /dev/null
@@ -0,0 +1,48 @@
+; RUN: llc -march=x86-64 < %s | FileCheck %s
+
+; Check for a sane output. This testcase used to crash. See PR29132.
+; CHECK: leal -1
+
+target triple = "x86_64-unknown-linux-gnu"
+
+@a = common local_unnamed_addr global i16 0, align 2
+@c = common global i32 0, align 4
+@d = common local_unnamed_addr global i8 0, align 1
+@b = common global i32 0, align 4
+
+; Function Attrs: norecurse nounwind optsize uwtable
+define i32 @main() local_unnamed_addr #0 {
+entry:
+  %0 = load volatile i32, i32* @c, align 4
+  %tobool = icmp eq i32 %0, 0
+  %1 = load i16, i16* @a, align 2
+  br i1 %tobool, label %lor.rhs, label %lor.end
+
+lor.rhs:                                          ; preds = %entry
+  %inc = add i16 %1, 1
+  store i16 %inc, i16* @a, align 2
+  br label %lor.end
+
+lor.end:                                          ; preds = %entry, %lor.rhs
+  %2 = phi i16 [ %inc, %lor.rhs ], [ %1, %entry ]
+  %dec = add i16 %2, -1
+  store i16 %dec, i16* @a, align 2
+  %3 = load i8, i8* @d, align 1
+  %sub = sub i8 0, %3
+  %tobool4 = icmp eq i16 %dec, 0
+  br i1 %tobool4, label %land.end, label %land.rhs
+
+land.rhs:                                         ; preds = %lor.end
+  %4 = load volatile i32, i32* @b, align 4
+  %tobool5 = icmp ne i32 %4, 0
+  br label %land.end
+
+land.end:                                         ; preds = %lor.end, %land.rhs
+  %5 = phi i1 [ false, %lor.end ], [ %tobool5, %land.rhs ]
+  %land.ext = zext i1 %5 to i8
+  %or = or i8 %land.ext, %sub
+  store i8 %or, i8* @d, align 1
+  ret i32 0
+}
+
+attributes #0 = { norecurse nounwind optsize uwtable "target-cpu"="x86-64" }