Index: lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCasts.cpp +++ lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1083,6 +1083,18 @@ uint32_t SrcBitsKept = SrcTy->getScalarSizeInBits()-BitsToClear; uint32_t DestBitSize = DestTy->getScalarSizeInBits(); + // Preserve any debug values referring to the zext by emitting + // a framgent expression. + insertReplacementDbgValues( + *Src, *Res, *std::next(CI.getIterator()), + [&](DbgInfoIntrinsic &OldDII) -> DIExpression * { + auto DIE = DIExpression::createFragmentExpression( + OldDII.getExpression(), SrcBitsKept, DestBitSize); + if (DIE == None) + return nullptr; + return DIE.getValue(); + }); + // If the high bits are already filled with zeros, just replace this // cast with the result. if (MaskedValueIsZero(Res, Index: test/Transforms/InstCombine/debuginfo-trunc-and-zext.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/debuginfo-trunc-and-zext.ll @@ -0,0 +1,28 @@ +; RUN: opt -debugify -instcombine -S < %s | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32" + +; Test that when merging zext we preserve +; the debug information via fragments in vector +; and non-vector cases + +define <2 x i64> @test-vector(<2 x i64> %A) { + %trunc = trunc <2 x i64> %A to <2 x i32> + %and = and <2 x i32> %trunc, + %zext = zext <2 x i32> %and to <2 x i64> + ret <2 x i64> %zext +} + +; CHECK-LABEL: define <2 x i64> @test-non-vector +; CHECK: call void @llvm.dbg.value{{.*}} +; CHECK: call void @llvm.dbg.value({{.*}}, metadata !DIExpression(DW_OP_LLVM_fragment, {{.*}} + +define i32 @test-non-vector(i32 %x, i32 %y) { + %A = trunc i32 %x to i8 + %B = trunc i32 %y to i8 + %C = mul i8 %A, %B + %D = zext i8 %C to i32 + ret i32 %D +} + +; todo: add checks for non-vector