diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -451,6 +451,26 @@ StrippedPtr != StorePtr) continue; + // If the load and the store have the same base and constant offsets and + // the ranges don't overlap, ignore the store. This is a simple form of + // alias analysis. + APInt LoadOffset(DL.getTypeSizeInBits(Ptr->getType()), 0); + APInt StoreOffset(DL.getTypeSizeInBits( + SI->getPointerOperand()->getType()), 0); + Value *LoadBase = Ptr->stripAndAccumulateConstantOffsets( + DL, LoadOffset, /* AllowNonInbounds */ false); + Value *StoreBase = StorePtr->stripAndAccumulateConstantOffsets( + DL, StoreOffset, /* AllowNonInbounds */ false); + auto StoreAccessSize = LocationSize::precise( + DL.getTypeStoreSize(SI->getPointerOperand()->getType())); + ConstantRange LoadRange(LoadOffset, + LoadOffset + AccessSize.toRaw()); + ConstantRange StoreRange(StoreOffset, + StoreOffset + StoreAccessSize.toRaw()); + if (LoadBase == StoreBase && + LoadRange.intersectWith(StoreRange).isEmptySet()) + continue; + // If we have alias analysis and it says the store won't modify the loaded // value, ignore the store. if (AA && !isModSet(AA->getModRefInfo(SI, StrippedPtr, AccessSize))) diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt --- a/llvm/unittests/Analysis/CMakeLists.txt +++ b/llvm/unittests/Analysis/CMakeLists.txt @@ -20,6 +20,7 @@ GlobalsModRefTest.cpp IVDescriptorsTest.cpp LazyCallGraphTest.cpp + LoadsTest.cpp LoopInfoTest.cpp MemoryBuiltinsTest.cpp MemorySSATest.cpp diff --git a/llvm/unittests/Analysis/LoadsTest.cpp b/llvm/unittests/Analysis/LoadsTest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/Analysis/LoadsTest.cpp @@ -0,0 +1,61 @@ +//===- LoadsTest.cpp - local load analysis unit tests ---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Loads.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" + +using namespace llvm; + +static std::unique_ptr parseIR(LLVMContext &C, const char *IR) { + SMDiagnostic Err; + std::unique_ptr Mod = parseAssemblyString(IR, Err, C); + if (!Mod) + Err.print("AnalysisTests", errs()); + return Mod; +} + +TEST(LoadsTest, FindAvailableLoadedValueSameBasePtrConstantOffsetsNullAA) { + LLVMContext C; + std::unique_ptr M = parseIR(C, + R"IR( +%class = type <{ i32, i32 }> + +define i32 @f() { +entry: + %o = alloca %class + %f1 = getelementptr inbounds %class, %class* %o, i32 0, i32 0 + store i32 42, i32* %f1 + %f2 = getelementptr inbounds %class, %class* %o, i32 0, i32 1 + store i32 43, i32* %f2 + %v = load i32, i32* %f1 + ret i32 %v +} +)IR"); + auto *GV = M->getNamedValue("f"); + ASSERT_TRUE(GV); + auto *F = dyn_cast(GV); + ASSERT_TRUE(F); + Instruction *Inst = &F->front().front(); + auto *AI = dyn_cast(Inst); + ASSERT_TRUE(AI); + Inst = &*++F->front().rbegin(); + auto *LI = dyn_cast(Inst); + ASSERT_TRUE(LI); + BasicBlock::iterator BBI(LI); + Value *Loaded = FindAvailableLoadedValue( + LI, LI->getParent(), BBI, 0, nullptr, nullptr); + ASSERT_TRUE(Loaded); + auto *CI = dyn_cast(Loaded); + ASSERT_TRUE(CI); + ASSERT_TRUE(CI->equalsInt(42)); +}