[llvm] [SelectionDAG] Handling Oversized Alloca Types under 32 bit Mode to Avoid Code Generator Crash (PR #71472)

Qiongsi Wu via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 13 05:35:14 PST 2023


https://github.com/qiongsiwu updated https://github.com/llvm/llvm-project/pull/71472

>From 2e98ef4542f04bebad5fc02ce4491710399bcabd Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qwu at ibm.com>
Date: Mon, 6 Nov 2023 19:17:55 -0500
Subject: [PATCH 1/4] Fix code generator crash when it sees an oversized alloca
 type

---
 .../SelectionDAG/SelectionDAGBuilder.cpp      |  7 +--
 llvm/test/CodeGen/PowerPC/alloca-neg-size.ll  | 46 +++++++++++++++++++
 2 files changed, 50 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/alloca-neg-size.ll

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index aab0d5c5a348bfe..d5ffaf28ca2d499 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4138,9 +4138,10 @@ void SelectionDAGBuilder::visitAlloca(const AllocaInst &I) {
                                           APInt(IntPtr.getScalarSizeInBits(),
                                                 TySize.getKnownMinValue())));
   else
-    AllocSize =
-        DAG.getNode(ISD::MUL, dl, IntPtr, AllocSize,
-                    DAG.getConstant(TySize.getFixedValue(), dl, IntPtr));
+    AllocSize = DAG.getNode(ISD::MUL, dl, IntPtr, AllocSize,
+                            DAG.getConstant(APInt(IntPtr.getScalarSizeInBits(),
+                                                  TySize.getFixedValue()),
+                                            dl, IntPtr));
 
   // Handle alignment.  If the requested alignment is less than or equal to
   // the stack alignment, ignore it.  If the size is greater than or equal to
diff --git a/llvm/test/CodeGen/PowerPC/alloca-neg-size.ll b/llvm/test/CodeGen/PowerPC/alloca-neg-size.ll
new file mode 100644
index 000000000000000..ba22c0a71294b8d
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/alloca-neg-size.ll
@@ -0,0 +1,46 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
+; The instcombine pass can turn
+;     alloca i32, i32 -1
+; to
+;     alloca [4294967295 x i32], i32 1
+; because it zero extends the NumElements to unit64_t.
+; The zero extension can lead to oversized arrays on a 32 bit system.
+; Alloca-ing an array of size bigger than half of the address space
+; is most likely an undefined behaviour, but the code generator
+; should not crash in such situations.
+; RUN: llc < %s -mtriple=powerpc-ibm-aix-xcoff | FileCheck %s
+define void @test_negalloc(ptr %dst, i32 %cond) {
+; CHECK-LABEL: test_negalloc:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    stw 31, -4(1)
+; CHECK-NEXT:    stwu 1, -80(1)
+; CHECK-NEXT:    cmplwi 4, 0
+; CHECK-NEXT:    mr 31, 1
+; CHECK-NEXT:    beq 0, L..BB0_2
+; CHECK-NEXT:  # %bb.1: # %if.then
+; CHECK-NEXT:    li 4, 0
+; CHECK-NEXT:    addi 5, 31, 80
+; CHECK-NEXT:    stwux 5, 1, 4
+; CHECK-NEXT:    addi 4, 1, 32
+; CHECK-NEXT:    b L..BB0_3
+; CHECK-NEXT:  L..BB0_2:
+; CHECK-NEXT:    addi 4, 31, 44
+; CHECK-NEXT:  L..BB0_3: # %if.end
+; CHECK-NEXT:    stw 4, 0(3)
+; CHECK-NEXT:    lwz 1, 0(1)
+; CHECK-NEXT:    lwz 31, -4(1)
+; CHECK-NEXT:    blr
+entry:
+  %0 = alloca [8 x i32], i32 1, align 4
+  %tobool = icmp ne i32 %cond, 0
+  br i1 %tobool, label %if.then, label %if.end
+
+if.then:
+  %vla1 = alloca [4294967295 x i32], i32 1, align 4
+  br label %if.end
+
+if.end:
+  %arr = phi ptr [%0, %entry], [%vla1, %if.then]
+  store ptr %arr, ptr %dst
+  ret void
+}

