Skip to content

[ConstantFolding] Handle reading from type padding #144330

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

Merged
merged 2 commits into from
Jun 17, 2025

Conversation

nikic
Copy link
Contributor

@nikic nikic commented Jun 16, 2025

ReadDataFromGlobal() did not handle reads from the padding of types (in the sense of type store size != type alloc size, rather than struct padding).

Return zero in that case.

Fixes #144279.

ReadDataFromGlobal() did not handle reads from the padding of
types (in the sense of type store size != type alloc size, rather
than struct padding).

Just bail out in that case. (Alternatively could make this return
zero as well, but the value seems dubious.)

Fixes llvm#144279.
@llvmbot
Copy link
Member

llvmbot commented Jun 16, 2025

@llvm/pr-subscribers-llvm-analysis

@llvm/pr-subscribers-llvm-transforms

Author: Nikita Popov (nikic)

Changes

ReadDataFromGlobal() did not handle reads from the padding of types (in the sense of type store size != type alloc size, rather than struct padding).

Just bail out in that case. (Alternatively could make this return zero as well, but the value seems dubious.)

Fixes #144279.


Full diff: https://github.com/llvm/llvm-project/pull/144330.diff

2 Files Affected:

  • (modified) llvm/lib/Analysis/ConstantFolding.cpp (+4)
  • (modified) llvm/test/Transforms/InstSimplify/ConstProp/loads.ll (+38)
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 2b7a438a9ef01..7bd67d2a95dbc 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -432,6 +432,10 @@ bool ReadDataFromGlobal(Constant *C, uint64_t ByteOffset, unsigned char *CurPtr,
   assert(ByteOffset <= DL.getTypeAllocSize(C->getType()) &&
          "Out of range access");
 
+  // Trying to read type padding.
+  if (ByteOffset >= DL.getTypeStoreSize(C->getType()))
+    return false;
+
   // If this element is zero or undefined, we can just return since *CurPtr is
   // zero initialized.
   if (isa<ConstantAggregateZero>(C) || isa<UndefValue>(C))
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll b/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll
index dd75560e25ced..134025514dcf6 100644
--- a/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll
@@ -441,3 +441,41 @@ define i128 @load-128bit(){
   %1 = load i128, ptr @global128, align 4
   ret i128 %1
 }
+
+
+@i40_struct = constant { i40, i8 } { i40 0, i8 1 }
+@i40_array = constant [2 x i40] [i40 0, i40 1]
+
+define i8 @load_i40_struct_padding() {
+; CHECK-LABEL: @load_i40_struct_padding(
+; CHECK-NEXT:    [[V:%.*]] = load i8, ptr getelementptr (i8, ptr @i40_struct, i64 6), align 1
+; CHECK-NEXT:    ret i8 [[V]]
+;
+  %v = load i8, ptr getelementptr (i8, ptr @i40_struct, i64 6)
+  ret i8 %v
+}
+
+define i16 @load_i40_struct_partial_padding() {
+; CHECK-LABEL: @load_i40_struct_partial_padding(
+; CHECK-NEXT:    ret i16 0
+;
+  %v = load i16, ptr getelementptr (i8, ptr @i40_struct, i64 4)
+  ret i16 %v
+}
+
+define i8 @load_i40_array_padding() {
+; CHECK-LABEL: @load_i40_array_padding(
+; CHECK-NEXT:    [[V:%.*]] = load i8, ptr getelementptr (i8, ptr @i40_array, i64 6), align 1
+; CHECK-NEXT:    ret i8 [[V]]
+;
+  %v = load i8, ptr getelementptr (i8, ptr @i40_array, i64 6)
+  ret i8 %v
+}
+
+define i16 @load_i40_array_partial_padding() {
+; CHECK-LABEL: @load_i40_array_partial_padding(
+; CHECK-NEXT:    ret i16 0
+;
+  %v = load i16, ptr getelementptr (i8, ptr @i40_array, i64 4)
+  ret i16 %v
+}

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

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

It is weird to me that the following load (across the padding) gets folded into 0.

@i40_struct = constant { i40, i8 } { i40 0, i8 1 }
define i16 @load_i40_struct_padding() {
  %v = load i16, ptr getelementptr (i8, ptr @i40_struct, i64 4) ; [4, 6)
  ret i16 %v
}

I think it is ok to always return zero, as the padding is initialized with undef.

@nikic
Copy link
Contributor Author

nikic commented Jun 16, 2025

Done.

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

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

LG. The PR title should be updated.

@nikic nikic changed the title [ConstantFolding] Bail out when reading padding of type [ConstantFolding] Handle reading from type padding Jun 16, 2025
@nikic nikic merged commit 80b79ce into llvm:main Jun 17, 2025
7 checks passed
@nikic nikic deleted the constant-folding-load-padding branch June 17, 2025 07:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[AggressiveInstCombine] assertion failure loading from non-power-of-two byte-sized zero field of global struct
3 participants