[llvm] ddd7d35 - [RegAlloc] Fix assertion failure caused by inline assembly

Bryan Chan via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 25 16:12:00 PDT 2023


Author: Qi Hu
Date: 2023-07-25T19:21:03-04:00
New Revision: ddd7d35c6c2697eec8d665e70d4e1395003cbec9

URL: https://github.com/llvm/llvm-project/commit/ddd7d35c6c2697eec8d665e70d4e1395003cbec9
DIFF: https://github.com/llvm/llvm-project/commit/ddd7d35c6c2697eec8d665e70d4e1395003cbec9.diff

LOG: [RegAlloc] Fix assertion failure caused by inline assembly

When inline assembly code requests more registers than available, the
MachineInstr::emitError function in the RegAllocFast pass emits an error
but doesn't stop the pass, and then the compiler crashes later with an
assertion failure. This commit, mimicking the RegAllocGreedy pass, assigns
a random physical register, and therefore avoids the crash after producing
the diagnostic. This problem has been observed for both rustc and clang,
while it doesn't occur in gcc.

Added: 
    llvm/test/CodeGen/X86/inline-asm-assertion.ll

Modified: 
    llvm/lib/CodeGen/RegAllocFast.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 864beb8720f439..e2a1b8f07e6118 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -932,9 +932,18 @@ bool RegAllocFast::defineVirtReg(MachineInstr &MI, unsigned OpNum,
       }
     }
   }
-  if (LRI->PhysReg == 0)
+  if (LRI->PhysReg == 0) {
     allocVirtReg(MI, *LRI, 0, LookAtPhysRegUses);
-  else {
+    // If no physical register is available for LRI, we assign one at random
+    // and bail out of this function immediately.
+    if (LRI->Error) {
+      const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg);
+      ArrayRef<MCPhysReg> AllocationOrder = RegClassInfo.getOrder(&RC);
+      if (AllocationOrder.empty())
+        return setPhysReg(MI, MO, MCRegister::NoRegister);
+      return setPhysReg(MI, MO, *AllocationOrder.begin());
+    }
+  } else {
     assert(!isRegUsedInInstr(LRI->PhysReg, LookAtPhysRegUses) &&
            "TODO: preassign mismatch");
     LLVM_DEBUG(dbgs() << "In def of " << printReg(VirtReg, TRI)
@@ -943,7 +952,6 @@ bool RegAllocFast::defineVirtReg(MachineInstr &MI, unsigned OpNum,
   }
 
   MCPhysReg PhysReg = LRI->PhysReg;
-  assert(PhysReg != 0 && "Register not assigned");
   if (LRI->Reloaded || LRI->LiveOut) {
     if (!MI.isImplicitDef()) {
       MachineBasicBlock::iterator SpillBefore =
@@ -1024,6 +1032,8 @@ bool RegAllocFast::useVirtReg(MachineInstr &MI, unsigned OpNum,
     if (LRI->Error) {
       const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg);
       ArrayRef<MCPhysReg> AllocationOrder = RegClassInfo.getOrder(&RC);
+      if (AllocationOrder.empty())
+        return setPhysReg(MI, MO, MCRegister::NoRegister);
       return setPhysReg(MI, MO, *AllocationOrder.begin());
     }
   }

diff  --git a/llvm/test/CodeGen/X86/inline-asm-assertion.ll b/llvm/test/CodeGen/X86/inline-asm-assertion.ll
new file mode 100644
index 00000000000000..d5507a1c441703
--- /dev/null
+++ b/llvm/test/CodeGen/X86/inline-asm-assertion.ll
@@ -0,0 +1,62 @@
+; RUN: not llc -verify-machineinstrs -O0 < %s 2>&1 | FileCheck %s
+; RUN: not --crash llc -verify-machineinstrs -O2 < %s 2>&1 | FileCheck %s --check-prefix=CHECK-O2
+; CHECK: error: inline assembly requires more registers than available
+; CHECK: .size   main, .Lfunc_end0-main
+; CHECK-O2: error: inline assembly requires more registers than available
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local i32 @main() #0 {
+entry:
+  %r0 = alloca i32, align 4
+  %r1 = alloca i32, align 4
+  %r2 = alloca i32, align 4
+  %r3 = alloca i32, align 4
+  %r4 = alloca i32, align 4
+  %r5 = alloca i32, align 4
+  %r6 = alloca i32, align 4
+  %r7 = alloca i32, align 4
+  %r8 = alloca i32, align 4
+  %r9 = alloca i32, align 4
+  %r10 = alloca i32, align 4
+  %r11 = alloca i32, align 4
+  %r12 = alloca i32, align 4
+  %r13 = alloca i32, align 4
+  %r14 = alloca i32, align 4
+  %0 = call { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } asm "movl $$0, $0;movl $$1, $1;movl $$2, $2;movl $$3, $3;movl $$4, $4;movl $$5, $5;movl $$6, $6;movl $$7, $7;movl $$8, $8;movl $$9, $9;movl $$10, $10;movl $$11, $11;movl $$12, $12;movl $$13, $13;movl $$14, $14;", "=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,~{dirflag},~{fpsr},~{flags}"() #1
+  %asmresult = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 0
+  %asmresult1 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 1
+  %asmresult2 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 2
+  %asmresult3 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 3
+  %asmresult4 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 4
+  %asmresult5 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 5
+  %asmresult6 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 6
+  %asmresult7 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 7
+  %asmresult8 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 8
+  %asmresult9 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 9
+  %asmresult10 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 10
+  %asmresult11 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 11
+  %asmresult12 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 12
+  %asmresult13 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 13
+  %asmresult14 = extractvalue { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } %0, 14
+  store i32 %asmresult, ptr %r0, align 4
+  store i32 %asmresult1, ptr %r1, align 4
+  store i32 %asmresult2, ptr %r2, align 4
+  store i32 %asmresult3, ptr %r3, align 4
+  store i32 %asmresult4, ptr %r4, align 4
+  store i32 %asmresult5, ptr %r5, align 4
+  store i32 %asmresult6, ptr %r6, align 4
+  store i32 %asmresult7, ptr %r7, align 4
+  store i32 %asmresult8, ptr %r8, align 4
+  store i32 %asmresult9, ptr %r9, align 4
+  store i32 %asmresult10, ptr %r10, align 4
+  store i32 %asmresult11, ptr %r11, align 4
+  store i32 %asmresult12, ptr %r12, align 4
+  store i32 %asmresult13, ptr %r13, align 4
+  store i32 %asmresult14, ptr %r14, align 4
+  ret i32 0
+}
+
+attributes #0 = { "frame-pointer"="all" }


        


More information about the llvm-commits mailing list