Index: include/llvm/BinaryFormat/Dwarf.h =================================================================== --- include/llvm/BinaryFormat/Dwarf.h +++ include/llvm/BinaryFormat/Dwarf.h @@ -130,7 +130,9 @@ #include "llvm/BinaryFormat/Dwarf.def" DW_OP_lo_user = 0xe0, DW_OP_hi_user = 0xff, - DW_OP_LLVM_fragment = 0x1000 ///< Only used in LLVM metadata. + DW_OP_LLVM_fragment = 0x1000, ///< Only used in LLVM metadata. + DW_OP_LLVM_magic_sext = 0x1001, ///< Only used in LLVM metadata. + DW_OP_LLVM_magic_zext = 0x1002 ///< Only used in LLVM metadata. }; enum TypeKind : uint8_t { Index: lib/BinaryFormat/Dwarf.cpp =================================================================== --- lib/BinaryFormat/Dwarf.cpp +++ lib/BinaryFormat/Dwarf.cpp @@ -146,6 +146,10 @@ #include "llvm/BinaryFormat/Dwarf.def" case DW_OP_LLVM_fragment: return "DW_OP_LLVM_fragment"; + case DW_OP_LLVM_magic_sext: + return "DW_OP_LLVM_magic_sext"; + case DW_OP_LLVM_magic_zext: + return "DW_OP_LLVM_magic_zext"; } } @@ -155,6 +159,8 @@ .Case("DW_OP_" #NAME, DW_OP_##NAME) #include "llvm/BinaryFormat/Dwarf.def" .Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment) + .Case("DW_OP_LLVM_magic_sext", DW_OP_LLVM_magic_sext) + .Case("DW_OP_LLVM_magic_zext", DW_OP_LLVM_magic_zext) .Default(0); } Index: lib/CodeGen/AsmPrinter/DwarfExpression.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -351,6 +351,47 @@ LocationKind = Unknown; return; } + case dwarf::DW_OP_LLVM_magic_sext: { + unsigned ToBits = Op->getArg(0); + //unsigned FromBits = Op->getArg(1); + + if (LocationKind == Memory) { + emitOp(dwarf::DW_OP_deref_size); + emitUnsigned(ToBits/8); + LocationKind = Implicit; + } + + // (((X >> (ToBits - 1)) * (~0)) << ToBits) | X + emitOp(dwarf::DW_OP_dup); + emitOp(dwarf::DW_OP_constu); + emitUnsigned(ToBits - 1); + emitOp(dwarf::DW_OP_shr); + emitOp(dwarf::DW_OP_lit0); + emitOp(dwarf::DW_OP_not); + emitOp(dwarf::DW_OP_mul); + emitOp(dwarf::DW_OP_constu); + emitUnsigned(ToBits); + emitOp(dwarf::DW_OP_shl); + emitOp(dwarf::DW_OP_or); + break; + } + case dwarf::DW_OP_LLVM_magic_zext: { + unsigned ToBits = Op->getArg(0); + //unsigned FromBits = Op->getArg(1); + + if (LocationKind == Memory) { + emitOp(dwarf::DW_OP_deref_size); + emitUnsigned(ToBits/8); + // deref_size zero extends so we are done here + LocationKind = Implicit; + } else { + // (X & (1 << ToBits - 1)) + emitOp(dwarf::DW_OP_constu); + emitUnsigned((1ULL << ToBits) - 1); + emitOp(dwarf::DW_OP_and); + } + break; + } case dwarf::DW_OP_plus_uconst: assert(LocationKind != Register); emitOp(dwarf::DW_OP_plus_uconst); Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -815,6 +815,8 @@ unsigned DIExpression::ExprOperand::getSize() const { switch (getOp()) { case dwarf::DW_OP_LLVM_fragment: + case dwarf::DW_OP_LLVM_magic_sext: + case dwarf::DW_OP_LLVM_magic_zext: return 3; case dwarf::DW_OP_constu: case dwarf::DW_OP_plus_uconst: @@ -876,6 +878,8 @@ case dwarf::DW_OP_lit0: case dwarf::DW_OP_not: case dwarf::DW_OP_dup: + case dwarf::DW_OP_LLVM_magic_sext: + case dwarf::DW_OP_LLVM_magic_zext: break; } } Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -1849,21 +1849,8 @@ return None; 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); - } 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}); - return DIExpression::appendToStack(DII.getExpression(), Ops); - } + SmallVector Ops({Signed ? dwarf::DW_OP_LLVM_magic_sext : dwarf::DW_OP_LLVM_magic_zext, ToBits, FromBits}); + return DIExpression::appendToStack(DII.getExpression(), Ops); }; return rewriteDebugUsers(From, To, DomPoint, DT, SignOrZeroExt); } 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_LLVM_magic_sext, 16, 32, 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 @@ -789,30 +789,24 @@ }; // 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})); + EXPECT_TRUE(hasADbgVal({DW_OP_LLVM_magic_sext, 32, 64, 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})); + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, + DW_OP_LLVM_magic_sext, 32, 64, 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, + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_magic_sext, 32, 64, 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})); + EXPECT_TRUE(hasADbgVal({DW_OP_LLVM_magic_sext, 32, 64, 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, + hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_LLVM_magic_sext, 32, 64, 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, + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_magic_sext, 32, 64, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); verifyModule(*M, &errs(), &BrokenDebugInfo);