Skip to content

[IR][ASMParser] Use default AS for alloca without explicit AS #135786

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

ritter-x2a
Copy link
Member

@ritter-x2a ritter-x2a commented Apr 15, 2025

The LangRef says about alloca instructions:
"If the address space is not explicitly specified, the object is allocated in the alloca address space from the datalayout string."

So far, while the BitcodeReader follows this specification and uses the alloca
AS from the datalayout when no AS record is present, the LLParser instead used
AS 0 as the default. Similarly, the AsmWriter would omit the AS iff it is 0.

This patch changes the textual IR parser and writer to follow the LangRef:

  • The LLParser now uses the alloca AS from the datalayout for allocas without
    explicit AS.
  • The AsmWriter only omits the addrspace of an alloca instruction if it is 0
    and if that is the default address space. It would be possible to always omit
    the AS if it is the default AS or to never omit the AS in the AsmWriter, but
    both variants would require changing many test cases without much benefit.

This patch can "break" existing textual IR if it contains allocas without
explicit AS while the datalayout specifies a non-zero alloca AS.

The large OpenMP Transforms test cases were adjusted by changing all allocas
without explicit AS to use AS 0 explicitly, to preserve their original
semantics.

For SWDEV-511252.

The [LangRef](https://llvm.org/docs/LangRef.html#alloca-instruction) says about
alloca instructions:
"If the address space is not explicitly specified, the object is allocated in
the alloca address space from the datalayout string."

So far, while the BitcodeReader follows this specification and uses the alloca
AS from the datalayout when no AS record is present, the LLParser instead used
AS 0 as the default. Similarly, the AsmWriter would omit the AS iff it is 0.

This patch changes the textual IR parser and writer to follow the LangRef:
- The LLParser now uses the alloca AS from the datalayout for allocas without
  explicit AS.
- The AsmWriter only omits the addrspace of an alloca instruction if it is 0
  and if that is the default address space. It would be possible to always omit
  the AS if it is the default AS or to never omit the AS in the AsmWriter, but
  both variants would require changing many test cases without much benefit.

This patch can "break" existing textual IR if it contains allocas without
explicit AS while the datalayout specifies a non-zero alloca AS.

The large OpenMP Transforms test cases were adjusted by changing all allocas
without explicit AS to use AS 0 explicitly, to preserve their original
semantics.

For SWDEV-511252.
Copy link
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@ritter-x2a ritter-x2a marked this pull request as ready for review April 15, 2025 12:33
@llvmbot llvmbot added backend:AMDGPU llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:ir llvm:transforms clang:openmp OpenMP related changes to Clang labels Apr 15, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 15, 2025

@llvm/pr-subscribers-llvm-ir
@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-backend-amdgpu

Author: Fabian Ritter (ritter-x2a)

Changes

The LangRef says about alloca instructions:
"If the address space is not explicitly specified, the object is allocated in the alloca address space from the datalayout string."

So far, while the BitcodeReader follows this specification and uses the alloca
AS from the datalayout when no AS record is present, the LLParser instead used
AS 0 as the default. Similarly, the AsmWriter would omit the AS iff it is 0.

This patch changes the textual IR parser and writer to follow the LangRef:

  • The LLParser now uses the alloca AS from the datalayout for allocas without
    explicit AS.
  • The AsmWriter only omits the addrspace of an alloca instruction if it is 0
    and if that is the default address space. It would be possible to always omit
    the AS if it is the default AS or to never omit the AS in the AsmWriter, but
    both variants would require changing many test cases without much benefit.

This patch can "break" existing textual IR if it contains allocas without
explicit AS while the datalayout specifies a non-zero alloca AS.

The large OpenMP Transforms test cases were adjusted by changing all allocas
without explicit AS to use AS 0 explicitly, to preserve their original
semantics.

For SWDEV-511252.


Patch is 325.74 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135786.diff

16 Files Affected:

  • (modified) llvm/include/llvm/AsmParser/LLParser.h (+2-1)
  • (modified) llvm/lib/AsmParser/LLParser.cpp (+11-7)
  • (modified) llvm/lib/IR/AsmWriter.cpp (+5-1)
  • (added) llvm/test/Assembler/alloca-addrspace-default.ll (+41)
  • (modified) llvm/test/Assembler/symbolic-addrspace.ll (+1-1)
  • (modified) llvm/test/CodeGen/AMDGPU/assert-wrong-alloca-addrspace.ll (+1-1)
  • (modified) llvm/test/CodeGen/AMDGPU/lower-indirect-lds-references.ll (+1-1)
  • (modified) llvm/test/Transforms/Attributor/ArgumentPromotion/alloca-as.ll (+3-3)
  • (modified) llvm/test/Transforms/InstCombine/alloca-in-non-alloca-as.ll (+6-6)
  • (modified) llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll (+15-15)
  • (modified) llvm/test/Transforms/OpenMP/custom_state_machines.ll (+349-349)
  • (modified) llvm/test/Transforms/OpenMP/custom_state_machines_pre_lto.ll (+465-465)
  • (modified) llvm/test/Transforms/OpenMP/spmdization.ll (+120-120)
  • (modified) llvm/test/Transforms/OpenMP/spmdization_constant_prop.ll (+1-1)
  • (modified) llvm/test/Transforms/OpenMP/spmdization_indirect.ll (+43-43)
  • (modified) llvm/test/Transforms/SafeStack/X86/alloca-addrspace-wrong-addrspace.ll (+1-1)
diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index c01de4a289a69..97e646cdb8f11 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -326,7 +326,8 @@ namespace llvm {
     bool parseOptionalStackAlignment(unsigned &Alignment);
     bool parseOptionalCommaAlign(MaybeAlign &Alignment, bool &AteExtraComma);
     bool parseOptionalCommaAddrSpace(unsigned &AddrSpace, LocTy &Loc,
-                                     bool &AteExtraComma);
+                                     bool &AteExtraComma,
+                                     unsigned DefaultAS = 0);
     bool parseAllocSizeArguments(unsigned &BaseSizeArg,
                                  std::optional<unsigned> &HowManyArg);
     bool parseVScaleRangeArguments(unsigned &MinValue, unsigned &MaxValue);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index af0422f09bc4f..3365ea57b760d 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2711,7 +2711,8 @@ bool LLParser::parseOptionalCommaAlign(MaybeAlign &Alignment,
 /// This returns with AteExtraComma set to true if it ate an excess comma at the
 /// end.
 bool LLParser::parseOptionalCommaAddrSpace(unsigned &AddrSpace, LocTy &Loc,
-                                           bool &AteExtraComma) {
+                                           bool &AteExtraComma,
+                                           unsigned DefaultAS) {
   AteExtraComma = false;
   while (EatIfPresent(lltok::comma)) {
     // Metadata at the end is an early exit.
@@ -2724,7 +2725,7 @@ bool LLParser::parseOptionalCommaAddrSpace(unsigned &AddrSpace, LocTy &Loc,
     if (Lex.getKind() != lltok::kw_addrspace)
       return error(Lex.getLoc(), "expected metadata or 'addrspace'");
 
-    if (parseOptionalAddrSpace(AddrSpace))
+    if (parseOptionalAddrSpace(AddrSpace, DefaultAS))
       return true;
   }
 
@@ -8354,7 +8355,8 @@ int LLParser::parseAlloc(Instruction *&Inst, PerFunctionState &PFS) {
   Value *Size = nullptr;
   LocTy SizeLoc, TyLoc, ASLoc;
   MaybeAlign Alignment;
-  unsigned AddrSpace = 0;
+  unsigned DefaultAS = M->getDataLayout().getAllocaAddrSpace();
+  unsigned AddrSpace = DefaultAS;
   Type *Ty = nullptr;
 
   bool IsInAlloca = EatIfPresent(lltok::kw_inalloca);
@@ -8371,11 +8373,12 @@ int LLParser::parseAlloc(Instruction *&Inst, PerFunctionState &PFS) {
     if (Lex.getKind() == lltok::kw_align) {
       if (parseOptionalAlignment(Alignment))
         return true;
-      if (parseOptionalCommaAddrSpace(AddrSpace, ASLoc, AteExtraComma))
+      if (parseOptionalCommaAddrSpace(AddrSpace, ASLoc, AteExtraComma,
+                                      DefaultAS))
         return true;
     } else if (Lex.getKind() == lltok::kw_addrspace) {
       ASLoc = Lex.getLoc();
-      if (parseOptionalAddrSpace(AddrSpace))
+      if (parseOptionalAddrSpace(AddrSpace, DefaultAS))
         return true;
     } else if (Lex.getKind() == lltok::MetadataVar) {
       AteExtraComma = true;
@@ -8386,11 +8389,12 @@ int LLParser::parseAlloc(Instruction *&Inst, PerFunctionState &PFS) {
         if (Lex.getKind() == lltok::kw_align) {
           if (parseOptionalAlignment(Alignment))
             return true;
-          if (parseOptionalCommaAddrSpace(AddrSpace, ASLoc, AteExtraComma))
+          if (parseOptionalCommaAddrSpace(AddrSpace, ASLoc, AteExtraComma,
+                                          DefaultAS))
             return true;
         } else if (Lex.getKind() == lltok::kw_addrspace) {
           ASLoc = Lex.getLoc();
-          if (parseOptionalAddrSpace(AddrSpace))
+          if (parseOptionalAddrSpace(AddrSpace, DefaultAS))
             return true;
         } else if (Lex.getKind() == lltok::MetadataVar) {
           AteExtraComma = true;
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index ac8aa0d35ea30..9653cf50e83ea 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -4724,7 +4724,11 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
     }
 
     unsigned AddrSpace = AI->getAddressSpace();
-    if (AddrSpace != 0) {
+    unsigned DefaultAllocaAS =
+        I.getModule()->getDataLayout().getAllocaAddrSpace();
+    // Avoid confusion by omitting the addrspace only if it is 0 and that is the
+    // default. Dropping the "AddrSpace != 0" condition would also be correct.
+    if (AddrSpace != 0 || AddrSpace != DefaultAllocaAS) {
       Out << ", addrspace(" << AddrSpace << ')';
     }
   } else if (isa<CastInst>(I)) {
diff --git a/llvm/test/Assembler/alloca-addrspace-default.ll b/llvm/test/Assembler/alloca-addrspace-default.ll
new file mode 100644
index 0000000000000..0572ed7f5dcd0
--- /dev/null
+++ b/llvm/test/Assembler/alloca-addrspace-default.ll
@@ -0,0 +1,41 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+
+target datalayout = "A9"
+; CHECK: target datalayout = "A9"
+
+
+; CHECK: %alloca_scalar_no_align = alloca i32, align 4, addrspace(9)
+; CHECK-NEXT: %alloca_scalar_align4 = alloca i32, align 4, addrspace(9)
+; CHECK-NEXT: %alloca_scalar_no_align_metadata = alloca i32, align 4, addrspace(9), !foo !0
+; CHECK-NEXT: %alloca_scalar_align4_metadata = alloca i32, align 4, addrspace(9), !foo !0
+; CHECK-NEXT: %alloca_inalloca_scalar_no_align = alloca inalloca i32, align 4, addrspace(9)
+; CHECK-NEXT: %alloca_inalloca_scalar_align4_metadata = alloca inalloca i32, align 4, addrspace(9), !foo !0
+define void @use_alloca_default() {
+  %alloca_scalar_no_align = alloca i32
+  %alloca_scalar_align4 = alloca i32, align 4
+  %alloca_scalar_no_align_metadata = alloca i32, !foo !0
+  %alloca_scalar_align4_metadata = alloca i32, align 4, !foo !0
+  %alloca_inalloca_scalar_no_align = alloca inalloca i32
+  %alloca_inalloca_scalar_align4_metadata = alloca inalloca i32, align 4, !foo !0
+
+  ret void
+}
+
+; CHECK: %alloca_scalar_no_align = alloca i32, align 4, addrspace(0)
+; CHECK-NEXT: %alloca_scalar_align4 = alloca i32, align 4, addrspace(0)
+; CHECK-NEXT: %alloca_scalar_no_align_metadata = alloca i32, align 4, addrspace(0), !foo !0
+; CHECK-NEXT: %alloca_scalar_align4_metadata = alloca i32, align 4, addrspace(0), !foo !0
+; CHECK-NEXT: %alloca_inalloca_scalar_no_align = alloca inalloca i32, align 4, addrspace(0)
+; CHECK-NEXT: %alloca_inalloca_scalar_align4_metadata = alloca inalloca i32, align 4, addrspace(0), !foo !0
+define void @use_alloca_nondefault0() {
+  %alloca_scalar_no_align = alloca i32, addrspace(0)
+  %alloca_scalar_align4 = alloca i32, align 4, addrspace(0)
+  %alloca_scalar_no_align_metadata = alloca i32, addrspace(0), !foo !0
+  %alloca_scalar_align4_metadata = alloca i32, align 4, addrspace(0), !foo !0
+  %alloca_inalloca_scalar_no_align = alloca inalloca i32, addrspace(0)
+  %alloca_inalloca_scalar_align4_metadata = alloca inalloca i32, align 4, addrspace(0), !foo !0
+
+  ret void
+}
+
+!0 = !{}
diff --git a/llvm/test/Assembler/symbolic-addrspace.ll b/llvm/test/Assembler/symbolic-addrspace.ll
index 7cdfb7cce1e93..6d00c58523b9a 100644
--- a/llvm/test/Assembler/symbolic-addrspace.ll
+++ b/llvm/test/Assembler/symbolic-addrspace.ll
@@ -38,7 +38,7 @@ target datalayout = "A1-G2-P3"
 define void @foo() {
   ; ALLOCA-IN-GLOBALS: %alloca = alloca i32, align 4, addrspace(2){{$}}
   ; ALLOCA-IN-GLOBALS: %alloca2 = alloca i32, align 4, addrspace(1){{$}}
-  ; ALLOCA-IN-GLOBALS: %alloca3 = alloca i32, align 4{{$}}
+  ; ALLOCA-IN-GLOBALS: %alloca3 = alloca i32, align 4, addrspace(1){{$}}
   ; ALLOCA-IN-GLOBALS: %alloca4 = alloca i32, align 4, addrspace(3){{$}}
   %alloca = alloca i32, addrspace("G")
   %alloca2 = alloca i32, addrspace("A")
diff --git a/llvm/test/CodeGen/AMDGPU/assert-wrong-alloca-addrspace.ll b/llvm/test/CodeGen/AMDGPU/assert-wrong-alloca-addrspace.ll
index 1e72e679e83c0..0b0e4a63d7ade 100644
--- a/llvm/test/CodeGen/AMDGPU/assert-wrong-alloca-addrspace.ll
+++ b/llvm/test/CodeGen/AMDGPU/assert-wrong-alloca-addrspace.ll
@@ -10,7 +10,7 @@ declare void @func(ptr)
 
 define void @main() {
 bb:
-  %alloca = alloca i32, align 4
+  %alloca = alloca i32, align 4, addrspace(0)
   call void @func(ptr %alloca)
   ret void
 }
diff --git a/llvm/test/CodeGen/AMDGPU/lower-indirect-lds-references.ll b/llvm/test/CodeGen/AMDGPU/lower-indirect-lds-references.ll
index 1b0c8d66d3ebc..2e73bcc91821d 100644
--- a/llvm/test/CodeGen/AMDGPU/lower-indirect-lds-references.ll
+++ b/llvm/test/CodeGen/AMDGPU/lower-indirect-lds-references.ll
@@ -16,7 +16,7 @@ define amdgpu_kernel void @offloading_kernel() {
 }
 
 define void @call_unknown() {
-  %1 = alloca ptr, align 8
+  %1 = alloca ptr, align 8, addrspace(0)
   %2 = call i32 %1()
   ret void
 }
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/alloca-as.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/alloca-as.ll
index 9e2cd06d26ea9..e14c6f8e3713a 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/alloca-as.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/alloca-as.ll
@@ -10,7 +10,7 @@ define i32 @bar(i32 %arg) {
 ; TUNIT-LABEL: define {{[^@]+}}@bar
 ; TUNIT-SAME: (i32 [[ARG:%.*]]) {
 ; TUNIT-NEXT:  entry:
-; TUNIT-NEXT:    [[STACK:%.*]] = alloca i32, align 4
+; TUNIT-NEXT:    [[STACK:%.*]] = alloca i32, align 4, addrspace(0)
 ; TUNIT-NEXT:    store i32 [[ARG]], ptr [[STACK]], align 4
 ; TUNIT-NEXT:    [[TMP0:%.*]] = load i32, ptr [[STACK]], align 4
 ; TUNIT-NEXT:    [[CALL:%.*]] = call i32 @foo(i32 [[TMP0]])
@@ -19,13 +19,13 @@ define i32 @bar(i32 %arg) {
 ; CGSCC-LABEL: define {{[^@]+}}@bar
 ; CGSCC-SAME: (i32 [[ARG:%.*]]) {
 ; CGSCC-NEXT:  entry:
-; CGSCC-NEXT:    [[STACK:%.*]] = alloca i32, align 4
+; CGSCC-NEXT:    [[STACK:%.*]] = alloca i32, align 4, addrspace(0)
 ; CGSCC-NEXT:    store i32 [[ARG]], ptr [[STACK]], align 4
 ; CGSCC-NEXT:    [[CALL:%.*]] = call i32 @foo(i32 [[ARG]])
 ; CGSCC-NEXT:    ret i32 [[CALL]]
 ;
 entry:
-  %stack = alloca i32
+  %stack = alloca i32, addrspace(0)
   store i32 %arg, ptr %stack
   %call = call i32 @foo(ptr %stack)
   ret i32 %call
diff --git a/llvm/test/Transforms/InstCombine/alloca-in-non-alloca-as.ll b/llvm/test/Transforms/InstCombine/alloca-in-non-alloca-as.ll
index 9a2bfac0feb02..33433f2c28964 100644
--- a/llvm/test/Transforms/InstCombine/alloca-in-non-alloca-as.ll
+++ b/llvm/test/Transforms/InstCombine/alloca-in-non-alloca-as.ll
@@ -12,12 +12,12 @@ declare void @use2(ptr, ptr)
 define weak amdgpu_kernel void @__omp_offloading_802_ea0109_main_l8(ptr %a) {
 ; CHECK-LABEL: @__omp_offloading_802_ea0109_main_l8(
 ; CHECK-NEXT:  .master:
-; CHECK-NEXT:    [[TMP0:%.*]] = alloca [8 x i8], align 1
+; CHECK-NEXT:    [[TMP0:%.*]] = alloca [8 x i8], align 1, addrspace(0)
 ; CHECK-NEXT:    call void @use2(ptr nonnull [[TMP0]], ptr nonnull [[TMP0]])
 ; CHECK-NEXT:    ret void
 ;
 .master:
-  %0 = alloca i8, i64 8, align 1
+  %0 = alloca i8, i64 8, align 1, addrspace(0)
   store ptr undef, ptr %0, align 8
   call void @use2(ptr %0, ptr %0)
   ret void
@@ -28,23 +28,23 @@ define weak amdgpu_kernel void @__omp_offloading_802_ea0109_main_l8(ptr %a) {
 define void @spam(ptr %arg1) {
 ; CHECK-LABEL: @spam(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[ALLOCA1:%.*]] = alloca [0 x [30 x %struct.widget]], align 16
+; CHECK-NEXT:    [[ALLOCA1:%.*]] = alloca [0 x [30 x %struct.widget]], align 16, addrspace(0)
 ; CHECK-NEXT:    call void @zot(ptr nonnull [[ALLOCA1]])
 ; CHECK-NEXT:    ret void
 ;
 bb:
-  %alloca = alloca [30 x %struct.widget], i32 0, align 16
+  %alloca = alloca [30 x %struct.widget], i32 0, align 16, addrspace(0)
   call void @zot(ptr %alloca)
   ret void
 }
 
 define i1 @alloca_addrspace_0_nonnull() {
 ; CHECK-LABEL: @alloca_addrspace_0_nonnull(
-; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i8, align 1
+; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i8, align 1, addrspace(0)
 ; CHECK-NEXT:    call void @use(ptr nonnull [[ALLOCA]])
 ; CHECK-NEXT:    ret i1 true
 ;
-  %alloca = alloca i8
+  %alloca = alloca i8, addrspace(0)
   call void @use(ptr %alloca)
   %cmp = icmp ne ptr %alloca, null
   ret i1 %cmp
diff --git a/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll b/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll
index f084fe38bb226..03f939de99e1a 100644
--- a/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll
+++ b/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll
@@ -153,7 +153,7 @@ define i32 @remove_alloca_ptr_arg(i1 %c, ptr %ptr) {
 ; CHECK-NEXT:    ret i32 [[V]]
 ;
 entry:
-  %alloca = alloca [32 x i8]
+  %alloca = alloca [32 x i8], addrspace(0)
   call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr @g1, i64 32, i1 false)
   br i1 %c, label %if, label %join
 
@@ -212,7 +212,7 @@ define i32 @test_memcpy_after_phi(i1 %cond, ptr %ptr) {
 ; CHECK-NEXT:    ret i32 [[V]]
 ;
 entry:
-  %a = alloca [32 x i8]
+  %a = alloca [32 x i8], addrspace(0)
   br i1 %cond, label %if, label %join
 
 if:
@@ -228,7 +228,7 @@ join:
 define i32 @addrspace_diff_keep_alloca(i1 %cond, ptr %x) {
 ; CHECK-LABEL: @addrspace_diff_keep_alloca(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[A:%.*]] = alloca [32 x i8], align 1
+; CHECK-NEXT:    [[A:%.*]] = alloca [32 x i8], align 1, addrspace(0)
 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p1.i64(ptr noundef nonnull align 1 dereferenceable(32) [[A]], ptr addrspace(1) noundef align 16 dereferenceable(32) @g2, i64 32, i1 false)
 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
 ; CHECK:       if:
@@ -239,7 +239,7 @@ define i32 @addrspace_diff_keep_alloca(i1 %cond, ptr %x) {
 ; CHECK-NEXT:    ret i32 [[V]]
 ;
 entry:
-  %a = alloca [32 x i8]
+  %a = alloca [32 x i8], addrspace(0)
   call void @llvm.memcpy.p0.p1.i64(ptr %a, ptr addrspace(1) @g2, i64 32, i1 false)
   br i1 %cond, label %if, label %join
 
@@ -255,7 +255,7 @@ join:
 define i32 @addrspace_diff_keep_alloca_extra_gep(i1 %cond, ptr %x) {
 ; CHECK-LABEL: @addrspace_diff_keep_alloca_extra_gep(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[A:%.*]] = alloca [32 x i8], align 1
+; CHECK-NEXT:    [[A:%.*]] = alloca [32 x i8], align 1, addrspace(0)
 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p1.i64(ptr noundef nonnull align 1 dereferenceable(32) [[A]], ptr addrspace(1) noundef align 16 dereferenceable(32) @g2, i64 32, i1 false)
 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
 ; CHECK:       if:
@@ -267,7 +267,7 @@ define i32 @addrspace_diff_keep_alloca_extra_gep(i1 %cond, ptr %x) {
 ; CHECK-NEXT:    ret i32 [[V]]
 ;
 entry:
-  %a = alloca [32 x i8]
+  %a = alloca [32 x i8], addrspace(0)
   call void @llvm.memcpy.p0.p1.i64(ptr %a, ptr addrspace(1) @g2, i64 32, i1 false)
   %gep = getelementptr i8, ptr %a, i64 4
   br i1 %cond, label %if, label %join
@@ -293,7 +293,7 @@ define i32 @addrspace_diff_remove_alloca(i1 %cond) {
 ; CHECK-NEXT:    ret i32 [[V]]
 ;
 entry:
-  %a = alloca [32 x i8]
+  %a = alloca [32 x i8], addrspace(0)
   call void @llvm.memcpy.p0.p1.i64(ptr %a, ptr addrspace(1) @g2, i64 32, i1 false)
   %gep = getelementptr inbounds [32 x i8], ptr %a, i32 0, i32 2
   br i1 %cond, label %if, label %join
@@ -320,7 +320,7 @@ define i32 @phi_loop(i1 %c) {
 ; CHECK-NEXT:    ret i32 [[V]]
 ;
 entry:
-  %alloca = alloca [32 x i8]
+  %alloca = alloca [32 x i8], addrspace(0)
   call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr @g1, i64 32, i1 false)
   br label %loop
 
@@ -337,7 +337,7 @@ exit:
 define i32 @phi_loop_different_addrspace(i1 %c) {
 ; CHECK-LABEL: @phi_loop_different_addrspace(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [32 x i8], align 1
+; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [32 x i8], align 1, addrspace(0)
 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p1.i64(ptr noundef nonnull align 1 dereferenceable(32) [[ALLOCA]], ptr addrspace(1) noundef align 16 dereferenceable(32) @g2, i64 32, i1 false)
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
@@ -349,7 +349,7 @@ define i32 @phi_loop_different_addrspace(i1 %c) {
 ; CHECK-NEXT:    ret i32 [[V]]
 ;
 entry:
-  %alloca = alloca [32 x i8]
+  %alloca = alloca [32 x i8], addrspace(0)
   call void @llvm.memcpy.p0.p1.i64(ptr %alloca, ptr addrspace(1) @g2, i64 32, i1 false)
   br label %loop
 
@@ -371,7 +371,7 @@ define i8 @select_same_addrspace_remove_alloca(i1 %cond, ptr %p) {
 ; CHECK-NEXT:    ret i8 [[LOAD]]
 ;
 entry:
-  %alloca = alloca [32 x i8]
+  %alloca = alloca [32 x i8], addrspace(0)
   call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr @g1, i64 32, i1 false)
   %ptr = select i1 %cond, ptr %alloca, ptr %p
   %load = load i8, ptr %ptr
@@ -381,14 +381,14 @@ entry:
 define i8 @select_after_memcpy_keep_alloca(i1 %cond, ptr %p) {
 ; CHECK-LABEL: @select_after_memcpy_keep_alloca(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [32 x i8], align 1
+; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [32 x i8], align 1, addrspace(0)
 ; CHECK-NEXT:    [[PTR:%.*]] = select i1 [[COND:%.*]], ptr [[ALLOCA]], ptr [[P:%.*]]
 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(32) [[PTR]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false)
 ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, ptr [[PTR]], align 1
 ; CHECK-NEXT:    ret i8 [[LOAD]]
 ;
 entry:
-  %alloca = alloca [32 x i8]
+  %alloca = alloca [32 x i8], addrspace(0)
   %ptr = select i1 %cond, ptr %alloca, ptr %p
   call void @llvm.memcpy.p0.p0.i64(ptr %ptr, ptr @g1, i64 32, i1 false)
   %load = load i8, ptr %ptr
@@ -418,7 +418,7 @@ define i8 @select_diff_addrspace_remove_alloca(i1 %cond, ptr %p) {
 ; CHECK-NEXT:    ret i8 0
 ;
 entry:
-  %alloca = alloca [32 x i8]
+  %alloca = alloca [32 x i8], addrspace(0)
   call void @llvm.memcpy.p0.p1.i64(ptr %alloca, ptr addrspace(1) @g2, i64 32, i1 false)
   %gep = getelementptr inbounds [32 x i8], ptr %alloca, i32 0, i32 2
   %sel = select i1 %cond, ptr %alloca, ptr %gep
@@ -435,7 +435,7 @@ define i8 @select_diff_addrspace_remove_alloca_asan(i1 %cond, ptr %p) sanitize_a
 ; CHECK-NEXT:    ret i8 [[LOAD]]
 ;
 entry:
-  %alloca = alloca [32 x i8]
+  %alloca = alloca [32 x i8], addrspace(0)
   call void @llvm.memcpy.p0.p1.i64(ptr %alloca, ptr addrspace(1) @g2, i64 32, i1 false)
   %gep = getelementptr inbounds [32 x i8], ptr %alloca, i32 0, i32 2
   %sel = select i1 %cond, ptr %alloca, ptr %gep
diff --git a/llvm/test/Transforms/OpenMP/custom_state_machines.ll b/llvm/test/Transforms/OpenMP/custom_state_machines.ll
index 10e521bbfcc10..140de716cb41f 100644
--- a/llvm/test/Transforms/OpenMP/custom_state_machines.ll
+++ b/llvm/test/Transforms/OpenMP/custom_state_machines.ll
@@ -140,8 +140,8 @@
 
 define weak ptx_kernel void @__omp_offloading_14_a36502b_no_state_machine_needed_l14(ptr %dyn) #0 {
 entry:
-  %.zero.addr = alloca i32, align 4
-  %.threadid_temp. = alloca i32, align 4
+  %.zero.addr = alloca i32, align 4, addrspace(0)
+  %.threadid_temp. = alloca i32, align 4, addrspace(0)
   store i32 0, ptr %.zero.addr, align 4
   %0 = call i32 @__kmpc_target_init(ptr @__omp_offloading_14_a36502b_no_state_machine_needed_l14_kernel_environment, ptr %dyn)
   %exec_user_code = icmp eq i32 %0, -1
@@ -165,8 +165,8 @@ define weak i32 @__kmpc_target_init(ptr, ptr) {
 
 define internal void @__omp_outlined__(ptr noalias %.global_tid., ptr noalias %.bound_tid.) #0 {
 entry:
-  %.global_tid..addr = alloca ptr, align 8
-  %.bound_tid..addr = alloca ptr, align 8
+  %.global_tid..addr = alloca ptr, align 8, addrspace(0)
+  %.bound_tid..addr = alloca ptr, align 8, addrspace(0)
   store ptr %.global_tid., ptr %.global_tid..addr, align 8
   store ptr %.bound_tid., ptr %.bound_tid..addr, align 8
   call void @no_parallel_region_in_here() #7
@@ -199,8 +199,8 @@ declare void @__kmpc_target_deinit()
 
 define weak ptx_kernel void @__omp_offloading_14_a36502b_simple_state_machine_l22(ptr %dyn) #0 {
 entry:
-  %.zero.addr = alloca i32, align 4
-  %.threadid_temp. = alloca i32, align 4
+  %.zero.addr = alloca i32, align 4, addrspace(0)
+  %.threadid_temp. = alloca i32, align 4, addrspace(0)
   store i32 0, ptr %.zero.addr, align 4
   %0 = call i32 @__kmpc_target_init(ptr @__omp_offloading_14_a36502b_simple_state_machine_l22_kernel_environment, ptr %dyn)
   %exec_user_code = icmp eq i32 %0, -1
@@ -219,10 +219,10 @@ worker.exit:                                      ; preds = %entry
 
 define internal void @__omp_outlined__1(ptr noalias %.global_tid., ptr noalias %.bound_tid.) #0 {
 entry:
-  %.global_tid..addr = alloca ptr, align 8
-  %.bound_tid..addr = alloca ptr, align 8
-  %captured_vars_addrs = alloca [0 x ptr], align 8
-  %captured_vars_addrs1 = alloca [0...
[truncated]

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be done. It's inconsistent behavior with every other context in the IR. The other case that tries to behave like this is the program address space, but that is confusing and should be removed. The syntax should be consistent, without context

Copy link
Member Author

Then we should probably change the langref instead. There is also the point that the bitcode reader/writer represents an alloca with the default address space by omitting the address space record; I guess it might be sufficiently unlikely to see inconsistencies because of that.

@shiltian
Copy link
Contributor

FWIW, I'm gonna make a PR to treat alloca in non-private AS as invalid IR.

Copy link
Member Author

FWIW, I'm gonna make a PR to treat alloca in non-private AS as invalid IR.

Sounds like we are looking into similar fuzzer tickets :)
Be aware that this probably needs to go into some kind of target-specific verifier, since there seem to be targets (for example WASM, according to https://reviews.llvm.org/D101045 ) that use non-default address spaces in allocas.

@shiltian
Copy link
Contributor

Sounds like we are looking into similar fuzzer tickets :)

Yeah, that was motivated by some fuzzer tickets which turns out to be invalid IR.

Be aware that this probably needs to go into some kind of target-specific verifier, since there seem to be targets (for example WASM, according to https://reviews.llvm.org/D101045 ) that use non-default address spaces in allocas.

Since we don't have a target specific verifier at the moment, I'm gonna just do it in the common one, and put a FIXME there when I hard code AS5 instead of AMDGPUAS::PRIVATE_ADDRESS, since we can't include the header there.

ritter-x2a added a commit to ritter-x2a/llvm-project that referenced this pull request Apr 16, 2025
…it AS

So far, the Language Reference said that the alloca address space from
the datalayout is used if no explicit address space is provided, which
is not what the LLParser and the AsmWriter implement. This patch adjusts
the documentation to match the implementation: The default AS 0 is used
if none is explicitly specified.

This is an alternative to PR llvm#135786, which would change the parser's
behavior to match the Language Reference instead.
@ritter-x2a ritter-x2a closed this Apr 16, 2025
Copy link
Member Author

Closing in favor of #135942, which changes the documentation instead.

@arsenm arsenm deleted the users/ritter-x2a/04-15-_ir_asmparser_use_default_as_for_alloca_without_explicit_as branch April 21, 2025 11:17
ritter-x2a added a commit that referenced this pull request Apr 22, 2025
…it AS (#135942)

So far, the Language Reference said that the alloca address space from
the datalayout is used if no explicit address space is provided, which
is not what the LLParser and the AsmWriter implement. This patch adjusts
the documentation to match the implementation: The default AS 0 is used
if none is explicitly specified.

This is an alternative to PR #135786, which would change the parser's
behavior to match the Language Reference instead.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…it AS (llvm#135942)

So far, the Language Reference said that the alloca address space from
the datalayout is used if no explicit address space is provided, which
is not what the LLParser and the AsmWriter implement. This patch adjusts
the documentation to match the implementation: The default AS 0 is used
if none is explicitly specified.

This is an alternative to PR llvm#135786, which would change the parser's
behavior to match the Language Reference instead.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…it AS (llvm#135942)

So far, the Language Reference said that the alloca address space from
the datalayout is used if no explicit address space is provided, which
is not what the LLParser and the AsmWriter implement. This patch adjusts
the documentation to match the implementation: The default AS 0 is used
if none is explicitly specified.

This is an alternative to PR llvm#135786, which would change the parser's
behavior to match the Language Reference instead.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…it AS (llvm#135942)

So far, the Language Reference said that the alloca address space from
the datalayout is used if no explicit address space is provided, which
is not what the LLParser and the AsmWriter implement. This patch adjusts
the documentation to match the implementation: The default AS 0 is used
if none is explicitly specified.

This is an alternative to PR llvm#135786, which would change the parser's
behavior to match the Language Reference instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AMDGPU clang:openmp OpenMP related changes to Clang llvm:asmparser llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:ir llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants