[PATCH] D30242: [ExecutionDepsFix] Don't make copies of LiveReg objects when collecting operands for soft instructions

Craig Topper via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 21 21:29:59 PST 2017


craig.topper created this revision.

While collecting operands we make copies of the LiveReg objects which are stored in the LiveRegs array. If the instruction uses the same register multiple times we end up with multiple copies. Later we iterate through the collected list of LiveReg objects and merge DomainValues. In the process of doing this the merge function can change the contents of the original LiveReg object in the LiveRegs array, but not the copies that have been made. So when we get to the second usage of the register we end up seeing a stale copy of the LiveReg object.

To fix this I've stopped copying and now just store a pointer to the original LiveReg object. Another option might be to avoid adding the same register to the Regs array twice, but this approach seemed simpler.

The included test case from PR 30284 exposes this bug due to an AVX-512 masked OR instruction using the same register for the passthru operand and one of the inputs to the OR operation.


https://reviews.llvm.org/D30242

Files:
  lib/CodeGen/ExecutionDepsFix.cpp
  test/CodeGen/X86/pr30284.ll


Index: test/CodeGen/X86/pr30284.ll
===================================================================
--- /dev/null
+++ test/CodeGen/X86/pr30284.ll
@@ -0,0 +1,21 @@
+; ModuleID = 'bugpoint-reduced-simplified.bc'
+source_filename = "bugpoint-output-21f4d9f.bc"
+target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
+target triple = "i386-unknown-linux-gnu"
+
+; Function Attrs: nounwind
+define void @f_f___un_3C_unf_3E_un_3C_unf_3E_() #0 {
+allocas:
+  %a_load22 = load <16 x i64>, <16 x i64>* null, align 1
+  %bitop = or <16 x i64> %a_load22, <i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736, i64 68719476736>
+  %v.i = load <16 x i64>, <16 x i64>* null
+  %v1.i41 = select <16 x i1> undef, <16 x i64> %bitop, <16 x i64> %v.i
+  store <16 x i64> %v1.i41, <16 x i64>* null
+  unreachable
+}
+
+attributes #0 = { nounwind }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 4.0.0 (trunk 278097)"}
Index: lib/CodeGen/ExecutionDepsFix.cpp
===================================================================
--- lib/CodeGen/ExecutionDepsFix.cpp
+++ lib/CodeGen/ExecutionDepsFix.cpp
@@ -721,7 +721,7 @@
 
   // Kill off any remaining uses that don't match available, and build a list of
   // incoming DomainValues that we want to merge.
-  SmallVector<LiveReg, 4> Regs;
+  SmallVector<const LiveReg*, 4> Regs;
   for (SmallVectorImpl<int>::iterator i=used.begin(), e=used.end(); i!=e; ++i) {
     int rx = *i;
     assert(LiveRegs && "no space allocated for live registers");
@@ -733,30 +733,30 @@
     }
     // Sorted insertion.
     bool Inserted = false;
-    for (SmallVectorImpl<LiveReg>::iterator i = Regs.begin(), e = Regs.end();
-           i != e && !Inserted; ++i) {
-      if (LR.Def < i->Def) {
+    for (SmallVectorImpl<const LiveReg*>::iterator i = Regs.begin(),
+           e = Regs.end(); i != e && !Inserted; ++i) {
+      if (LR.Def < (*i)->Def) {
         Inserted = true;
-        Regs.insert(i, LR);
+        Regs.insert(i, &LR);
       }
     }
     if (!Inserted)
-      Regs.push_back(LR);
+      Regs.push_back(&LR);
   }
 
   // doms are now sorted in order of appearance. Try to merge them all, giving
   // priority to the latest ones.
   DomainValue *dv = nullptr;
   while (!Regs.empty()) {
     if (!dv) {
-      dv = Regs.pop_back_val().Value;
+      dv = Regs.pop_back_val()->Value;
       // Force the first dv to match the current instruction.
       dv->AvailableDomains = dv->getCommonDomains(available);
       assert(dv->AvailableDomains && "Domain should have been filtered");
       continue;
     }
 
-    DomainValue *Latest = Regs.pop_back_val().Value;
+    DomainValue *Latest = Regs.pop_back_val()->Value;
     // Skip already merged values.
     if (Latest == dv || Latest->Next)
       continue;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D30242.89319.patch
Type: text/x-patch
Size: 2962 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170222/edbc8ab7/attachment.bin>


More information about the llvm-commits mailing list