Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -76,27 +76,6 @@ return Ty; } -/// Given an aggregate type which ultimately holds a single scalar element, -/// like {{{type}}} or [1 x type], return type. -static Type *reduceToSingleValueType(Type *T) { - while (!T->isSingleValueType()) { - if (StructType *STy = dyn_cast(T)) { - if (STy->getNumElements() == 1) - T = STy->getElementType(0); - else - break; - } else if (ArrayType *ATy = dyn_cast(T)) { - if (ATy->getNumElements() == 1) - T = ATy->getElementType(); - else - break; - } else - break; - } - - return T; -} - /// Return a constant boolean vector that has true elements in all positions /// where the input constant data vector has an element with the sign bit set. static Constant *getNegativeIsTrueBoolVec(ConstantDataVector *V) { @@ -222,41 +201,19 @@ Type *NewSrcPtrTy = PointerType::get(IntType, SrcAddrSp); Type *NewDstPtrTy = PointerType::get(IntType, DstAddrSp); - // Memcpy forces the use of i8* for the source and destination. That means - // that if you're using memcpy to move one double around, you'll get a cast - // from double* to i8*. We'd much rather use a double load+store rather than - // an i64 load+store, here because this improves the odds that the source or - // dest address will be promotable. See if we can find a better type than the - // integer datatype. - Value *StrippedDest = MI->getArgOperand(0)->stripPointerCasts(); + // If the memcpy has metadata describing the members, see if we can get the + // TBAA tag describing our copy. MDNode *CopyMD = nullptr; - if (StrippedDest != MI->getArgOperand(0)) { - Type *SrcETy = cast(StrippedDest->getType()) - ->getElementType(); - if (SrcETy->isSized() && DL.getTypeStoreSize(SrcETy) == Size) { - // The SrcETy might be something like {{{double}}} or [1 x double]. Rip - // down through these levels if so. - SrcETy = reduceToSingleValueType(SrcETy); - - if (SrcETy->isSingleValueType()) { - NewSrcPtrTy = PointerType::get(SrcETy, SrcAddrSp); - NewDstPtrTy = PointerType::get(SrcETy, DstAddrSp); - - // If the memcpy has metadata describing the members, see if we can - // get the TBAA tag describing our copy. - if (MDNode *M = MI->getMetadata(LLVMContext::MD_tbaa_struct)) { - if (M->getNumOperands() == 3 && M->getOperand(0) && - mdconst::hasa(M->getOperand(0)) && - mdconst::extract(M->getOperand(0))->isNullValue() && - M->getOperand(1) && - mdconst::hasa(M->getOperand(1)) && - mdconst::extract(M->getOperand(1))->getValue() == - Size && - M->getOperand(2) && isa(M->getOperand(2))) - CopyMD = cast(M->getOperand(2)); - } - } - } + if (MDNode *M = MI->getMetadata(LLVMContext::MD_tbaa_struct)) { + if (M->getNumOperands() == 3 && M->getOperand(0) && + mdconst::hasa(M->getOperand(0)) && + mdconst::extract(M->getOperand(0))->isNullValue() && + M->getOperand(1) && + mdconst::hasa(M->getOperand(1)) && + mdconst::extract(M->getOperand(1))->getValue() == + Size && + M->getOperand(2) && isa(M->getOperand(2))) + CopyMD = cast(M->getOperand(2)); } // If the memcpy/memmove provides better alignment info than we can Index: llvm/trunk/test/Transforms/InstCombine/memcpy-to-load.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/memcpy-to-load.ll +++ llvm/trunk/test/Transforms/InstCombine/memcpy-to-load.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -instcombine -S | grep "load double" +; RUN: opt < %s -instcombine -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i686-apple-darwin8" @@ -10,4 +10,8 @@ ret void } +; Make sure that the memcpy has been replace with a load/store of i64 +; CHECK: [[TMP:%[0-9]+]] = load i64 +; CHECK: store i64 [[TMP]] + declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind Index: llvm/trunk/test/Transforms/InstCombine/pr31990_wrong_memcpy.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/pr31990_wrong_memcpy.ll +++ llvm/trunk/test/Transforms/InstCombine/pr31990_wrong_memcpy.ll @@ -0,0 +1,26 @@ +; RUN: opt -S -instcombine %s -o - | FileCheck %s + +; Regression test of PR31990. A memcpy of one byte, copying 0xff, was +; replaced with a single store of an i4 0xf. + +@g = constant i8 -1 + +define void @foo() { +entry: + %0 = alloca i8 + %1 = bitcast i8* %0 to i4* + call void @bar(i4* %1) + %2 = bitcast i4* %1 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %2, i8* @g, i32 1, i32 1, i1 false) + call void @gaz(i8* %2) + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, + i8* nocapture readonly, i32, i32, i1) +declare void @bar(i4*) +declare void @gaz(i8*) + +; The mempcy should be simplified to a single store of an i8, not i4 +; CHECK: store i8 -1 +; CHECK-NOT: store i4 -1