>From e978491b85ab5a31ed2ee6e19acdfcf326a4ba93 Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qwu at ibm.com>
Date: Tue, 7 Nov 2023 09:19:09 -0500
Subject: [PATCH 2/4] Address review comments in the test

---
 .../{alloca-neg-size.ll => alloca-oversized.ll}    | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)
 rename llvm/test/CodeGen/PowerPC/{alloca-neg-size.ll => alloca-oversized.ll} (72%)

diff --git a/llvm/test/CodeGen/PowerPC/alloca-neg-size.ll b/llvm/test/CodeGen/PowerPC/alloca-oversized.ll
similarity index 72%
rename from llvm/test/CodeGen/PowerPC/alloca-neg-size.ll
rename to llvm/test/CodeGen/PowerPC/alloca-oversized.ll
index ba22c0a71294b8d..e102131d397218e 100644
--- a/llvm/test/CodeGen/PowerPC/alloca-neg-size.ll
+++ b/llvm/test/CodeGen/PowerPC/alloca-oversized.ll
@@ -1,16 +1,12 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
-; The instcombine pass can turn
+;
 ;     alloca i32, i32 -1
-; to
+; and
 ;     alloca [4294967295 x i32], i32 1
-; because it zero extends the NumElements to unit64_t.
-; The zero extension can lead to oversized arrays on a 32 bit system.
-; Alloca-ing an array of size bigger than half of the address space
-; is most likely an undefined behaviour, but the code generator
-; should not crash in such situations.
+; are equivalent and the assembly code sequences generated are the same.
 ; RUN: llc < %s -mtriple=powerpc-ibm-aix-xcoff | FileCheck %s
