[llvm] [SelectionDAG] Fix dangling SUnit node after unfold during scheduling (PR #202295)

Paweł Bylica via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 14 03:27:28 PDT 2026


https://github.com/chfast updated https://github.com/llvm/llvm-project/pull/202295

>From 3fa62cd19ab11585e67cada4b56b40aadef75614 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Bylica?= <pawel at hepcolgum.band>
Date: Mon, 8 Jun 2026 10:39:43 +0200
Subject: [PATCH 1/2] [SelectionDAG] Fix dangling SUnit node after unfold
 during scheduling

When a scheduler unfolds a load (TryUnfoldSU), it replaces all uses of the
folded node. A replacement can recursively CSE-merge a user into an existing
equivalent node and delete it; if that deleted node was owned by an SUnit, the
SUnit was left with a dangling SDNode pointer, later causing a use-after-free
and "Node emitted out of order - early" in InstrEmitter.

Register a DAGNodeDeletedListener around the replacements that redirects the
affected SUnit to the surviving node, shared via a RedirectMergedNode helper
on the common base. Apply the same fix to the fast scheduler.

Fixes #63309.
Fixes #63312.
Fixes #120631.
---
 .../CodeGen/SelectionDAG/ScheduleDAGFast.cpp  |  5 ++
 .../SelectionDAG/ScheduleDAGRRList.cpp        |  7 +-
 .../SelectionDAG/ScheduleDAGSDNodes.cpp       | 10 +++
 .../CodeGen/SelectionDAG/ScheduleDAGSDNodes.h |  5 ++
 llvm/test/CodeGen/X86/pr63309.ll              | 85 +++++++++++++++++++
 5 files changed, 111 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/X86/pr63309.ll

diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
index 0f67cee757407..817814b5b1b86 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp
@@ -232,6 +232,11 @@ SUnit *ScheduleDAGFast::CopyAndMoveSuccessors(SUnit *SU) {
     SDNode *LoadNode = NewNodes[0];
     unsigned NumVals = N->getNumValues();
     unsigned OldNumVals = SU->getNode()->getNumValues();
+    // Fix up SUnits whose nodes get deleted by the replacements below.
+    SelectionDAG::DAGNodeDeletedListener Listener(
+        *DAG, [&](SDNode *DeadNode, SDNode *NewNode) {
+          RedirectMergedNode(DeadNode, NewNode);
+        });
     for (unsigned i = 0; i != NumVals; ++i)
       DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i));
     DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals-1),
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
index fffe5b8a83501..b6b74f623e98d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
@@ -1045,7 +1045,12 @@ SUnit *ScheduleDAGRRList::TryUnfoldSU(SUnit *SU) {
 
   LLVM_DEBUG(dbgs() << "Unfolding SU #" << SU->NodeNum << "\n");
 
-  // Now that we are committed to unfolding replace DAG Uses.
+  // Now that we are committed to unfolding replace DAG Uses, fixing up SUnits
+  // whose nodes get deleted by the replacements.
+  SelectionDAG::DAGNodeDeletedListener Listener(
+      *DAG, [&](SDNode *DeadNode, SDNode *NewNode) {
+        RedirectMergedNode(DeadNode, NewNode);
+      });
   for (unsigned i = 0; i != NumVals; ++i)
     DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i));
   DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals - 1),
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
index 58101f415ce51..39429e30edf1b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
@@ -105,6 +105,16 @@ SUnit *ScheduleDAGSDNodes::Clone(SUnit *Old) {
   return SU;
 }
 
+void ScheduleDAGSDNodes::RedirectMergedNode(SDNode *DeadNode, SDNode *NewNode) {
+  int Id = DeadNode->getNodeId();
+  if (Id == -1 || unsigned(Id) >= SUnits.size() ||
+      SUnits[Id].getNode() != DeadNode)
+    return;
+  SUnits[Id].setNode(NewNode);
+  if (NewNode->getNodeId() == -1)
+    NewNode->setNodeId(Id);
+}
+
 /// CheckForPhysRegDependency - Check if the dependency between def and use of
 /// a specified operand is a physical register dependency. If so, returns the
 /// register and the cost of copying the register.
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
index ff5615b7658f3..e6551f6ab186d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h
@@ -90,6 +90,11 @@ class InstrItineraryData;
     ///
     SUnit *Clone(SUnit *Old);
 
