mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-16 11:30:51 +00:00
fix infinite loop in instcombine with more than 4GB memcpy
- memcpy size is wrongly truncated into 32-bit and treat 8GB memcpy is 0-sized memcpy - as 0-sized memcpy/memset is already removed before SimplifyMemTransfer and SimplifyMemSet in visitCallInst, replace 0 checking with assertions. - replace getZExtValue() with getLimitedValue() according to Eli Friedman git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161923 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c2de3ddb23
commit
9441ad0b6e
@ -51,8 +51,8 @@ Instruction *InstCombiner::SimplifyMemTransfer(MemIntrinsic *MI) {
|
|||||||
// if the size is something we can handle with a single primitive load/store.
|
// if the size is something we can handle with a single primitive load/store.
|
||||||
// A single load+store correctly handles overlapping memory in the memmove
|
// A single load+store correctly handles overlapping memory in the memmove
|
||||||
// case.
|
// case.
|
||||||
unsigned Size = MemOpLength->getZExtValue();
|
uint64_t Size = MemOpLength->getLimitedValue();
|
||||||
if (Size == 0) return MI; // Delete this mem transfer.
|
assert(Size && "0-sized memory transfering should be removed already.");
|
||||||
|
|
||||||
if (Size > 8 || (Size&(Size-1)))
|
if (Size > 8 || (Size&(Size-1)))
|
||||||
return 0; // If not 1/2/4/8 bytes, exit.
|
return 0; // If not 1/2/4/8 bytes, exit.
|
||||||
@ -133,11 +133,9 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) {
|
|||||||
ConstantInt *FillC = dyn_cast<ConstantInt>(MI->getValue());
|
ConstantInt *FillC = dyn_cast<ConstantInt>(MI->getValue());
|
||||||
if (!LenC || !FillC || !FillC->getType()->isIntegerTy(8))
|
if (!LenC || !FillC || !FillC->getType()->isIntegerTy(8))
|
||||||
return 0;
|
return 0;
|
||||||
uint64_t Len = LenC->getZExtValue();
|
uint64_t Len = LenC->getLimitedValue();
|
||||||
Alignment = MI->getAlignment();
|
Alignment = MI->getAlignment();
|
||||||
|
assert(Len && "0-sized memory setting should be removed already.");
|
||||||
// If the length is zero, this is a no-op
|
|
||||||
if (Len == 0) return MI; // memset(d,c,0,a) -> noop
|
|
||||||
|
|
||||||
// memset(s,c,n) -> store s, c (for n=1,2,4,8)
|
// memset(s,c,n) -> store s, c (for n=1,2,4,8)
|
||||||
if (Len <= 8 && isPowerOf2_32((uint32_t)Len)) {
|
if (Len <= 8 && isPowerOf2_32((uint32_t)Len)) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
; RUN: opt < %s -instcombine -S | FileCheck %s
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||||
|
|
||||||
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
|
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
|
||||||
|
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
|
||||||
|
|
||||||
define void @test1(i8* %a) {
|
define void @test1(i8* %a) {
|
||||||
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %a, i32 100, i32 1, i1 false)
|
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %a, i32 100, i32 1, i1 false)
|
||||||
@ -17,3 +18,10 @@ define void @test2(i8* %a) {
|
|||||||
; CHECK: define void @test2
|
; CHECK: define void @test2
|
||||||
; CHECK-NEXT: call void @llvm.memcpy
|
; CHECK-NEXT: call void @llvm.memcpy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define void @test3(i8* %d, i8* %s) {
|
||||||
|
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %d, i8* %s, i64 17179869184, i32 4, i1 false)
|
||||||
|
ret void
|
||||||
|
; CHECK: define void @test3
|
||||||
|
; CHECK-NEXT: call void @llvm.memcpy
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user