Index: lib/Transforms/Scalar/GVN.cpp =================================================================== --- lib/Transforms/Scalar/GVN.cpp +++ lib/Transforms/Scalar/GVN.cpp @@ -882,6 +882,25 @@ } } + // To remove LI in following case: + // load a0, Addr1 <- LItoSI + // store a0, Addr2 <- DepSI + // load a0, Addr1 <- LI + // If LI and LItoSI load from same address, the value load from LItoSI + // could propagate to LI even if Addr1 alias to Addr2. + if (StoreInst *DepSI = dyn_cast(DepInfo.getInst())) { + if (Address && !LI->isAtomic() && !LI->isVolatile()) { + if (LoadInst *LItoSI = dyn_cast(DepSI->getValueOperand())) { + if (!LItoSI->isAtomic() && !LItoSI->isVolatile() && + (LItoSI->getPointerOperand() == LI->getPointerOperand() && + (LItoSI != LI))) { + Res = AvailableValue::get(DepSI->getValueOperand(), 0); + return true; + } + } + } + } + // Check to see if we have something like this: // load i32* P // load i8* (P+1) Index: test/Transforms/GVN/remove-redundant-load.ll =================================================================== --- /dev/null +++ test/Transforms/GVN/remove-redundant-load.ll @@ -0,0 +1,35 @@ +; RUN: opt -S -memdep -gvn -basicaa < %s | FileCheck %s +; CHECK-LABEL: @test( +; CHECK: %1 = load i32, i32* %Addr1 +; CHECK: store i32 %1, i32* %Addr2 +; CHECK: ret i32 %1 +define i32 @test(i32* %Addr1, i32* %Addr2) { + %1 = load i32, i32* %Addr1 + store i32 %1, i32* %Addr2 + %2 = load i32, i32* %Addr1 + ret i32 %2 +} + +; CHECK-LABEL: @test_atomic( +; CHECK: %1 = load atomic i32, i32* %Addr1 unordered, align 4 +; CHECK: store i32 %1, i32* %Addr2 +; CHECK: %2 = load i32, i32* %Addr1 +; CHECK: ret i32 %2 +define i32 @test_atomic(i32* %Addr1, i32* %Addr2) { + %1 = load atomic i32, i32* %Addr1 unordered, align 4 + store i32 %1, i32* %Addr2 + %2 = load i32, i32* %Addr1 + ret i32 %2 +} + +; CHECK-LABEL: @test_volatile( +; CHECK: %1 = load volatile i32, i32* %Addr +; CHECK: store i32 %1, i32* %Addr2 +; CHECK: %2 = load i32, i32* %Addr1 +; CHECK: ret i32 %2 +define i32 @test_volatile(i32* %Addr1, i32* %Addr2) { + %1 = load volatile i32, i32* %Addr1 + store i32 %1, i32* %Addr2 + %2 = load i32, i32* %Addr1 + ret i32 %2 +}