Transform Passes
Lotus provides a collection of LLVM IR transformation passes under lib/Transform.
These passes are primarily used to normalize and simplify bitcode before running
analyses (alias analysis, numerical abstract interpretation, symbolic abstraction)
or to build light-weight optimization pipelines.
Overview
Use these passes when you need IR that is easier for analyses and tools to consume:
Core normalization: simplify PHI/select/constant expressions so downstream analyses do not need to handle every LLVM IR corner case.
Memory and data canonicalization: make aggregates, GEPs, and global initializers easier to reason about.
Control-flow cleanup: remove dead blocks, normalize loop latches, and give blocks stable names.
Specialized transforms: lower vector and floating-point operations for analysis or targeted environments.
All passes live in lib/Transform and are exposed as standard LLVM passes.
Core Transforms
Normalization passes that rewrite IR into a simpler, analysis-friendly form.
Location: lib/Transform
Main passes:
ElimPhi – Convert PHI nodes to explicit select or copy operations when possible.
ExpandAssume – Expand
llvm.assumeintrinsics into explicit branches and checks.FlattenInit – Normalize complex global initializers into flat, explicit forms (source retained; disabled in default build).
LowerConstantExpr – Lower
ConstantExprnodes into instructions so analyses can work over a uniform instruction set.LowerSelect – Lower
selectinstructions into equivalent branch-based control flow.MergeReturn – Merge multiple
returninstructions into a single exit block.
Typical use cases:
Prepare bitcode for alias or numerical analyses that assume instruction-level IR.
Simplify unusual IR patterns produced by front-ends or optimizers.
Make control-flow and data-flow graphs easier to traverse.
Basic usage (C++):
#include <Transform/LowerConstantExpr.h>
#include <llvm/IR/PassManager.h>
llvm::Module &M = ...;
llvm::ModuleAnalysisManager MAM;
LowerConstantExprPass Pass;
llvm::PreservedAnalyses PA = Pass.run(M, MAM);
Memory and Data Transforms
Transformations that simplify memory layout and aggregate operations.
Location: lib/Transform
Main passes:
LowerGlobalConstantArraySelect – Lower selects over constant global arrays to simpler forms.
MergeGEP – Merge chained GEP instructions into a single GEP when possible.
SimplifyExtractValue – Simplify
extractvalueinstructions on aggregates.SimplifyInsertValue – Simplify
insertvalueinstructions on aggregates.
Typical use cases:
Canonicalize pointer arithmetic and field accesses before pointer analysis.
Reduce the number of aggregate operations that downstream passes must understand.
Improve readability of IR when inspecting transformed modules.
Control-Flow Transforms
Transformations that restructure and clean up control flow.
Location: lib/Transform
Main passes:
RemoveDeadBlock – Eliminate unreachable or trivially dead basic blocks.
RemoveNoRetFunction – Remove calls to known non-returning functions and tidy up unreachable code.
SimplifyLatch – Normalize loop latch structure to a canonical form.
NameBlock – Assign stable, human-readable names to basic blocks.
Typical use cases:
Cleanup after aggressive inlining or partial optimization.
Prepare IR for analyses that assume canonical loop shapes.
Improve the stability of analysis results and debug dumps.
Vector and Floating-Point Transforms
Transformations for vector operations and software floating-point emulation. For general module optimization pipelines, see Pass Ordering Utilities.
Location: lib/Transform
Main passes:
SoftFloat – Header interface for replacing hardware floating-point operations with software implementations (defined in
include/Transform/SoftFloat.h; currently not built intoCanaryTransform).UnrollVectors – Unroll short vector operations when profitable.
Typical use cases:
Lower vector operations prior to analyses that do not model vector instructions.
Replace floating-point operations in environments without hardware FP support.
Pipeline usage example (C++):
#include <Transform/LowerSelect.h>
#include <Transform/MergeReturn.h>
#include <Transform/MergeGEP.h>
#include <llvm/IR/PassManager.h>
llvm::Module &M = ...;
llvm::ModuleAnalysisManager MAM;
LowerSelectPass SelectLowerer;
MergeReturnPass ReturnMerger;
llvm::MergeArrayGEP GEPMerger;
SelectLowerer.run(M, MAM);
ReturnMerger.run(M, MAM);
GEPMerger.run(M, MAM);