Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ Instruction *InstCombinerImpl::commonCastTransforms(CastInst &CI) {
Value *Src = CI.getOperand(0);
Type *Ty = CI.getType();

if (auto *SrcC = dyn_cast<Constant>(Src))
if (Constant *Res = ConstantFoldCastOperand(CI.getOpcode(), SrcC, Ty, DL))
return replaceInstUsesWith(CI, Res);
if (Value *Res =
simplifyCastInst(CI.getOpcode(), Src, Ty, SQ.getWithInstruction(&CI)))
return replaceInstUsesWith(CI, Res);

// Try to eliminate a cast of a cast.
if (auto *CSrc = dyn_cast<CastInst>(Src)) { // A->B->C cast
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ define i16 @test5(i16 %A) !dbg !34 {
call void @llvm.dbg.value(metadata i32 %C, metadata !37, metadata !DIExpression()), !dbg !41

; Preserve the dbg.value for the DCE'd 32-bit 'and'.
;
; The high 16 bits of the original 'and' require sign-extending the new 16-bit and:
; CHECK-NEXT: #dbg_value(i16 [[and]], [[C:![0-9]+]],
; CHECK-SAME: !DIExpression(DW_OP_LLVM_convert, 16, DW_ATE_signed, DW_OP_LLVM_convert, 32, DW_ATE_signed, DW_OP_stack_value)
; CHECK-SAME: !DIExpression(DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value)
Copy link
Contributor Author

@nikic nikic Oct 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My reading of this DIExpression is that we're first extending to 32-bit and then truncating to 16-bit, in which case the signedness does not matter. But I'm not confident on that reading...

The difference in behavior is that we're directly removing a cast pair instead of converting it into a bitcast first, which has some special handling here, though I have no idea what it's doing: https://github.com/nikic/llvm-project/blob/087ad0bea2e991d6c6b546170994cb2d172a6261/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp#L169-L171

Copy link
Contributor

@OCHyams OCHyams Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm this is interesting. Salvaging (salvageDebugInfo) a trunk or s|zext adds a convert which is signed if the instruction isa<SExtInst>, whereas replaceAllDbgUsesWith applies the signedness of the variable itself (ignores the instruction) to the convert.

It's not immediately clear to me which is best.

Either way, I think we should consider that separately and I don't think it should block this change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uurgh. This is similar to #151225, there's no strong typing of dbg.value operands, and so the transformation of IR Values sometimes isn't observed by any debug-info code (or: isn't always accounted for).

I don't think we really have a solid answer for what should happen here: is the sign-extend to produce a Value for an unsigned variable meaningful, or just an artifact of optimisation? CC @slinder1 on the topic of typed DIExpressions again.

IMO we're best off just letting this slide for now (land the patch, raise an issue?) because it's just as likely that the existing behaviour is unexpected as the new behaviour, and it shouldn't block better optimisations.


%D = trunc i32 %C to i16, !dbg !42
call void @llvm.dbg.value(metadata i16 %D, metadata !38, metadata !DIExpression()), !dbg !42
Expand Down
11 changes: 11 additions & 0 deletions llvm/test/Transforms/InstCombine/ptr-int-cast.ll
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,14 @@ define <4 x ptr> @test7(<4 x i128> %arg) nounwind {
%p1 = inttoptr <4 x i128> %arg to <4 x ptr>
ret <4 x ptr> %p1
}

define i64 @ptrtoint_gep_sub(ptr %ptr, i64 %end.addr) {
; CHECK-LABEL: @ptrtoint_gep_sub(
; CHECK-NEXT: ret i64 [[END_ADDR:%.*]]
;
%ptr.addr = ptrtoint ptr %ptr to i64
%size = sub i64 %end.addr, %ptr.addr
%end = getelementptr i8, ptr %ptr, i64 %size
%end.addr2 = ptrtoint ptr %end to i64
ret i64 %end.addr2
}