From 0b875a0c29d5f97c8a5e09404e0de79c4fe49858 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Wed, 25 Jul 2012 09:14:54 +0000 Subject: [PATCH] When folding a load from a global constant, if the load started in the middle of an array element (rather than at the beginning of the element) and extended into the next element, then the load from the second element was being handled wrong due to incorrect updating of the notion of which byte to load next. This fixes PR13442. Thanks to Chris Smowton for reporting the problem, analyzing it and providing a fix. llvm-svn: 160711 --- llvm/lib/Analysis/ConstantFolding.cpp | 13 ++++++++----- .../Transforms/InstCombine/2012-07-25-LoadPart.ll | 12 ++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 llvm/test/Transforms/InstCombine/2012-07-25-LoadPart.ll diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 7ced848aa1b6..a7c9e550432d 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -358,17 +358,20 @@ static bool ReadDataFromGlobal(Constant *C, uint64_t ByteOffset, NumElts = AT->getNumElements(); else NumElts = cast(C->getType())->getNumElements(); - + for (; Index != NumElts; ++Index) { if (!ReadDataFromGlobal(C->getAggregateElement(Index), Offset, CurPtr, BytesLeft, TD)) return false; - if (EltSize >= BytesLeft) + + uint64_t BytesWritten = EltSize - Offset; + assert(BytesWritten <= EltSize && "Not indexing into this element?"); + if (BytesWritten >= BytesLeft) return true; - + Offset = 0; - BytesLeft -= EltSize; - CurPtr += EltSize; + BytesLeft -= BytesWritten; + CurPtr += BytesWritten; } return true; } diff --git a/llvm/test/Transforms/InstCombine/2012-07-25-LoadPart.ll b/llvm/test/Transforms/InstCombine/2012-07-25-LoadPart.ll new file mode 100644 index 000000000000..01dce7c7e43c --- /dev/null +++ b/llvm/test/Transforms/InstCombine/2012-07-25-LoadPart.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +; PR13442 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" + +@test = constant [4 x i32] [i32 1, i32 2, i32 3, i32 4] + +define i64 @foo() { + %ret = load i64* bitcast (i8* getelementptr (i8* bitcast ([4 x i32]* @test to i8*), i64 2) to i64*) + ret i64 %ret + ; CHECK: ret i64 844424930263040 +}