Other optimization passes

In this recipe, we will look at some more transformational passes, which are more like of utility passes. We will look at the strip-debug-symbols pass and the prune-eh pass.

Getting ready…

The opt tool must be installed.

How to do it…

  1. Write a test case for checking the strip-debug pass, which strips off the debug symbols from the test code:
    $ cat teststripdebug.ll
    @x = common global i32 0                          ; <i32*> [#uses=0]
    
    define void @foo() nounwind readnone optsize ssp {
    entry:
      tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !5, metadata !{}), !dbg !10
      ret void, !dbg !11
    }
    
    declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone
    
    !llvm.dbg.cu = !{!2}
    !llvm.module.flags = !{!13}
    !llvm.dbg.sp = !{!0}
    !llvm.dbg.lv.foo = !{!5}
    !llvm.dbg.gv = !{!8}
    
    !0 = !MDSubprogram(name: "foo", linkageName: "foo", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, file: !12, scope: !1, type: !3, function: void ()* @foo)
    !1 = !MDFile(filename: "b.c", directory: "/tmp")
    !2 = !MDCompileUnit(language: DW_LANG_C89, producer: "4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", isOptimized: true, emissionKind: 0, file: !12, enums: !4, retainedTypes: !4)
    !3 = !MDSubroutineType(types: !4)
    !4 = !{null}
    !5 = !MDLocalVariable(tag: DW_TAG_auto_variable, name: "y", line: 3, scope: !6, file: !1, type: !7)
    !6 = distinct !MDLexicalBlock(line: 2, column: 0, file: !12, scope: !0)
    !7 = !MDBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
    !8 = !MDGlobalVariable(name: "x", line: 1, isLocal: false, isDefinition: true, scope: !1, file: !1, type: !7, variable: i32* @x)
    !9 = !{i32 0}
    !10 = !MDLocation(line: 3, scope: !6)
    !11 = !MDLocation(line: 4, scope: !6)
    !12 = !MDFile(filename: "b.c", directory: "/tmp")
    !13 = !{i32 1, !"Debug Info Version", i32 3}
    
  2. Run the strip-debug-symbols pass by passing the –strip-debug command-line option to the opt tool:
    $ opt -strip-debug teststripdebug.ll  -S
    ; ModuleID = ' teststripdebug.ll'
    
    @x = common global i32 0
    
    ; Function Attrs: nounwind optsize readnone ssp
    define void @foo() #0 {
    entry:
      ret void
    }
    
    attributes #0 = { nounwind optsize readnone ssp }
    
    !llvm.module.flags = !{!0}
    
    !0 = metadata !{i32 1, metadata !"Debug Info Version", i32 2}
    
  3. Write a test case for checking the prune-eh pass:
    $ cat simpletest.ll
    declare void @nounwind() nounwind
    
    define internal void @foo() {
      call void @nounwind()
      ret void
    }
    
    define i32 @caller() {
      invoke void @foo( )
            to label %Normal unwind label %Except
    
    Normal:        ; preds = %0
      ret i32 0
    
    Except:        ; preds = %0
        landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
                    catch i8* null
      ret i32 1
    }
    declare i32 @__gxx_personality_v0(...)
    
  4. Run the pass to remove unused exception information by passing the –prune-eh command-line option to the opt tool:
    $ opt -prune-eh -S simpletest.ll
    ; ModuleID = 'simpletest.ll'
    
    ; Function Attrs: nounwind
    declare void @nounwind() #0
    
    ; Function Attrs: nounwind
    define internal void @foo() #0 {
      call void @nounwind()
      ret void
    }
    ; Function Attrs: nounwind
    define i32 @caller() #0 {
      call void @foo()
      br label %Normal
    
    Normal:                                           ; preds = %0
      ret i32 0
    }
    
    declare i32 @__gxx_personality_v0(...)
    
    attributes #0 = { nounwind }
    

How it works…

In the first case, where we are running the strip-debug pass, it removes the debug information from the code, and we can get compact code. This pass must be used only when we are looking for compact code, as it can delete the names of virtual registers and the symbols for internal global variables and functions, thus making the source code less readable and making it difficult to reverse engineer the code.

The part of code that handles this transformation is located in the llvm/lib/Transforms/IPO/StripSymbols.cpp file, where the StripDeadDebugInfo::runOnModule function is responsible for stripping the debug information.

The second test is for removing unused exception information using the prune-eh pass, which implements an interprocedural pass. This walks the call-graph, turning invoke instructions into call instructions only if the callee cannot throw an exception, and marking functions as nounwind if they cannot throw the exceptions.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.5.57