Bug type: miscompilation
Component: AggressiveInstCombine
Bug location: llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp: foldConsecutiveLoads
Issue title: Invalid LLVM IR code generated on x86-64 with a very simple sample (crash the generated executable code)
Labels: miscompilation
llvm:transforms
Reported by: dje64240

Below is a very simple program that's loading 16 bits table value into a 32 bits variable from a 8 bits table.
On **x86-64** with **-O2** or **-O3** flags, this program works fine with LLVM 16.0.0 and below, but since LLVM 17.0.0, the LLVM IR and the generated assembly code are using a wrong calculated offset on the table (doesn't occurs on LLVM armv8 whatever the version).
As you can see below, the offset in the table which is supposed to be **2149675576** (**0x80217238**) has its 32 upper bits inverted for **-2145291720** (**0xFFFFFFFF80217238**).

```c

#include <stdint.h>

// Load 16 bits into 32 bits value from data offset 0x80217238

uint32_t Test(const uint8_t* data)
{        
    uint32_t a, b, c;    
	b = 0xFFFF8022 << 16;
    b += 0xFFFFE808;    
    a = data[b + 0xFFFF8A31];
    c = data[b + 0xFFFF8A30];
    c &= ~0x0000FF00;
    c |= ((a << 8) | (a >> 24)) & 0x0000FF00;
	return c;
}

```

LLVM IR with LLVM 16.0.0 (from Compiler Explorer)
```ll
define dso_local noundef i32 @Test(unsigned char const*)(ptr nocapture noundef readonly %data) local_unnamed_addr {
entry:
  %arrayidx4 = getelementptr inbounds i8, ptr %data, i64 2149675576
  %0 = load i16, ptr %arrayidx4, align 1
  %1 = zext i16 %0 to i32
  ret i32 %1
}

declare void @llvm.dbg.value(metadata, metadata, metadata) #1
```
LLVM IR with LLVM 19.1.0 and trunk (from Compiler Explorer)
```ll
define dso_local noundef range(i32 0, 65536) i32 @Test(unsigned char const*)(ptr nocapture noundef readonly %data) local_unnamed_addr {
entry:
  %0 = getelementptr i8, ptr %data, i64 -2145291720
  %1 = load i16, ptr %0, align 1
  %2 = zext i16 %1 to i32
  ret i32 %2
}
```







Comments: author: topperc
body: opt-bisect suggests AggressiveInstCominer. There were two separate loads that got merged. The resulting GEP had an index of `i32 -2145291720` with trunk and `i64 2149675576` with clang 16. Those would be the same number if GEP zero extended indices instead of sign extending.
author: antoniofrighetto
body: Alive2: https://alive2.llvm.org/ce/z/G5CgkD.
author: AZero13
body: > opt-bisect suggests AggressiveInstCominer. There were two separate loads that got merged. The resulting GEP had an index of `i32 -2145291720` with trunk and `i64 2149675576` with clang 16. Those would be the same number if GEP zero extended indices instead of sign extending.

See my PR for 19.x 

Fix patch:
commit f68b0e36997322eeda8fd199ea80deb1b49c5410
Author: Antonio Frighetto <me@antoniofrighetto.com>
Date:   Wed Dec 4 10:15:11 2024 +0100

    [AggressiveInstCombine] Use APInt and avoid truncation when folding loads
    
    A miscompilation issue has been addressed with improved handling.
    
    Fixes: https://github.com/llvm/llvm-project/issues/118467.

diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
index b5b561797f75..45ee2d472a11 100644
--- a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
+++ b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
@@ -803,8 +803,7 @@ static bool foldConsecutiveLoads(Instruction &I, const DataLayout &DL,
     APInt Offset1(DL.getIndexTypeSizeInBits(Load1Ptr->getType()), 0);
     Load1Ptr = Load1Ptr->stripAndAccumulateConstantOffsets(
         DL, Offset1, /* AllowNonInbounds */ true);
-    Load1Ptr = Builder.CreatePtrAdd(Load1Ptr,
-                                    Builder.getInt32(Offset1.getZExtValue()));
+    Load1Ptr = Builder.CreatePtrAdd(Load1Ptr, Builder.getInt(Offset1));
   }
   // Generate wider load.
   NewLoad = Builder.CreateAlignedLoad(WiderType, Load1Ptr, LI1->getAlign(),


Regression tests:
file: llvm/test/Transforms/AggressiveInstCombine/X86/or-load.ll
commands: opt < %s -passes=aggressive-instcombine -mtriple x86_64-none-eabi -mattr=avx2 -data-layout="e-n64" -S
opt < %s -passes=aggressive-instcombine -mtriple x86_64-none-eabi -mattr=avx2 -data-layout="E-n64" -S
tests: test_name: loadcombine_consecutive_idx_64
test_body: define i32 @loadcombine_consecutive_idx_64(ptr %data) {
entry:
  %arrayidx = getelementptr inbounds nuw i8, ptr %data, i64 2149675577
  %val = load i8, ptr %arrayidx, align 1
  %conv = zext i8 %val to i32
  %arrayidx.2 = getelementptr inbounds nuw i8, ptr %data, i64 2149675576
  %val.2 = load i8, ptr %arrayidx.2, align 1
  %conv.2 = zext i8 %val.2 to i32
  %shl = shl nuw nsw i32 %conv, 8
  %or = or disjoint i32 %shl, %conv.2
  ret i32 %or
}