-define void @test_negalloc(ptr %dst, i32 %cond) {
-; CHECK-LABEL: test_negalloc:
+define void @test_oversized(ptr %dst, i32 %cond) {
+; CHECK-LABEL: test_oversized:
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    stw 31, -4(1)
 ; CHECK-NEXT:    stwu 1, -80(1)

>From 3fe11dcea4a6776862ca5b738bd9f981807621bd Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qwu at ibm.com>
Date: Fri, 10 Nov 2023 16:23:12 -0500
Subject: [PATCH 3/4] Address review comments

---
 .../SelectionDAG/SelectionDAGBuilder.cpp      | 11 ++++----
 llvm/test/CodeGen/PowerPC/alloca-oversized.ll | 28 +++++++++++++++----
 2 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index d5ffaf28ca2d499..b87c5e1914a079f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4128,7 +4128,7 @@ void SelectionDAGBuilder::visitAlloca(const AllocaInst &I) {
 
   SDValue AllocSize = getValue(I.getArraySize());
 
-  EVT IntPtr = TLI.getPointerTy(DAG.getDataLayout(), I.getAddressSpace());
+  EVT IntPtr = TLI.getPointerTy(DL, I.getAddressSpace());
   if (AllocSize.getValueType() != IntPtr)
     AllocSize = DAG.getZExtOrTrunc(AllocSize, dl, IntPtr);
 
@@ -4138,10 +4138,11 @@ void SelectionDAGBuilder::visitAlloca(const AllocaInst &I) {
                                           APInt(IntPtr.getScalarSizeInBits(),
                                                 TySize.getKnownMinValue())));
   else
-    AllocSize = DAG.getNode(ISD::MUL, dl, IntPtr, AllocSize,
-                            DAG.getConstant(APInt(IntPtr.getScalarSizeInBits(),
-                                                  TySize.getFixedValue()),
-                                            dl, IntPtr));
+    AllocSize = DAG.getNode(
+        ISD::MUL, dl, IntPtr, AllocSize,
+        DAG.getZExtOrTrunc(
+            DAG.getConstant(TySize.getFixedValue(), dl, MVT::getIntegerVT(64)),
+            dl, IntPtr));
 
   // Handle alignment.  If the requested alignment is less than or equal to
   // the stack alignment, ignore it.  If the size is greater than or equal to
diff --git a/llvm/test/CodeGen/PowerPC/alloca-oversized.ll b/llvm/test/CodeGen/PowerPC/alloca-oversized.ll
index e102131d397218e..56e23509923ae66 100644
--- a/llvm/test/CodeGen/PowerPC/alloca-oversized.ll
+++ b/llvm/test/CodeGen/PowerPC/alloca-oversized.ll
@@ -1,10 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
-;
-;     alloca i32, i32 -1
-; and
-;     alloca [4294967295 x i32], i32 1
-; are equivalent and the assembly code sequences generated are the same.
 ; RUN: llc < %s -mtriple=powerpc-ibm-aix-xcoff | FileCheck %s
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck --check-prefix=GISEL %s
 define void @test_oversized(ptr %dst, i32 %cond) {
 ; CHECK-LABEL: test_oversized:
 ; CHECK:       # %bb.0: # %entry
@@ -26,13 +22,33 @@ define void @test_oversized(ptr %dst, i32 %cond) {
 ; CHECK-NEXT:    lwz 1, 0(1)
 ; CHECK-NEXT:    lwz 31, -4(1)
 ; CHECK-NEXT:    blr
+;
+; GISEL-LABEL: test_oversized:
+; GISEL:       // %bb.0: // %entry
+; GISEL-NEXT:    stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
+; GISEL-NEXT:    mov x29, sp
+; GISEL-NEXT:    sub sp, sp, #32
+; GISEL-NEXT:    .cfi_def_cfa w29, 16
+; GISEL-NEXT:    .cfi_offset w30, -8
+; GISEL-NEXT:    .cfi_offset w29, -16
+; GISEL-NEXT:    mov x8, sp
+; GISEL-NEXT:    mov x9, #2305843009213693952 // =0x2000000000000000
+; GISEL-NEXT:    sub x8, x8, x9
+; GISEL-NEXT:    sub x9, x29, #32
+; GISEL-NEXT:    mov sp, x8
+; GISEL-NEXT:    cmp w1, #0
+; GISEL-NEXT:    csel x8, x9, x8, eq
+; GISEL-NEXT:    str x8, [x0]
+; GISEL-NEXT:    mov sp, x29
+; GISEL-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
+; GISEL-NEXT:    ret
 entry:
   %0 = alloca [8 x i32], i32 1, align 4
   %tobool = icmp ne i32 %cond, 0
   br i1 %tobool, label %if.then, label %if.end
 
 if.then:
-  %vla1 = alloca [4294967295 x i32], i32 1, align 4
+  %vla1 = alloca [18446744073709551615 x i32], i32 1, align 4
   br label %if.end
 
 if.end:

>From 35388a2a6cc1c0daa189083dab87c0868ac7f7fd Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qwu at ibm.com>
Date: Mon, 13 Nov 2023 09:21:19 -0500
Subject: [PATCH 4/4] Revise tests

---
 llvm/test/CodeGen/AArch64/alloca-oversized.ll | 36 +++++++++++++++++++
 llvm/test/CodeGen/PowerPC/alloca-oversized.ll | 23 +-----------
 2 files changed, 37 insertions(+), 22 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/alloca-oversized.ll

diff --git a/llvm/test/CodeGen/AArch64/alloca-oversized.ll b/llvm/test/CodeGen/AArch64/alloca-oversized.ll
new file mode 100644
index 000000000000000..e57bbcdf998003b
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/alloca-oversized.ll
@@ -0,0 +1,36 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s
+define void @test_oversized(ptr %dst, i32 %cond) {
+; CHECK-LABEL: test_oversized:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
+; CHECK-NEXT:    mov x29, sp
+; CHECK-NEXT:    sub sp, sp, #32
+; CHECK-NEXT:    .cfi_def_cfa w29, 16
+; CHECK-NEXT:    .cfi_offset w30, -8
+; CHECK-NEXT:    .cfi_offset w29, -16
+; CHECK-NEXT:    mov x8, sp
+; CHECK-NEXT:    mov x9, #2305843009213693952 // =0x2000000000000000
+; CHECK-NEXT:    sub x8, x8, x9
+; CHECK-NEXT:    sub x9, x29, #32
+; CHECK-NEXT:    mov sp, x8
+; CHECK-NEXT:    cmp w1, #0
+; CHECK-NEXT:    csel x8, x9, x8, eq
+; CHECK-NEXT:    str x8, [x0]
+; CHECK-NEXT:    mov sp, x29
+; CHECK-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
+; CHECK-NEXT:    ret
+entry:
+  %0 = alloca [8 x i32], i32 1, align 4
+  %tobool = icmp ne i32 %cond, 0
+  br i1 %tobool, label %if.then, label %if.end
+
+if.then:
+  %vla1 = alloca [18446744073709551615 x i32], i32 1, align 4
+  br label %if.end
+
+if.end:
+  %arr = phi ptr [%0, %entry], [%vla1, %if.then]
+  store ptr %arr, ptr %dst
+  ret void
+}
diff --git a/llvm/test/CodeGen/PowerPC/alloca-oversized.ll b/llvm/test/CodeGen/PowerPC/alloca-oversized.ll
index 56e23509923ae66..89922c348385869 100644
--- a/llvm/test/CodeGen/PowerPC/alloca-oversized.ll
+++ b/llvm/test/CodeGen/PowerPC/alloca-oversized.ll
@@ -1,6 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
 ; RUN: llc < %s -mtriple=powerpc-ibm-aix-xcoff | FileCheck %s
-; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck --check-prefix=GISEL %s
 define void @test_oversized(ptr %dst, i32 %cond) {
 ; CHECK-LABEL: test_oversized:
 ; CHECK:       # %bb.0: # %entry
@@ -22,33 +21,13 @@ define void @test_oversized(ptr %dst, i32 %cond) {
 ; CHECK-NEXT:    lwz 1, 0(1)
 ; CHECK-NEXT:    lwz 31, -4(1)
 ; CHECK-NEXT:    blr
-;
-; GISEL-LABEL: test_oversized:
-; GISEL:       // %bb.0: // %entry
-; GISEL-NEXT:    stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
-; GISEL-NEXT:    mov x29, sp
-; GISEL-NEXT:    sub sp, sp, #32
-; GISEL-NEXT:    .cfi_def_cfa w29, 16
-; GISEL-NEXT:    .cfi_offset w30, -8
-; GISEL-NEXT:    .cfi_offset w29, -16
-; GISEL-NEXT:    mov x8, sp
-; GISEL-NEXT:    mov x9, #2305843009213693952 // =0x2000000000000000
-; GISEL-NEXT:    sub x8, x8, x9
-; GISEL-NEXT:    sub x9, x29, #32
-; GISEL-NEXT:    mov sp, x8
-; GISEL-NEXT:    cmp w1, #0
-; GISEL-NEXT:    csel x8, x9, x8, eq
-; GISEL-NEXT:    str x8, [x0]
-; GISEL-NEXT:    mov sp, x29
-; GISEL-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
-; GISEL-NEXT:    ret
 entry:
   %0 = alloca [8 x i32], i32 1, align 4
   %tobool = icmp ne i32 %cond, 0
   br i1 %tobool, label %if.then, label %if.end
 
 if.then:
-  %vla1 = alloca [18446744073709551615 x i32], i32 1, align 4
+  %vla1 = alloca [4294967295 x i32], i32 1, align 4
   br label %if.end
 
 if.end:



More information about the llvm-commits mailing list