From f2e7bb5d2f983472df351572ffea52f7b0b93b25 Mon Sep 17 00:00:00 2001 From: Artur Pilipenko Date: Thu, 25 Jun 2015 12:18:43 +0000 Subject: [PATCH] Take alignment into account in isSafeToLoadUnconditionally Reviewed By: hfinkel Differential Revision: http://reviews.llvm.org/D10475 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240636 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/Loads.cpp | 26 ++++++++++++++++++++------ test/Transforms/InstCombine/select.ll | 17 +++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/lib/Analysis/Loads.cpp b/lib/Analysis/Loads.cpp index aed3b04ebca..624c5a18d67 100644 --- a/lib/Analysis/Loads.cpp +++ b/lib/Analysis/Loads.cpp @@ -65,6 +65,12 @@ static bool AreEquivalentAddressValues(const Value *A, const Value *B) { bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, unsigned Align) { const DataLayout &DL = ScanFrom->getModule()->getDataLayout(); + + // Zero alignment means that the load has the ABI alignment for the target + if (Align == 0) + Align = DL.getABITypeAlignment(V->getType()->getPointerElementType()); + assert(isPowerOf2_32(Align)); + int64_t ByteOffset = 0; Value *Base = V; Base = GetPointerBaseWithConstantOffset(V, ByteOffset, DL); @@ -102,7 +108,7 @@ bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, if (Align <= BaseAlign) { // Check if the load is within the bounds of the underlying object. if (ByteOffset + LoadSize <= DL.getTypeAllocSize(BaseType) && - (Align == 0 || (ByteOffset % Align) == 0)) + ((ByteOffset % Align) == 0)) return true; } } @@ -128,20 +134,28 @@ bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, return false; Value *AccessedPtr; - if (LoadInst *LI = dyn_cast(BBI)) + unsigned AccessedAlign; + if (LoadInst *LI = dyn_cast(BBI)) { AccessedPtr = LI->getPointerOperand(); - else if (StoreInst *SI = dyn_cast(BBI)) + AccessedAlign = LI->getAlignment(); + } else if (StoreInst *SI = dyn_cast(BBI)) { AccessedPtr = SI->getPointerOperand(); - else + AccessedAlign = SI->getAlignment(); + } else + continue; + + Type *AccessedTy = AccessedPtr->getType()->getPointerElementType(); + if (AccessedAlign == 0) + AccessedAlign = DL.getABITypeAlignment(AccessedTy); + if (AccessedAlign < Align) continue; // Handle trivial cases. if (AccessedPtr == V) return true; - auto *AccessedTy = cast(AccessedPtr->getType()); if (AreEquivalentAddressValues(AccessedPtr->stripPointerCasts(), V) && - LoadSize <= DL.getTypeStoreSize(AccessedTy->getElementType())) + LoadSize <= DL.getTypeStoreSize(AccessedTy)) return true; } return false; diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index 8be247228b8..fdf1199a66f 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -1296,6 +1296,23 @@ entry: ret i32 %v } +define i32 @test78_neg(i1 %flag, i32* %x, i32* %y, i32* %z) { +; The same as @test78 but we can't speculate the load because it can trap +; if under-aligned. +; CHECK-LABEL: @test78_neg( +; CHECK: %p = select i1 %flag, i32* %x, i32* %y +; CHECK-NEXT: %v = load i32, i32* %p, align 16 +; CHECK-NEXT: ret i32 %v +entry: + store i32 0, i32* %x + store i32 0, i32* %y + ; Block forwarding by storing to %z which could alias either %x or %y. + store i32 42, i32* %z + %p = select i1 %flag, i32* %x, i32* %y + %v = load i32, i32* %p, align 16 + ret i32 %v +} + define float @test79(i1 %flag, float* %x, i32* %y, i32* %z) { ; Test that we can speculate the loads around the select even when we can't ; fold the load completely away. -- 2.34.1