From a54b82a9fe512e15577ee9ec759d9684fd912762 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sat, 7 Feb 2015 19:29:02 +0000 Subject: [PATCH] ValueTracking: Make isBytewiseValue simpler and more powerful at the same time. Turns out there is a simpler way of checking that all bytes in a word are equal than binary decomposition. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228503 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ValueTracking.cpp | 28 ++++++++---------------- test/Transforms/MemCpyOpt/form-memset.ll | 15 +++++++++++++ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 91b64692eac..5ae8574ebe1 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -2121,26 +2121,16 @@ Value *llvm::isBytewiseValue(Value *V) { // Don't handle long double formats, which have strange constraints. } - // We can handle constant integers that are power of two in size and a - // multiple of 8 bits. + // We can handle constant integers that are multiple of 8 bits. if (ConstantInt *CI = dyn_cast(V)) { - unsigned Width = CI->getBitWidth(); - if (isPowerOf2_32(Width) && Width > 8) { - // We can handle this value if the recursive binary decomposition is the - // same at all levels. - APInt Val = CI->getValue(); - APInt Val2; - while (Val.getBitWidth() != 8) { - unsigned NextWidth = Val.getBitWidth()/2; - Val2 = Val.lshr(NextWidth); - Val2 = Val2.trunc(Val.getBitWidth()/2); - Val = Val.trunc(Val.getBitWidth()/2); - - // If the top/bottom halves aren't the same, reject it. - if (Val != Val2) - return nullptr; - } - return ConstantInt::get(V->getContext(), Val); + if (CI->getBitWidth() % 8 == 0) { + assert(CI->getBitWidth() > 8 && "8 bits should be handled above!"); + + // We can check that all bytes of an integer are equal by making use of a + // little trick: rotate by 8 and check if it's still the same value. + if (CI->getValue() != CI->getValue().rotl(8)) + return nullptr; + return ConstantInt::get(V->getContext(), CI->getValue().trunc(8)); } } diff --git a/test/Transforms/MemCpyOpt/form-memset.ll b/test/Transforms/MemCpyOpt/form-memset.ll index d980b7fdbd6..0a409437c9a 100644 --- a/test/Transforms/MemCpyOpt/form-memset.ll +++ b/test/Transforms/MemCpyOpt/form-memset.ll @@ -284,3 +284,18 @@ define void @test10(i8* nocapture %P) nounwind { ; CHECK-NOT: memset ; CHECK: ret void } + +; Memset followed by odd store. +define void @test11(i32* nocapture %P) nounwind ssp { +entry: + %add.ptr = getelementptr inbounds i32* %P, i64 3 + %0 = bitcast i32* %add.ptr to i8* + tail call void @llvm.memset.p0i8.i64(i8* %0, i8 1, i64 11, i32 1, i1 false) + %arrayidx = getelementptr inbounds i32* %P, i64 0 + %arrayidx.cast = bitcast i32* %arrayidx to i96* + store i96 310698676526526814092329217, i96* %arrayidx.cast, align 4 + ret void +; CHECK-LABEL: @test11( +; CHECK-NOT: store +; CHECK: call void @llvm.memset.p0i8.i64(i8* %1, i8 1, i64 23, i32 4, i1 false) +} -- 2.34.1