mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-24 09:29:42 +00:00
constant fold loads from memcpy's from global constants. This is important
because clang lowers nontrivial automatic struct/array inits to memcpy from a global array. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@90698 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
cb9cbc4949
commit
bc9a28dd54
@ -31,8 +31,9 @@
|
|||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/Analysis/Dominators.h"
|
|
||||||
#include "llvm/Analysis/AliasAnalysis.h"
|
#include "llvm/Analysis/AliasAnalysis.h"
|
||||||
|
#include "llvm/Analysis/ConstantFolding.h"
|
||||||
|
#include "llvm/Analysis/Dominators.h"
|
||||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||||
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
||||||
#include "llvm/Support/CFG.h"
|
#include "llvm/Support/CFG.h"
|
||||||
@ -1094,11 +1095,39 @@ static int AnalyzeLoadFromClobberingMemInst(LoadInst *L, MemIntrinsic *MI,
|
|||||||
ConstantInt *SizeCst = dyn_cast<ConstantInt>(MI->getLength());
|
ConstantInt *SizeCst = dyn_cast<ConstantInt>(MI->getLength());
|
||||||
if (SizeCst == 0) return -1;
|
if (SizeCst == 0) return -1;
|
||||||
uint64_t MemSizeInBits = SizeCst->getZExtValue()*8;
|
uint64_t MemSizeInBits = SizeCst->getZExtValue()*8;
|
||||||
|
|
||||||
|
// If this is memset, we just need to see if the offset is valid in the size
|
||||||
|
// of the memset..
|
||||||
if (MI->getIntrinsicID() == Intrinsic::memset)
|
if (MI->getIntrinsicID() == Intrinsic::memset)
|
||||||
return AnalyzeLoadFromClobberingWrite(L, MI->getDest(), MemSizeInBits, TD);
|
return AnalyzeLoadFromClobberingWrite(L, MI->getDest(), MemSizeInBits, TD);
|
||||||
|
|
||||||
// Unhandled memcpy/memmove.
|
// If we have a memcpy/memmove, the only case we can handle is if this is a
|
||||||
|
// copy from constant memory. In that case, we can read directly from the
|
||||||
|
// constant memory.
|
||||||
|
MemTransferInst *MTI = cast<MemTransferInst>(MI);
|
||||||
|
|
||||||
|
Constant *Src = dyn_cast<Constant>(MTI->getSource());
|
||||||
|
if (Src == 0) return -1;
|
||||||
|
|
||||||
|
GlobalVariable *GV = dyn_cast<GlobalVariable>(Src->getUnderlyingObject());
|
||||||
|
if (GV == 0 || !GV->isConstant()) return -1;
|
||||||
|
|
||||||
|
// See if the access is within the bounds of the transfer.
|
||||||
|
int Offset =
|
||||||
|
AnalyzeLoadFromClobberingWrite(L, MI->getDest(), MemSizeInBits, TD);
|
||||||
|
if (Offset == -1)
|
||||||
|
return Offset;
|
||||||
|
|
||||||
|
// Otherwise, see if we can constant fold a load from the constant with the
|
||||||
|
// offset applied as appropriate.
|
||||||
|
Src = ConstantExpr::getBitCast(Src,
|
||||||
|
llvm::Type::getInt8PtrTy(Src->getContext()));
|
||||||
|
Constant *OffsetCst =
|
||||||
|
ConstantInt::get(Type::getInt64Ty(Src->getContext()), (unsigned)Offset);
|
||||||
|
Src = ConstantExpr::getGetElementPtr(Src, &OffsetCst, 1);
|
||||||
|
Src = ConstantExpr::getBitCast(Src, PointerType::getUnqual(L->getType()));
|
||||||
|
if (ConstantFoldLoadFromConstPtr(Src, &TD))
|
||||||
|
return Offset;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1182,9 +1211,20 @@ static Value *GetMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset,
|
|||||||
|
|
||||||
return CoerceAvailableValueToLoadType(Val, LoadTy, InsertPt, TD);
|
return CoerceAvailableValueToLoadType(Val, LoadTy, InsertPt, TD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ABORT;
|
// Otherwise, this is a memcpy/memmove from a constant global.
|
||||||
return 0;
|
MemTransferInst *MTI = cast<MemTransferInst>(SrcInst);
|
||||||
|
Constant *Src = cast<Constant>(MTI->getSource());
|
||||||
|
|
||||||
|
// Otherwise, see if we can constant fold a load from the constant with the
|
||||||
|
// offset applied as appropriate.
|
||||||
|
Src = ConstantExpr::getBitCast(Src,
|
||||||
|
llvm::Type::getInt8PtrTy(Src->getContext()));
|
||||||
|
Constant *OffsetCst =
|
||||||
|
ConstantInt::get(Type::getInt64Ty(Src->getContext()), (unsigned)Offset);
|
||||||
|
Src = ConstantExpr::getGetElementPtr(Src, &OffsetCst, 1);
|
||||||
|
Src = ConstantExpr::getBitCast(Src, PointerType::getUnqual(LoadTy));
|
||||||
|
return ConstantFoldLoadFromConstPtr(Src, &TD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,8 +187,24 @@ Cont:
|
|||||||
; CHECK: ret i16 %A
|
; CHECK: ret i16 %A
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GCst = constant {i32, float, i32 } { i32 42, float 14., i32 97 }
|
||||||
|
|
||||||
|
; memset -> float forwarding.
|
||||||
|
define float @memcpy_to_float_local(float* %A) nounwind ssp {
|
||||||
|
entry:
|
||||||
|
%conv = bitcast float* %A to i8* ; <i8*> [#uses=1]
|
||||||
|
tail call void @llvm.memcpy.i64(i8* %conv, i8* bitcast ({i32, float, i32 }* @GCst to i8*), i64 12, i32 1)
|
||||||
|
%arrayidx = getelementptr inbounds float* %A, i64 1 ; <float*> [#uses=1]
|
||||||
|
%tmp2 = load float* %arrayidx ; <float> [#uses=1]
|
||||||
|
ret float %tmp2
|
||||||
|
; CHECK: @memcpy_to_float_local
|
||||||
|
; CHECK-NOT: load
|
||||||
|
; CHECK: ret float 1.400000e+01
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
declare void @llvm.memset.i64(i8* nocapture, i8, i64, i32) nounwind
|
declare void @llvm.memset.i64(i8* nocapture, i8, i64, i32) nounwind
|
||||||
|
declare void @llvm.memcpy.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user