From f68b0e36997322eeda8fd199ea80deb1b49c5410 Mon Sep 17 00:00:00 2001 From: Antonio Frighetto Date: Wed, 4 Dec 2024 10:15:11 +0100 Subject: [PATCH] [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. --- .../AggressiveInstCombine.cpp | 3 +- .../AggressiveInstCombine/AArch64/or-load.ll | 20 +++---- .../AggressiveInstCombine/X86/or-load.ll | 52 +++++++++++++++---- 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp index b5b561797f75ab..45ee2d472a11b9 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(), diff --git a/llvm/test/Transforms/AggressiveInstCombine/AArch64/or-load.ll b/llvm/test/Transforms/AggressiveInstCombine/AArch64/or-load.ll index 1400ee7f703cab..10c4c9b0ca4c99 100644 --- a/llvm/test/Transforms/AggressiveInstCombine/AArch64/or-load.ll +++ b/llvm/test/Transforms/AggressiveInstCombine/AArch64/or-load.ll @@ -1121,19 +1121,19 @@ entry: define i32 @loadCombine_4consecutive_metadata(ptr %p, ptr %pstr) { ; LE-LABEL: @loadCombine_4consecutive_metadata( -; LE-NEXT: [[L1:%.*]] = load i32, ptr [[P:%.*]], align 1, !alias.scope !0 -; LE-NEXT: store i32 25, ptr [[PSTR:%.*]], align 4, !noalias !0 +; LE-NEXT: [[L1:%.*]] = load i32, ptr [[P:%.*]], align 1, !alias.scope [[META0:![0-9]+]] +; LE-NEXT: store i32 25, ptr [[PSTR:%.*]], align 4, !noalias [[META0]] ; LE-NEXT: ret i32 [[L1]] ; ; BE-LABEL: @loadCombine_4consecutive_metadata( ; BE-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1 ; BE-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2 ; BE-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3 -; BE-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1, !alias.scope !0 -; BE-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1, !alias.scope !0 -; BE-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1, !alias.scope !0 -; BE-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1, !alias.scope !0 -; BE-NEXT: store i32 25, ptr [[PSTR:%.*]], align 4, !noalias !0 +; BE-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1, !alias.scope [[META0:![0-9]+]] +; BE-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1, !alias.scope [[META0]] +; BE-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1, !alias.scope [[META0]] +; BE-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1, !alias.scope [[META0]] +; BE-NEXT: store i32 25, ptr [[PSTR:%.*]], align 4, !noalias [[META0]] ; BE-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 ; BE-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 ; BE-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 @@ -1869,7 +1869,7 @@ define i32 @loadCombine_4consecutive_badinsert2(ptr %p) { define i32 @loadCombine_4consecutive_badinsert3(ptr %p) { ; LE-LABEL: @loadCombine_4consecutive_badinsert3( -; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1 +; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 ; LE-NEXT: [[L1:%.*]] = load i32, ptr [[TMP1]], align 1 ; LE-NEXT: ret i32 [[L1]] ; @@ -2088,7 +2088,7 @@ define i32 @loadCombine_4consecutive_badinsert6(ptr %p) { define void @nested_gep(ptr %p, ptr %dest) { ; LE-LABEL: @nested_gep( -; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 68 +; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 68 ; LE-NEXT: [[LD2:%.*]] = load i64, ptr [[TMP1]], align 4 ; LE-NEXT: [[TRUNC:%.*]] = trunc i64 [[LD2]] to i32 ; LE-NEXT: store i32 [[TRUNC]], ptr [[DEST:%.*]], align 4 @@ -2128,7 +2128,7 @@ define void @nested_gep(ptr %p, ptr %dest) { define void @bitcast_gep(ptr %p, ptr %dest) { ; LE-LABEL: @bitcast_gep( -; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 68 +; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 68 ; LE-NEXT: [[LD2:%.*]] = load i64, ptr [[TMP1]], align 4 ; LE-NEXT: [[TRUNC:%.*]] = trunc i64 [[LD2]] to i32 ; LE-NEXT: store i32 [[TRUNC]], ptr [[DEST:%.*]], align 4 diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/or-load.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/or-load.ll index 0aa6f9ecdf884a..1b53c8f71222b7 100644 --- a/llvm/test/Transforms/AggressiveInstCombine/X86/or-load.ll +++ b/llvm/test/Transforms/AggressiveInstCombine/X86/or-load.ll @@ -1205,19 +1205,19 @@ entry: define i32 @loadCombine_4consecutive_metadata(ptr %p, ptr %pstr) { ; LE-LABEL: @loadCombine_4consecutive_metadata( -; LE-NEXT: [[L1:%.*]] = load i32, ptr [[P:%.*]], align 1, !alias.scope !0 -; LE-NEXT: store i32 25, ptr [[PSTR:%.*]], align 4, !noalias !0 +; LE-NEXT: [[L1:%.*]] = load i32, ptr [[P:%.*]], align 1, !alias.scope [[META0:![0-9]+]] +; LE-NEXT: store i32 25, ptr [[PSTR:%.*]], align 4, !noalias [[META0]] ; LE-NEXT: ret i32 [[L1]] ; ; BE-LABEL: @loadCombine_4consecutive_metadata( ; BE-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1 ; BE-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2 ; BE-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3 -; BE-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1, !alias.scope !0 -; BE-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1, !alias.scope !0 -; BE-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1, !alias.scope !0 -; BE-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1, !alias.scope !0 -; BE-NEXT: store i32 25, ptr [[PSTR:%.*]], align 4, !noalias !0 +; BE-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1, !alias.scope [[META0:![0-9]+]] +; BE-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1, !alias.scope [[META0]] +; BE-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1, !alias.scope [[META0]] +; BE-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1, !alias.scope [[META0]] +; BE-NEXT: store i32 25, ptr [[PSTR:%.*]], align 4, !noalias [[META0]] ; BE-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 ; BE-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 ; BE-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 @@ -2005,7 +2005,7 @@ define i32 @loadCombine_4consecutive_badinsert2(ptr %p) { define i32 @loadCombine_4consecutive_badinsert3(ptr %p) { ; LE-LABEL: @loadCombine_4consecutive_badinsert3( -; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1 +; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 ; LE-NEXT: [[L1:%.*]] = load i32, ptr [[TMP1]], align 1 ; LE-NEXT: ret i32 [[L1]] ; @@ -2306,7 +2306,7 @@ define i64 @loadCombine_nonConstShift2(ptr %arg, i8 %b) { define void @nested_gep(ptr %p, ptr %dest) { ; LE-LABEL: @nested_gep( -; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 68 +; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 68 ; LE-NEXT: [[LD2:%.*]] = load i64, ptr [[TMP1]], align 4 ; LE-NEXT: [[TRUNC:%.*]] = trunc i64 [[LD2]] to i32 ; LE-NEXT: store i32 [[TRUNC]], ptr [[DEST:%.*]], align 4 @@ -2346,7 +2346,7 @@ define void @nested_gep(ptr %p, ptr %dest) { define void @bitcast_gep(ptr %p, ptr %dest) { ; LE-LABEL: @bitcast_gep( -; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 68 +; LE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 68 ; LE-NEXT: [[LD2:%.*]] = load i64, ptr [[TMP1]], align 4 ; LE-NEXT: [[TRUNC:%.*]] = trunc i64 [[LD2]] to i32 ; LE-NEXT: store i32 [[TRUNC]], ptr [[DEST:%.*]], align 4 @@ -2382,3 +2382,35 @@ define void @bitcast_gep(ptr %p, ptr %dest) { store i32 %trunc, ptr %dest, align 4 ret void } + +define i32 @loadcombine_consecutive_idx_64(ptr %data) { +; LE-LABEL: @loadcombine_consecutive_idx_64( +; LE-NEXT: entry: +; LE-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[DATA:%.*]], i64 2149675576 +; LE-NEXT: [[VAL_2:%.*]] = load i16, ptr [[TMP0]], align 1 +; LE-NEXT: [[TMP1:%.*]] = zext i16 [[VAL_2]] to i32 +; LE-NEXT: ret i32 [[TMP1]] +; +; BE-LABEL: @loadcombine_consecutive_idx_64( +; BE-NEXT: entry: +; BE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[DATA:%.*]], i64 2149675577 +; BE-NEXT: [[VAL:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; BE-NEXT: [[CONV:%.*]] = zext i8 [[VAL]] to i32 +; BE-NEXT: [[ARRAYIDX_2:%.*]] = getelementptr inbounds nuw i8, ptr [[DATA]], i64 2149675576 +; BE-NEXT: [[VAL_2:%.*]] = load i8, ptr [[ARRAYIDX_2]], align 1 +; BE-NEXT: [[CONV_2:%.*]] = zext i8 [[VAL_2]] to i32 +; BE-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[CONV]], 8 +; BE-NEXT: [[OR:%.*]] = or disjoint i32 [[SHL]], [[CONV_2]] +; BE-NEXT: ret i32 [[OR]] +; +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 +}