+    /// If an SUnit owns \p DeadNode, which is being deleted and replaced by
+    /// \p NewNode (e.g. when a node is CSE'd into an existing one), point that
+    /// SUnit at \p NewNode so it is not left with a dangling node pointer.
+    void RedirectMergedNode(SDNode *DeadNode, SDNode *NewNode);
+
     /// BuildSchedGraph - Build the SUnit graph from the selection dag that we
     /// are input.  This SUnit graph is similar to the SelectionDAG, but
     /// excludes nodes that aren't interesting to scheduling, and represents
diff --git a/llvm/test/CodeGen/X86/pr63309.ll b/llvm/test/CodeGen/X86/pr63309.ll
new file mode 100644
index 0000000000000..4a89cb090fdc5
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr63309.ll
@@ -0,0 +1,85 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=RRLIST
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -pre-RA-sched=fast | FileCheck %s --check-prefix=FAST
+
+; Make sure this does not crash with "Node emitted out of order - early".
+; Unfolding a load during scheduling replaces all uses of the folded node,
+; which can CSE-merge and delete a node still referenced by another SUnit.
+; Both the list (ScheduleDAGRRList) and fast (ScheduleDAGFast) schedulers
+; perform this unfold, so exercise both.
+
+ at G.1 = external global i1
+ at G.5 = external global ptr
+
+define void @pr63309(ptr %G.5, i64 %L3) {
+; RRLIST-LABEL: pr63309:
+; RRLIST:       # %bb.0: # %BB
+; RRLIST-NEXT:    movzbl -{{[0-9]+}}(%rsp), %eax
+; RRLIST-NEXT:    andl $1, %eax
+; RRLIST-NEXT:    negq %rax
+; RRLIST-NEXT:    movb $0, -{{[0-9]+}}(%rsp)
+; RRLIST-NEXT:    movzbl (%rax), %eax
+; RRLIST-NEXT:    movq G.1 at GOTPCREL(%rip), %rcx
+; RRLIST-NEXT:    movq 0, %rdx
+; RRLIST-NEXT:    movb $0, (%rcx)
+; RRLIST-NEXT:    movq $0, -{{[0-9]+}}(%rsp)
+; RRLIST-NEXT:    movq G.5 at GOTPCREL(%rip), %rcx
+; RRLIST-NEXT:    movq $0, (%rcx)
+; RRLIST-NEXT:    testq %rsi, %rsi
+; RRLIST-NEXT:    setg 0
+; RRLIST-NEXT:    testq %rdx, %rdx
+; RRLIST-NEXT:    movq $0, (%rdi)
+; RRLIST-NEXT:    movb %al, 0
+; RRLIST-NEXT:    setne (%rdi)
+; RRLIST-NEXT:    testb %al, %al
+; RRLIST-NEXT:    sets 0
+; RRLIST-NEXT:    retq
+;
+; FAST-LABEL: pr63309:
+; FAST:       # %bb.0: # %BB
+; FAST-NEXT:    movq G.1 at GOTPCREL(%rip), %rax
+; FAST-NEXT:    movzbl -{{[0-9]+}}(%rsp), %ecx
+; FAST-NEXT:    andl $1, %ecx
+; FAST-NEXT:    negq %rcx
+; FAST-NEXT:    movb $0, -{{[0-9]+}}(%rsp)
+; FAST-NEXT:    movzbl (%rcx), %ecx
+; FAST-NEXT:    movq 0, %rdx
+; FAST-NEXT:    movb $0, (%rax)
+; FAST-NEXT:    movq G.5 at GOTPCREL(%rip), %rax
+; FAST-NEXT:    movq $0, (%rax)
+; FAST-NEXT:    movq $0, -{{[0-9]+}}(%rsp)
+; FAST-NEXT:    testq %rsi, %rsi
+; FAST-NEXT:    setg 0
+; FAST-NEXT:    testq %rdx, %rdx
+; FAST-NEXT:    movq $0, (%rdi)
+; FAST-NEXT:    movb %cl, 0
+; FAST-NEXT:    setne (%rdi)
+; FAST-NEXT:    testb %cl, %cl
+; FAST-NEXT:    sets 0
+; FAST-NEXT:    retq
+BB:
+  %A31 = alloca i1, i32 0, align 1
+  %A = alloca i1, i32 0, align 1
+  %L2 = load i1, ptr %A, align 1
+  %L = load i1, ptr %A, align 1
+  store i1 poison, ptr null, align 1
+  store i1 false, ptr %A31, align 1
+  %LGV3 = load i64, ptr null, align 4
+  %G3 = getelementptr i1, ptr null, i1 %L2
+  %L4 = load i1, ptr %G3, align 1
+  %G1 = getelementptr i1, ptr null, i1 %L
+  %L9 = load i8, ptr %G1, align 1
+  %C10 = icmp sgt i8 0, %L9
+  %L31 = load i64, ptr %A31, align 4
+  store i1 false, ptr @G.1, align 1
+  %C4 = icmp ne i64 0, %LGV3
+  store ptr null, ptr %A31, align 8
+  store ptr null, ptr @G.5, align 8
+  %C5 = icmp sgt i64 %L3, 0
+  store i1 %C5, ptr null, align 1
+  store ptr null, ptr %G.5, align 8
+  store i1 %L4, ptr null, align 1
+  store i1 %C4, ptr %G.5, align 1
+  store i1 %C10, ptr null, align 1
+  ret void
+}

