summaryrefslogtreecommitdiff
path: root/src/compiler/dex/compiler_ir.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/dex/compiler_ir.h')
-rw-r--r--src/compiler/dex/compiler_ir.h409
1 files changed, 14 insertions, 395 deletions
diff --git a/src/compiler/dex/compiler_ir.h b/src/compiler/dex/compiler_ir.h
index efae1f568a..d4bf3da182 100644
--- a/src/compiler/dex/compiler_ir.h
+++ b/src/compiler/dex/compiler_ir.h
@@ -18,10 +18,9 @@
#define ART_SRC_COMPILER_DEX_COMPILER_IR_H_
#include <vector>
-
#include <llvm/IR/Module.h>
-
-#include "compiler/dex/quick/codegen.h"
+#include "compiler/dex/quick/mir_to_lir.h"
+#include "backend.h"
#include "compiler/driver/compiler_driver.h"
#include "compiler/driver/dex_compilation_unit.h"
#include "compiler/llvm/intrinsic_helper.h"
@@ -33,268 +32,16 @@
namespace art {
-//TODO: replace these macros
-#define SLOW_FIELD_PATH (cu->enable_debug & (1 << kDebugSlowFieldPath))
-#define SLOW_INVOKE_PATH (cu->enable_debug & (1 << kDebugSlowInvokePath))
-#define SLOW_STRING_PATH (cu->enable_debug & (1 << kDebugSlowStringPath))
-#define SLOW_TYPE_PATH (cu->enable_debug & (1 << kDebugSlowTypePath))
-#define EXERCISE_SLOWEST_STRING_PATH (cu->enable_debug & \
- (1 << kDebugSlowestStringPath))
-
-// Minimum field size to contain Dalvik v_reg number.
-#define VREG_NUM_WIDTH 16
-
struct ArenaBitVector;
-struct LIR;
class LLVMInfo;
namespace llvm {
class LlvmCompilationUnit;
} // namespace llvm
-struct PromotionMap {
- RegLocationType core_location:3;
- uint8_t core_reg;
- RegLocationType fp_location:3;
- uint8_t FpReg;
- bool first_in_pair;
-};
-
-struct RegLocation {
- RegLocationType location:3;
- unsigned wide:1;
- unsigned defined:1; // Do we know the type?
- unsigned is_const:1; // Constant, value in mir_graph->constant_values[].
- unsigned fp:1; // Floating point?
- unsigned core:1; // Non-floating point?
- unsigned ref:1; // Something GC cares about.
- unsigned high_word:1; // High word of pair?
- unsigned home:1; // Does this represent the home location?
- uint8_t low_reg; // First physical register.
- uint8_t high_reg; // 2nd physical register (if wide).
- int32_t s_reg_low; // SSA name for low Dalvik word.
- int32_t orig_sreg; // TODO: remove after Bitcode gen complete
- // and consolodate usage w/ s_reg_low.
-};
-
-struct CompilerTemp {
- int s_reg;
- ArenaBitVector* bv;
-};
-
-struct CallInfo {
- int num_arg_words; // Note: word count, not arg count.
- RegLocation* args; // One for each word of arguments.
- RegLocation result; // Eventual target of MOVE_RESULT.
- int opt_flags;
- InvokeType type;
- uint32_t dex_idx;
- uint32_t index; // Method idx for invokes, type idx for FilledNewArray.
- uintptr_t direct_code;
- uintptr_t direct_method;
- RegLocation target; // Target of following move_result.
- bool skip_this;
- bool is_range;
- int offset; // Dalvik offset.
-};
-
- /*
- * Data structure tracking the mapping between a Dalvik register (pair) and a
- * native register (pair). The idea is to reuse the previously loaded value
- * if possible, otherwise to keep the value in a native register as long as
- * possible.
- */
-struct RegisterInfo {
- int reg; // Reg number
- bool in_use; // Has it been allocated?
- bool is_temp; // Can allocate as temp?
- bool pair; // Part of a register pair?
- int partner; // If pair, other reg of pair.
- bool live; // Is there an associated SSA name?
- bool dirty; // If live, is it dirty?
- int s_reg; // Name of live value.
- LIR *def_start; // Starting inst in last def sequence.
- LIR *def_end; // Ending inst in last def sequence.
-};
-
-struct RegisterPool {
- int num_core_regs;
- RegisterInfo *core_regs;
- int next_core_reg;
- int num_fp_regs;
- RegisterInfo *FPRegs;
- int next_fp_reg;
-};
-
-#define INVALID_SREG (-1)
-#define INVALID_VREG (0xFFFFU)
-#define INVALID_REG (0xFF)
-#define INVALID_OFFSET (0xDEADF00FU)
-
-/* SSA encodings for special registers */
-#define SSA_METHOD_BASEREG (-2)
-/* First compiler temp basereg, grows smaller */
-#define SSA_CTEMP_BASEREG (SSA_METHOD_BASEREG - 1)
-
-/*
- * Some code patterns cause the generation of excessively large
- * methods - in particular initialization sequences. There isn't much
- * benefit in optimizing these methods, and the cost can be very high.
- * We attempt to identify these cases, and avoid performing most dataflow
- * analysis. Two thresholds are used - one for known initializers and one
- * for everything else.
- */
-#define MANY_BLOCKS_INITIALIZER 1000 /* Threshold for switching dataflow off */
-#define MANY_BLOCKS 4000 /* Non-initializer threshold */
-
-// Utility macros to traverse the LIR list.
-#define NEXT_LIR(lir) (lir->next)
-#define PREV_LIR(lir) (lir->prev)
-
-// Defines for alias_info (tracks Dalvik register references).
-#define DECODE_ALIAS_INFO_REG(X) (X & 0xffff)
-#define DECODE_ALIAS_INFO_WIDE_FLAG (0x80000000)
-#define DECODE_ALIAS_INFO_WIDE(X) ((X & DECODE_ALIAS_INFO_WIDE_FLAG) ? 1 : 0)
-#define ENCODE_ALIAS_INFO(REG, ISWIDE) (REG | (ISWIDE ? DECODE_ALIAS_INFO_WIDE_FLAG : 0))
-
-// Common resource macros.
-#define ENCODE_CCODE (1ULL << kCCode)
-#define ENCODE_FP_STATUS (1ULL << kFPStatus)
-
-// Abstract memory locations.
-#define ENCODE_DALVIK_REG (1ULL << kDalvikReg)
-#define ENCODE_LITERAL (1ULL << kLiteral)
-#define ENCODE_HEAP_REF (1ULL << kHeapRef)
-#define ENCODE_MUST_NOT_ALIAS (1ULL << kMustNotAlias)
-
-#define ENCODE_ALL (~0ULL)
-#define ENCODE_MEM (ENCODE_DALVIK_REG | ENCODE_LITERAL | \
- ENCODE_HEAP_REF | ENCODE_MUST_NOT_ALIAS)
-
-#define is_pseudo_opcode(opcode) (static_cast<int>(opcode) < 0)
-
-struct LIR {
- int offset; // Offset of this instruction.
- int dalvik_offset; // Offset of Dalvik opcode.
- LIR* next;
- LIR* prev;
- LIR* target;
- int opcode;
- int operands[5]; // [0..4] = [dest, src1, src2, extra, extra2].
- struct {
- bool is_nop:1; // LIR is optimized away.
- bool pcRelFixup:1; // May need pc-relative fixup.
- unsigned int size:5; // Note: size is in bytes.
- unsigned int unused:25;
- } flags;
- int alias_info; // For Dalvik register & litpool disambiguation.
- uint64_t use_mask; // Resource mask for use.
- uint64_t def_mask; // Resource mask for def.
-};
-
-extern const char* extended_mir_op_names[kMirOpLast - kMirOpFirst];
-
-struct SSARepresentation;
-
-#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck)
-#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly)
-#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck)
-#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly)
-#define MIR_INLINED (1 << kMIRInlined)
-#define MIR_INLINED_PRED (1 << kMIRInlinedPred)
-#define MIR_CALLEE (1 << kMIRCallee)
-#define MIR_IGNORE_SUSPEND_CHECK (1 << kMIRIgnoreSuspendCheck)
-#define MIR_DUP (1 << kMIRDup)
-
-struct Checkstats {
- int null_checks;
- int null_checks_eliminated;
- int range_checks;
- int range_checks_eliminated;
-};
-
-struct MIR {
- DecodedInstruction dalvikInsn;
- unsigned int width;
- unsigned int offset;
- int m_unit_index; // From which method was this MIR included
- MIR* prev;
- MIR* next;
- SSARepresentation* ssa_rep;
- int optimization_flags;
- union {
- // Establish link between two halves of throwing instructions.
- MIR* throw_insn;
- // Saved opcode for NOP'd MIRs
- Instruction::Code original_opcode;
- } meta;
-};
-
-struct BasicBlockDataFlow {
- ArenaBitVector* use_v;
- ArenaBitVector* def_v;
- ArenaBitVector* live_in_v;
- ArenaBitVector* phi_v;
- int* vreg_to_ssa_map;
- ArenaBitVector* ending_null_check_v;
-};
-
-struct SSARepresentation {
- int num_uses;
- int* uses;
- bool* fp_use;
- int num_defs;
- int* defs;
- bool* fp_def;
-};
-
-struct BasicBlock {
- int id;
- int dfs_id;
- bool visited;
- bool hidden;
- bool catch_entry;
- bool explicit_throw;
- bool conditional_branch;
- bool terminated_by_return; // Block ends with a Dalvik return opcode.
- bool dominates_return; // Is a member of return extended basic block.
- uint16_t start_offset;
- uint16_t nesting_depth;
- BBType block_type;
- MIR* first_mir_insn;
- MIR* last_mir_insn;
- BasicBlock* fall_through;
- BasicBlock* taken;
- BasicBlock* i_dom; // Immediate dominator.
- BasicBlockDataFlow* data_flow_info;
- GrowableList* predecessors;
- ArenaBitVector* dominators;
- ArenaBitVector* i_dominated; // Set nodes being immediately dominated.
- ArenaBitVector* dom_frontier; // Dominance frontier.
- struct { // For one-to-many successors like.
- BlockListType block_list_type; // switch and exception handling.
- GrowableList blocks;
- } successor_block_list;
-};
-
-/*
- * The "blocks" field in "successor_block_list" points to an array of
- * elements with the type "SuccessorBlockInfo".
- * For catch blocks, key is type index for the exception.
- * For swtich blocks, key is the case value.
- */
-struct SuccessorBlockInfo {
- BasicBlock* block;
- int key;
-};
-
-struct LoopAnalysis;
-struct RegisterPool;
struct ArenaMemBlock;
struct Memstats;
class MIRGraph;
-class Codegen;
-
-#define NOTVISITED (-1)
+class Mir2Lir;
struct CompilationUnit {
CompilationUnit()
@@ -311,54 +58,21 @@ struct CompilationUnit {
disable_opt(0),
enable_debug(0),
verbose(false),
- gen_bitcode(false),
- disable_dataflow(false),
+ compiler_backend(kNoBackend),
instruction_set(kNone),
num_dalvik_registers(0),
insns(NULL),
num_ins(0),
num_outs(0),
num_regs(0),
- num_core_spills(0),
- num_fp_spills(0),
num_compiler_temps(0),
- frame_size(0),
- core_spill_mask(0),
- fp_spill_mask(0),
- attributes(0),
compiler_flip_match(false),
arena_head(NULL),
current_arena(NULL),
num_arena_blocks(0),
mstats(NULL),
- checkstats(NULL),
mir_graph(NULL),
- cg(NULL),
- live_sreg(0),
- llvm_info(NULL),
- context(NULL),
- module(NULL),
- func(NULL),
- intrinsic_helper(NULL),
- irb(NULL),
- placeholder_bb(NULL),
- entry_bb(NULL),
- entryTarget_bb(NULL),
- temp_name(0),
- first_lir_insn(NULL),
- last_lir_insn(NULL),
- literal_list(NULL),
- method_literal_list(NULL),
- code_literal_list(NULL),
- data_offset(0),
- total_size(0),
- reg_pool(NULL),
- reg_location(NULL),
- promotion_map(NULL),
- method_sreg(0),
- block_label_list(NULL),
- current_dalvik_offset(0)
- {}
+ cg(NULL) {}
/*
* Fields needed/generated by common frontend and generally used throughout
* the compiler.
@@ -375,130 +89,35 @@ struct CompilationUnit {
const char* shorty; // compiling method's shorty.
uint32_t disable_opt; // opt_control_vector flags.
uint32_t enable_debug; // debugControlVector flags.
- std::vector<uint8_t> code_buffer;
bool verbose;
- std::vector<uint32_t> combined_mapping_table;
- std::vector<uint32_t> core_vmap_table;
- std::vector<uint32_t> fp_vmap_table;
- std::vector<uint8_t> native_gc_map;
- bool gen_bitcode;
- bool disable_dataflow; // Skip dataflow analysis if possible
+ CompilerBackend compiler_backend;
InstructionSet instruction_set;
- // CLEANUP: much of this info available elsewhere. Go to the original source?
+ // TODO: much of this info available elsewhere. Go to the original source?
int num_dalvik_registers; // method->registers_size.
const uint16_t* insns;
- /*
- * Frame layout details.
- * NOTE: for debug support it will be necessary to add a structure
- * to map the Dalvik virtual registers to the promoted registers.
- * NOTE: "num" fields are in 4-byte words, "Size" and "Offset" in bytes.
- */
int num_ins;
int num_outs;
int num_regs; // Unlike num_dalvik_registers, does not include ins.
- int num_core_spills;
- int num_fp_spills;
+
+ // TODO: may want to move this to MIRGraph.
int num_compiler_temps;
- int frame_size;
- unsigned int core_spill_mask;
- unsigned int fp_spill_mask;
- unsigned int attributes;
+
// If non-empty, apply optimizer/debug flags only to matching methods.
std::string compiler_method_match;
// Flips sense of compiler_method_match - apply flags if doesn't match.
bool compiler_flip_match;
+
+ // TODO: move memory management to mir_graph, or just switch to using standard containers.
ArenaMemBlock* arena_head;
ArenaMemBlock* current_arena;
int num_arena_blocks;
Memstats* mstats;
- Checkstats* checkstats;
- UniquePtr<MIRGraph> mir_graph; // MIR container.
- UniquePtr<Codegen> cg; // Target-specific codegen.
- /*
- * Sanity checking for the register temp tracking. The same ssa
- * name should never be associated with one temp register per
- * instruction compilation.
- */
- int live_sreg;
-
- // Fields for Portable
- llvm::LlvmCompilationUnit* llvm_compilation_unit;
- /*
- * Fields needed by GBC creation. Candidates for moving to a new MIR to
- * llvm bitcode class.
- */
- LLVMInfo* llvm_info;
- std::string symbol;
- ::llvm::LLVMContext* context;
- ::llvm::Module* module;
- ::llvm::Function* func;
- art::llvm::IntrinsicHelper* intrinsic_helper;
- art::llvm::IRBuilder* irb;
- ::llvm::BasicBlock* placeholder_bb;
- ::llvm::BasicBlock* entry_bb;
- ::llvm::BasicBlock* entryTarget_bb;
- std::string bitcode_filename;
- GrowableList llvm_values;
- int32_t temp_name;
- SafeMap<int32_t, ::llvm::BasicBlock*> id_to_block_map; // block id -> llvm bb.
-
- /*
- * Fields needed by the Quick backend. Candidates for moving to a new
- * QuickBackend class.
- */
- LIR* first_lir_insn;
- LIR* last_lir_insn;
- LIR* literal_list; // Constants.
- LIR* method_literal_list; // Method literals requiring patching.
- LIR* code_literal_list; // Code literals requiring patching.
- int data_offset; // starting offset of literal pool.
- int total_size; // header + code size.
- RegisterPool* reg_pool;
- // Map SSA names to location.
- RegLocation* reg_location;
- // Keep track of Dalvik v_reg to physical register mappings.
- PromotionMap* promotion_map;
- // SSA name for Method*.
- int method_sreg;
- RegLocation method_loc; // Describes location of method*.
- GrowableList throw_launchpads;
- GrowableList suspend_launchpads;
- GrowableList intrinsic_launchpads;
- GrowableList compiler_temps;
- LIR* block_label_list;
- /*
- * TODO: The code generation utilities don't have a built-in
- * mechanism to propagate the original Dalvik opcode address to the
- * associated generated instructions. For the trace compiler, this wasn't
- * necessary because the interpreter handled all throws and debugging
- * requests. For now we'll handle this by placing the Dalvik offset
- * in the CompilationUnit struct before codegen for each instruction.
- * The low-level LIR creation utilites will pull it from here. Rework this.
- */
- int current_dalvik_offset;
- GrowableList switch_tables;
- GrowableList fill_array_data;
- SafeMap<unsigned int, unsigned int> block_id_map; // Block collapse lookup cache.
- SafeMap<unsigned int, LIR*> boundary_map; // boundary lookup cache.
- /*
- * Holds mapping from native PC to dex PC for safepoints where we may deoptimize.
- * Native PC is on the return address of the safepointed operation. Dex PC is for
- * the instruction being executed at the safepoint.
- */
- std::vector<uint32_t> pc2dexMappingTable;
- /*
- * Holds mapping from Dex PC to native PC for catch entry points. Native PC and Dex PC
- * immediately preceed the instruction.
- */
- std::vector<uint32_t> dex2pcMappingTable;
+ UniquePtr<MIRGraph> mir_graph; // MIR container.
+ UniquePtr<Backend> cg; // Target-specific codegen.
};
-// TODO: move this
-int SRegToVReg(const CompilationUnit* cu, int ssa_reg);
-
-
} // namespace art
#endif // ART_SRC_COMPILER_DEX_COMPILER_IR_H_