Bug type: crash
Component: ConstantFold
Bug location: llvm/lib/Analysis/ConstantFolding.cpp: ReadDataFromGlobal
Issue title: [AggressiveInstCombine] assertion failure loading from non-power-of-two byte-sized zero field of global struct
Labels: crash
llvm:analysis
Reported by: jacobly0

```llvm
@0 = constant { i40, i1 } { i40 0, i1 1 }
define void @f() {
  %1 = load i1, ptr @0
  ret void
}
```
```
$ opt --version
LLVM (http://llvm.org/):
  LLVM version 20.1.7
  DEBUG build with assertions.
  Default target: x86_64-unknown-linux-gnu
  Host CPU: znver5
$ opt -S -passes aggressive-instcombine reduced.ll
opt: llvm/lib/Support/APInt.cpp:457: APInt llvm::APInt::extractBits(unsigned int, unsigned int) const: Assertion `bitPosition < BitWidth && (numBits + bitPosition) <= BitWidth && "Illegal bit extraction"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: 20.x-Debug/bin/opt -passes aggressive-instcombine reduced.ll -S
1.	Running pass "function(aggressive-instcombine)" on module "reduced.ll"
2.	Running pass "aggressive-instcombine" on function "f"
 #0 0x00007f6af9311bc6 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) llvm/lib/Support/Unix/Signals.inc:799:11
 #1 0x00007f6af931212f PrintStackTraceSignalHandler(void*) llvm/lib/Support/Unix/Signals.inc:875:1
 #2 0x00007f6af93101a0 llvm::sys::RunSignalHandlers() llvm/lib/Support/Signals.cpp:105:5
 #3 0x00007f6af931275e SignalHandler(int) llvm/lib/Support/Unix/Signals.inc:415:1
 #4 0x00007f6af8b56750 (/usr/lib64/libc.so.6+0x3d750)
 #5 0x00007f6af8bafa9c (/usr/lib64/libc.so.6+0x96a9c)
 #6 0x00007f6af8b56616 raise (/usr/lib64/libc.so.6+0x3d616)
 #7 0x00007f6af8b3e28d abort (/usr/lib64/libc.so.6+0x2528d)
 #8 0x00007f6af8b3e1f5 __assert_perror_fail (/usr/lib64/libc.so.6+0x251f5)
 #9 0x00007f6af91021db llvm::APInt::extractBits(unsigned int, unsigned int) const llvm/lib/Support/APInt.cpp:0:3
#10 0x00007f6afaa4c319 (anonymous namespace)::ReadDataFromGlobal(llvm::Constant*, unsigned long, unsigned char*, unsigned int, llvm::DataLayout const&) llvm/lib/Analysis/ConstantFolding.cpp:445:45
#11 0x00007f6afaa4c68b (anonymous namespace)::ReadDataFromGlobal(llvm::Constant*, unsigned long, unsigned char*, unsigned int, llvm::DataLayout const&) llvm/lib/Analysis/ConstantFolding.cpp:478:32
#12 0x00007f6afaa4d3ee (anonymous namespace)::FoldReinterpretLoadFromConst(llvm::Constant*, llvm::Type*, long, llvm::DataLayout const&) llvm/lib/Analysis/ConstantFolding.cpp:622:7
#13 0x00007f6afaa4cf72 llvm::ConstantFoldLoadFromConst(llvm::Constant*, llvm::Type*, llvm::APInt const&, llvm::DataLayout const&) llvm/lib/Analysis/ConstantFolding.cpp:723:19
#14 0x00007f6afc550eb3 foldPatternedLoads(llvm::Instruction&, llvm::DataLayout const&) llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp:910:15
#15 0x00007f6afc54dca8 foldUnusualPatterns(llvm::Function&, llvm::DominatorTree&, llvm::TargetTransformInfo&, llvm::TargetLibraryInfo&, llvm::AAResults&, llvm::AssumptionCache&, bool&) llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp:1253:21
#16 0x00007f6afc54d9bd runImpl(llvm::Function&, llvm::AssumptionCache&, llvm::TargetTransformInfo&, llvm::TargetLibraryInfo&, llvm::DominatorTree&, llvm::AAResults&, bool&) llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp:1278:17
#17 0x00007f6afc54d855 llvm::AggressiveInstCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp:1290:7
#18 0x00007f6aff99a1d8 llvm::detail::PassModel<llvm::Function, llvm::AggressiveInstCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) llvm/include/llvm/IR/PassManagerInternal.h:91:17
#19 0x00007f6af9de0ed2 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) llvm/include/llvm/IR/PassManagerImpl.h:85:5
#20 0x00007f6b06c0be58 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) llvm/include/llvm/IR/PassManagerInternal.h:91:17
#21 0x00007f6af9ddf7f5 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) llvm/lib/IR/PassManager.cpp:124:38
#22 0x00007f6b06c2d648 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) llvm/include/llvm/IR/PassManagerInternal.h:91:17
#23 0x00007f6af9ddfdf2 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) llvm/include/llvm/IR/PassManagerImpl.h:85:5
#24 0x00007f6b088241ce llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::__1::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) llvm/tools/opt/NewPMDriver.cpp:541:3
#25 0x00007f6b08861f85 optMain llvm/tools/opt/optdriver.cpp:739:12
#26 0x00005575215c34a9 main llvm/tools/opt/opt.cpp:25:42
#27 0x00007f6af8b403fb (/usr/lib64/libc.so.6+0x273fb)
#28 0x00007f6af8b404ab __libc_start_main (/usr/lib64/libc.so.6+0x274ab)
#29 0x00005575215c33b5 _start (20.x-Debug/bin/opt+0x23b5)
```
Also repros at 087a6ac420ad99c523b9dd517351e0c6d1f1a980.

Comments: author: nikic
body: To make it clearer what the core problem is:
```
; RUN: opt -S -passes=instsimplify
@g = constant { i40, i8 } { i40 0, i8 1 }
define i8 @f() {
  %v = load i8, ptr getelementptr (i8, ptr @g, i64 6)
  ret i8 %v
}
```
This is accessing the padding between the store size and the alloc size of `i40`, which ReadDataFromGlobal does not correctly handle.

Fix patch:
commit 80b79ce432bbe12701fd9fe495ff9feeb5e4b9ca
Author: Nikita Popov <npopov@redhat.com>
Date:   Tue Jun 17 09:30:28 2025 +0200

    [ConstantFolding] Handle reading from type padding (#144330)
    
    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 https://github.com/llvm/llvm-project/issues/144279.

diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 2b7a438a9ef0..b58f9b26a865 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");
 
+  // Reading type padding, return zero.
+  if (ByteOffset >= DL.getTypeStoreSize(C->getType()))
+    return true;
+
   // If this element is zero or undefined, we can just return since *CurPtr is
   // zero initialized.
   if (isa<ConstantAggregateZero>(C) || isa<UndefValue>(C))


Regression tests:
file: llvm/test/Transforms/InstSimplify/ConstProp/loads.ll
commands: opt < %s -passes=instsimplify -S
tests: test_name: <module>
test_body: @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() {
  %v = load i8, ptr getelementptr (i8, ptr @i40_struct, i64 6)
  ret i8 %v
}