Skip to content

Commit 890fbcd

Browse files
tromeyaokblast
authored andcommitted
Minor optimizations to DW_OP_LLVM_extract_bits_* (llvm#163812)
I noticed a couple more small optimization opportunities when generating DWARF expressions from the internal DW_OP_LLVM_extract_bits_* operations: * DW_OP_deref can be used, rather than DW_OP_deref_size, when the deref size is the word size. * If the bit offset is 0 and an unsigned extraction is desired, then sometimes the shifting can be skipped entirely, or replaced with DW_OP_and.
1 parent c549550 commit 890fbcd

File tree

2 files changed

+44
-22
lines changed

2 files changed

+44
-22
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -566,32 +566,54 @@ bool DwarfExpression::addExpression(
566566
case dwarf::DW_OP_LLVM_extract_bits_zext: {
567567
unsigned SizeInBits = Op->getArg(1);
568568
unsigned BitOffset = Op->getArg(0);
569+
unsigned DerefSize = 0;
570+
// Operations are done in the DWARF "generic type" whose size
571+
// is the size of a pointer.
572+
unsigned PtrSizeInBytes = CU.getAsmPrinter()->MAI->getCodePointerSize();
569573

570574
// If we have a memory location then dereference to get the value, though
571575
// we have to make sure we don't dereference any bytes past the end of the
572576
// object.
573577
if (isMemoryLocation()) {
574-
emitOp(dwarf::DW_OP_deref_size);
575-
emitUnsigned(alignTo(BitOffset + SizeInBits, 8) / 8);
578+
DerefSize = alignTo(BitOffset + SizeInBits, 8) / 8;
579+
if (DerefSize == PtrSizeInBytes) {
580+
emitOp(dwarf::DW_OP_deref);
581+
} else {
582+
emitOp(dwarf::DW_OP_deref_size);
583+
emitUnsigned(DerefSize);
584+
}
576585
}
577586

578-
// Extract the bits by a shift left (to shift out the bits after what we
579-
// want to extract) followed by shift right (to shift the bits to position
580-
// 0 and also sign/zero extend). These operations are done in the DWARF
581-
// "generic type" whose size is the size of a pointer.
582-
unsigned PtrSizeInBytes = CU.getAsmPrinter()->MAI->getCodePointerSize();
583-
unsigned LeftShift = PtrSizeInBytes * 8 - (SizeInBits + BitOffset);
584-
unsigned RightShift = LeftShift + BitOffset;
585-
if (LeftShift) {
586-
emitOp(dwarf::DW_OP_constu);
587-
emitUnsigned(LeftShift);
588-
emitOp(dwarf::DW_OP_shl);
589-
}
590-
if (RightShift) {
591-
emitOp(dwarf::DW_OP_constu);
592-
emitUnsigned(RightShift);
593-
emitOp(OpNum == dwarf::DW_OP_LLVM_extract_bits_sext ? dwarf::DW_OP_shra
594-
: dwarf::DW_OP_shr);
587+
// If a dereference was emitted for an unsigned value, and
588+
// there's no bit offset, then a bit of optimization is
589+
// possible.
590+
if (OpNum == dwarf::DW_OP_LLVM_extract_bits_zext && BitOffset == 0) {
591+
if (8 * DerefSize == SizeInBits) {
592+
// The correct value is already on the stack.
593+
} else {
594+
// No need to shift, we can just mask off the desired bits.
595+
emitOp(dwarf::DW_OP_constu);
596+
emitUnsigned((1u << SizeInBits) - 1);
597+
emitOp(dwarf::DW_OP_and);
598+
}
599+
} else {
600+
// Extract the bits by a shift left (to shift out the bits after what we
601+
// want to extract) followed by shift right (to shift the bits to
602+
// position 0 and also sign/zero extend).
603+
unsigned LeftShift = PtrSizeInBytes * 8 - (SizeInBits + BitOffset);
604+
unsigned RightShift = LeftShift + BitOffset;
605+
if (LeftShift) {
606+
emitOp(dwarf::DW_OP_constu);
607+
emitUnsigned(LeftShift);
608+
emitOp(dwarf::DW_OP_shl);
609+
}
610+
if (RightShift) {
611+
emitOp(dwarf::DW_OP_constu);
612+
emitUnsigned(RightShift);
613+
emitOp(OpNum == dwarf::DW_OP_LLVM_extract_bits_sext
614+
? dwarf::DW_OP_shra
615+
: dwarf::DW_OP_shr);
616+
}
595617
}
596618

597619
// The value is now at the top of the stack, so set the location to

llvm/test/DebugInfo/X86/DW_OP_LLVM_extract_bits.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
; CHECK-LABEL: DW_TAG_subprogram
99
; CHECK: DW_AT_name ("test1")
1010
; CHECK: DW_TAG_variable
11-
; CHECK: DW_AT_location (DW_OP_fbreg -1, DW_OP_deref_size 0x1, DW_OP_constu 0x3d, DW_OP_shl, DW_OP_constu 0x3d, DW_OP_shr, DW_OP_stack_value)
11+
; CHECK: DW_AT_location (DW_OP_fbreg -1, DW_OP_deref_size 0x1, DW_OP_constu 0x7, DW_OP_and, DW_OP_stack_value)
1212
; CHECK: DW_AT_name ("x")
1313
; CHECK: DW_TAG_variable
1414
; CHECK: DW_AT_location (DW_OP_fbreg -1, DW_OP_deref_size 0x1, DW_OP_constu 0x39, DW_OP_shl, DW_OP_constu 0x3c, DW_OP_shra, DW_OP_stack_value)
@@ -25,7 +25,7 @@ entry:
2525
; CHECK-LABEL: DW_TAG_subprogram
2626
; CHECK: DW_AT_name ("test2")
2727
; CHECK: DW_TAG_variable
28-
; CHECK: DW_AT_location (DW_OP_breg0 {{R[^+]+}}+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_constu 0x3d, DW_OP_shl, DW_OP_constu 0x3d, DW_OP_shr, DW_OP_stack_value)
28+
; CHECK: DW_AT_location (DW_OP_breg0 {{R[^+]+}}+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_constu 0x7, DW_OP_and, DW_OP_stack_value)
2929
; CHECK: DW_AT_name ("x")
3030
; CHECK: DW_TAG_variable
3131
; CHECK: DW_AT_location (DW_OP_breg0 {{R[^+]+}}+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_constu 0x39, DW_OP_shl, DW_OP_constu 0x3c, DW_OP_shra, DW_OP_stack_value)
@@ -67,7 +67,7 @@ entry:
6767
; CHECK: DW_TAG_variable
6868
; CHECK: DW_AT_location (DW_OP_fbreg -4, DW_OP_plus_uconst 0x3, DW_OP_deref_size 0x1, DW_OP_constu 0x38, DW_OP_shl, DW_OP_constu 0x39, DW_OP_shr, DW_OP_stack_value)
6969
; CHECK: DW_AT_name ("z")
70-
; CHECK: DW_AT_location (DW_OP_fbreg -4, DW_OP_deref_size 0x8, DW_OP_stack_value)
70+
; CHECK: DW_AT_location (DW_OP_fbreg -4, DW_OP_deref, DW_OP_stack_value)
7171
; CHECK: DW_AT_name ("q")
7272

7373
define i32 @test4() !dbg !28 {

0 commit comments

Comments
 (0)