>From c9f596bccbbbe5c420c8ca7c6747f485b9d2471e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Bylica?= <pawel at hepcolgum.band>
Date: Mon, 14 Sep 2026 11:46:37 +0200
Subject: [PATCH 2/2] Replace the UB-dependent test with a reduction from real
 code

arsenm asked the test not to depend on UB. pr63309.ll could not be cleaned in
place: it is a fuzzer reduction whose reproduction depends on the UB itself.
Changing only `store i1 poison` to `store i1 false` stops it reproducing,
because the poison kept that store distinct from the neighbouring
`store i1 false` instead of CSE-ing with it early; substituting `true`, an
existing value, a parameter or `freeze poison` all lose it too. Keeping the
poison but replacing the null addresses loses it as well, so both UB sources
are load-bearing.

Use the reproducer from #120631 instead. It comes from a real workload
(google/xls#1776) rather than a fuzzer, so its only UB is the null pointers
llvm-reduce introduced, and replacing those with a second pointer argument
leaves it reproducing. No poison, no null, no zero-sized alloca.

Verified both ways with an assertions build: without the scheduler fix it
aborts on the list and fast schedulers alike, and with the fix both pass.

Assisted-by: Claude Code
---
 llvm/test/CodeGen/X86/pr120631.ll | 110 ++++++++++++++++++++++++++++++
 llvm/test/CodeGen/X86/pr63309.ll  |  85 -----------------------
 2 files changed, 110 insertions(+), 85 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/pr120631.ll
 delete mode 100644 llvm/test/CodeGen/X86/pr63309.ll

diff --git a/llvm/test/CodeGen/X86/pr120631.ll b/llvm/test/CodeGen/X86/pr120631.ll
new file mode 100644
index 0000000000000..eeedac40770f4
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr120631.ll
@@ -0,0 +1,110 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=RRLIST
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -pre-RA-sched=fast | FileCheck %s --check-prefix=FAST
+
+; Unfolding a load during scheduling replaces all uses of the folded node,
+; which can CSE-merge and delete a node still owned by another SUnit, leaving
+; it dangling. Both the list and fast schedulers unfold, so exercise both.
+; Reduced from a real workload (https://github.com/google/xls/issues/1776).
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+
+define i1 @pr120631(ptr %tmp_buffer, ptr %p2) {
+; RRLIST-LABEL: pr120631:
+; RRLIST:       # %bb.0: # %entry
+; RRLIST-NEXT:    movq (%rsi), %rax
+; RRLIST-NEXT:    movq %rax, 16(%rdi)
+; RRLIST-NEXT:    movzbl 8(%rsi), %eax
+; RRLIST-NEXT:    movb %al, 24(%rdi)
+; RRLIST-NEXT:    movzbl (%rdi), %eax
+; RRLIST-NEXT:    movb %al, 25(%rdi)
+; RRLIST-NEXT:    movb $0, 16(%rdi)
+; RRLIST-NEXT:    movq (%rsi), %rcx
+; RRLIST-NEXT:    movq 8(%rsi), %rdx
+; RRLIST-NEXT:    movq %rdx, 24(%rdi)
+; RRLIST-NEXT:    movq %rcx, 16(%rdi)
+; RRLIST-NEXT:    movzbl (%rsi), %ecx
+; RRLIST-NEXT:    movzbl (%rdi), %edx
+; RRLIST-NEXT:    movzbl (%rdi), %r8d
+; RRLIST-NEXT:    movb %r8b, 1(%rdi)
+; RRLIST-NEXT:    movzbl (%rsi), %r8d
+; RRLIST-NEXT:    andb $127, %r8b
+; RRLIST-NEXT:    xorl %r9d, %r9d
+; RRLIST-NEXT:    testb %cl, %cl
+; RRLIST-NEXT:    movzbl %r8b, %r8d
+; RRLIST-NEXT:    cmovel %r9d, %r8d
+; RRLIST-NEXT:    addb %cl, %cl
+; RRLIST-NEXT:    movzbl %cl, %ecx
+; RRLIST-NEXT:    orl %edx, %ecx
+; RRLIST-NEXT:    movb %al, (%rsi)
+; RRLIST-NEXT:    movb %r8b, (%rdi)
+; RRLIST-NEXT:    movw %cx, (%rsi)
+; RRLIST-NEXT:    xorl %eax, %eax
+; RRLIST-NEXT:    retq
+;
+; FAST-LABEL: pr120631:
+; FAST:       # %bb.0: # %entry
+; FAST-NEXT:    xorl %eax, %eax
+; FAST-NEXT:    movq (%rsi), %rcx
+; FAST-NEXT:    movq %rcx, 16(%rdi)
+; FAST-NEXT:    movzbl 8(%rsi), %ecx
+; FAST-NEXT:    movb $0, 16(%rdi)
+; FAST-NEXT:    movzbl (%rdi), %edx
+; FAST-NEXT:    movb %dl, 25(%rdi)
+; FAST-NEXT:    movb %cl, 24(%rdi)
+; FAST-NEXT:    movq (%rsi), %rcx
+; FAST-NEXT:    movq 8(%rsi), %r8
+; FAST-NEXT:    movq %rcx, 16(%rdi)
+; FAST-NEXT:    movq %r8, 24(%rdi)
+; FAST-NEXT:    movzbl (%rsi), %ecx
+; FAST-NEXT:    movzbl (%rdi), %r8d
+; FAST-NEXT:    movzbl (%rdi), %r9d
+; FAST-NEXT:    movb %r9b, 1(%rdi)
+; FAST-NEXT:    movzbl (%rsi), %r9d
+; FAST-NEXT:    andb $127, %r9b
+; FAST-NEXT:    leal (%rcx,%rcx), %r10d
+; FAST-NEXT:    movzbl %r10b, %r10d
+; FAST-NEXT:    orl %r8d, %r10d
+; FAST-NEXT:    testb %cl, %cl
+; FAST-NEXT:    movzbl %r9b, %ecx
+; FAST-NEXT:    cmovel %eax, %ecx
+; FAST-NEXT:    movb %dl, (%rsi)
+; FAST-NEXT:    movb %cl, (%rdi)
+; FAST-NEXT:    movw %r10w, (%rsi)
+; FAST-NEXT:    xorl %eax, %eax
+; FAST-NEXT:    retq
+entry:
+  %0 = ptrtoint ptr %tmp_buffer to i64
+  %1 = add i64 %0, 16
+  %2 = inttoptr i64 %1 to ptr
+  tail call void @llvm.memcpy.p0.p0.i64(ptr %2, ptr %p2, i64 9, i1 false)
+  %3 = getelementptr i8, ptr %2, i64 9
+  %4 = load i8, ptr %tmp_buffer, align 1
+  store i8 %4, ptr %3, align 1
+  %5 = load i8, ptr %p2, align 1
+  store i8 0, ptr %2, align 1
+  tail call void @llvm.memcpy.p0.p0.i64(ptr %2, ptr %p2, i64 16, i1 false)
+  %.val25 = load i1, ptr %p2, align 1
+  %.val26 = load i8, ptr %p2, align 1
+  %.val27 = load i1, ptr %tmp_buffer, align 1
+  %6 = shl i8 %.val26, 1
+  %7 = zext i1 %.val27 to i8
+  %8 = or i8 %6, %7
+  %.sroa.066.0..sroa.066.0..sroa.066.0..sroa.066.0. = load i8, ptr %tmp_buffer, align 1
+  %9 = add i64 %0, 1
+  %10 = inttoptr i64 %9 to ptr
+  tail call void @llvm.memcpy.p0.p0.i64(ptr %10, ptr %tmp_buffer, i64 1, i1 false)
+  %.val30 = load i8, ptr %p2, align 1
+  %11 = and i8 %.val30, 127
+  %12 = zext i8 %8 to i16
+  store i8 %.sroa.066.0..sroa.066.0..sroa.066.0..sroa.066.0., ptr %p2, align 1
+  %13 = select i1 %.val25, i8 %11, i8 0
+  store i8 %13, ptr %tmp_buffer, align 1
+  store i16 %12, ptr %p2, align 2
+  ret i1 false
+}
+
+; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
+declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #0
+
+attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
diff --git a/llvm/test/CodeGen/X86/pr63309.ll b/llvm/test/CodeGen/X86/pr63309.ll
deleted file mode 100644
index 4a89cb090fdc5..0000000000000
--- a/llvm/test/CodeGen/X86/pr63309.ll
+++ /dev/null
@@ -1,85 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=RRLIST
-; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -pre-RA-sched=fast | FileCheck %s --check-prefix=FAST
-
-; Make sure this does not crash with "Node emitted out of order - early".
-; Unfolding a load during scheduling replaces all uses of the folded node,
-; which can CSE-merge and delete a node still referenced by another SUnit.
-; Both the list (ScheduleDAGRRList) and fast (ScheduleDAGFast) schedulers
-; perform this unfold, so exercise both.
-
- at G.1 = external global i1
- at G.5 = external global ptr
-
-define void @pr63309(ptr %G.5, i64 %L3) {
-; RRLIST-LABEL: pr63309:
-; RRLIST:       # %bb.0: # %BB
-; RRLIST-NEXT:    movzbl -{{[0-9]+}}(%rsp), %eax
-; RRLIST-NEXT:    andl $1, %eax
-; RRLIST-NEXT:    negq %rax
-; RRLIST-NEXT:    movb $0, -{{[0-9]+}}(%rsp)
-; RRLIST-NEXT:    movzbl (%rax), %eax
-; RRLIST-NEXT:    movq G.1 at GOTPCREL(%rip), %rcx
-; RRLIST-NEXT:    movq 0, %rdx
-; RRLIST-NEXT:    movb $0, (%rcx)
-; RRLIST-NEXT:    movq $0, -{{[0-9]+}}(%rsp)
-; RRLIST-NEXT:    movq G.5 at GOTPCREL(%rip), %rcx
-; RRLIST-NEXT:    movq $0, (%rcx)
-; RRLIST-NEXT:    testq %rsi, %rsi
-; RRLIST-NEXT:    setg 0
-; RRLIST-NEXT:    testq %rdx, %rdx
-; RRLIST-NEXT:    movq $0, (%rdi)
-; RRLIST-NEXT:    movb %al, 0
-; RRLIST-NEXT:    setne (%rdi)
-; RRLIST-NEXT:    testb %al, %al
-; RRLIST-NEXT:    sets 0
-; RRLIST-NEXT:    retq
-;
-; FAST-LABEL: pr63309:
-; FAST:       # %bb.0: # %BB
-; FAST-NEXT:    movq G.1 at GOTPCREL(%rip), %rax
-; FAST-NEXT:    movzbl -{{[0-9]+}}(%rsp), %ecx
-; FAST-NEXT:    andl $1, %ecx
-; FAST-NEXT:    negq %rcx
-; FAST-NEXT:    movb $0, -{{[0-9]+}}(%rsp)
-; FAST-NEXT:    movzbl (%rcx), %ecx
-; FAST-NEXT:    movq 0, %rdx
-; FAST-NEXT:    movb $0, (%rax)
-; FAST-NEXT:    movq G.5 at GOTPCREL(%rip), %rax
-; FAST-NEXT:    movq $0, (%rax)
-; FAST-NEXT:    movq $0, -{{[0-9]+}}(%rsp)
-; FAST-NEXT:    testq %rsi, %rsi
-; FAST-NEXT:    setg 0
-; FAST-NEXT:    testq %rdx, %rdx
-; FAST-NEXT:    movq $0, (%rdi)
-; FAST-NEXT:    movb %cl, 0
-; FAST-NEXT:    setne (%rdi)
-; FAST-NEXT:    testb %cl, %cl
-; FAST-NEXT:    sets 0
-; FAST-NEXT:    retq
-BB:
-  %A31 = alloca i1, i32 0, align 1
-  %A = alloca i1, i32 0, align 1
-  %L2 = load i1, ptr %A, align 1
-  %L = load i1, ptr %A, align 1
-  store i1 poison, ptr null, align 1
-  store i1 false, ptr %A31, align 1
-  %LGV3 = load i64, ptr null, align 4
-  %G3 = getelementptr i1, ptr null, i1 %L2
-  %L4 = load i1, ptr %G3, align 1
-  %G1 = getelementptr i1, ptr null, i1 %L
-  %L9 = load i8, ptr %G1, align 1
-  %C10 = icmp sgt i8 0, %L9
-  %L31 = load i64, ptr %A31, align 4
-  store i1 false, ptr @G.1, align 1
-  %C4 = icmp ne i64 0, %LGV3
-  store ptr null, ptr %A31, align 8
-  store ptr null, ptr @G.5, align 8
-  %C5 = icmp sgt i64 %L3, 0
-  store i1 %C5, ptr null, align 1
-  store ptr null, ptr %G.5, align 8
-  store i1 %L4, ptr null, align 1
-  store i1 %C4, ptr %G.5, align 1
-  store i1 %C10, ptr null, align 1
-  ret void
-}



More information about the llvm-commits mailing list