Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -1850,18 +1850,25 @@ bool Signed = *Signedness == DIBasicType::Signedness::Signed; - if (!Signed) { - // In the unsigned case, assume that a debugger will initialize the - // high bits to 0 and do a no-op conversion. - return Identity(DII); + if (Signed) { + // Sign extend To to FromBits + // (((To >> (ToBits - 1)) * (~0)) << ToBits) | To + SmallVector Ops({dwarf::DW_OP_dup, + dwarf::DW_OP_constu, ToBits - 1, + dwarf::DW_OP_shr, + dwarf::DW_OP_lit0, dwarf::DW_OP_not, + dwarf::DW_OP_mul, + dwarf::DW_OP_constu, ToBits, + dwarf::DW_OP_shl, + dwarf::DW_OP_or}); + return DIExpression::appendToStack(DII.getExpression(), Ops); } else { - // In the signed case, the high bits are given by sign extension, i.e: - // (To >> (ToBits - 1)) * ((2 ^ FromBits) - 1) - // Calculate the high bits and OR them together with the low bits. - SmallVector Ops({dwarf::DW_OP_dup, dwarf::DW_OP_constu, - (ToBits - 1), dwarf::DW_OP_shr, - dwarf::DW_OP_lit0, dwarf::DW_OP_not, - dwarf::DW_OP_mul, dwarf::DW_OP_or}); + // Zero extend To to FromBits i.e. make sure that any bits in the range + // [FromBits-1:ToBits] are cleared. + // (To & ((1 << ToBits) - 1)) + SmallVector Ops({dwarf::DW_OP_constu, + (1ULL << ToBits) - 1, + dwarf::DW_OP_and}); return DIExpression::appendToStack(DII.getExpression(), Ops); } }; Index: test/Transforms/InstCombine/cast-set-preserve-signed-dbg-val.ll =================================================================== --- test/Transforms/InstCombine/cast-set-preserve-signed-dbg-val.ll +++ test/Transforms/InstCombine/cast-set-preserve-signed-dbg-val.ll @@ -14,7 +14,7 @@ ; ; The high 16 bits of the original 'and' require sign-extending the new 16-bit and: ; CHECK-NEXT: call void @llvm.dbg.value(metadata i16 [[and]], metadata [[C:![0-9]+]], - ; CHECK-SAME: metadata !DIExpression(DW_OP_dup, DW_OP_constu, 15, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, DW_OP_stack_value) + ; CHECK-SAME: metadata !DIExpression(DW_OP_dup, DW_OP_constu, 15, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_constu, 16, DW_OP_shl, DW_OP_or, DW_OP_stack_value) %D = trunc i32 %C to i16, !dbg !42 call void @llvm.dbg.value(metadata i16 %D, metadata !38, metadata !DIExpression()), !dbg !42 Index: unittests/Transforms/Utils/LocalTest.cpp =================================================================== --- unittests/Transforms/Utils/LocalTest.cpp +++ unittests/Transforms/Utils/LocalTest.cpp @@ -790,29 +790,34 @@ // Case 1: The original expr is empty, so no deref is needed. EXPECT_TRUE(hasADbgVal({DW_OP_dup, DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, - DW_OP_not, DW_OP_mul, DW_OP_or, DW_OP_stack_value})); + DW_OP_not, DW_OP_mul, DW_OP_constu, 32, DW_OP_shl, + DW_OP_or, DW_OP_stack_value})); // Case 2: Perform an address calculation with the original expr, deref it, // then sign-extend the result. EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_dup, DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, DW_OP_not, - DW_OP_mul, DW_OP_or, DW_OP_stack_value})); + DW_OP_mul, DW_OP_constu, 32, DW_OP_shl, + DW_OP_or, DW_OP_stack_value})); // Case 3: Insert the sign-extension logic before the DW_OP_stack_value. EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_dup, DW_OP_constu, 31, - DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, + DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, + DW_OP_constu, 32, DW_OP_shl, DW_OP_or, DW_OP_stack_value})); // Cases 4-6: Just like cases 1-3, but preserve the fragment at the end. EXPECT_TRUE(hasADbgVal({DW_OP_dup, DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, - DW_OP_not, DW_OP_mul, DW_OP_or, DW_OP_stack_value, - DW_OP_LLVM_fragment, 0, 8})); + DW_OP_not, DW_OP_mul, DW_OP_constu, 32, DW_OP_shl, + DW_OP_or, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); EXPECT_TRUE( hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_dup, DW_OP_constu, - 31, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, + 31, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, + DW_OP_constu, 32, DW_OP_shl, DW_OP_or, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_dup, DW_OP_constu, 31, - DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, + DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, + DW_OP_constu, 32, DW_OP_shl, DW_OP_or, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); verifyModule(*M, &errs(), &BrokenDebugInfo);