From 25bab8b1fb2fc851ea3f1f630b3de65ca6afdc22 Mon Sep 17 00:00:00 2001 From: Ash Wolf Date: Wed, 14 Dec 2022 00:16:59 +0000 Subject: haha it's been a while since i last committed, hasn't it --- compiler_and_linker/unsorted/AddPropagation.c | 271 + compiler_and_linker/unsorted/Alias.c | 766 +++ compiler_and_linker/unsorted/BitVectors.c | 122 + compiler_and_linker/unsorted/COptimizer.c | 74 + compiler_and_linker/unsorted/CodeMotion.c | 916 +++ compiler_and_linker/unsorted/Coloring.c | 268 + compiler_and_linker/unsorted/ConstantPropagation.c | 643 +++ compiler_and_linker/unsorted/CopyPropagation.c | 474 ++ compiler_and_linker/unsorted/IROUseDef.c | 1448 +++++ compiler_and_linker/unsorted/InlineAsmPPC.c | 4 +- compiler_and_linker/unsorted/InterferenceGraph.c | 404 ++ compiler_and_linker/unsorted/IrOptimizer.c | 45 + compiler_and_linker/unsorted/IroBitVect.c | 2 +- compiler_and_linker/unsorted/IroCSE.c | 1039 ++++ compiler_and_linker/unsorted/IroDump.c | 652 +++ compiler_and_linker/unsorted/IroEmptyLoop.c | 567 ++ compiler_and_linker/unsorted/IroExprRegeneration.c | 1531 +++++ compiler_and_linker/unsorted/IroFlowgraph.c | 336 ++ compiler_and_linker/unsorted/IroJump.c | 267 + compiler_and_linker/unsorted/IroLinearForm.c | 1831 ++++++ compiler_and_linker/unsorted/IroLoop.c | 2335 ++++++++ compiler_and_linker/unsorted/IroMalloc.c | 564 ++ compiler_and_linker/unsorted/IroPointerAnalysis.c | 5912 ++++++++++++++++++++ .../unsorted/IroPointerAnalysisADTs.c | 2925 ++++++++++ compiler_and_linker/unsorted/IroPropagate.c | 595 ++ compiler_and_linker/unsorted/IroRangePropagation.c | 776 +++ compiler_and_linker/unsorted/IroSubable.c | 160 + compiler_and_linker/unsorted/IroTransform.c | 3 + compiler_and_linker/unsorted/IroUnrollLoop.c | 95 + compiler_and_linker/unsorted/IroUtil.c | 1250 +++++ compiler_and_linker/unsorted/IroVars.c | 1449 +++++ compiler_and_linker/unsorted/LiveInfo.c | 167 + compiler_and_linker/unsorted/LoadDeletion.c | 46 + compiler_and_linker/unsorted/LoopDetection.c | 889 +++ compiler_and_linker/unsorted/LoopOptimization.c | 1565 ++++++ compiler_and_linker/unsorted/PCode.c | 2 +- compiler_and_linker/unsorted/PCodeAssembly.c | 27 + compiler_and_linker/unsorted/PCodeListing.c | 527 ++ compiler_and_linker/unsorted/Scheduler.c | 548 ++ compiler_and_linker/unsorted/SpillCode.c | 464 ++ compiler_and_linker/unsorted/StrengthReduction.c | 752 +++ compiler_and_linker/unsorted/Switch.c | 465 +- compiler_and_linker/unsorted/TOC.c | 1 + compiler_and_linker/unsorted/UseDefChains.c | 563 ++ compiler_and_linker/unsorted/ValueNumbering.c | 664 +++ compiler_and_linker/unsorted/VectorArraysToRegs.c | 549 ++ 46 files changed, 34940 insertions(+), 13 deletions(-) create mode 100644 compiler_and_linker/unsorted/IroPointerAnalysisADTs.c create mode 100644 compiler_and_linker/unsorted/LiveInfo.c (limited to 'compiler_and_linker') diff --git a/compiler_and_linker/unsorted/AddPropagation.c b/compiler_and_linker/unsorted/AddPropagation.c index e69de29..78b3393 100644 --- a/compiler_and_linker/unsorted/AddPropagation.c +++ b/compiler_and_linker/unsorted/AddPropagation.c @@ -0,0 +1,271 @@ +#include "compiler/AddPropagation.h" +#include "compiler/Alias.h" +#include "compiler/BitVectors.h" +#include "compiler/CopyPropagation.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/objects.h" + +int propagatedadds; + +static int is_add(PCode *instr) { + return + ( + instr->op == PC_ADD || + ( + instr->op == PC_ADDI && + ( + instr->args[2].kind == PCOp_IMMEDIATE || + (instr->args[2].kind == PCOp_MEMORY && (unsigned char) instr->args[2].arg == 1) + ) + ) + ) + && + instr->args[0].data.reg.reg >= n_real_registers[(char) instr->args[0].arg]; +} + +static int addpropagatestouse(int candidateID, int useID) { + int reg2; + PCode *candidateInstr; + PCode *useInstr; + int reg1; + int reg27; + Object *object; + SInt32 offset; + int i; + PCode *instr; + PCodeArg *op; + + candidateInstr = Candidates[candidateID].pcode; + useInstr = Uses[useID].pcode; + reg1 = candidateInstr->args[0].data.reg.reg; + reg2 = candidateInstr->args[1].data.reg.reg; + reg27 = reg2; + + if (!useInstr->block) { + recursive_propagation = 1; + return 0; + } + + if (useInstr->flags & (fPCodeFlag2 | fPCodeFlag4)) { + if (PCODE_FLAG_SET_F(useInstr) & fPCodeFlag2000000) + return 0; + } else if (useInstr->op == PC_ADDI) { + if (useInstr->args[2].kind != PCOp_IMMEDIATE) + return 0; + } else if (useInstr->op != PC_MR) { + return 0; + } + + if (candidateInstr->op == PC_ADD) { + if (useInstr->argCount < 3) { + if (useInstr->op != PC_MR) + return 0; + } else if (useInstr->args[2].kind == PCOp_IMMEDIATE) { + if (useInstr->args[2].data.imm.value != 0) + return 0; + } else if (useInstr->args[2].kind == PCOp_REGISTER) { + if ( + useInstr->args[1].kind != PCOp_REGISTER || + useInstr->args[2].data.reg.reg != reg1 || + useInstr->args[1].data.reg.reg != 0 + ) + return 0; + } else { + return 0; + } + + object = NULL; + offset = 0; + if (candidateInstr->alias && candidateInstr->alias->type == AliasType0) { + object = candidateInstr->alias->object; + offset = candidateInstr->alias->offset; + } + reg27 = candidateInstr->args[2].data.reg.reg; + } else if (candidateInstr->op == PC_ADDI) { + if (candidateInstr->alias && candidateInstr->alias->type == AliasType0) { + object = candidateInstr->alias->object; + offset = candidateInstr->alias->offset; + } else if (candidateInstr->args[2].kind == PCOp_MEMORY) { + object = candidateInstr->args[2].data.mem.obj; + offset = candidateInstr->args[2].data.mem.offset; + } else if (candidateInstr->args[2].kind == PCOp_IMMEDIATE) { + object = NULL; + offset = candidateInstr->args[2].data.imm.value; + } else { + return 0; + } + + if (useInstr->argCount < 3) { + if (useInstr->op != PC_MR) + return 0; + } else if (useInstr->args[2].kind == PCOp_IMMEDIATE) { + offset += useInstr->args[2].data.imm.value; + if (object) { + if (object->datatype == DLOCAL) { + if (!can_add_displ_to_local(object, offset)) + return 0; + } else { + return 0; + } + } else if (!FITS_IN_SHORT(offset)) { + return 0; + } + } else { + return 0; + } + } else { +#line 225 + CError_FATAL(); + return 0; + } + + if ( + (useInstr->flags & fPCodeFlag4) && + useInstr->args[0].kind == PCOp_REGISTER && + useInstr->args[0].arg == RegClass_GPR && + useInstr->args[0].data.reg.reg == reg1 + ) + return 0; + + if (useInstr->args[1].data.reg.reg != reg1) + return 0; + + if (candidateInstr->block == useInstr->block && precedes(candidateInstr, useInstr)) { + for (instr = candidateInstr->nextPCode; instr && instr != useInstr; instr = instr->nextPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) && + (op->data.reg.reg == reg2 || op->data.reg.reg == reg27) + ) + return 0; + op++; + } + } + } else { + if (!bitvectorgetbit(candidateID, propinfo[useInstr->block->blockIndex].vec8)) + return 0; + + for (instr = useInstr->block->firstPCode; instr; instr = instr->nextPCode) { + if (instr == useInstr) + break; + + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) && + (op->data.reg.reg == reg2 || op->data.reg.reg == reg27) + ) + return 0; + op++; + } + } + } + + if ((useInstr->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) && object) + useInstr->alias = make_alias(object, offset, nbytes_loaded_or_stored_by(useInstr)); + + return 1; +} + +static void propagateandremoveadd(int id) { + PCode *instr; + RegUseOrDef *list; + Candidate *candidate; + PCode *useInstr; + + candidate = Candidates + id; + instr = candidate->pcode; + + if (instr->op == PC_ADDI && instr->args[2].kind == PCOp_MEMORY) + instr->alias = make_alias(instr->args[2].data.mem.obj, instr->args[2].data.mem.offset, 1); + + for (list = candidate->list; list; list = list->next) { + useInstr = Uses[list->id].pcode; + + if (instr->op == PC_ADD) { + if (useInstr->flags & (fPCodeFlag2 | fPCodeFlag4)) { + if (useInstr->args[2].kind != PCOp_REGISTER) { + useInstr->op += 2; + useInstr->flags |= fPCodeFlag20; + } + useInstr->args[1] = instr->args[1]; + useInstr->args[2] = instr->args[2]; + useInstr->alias = instr->alias; + } else if (useInstr->op == PC_ADDI) { +#line 338 + CError_ASSERT(useInstr->args[2].data.imm.value == 0); + change_opcode(useInstr, PC_ADD); + useInstr->args[1] = instr->args[1]; + useInstr->args[2] = instr->args[2]; + useInstr->alias = instr->alias; + } else if (useInstr->op == PC_MR) { + change_opcode(useInstr, PC_ADD); + useInstr->flags = instr->flags; + change_num_operands(useInstr, 3); + useInstr->args[1] = instr->args[1]; + useInstr->args[2] = instr->args[2]; + useInstr->alias = instr->alias; + } else { +#line 352 + CError_FATAL(); + } + } else if (useInstr->op == PC_MR) { + change_opcode(useInstr, PC_ADDI); + useInstr->flags = instr->flags; + useInstr->alias = instr->alias; + change_num_operands(useInstr, 3); + useInstr->args[1] = instr->args[1]; + useInstr->args[2] = instr->args[2]; + } else { + useInstr->args[1] = instr->args[1]; + if (instr->args[2].kind == PCOp_IMMEDIATE) { + SInt32 newValue = useInstr->args[2].data.imm.value + instr->args[2].data.imm.value; + useInstr->args[2] = instr->args[2]; + useInstr->args[2].data.imm.value = newValue; + useInstr->flags |= fPCodeFlag20; + } else if (instr->args[2].kind == PCOp_MEMORY) { + SInt32 newValue = useInstr->args[2].data.imm.value + instr->args[2].data.mem.offset; + useInstr->args[2] = instr->args[2]; + useInstr->args[2].data.mem.offset = newValue; + useInstr->flags &= ~fPCodeFlag20; + if (useInstr->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) + useInstr->alias = make_alias( + useInstr->args[2].data.mem.obj, + useInstr->args[2].data.mem.offset, + nbytes_loaded_or_stored_by(useInstr)); + } else { +#line 382 + CError_FATAL(); + } + } + } + + deletepcode(instr); + propagatedadds = 1; +} + +static Propagation add_prop = { + &is_add, + &addpropagatestouse, + &propagateandremoveadd, + "ADD", + "ADDS", + "a%ld", + 0 +}; + +void propagateaddinstructions(Object *proc) { + propagateinstructions(proc, &add_prop, (copts.optimizationlevel >= 4) ? 4 : 1, 1); + propagatedadds = propagated_instructions; +} diff --git a/compiler_and_linker/unsorted/Alias.c b/compiler_and_linker/unsorted/Alias.c index e69de29..4c0f064 100644 --- a/compiler_and_linker/unsorted/Alias.c +++ b/compiler_and_linker/unsorted/Alias.c @@ -0,0 +1,766 @@ +#include "compiler/Alias.h" +#include "compiler/CClass.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/CMachine.h" +#include "compiler/CodeGen.h" +#include "compiler/CopyPropagation.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/RegisterInfo.h" +#include "compiler/UseDefChains.h" +#include "compiler/ValueNumbering.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +static Alias *aliases; +static int n_aliases; +static int n_gathered_aliases; +static Alias *alias_hash[997]; +Alias *worst_case; +Object worst_case_obj; + +static TypePointer worst_case_memory_type = { + TYPEARRAY, + 0xFFFFFF, + TYPE(&stchar) +}; + +static Boolean is_safe_const(Object *obj) { + Type *type; + + type = obj->type; + while (IS_TYPE_ARRAY(type)) + type = TPTR_TARGET(type); + + if (TYPE_FITS_IN_REGISTER(type) || IS_TYPE_VECTOR(type) || IS_TYPE_FLOAT(type) || IS_TYPE_STRUCT(type)) + return is_const_object(obj); + + if (IS_TYPE_CLASS(type)) + return is_const_object(obj) && CClass_IsPODClass(TYPE_CLASS(type)); + + return 0; +} + +void initialize_aliases(void) { + int i; + + memclrw(&worst_case_obj, sizeof(Object)); + worst_case_obj.otype = OT_OBJECT; + worst_case_obj.type = TYPE(&worst_case_memory_type); + worst_case_obj.datatype = DDATA; + worst_case_obj.name = GetHashNameNodeExport("@worst_case@"); + + aliases = NULL; + n_aliases = 0; + n_gathered_aliases = 0; + for (i = 0; i < 997; i++) + alias_hash[i] = NULL; + + worst_case = make_alias_set(); + add_alias_member(worst_case, make_alias(&worst_case_obj, 0, 0)); +} + +static UInt32 hash_alias(Object *object, SInt32 offset, SInt32 size) { + return (UInt32) (object->name->hashval * offset * size) % 997; +} + +static Alias *create_alias(AliasType type, Object *object, SInt32 offset, SInt32 size, Boolean addToHash) { + Alias *alias; + UInt32 hash; + + alias = lalloc(sizeof(Alias)); + memclrw(alias, sizeof(Alias)); + alias->type = type; + alias->index = n_aliases++; + alias->next = aliases; + aliases = alias; + alias->object = object; + alias->offset = offset; + alias->size = size; + + if (addToHash) { + hash = hash_alias(object, offset, size); + alias->hashNext = alias_hash[hash]; + alias_hash[hash] = alias; + } + + return alias; +} + +static Alias *lookup_alias(Object *object, SInt32 offset, SInt32 size) { + Alias *scan; + + for (scan = alias_hash[hash_alias(object, offset, size)]; scan; scan = scan->hashNext) { + if (scan->object == object && scan->offset == offset && scan->size == size) + return scan; + } + + return NULL; +} + +Alias *make_alias(Object *object, SInt32 offset, SInt32 size) { + Alias *alias; + Alias *alias2; + + if (!offset && !size) + size = object->type->size; + + alias = lookup_alias(object, offset, size); + if (!alias) { + if (offset > 0 || size != object->type->size) { + alias2 = make_alias(object, 0, object->type->size); + alias = create_alias(AliasType1, object, offset, size, 1); + add_alias_member(alias2, alias); + } else { + alias = create_alias(AliasType0, object, offset, size, 1); + } + + switch (object->datatype) { + case DLOCAL: + case DNONLAZYPTR: + break; + default: + if (!is_safe_const(object)) + add_alias_member(worst_case, make_alias(object, 0, 0)); + } + } + + if (offset > object->type->size) + return NULL; + else + return alias; +} + +Alias *make_alias_set(void) { + return create_alias(AliasType2, NULL, 0, 0, 0); +} + +void add_alias_member(Alias *parent, Alias *child) { + AliasMember *member; + + if (child->type == AliasType2) { + for (member = child->parents; member; member = member->nextParent) + add_alias_member(parent, member->child); + } else { + if (parent == worst_case && child->type == AliasType1) + child = make_alias(child->object, 0, 0); + + for (member = parent->parents; member; member = member->nextParent) { + if (member->child == child) + return; + } + + member = lalloc(sizeof(AliasMember)); + member->parent = parent; + member->child = child; + member->nextParent = parent->parents; + parent->parents = member; + member->nextChild = child->children; + child->children = member; + } +} + +Alias *make_alias_set_from_IR(void) { +#line 333 + CError_FATAL(); + return NULL; +} + +static Boolean aliases_overlap(Alias *a, Alias *b) { + return ( + a->offset == b->offset || + (a->offset > b->offset && a->offset < (b->offset + b->size)) || + (b->offset > a->offset && b->offset < (a->offset + a->size)) + ); +} + +static int is_address_load(PCode *pcode) { + Object *obj; + + switch (pcode->op) { + case PC_LWZ: + if (pcode->args[2].kind == PCOp_MEMORY && pcode->args[2].data.mem.obj->datatype == DNONLAZYPTR) + return 1; + break; + case PC_LBZU: + case PC_LBZUX: + case PC_LHZU: + case PC_LHZUX: + case PC_LHAU: + case PC_LHAUX: + case PC_LWZU: + case PC_LWZUX: + case PC_STBU: + case PC_STBUX: + case PC_STHU: + case PC_STHUX: + case PC_STWU: + case PC_STWUX: + return 1; + case PC_ADDI: + case PC_ADDIS: + if (pcode->args[0].data.reg.reg < n_real_registers[RegClass_GPR]) { + if (pcode->args[2].kind == PCOp_MEMORY) { + obj = pcode->args[2].data.mem.obj; + if (obj->datatype == DLOCAL && !is_safe_const(obj)) + add_alias_member(worst_case, make_alias(obj, 0, 0)); + return 0; + } + } else { + return 1; + } + break; + case PC_ADD: + return 1; + } + + return 0; +} + +static int addresspropagatestouse(int candidateID, int useID) { + PCode *candidate_pcode; // r30 + PCode *use_pcode; // r29 + int reg; // r28 + short reg2; + Object *object; // r27 + SInt32 offset; // r26 + Alias *alias; // r25 + Boolean flag24; // r24 + SInt32 size; // r23 + Alias *aliasSet; // r22 + int i; + PCode *scan; + PCodeArg *op; + + candidate_pcode = Candidates[candidateID].pcode; + use_pcode = Uses[useID].pcode; + flag24 = 0; + size = 1; + reg = candidate_pcode->args[0].data.reg.reg; + + if (candidate_pcode->alias && (candidate_pcode->alias->type == AliasType0 || candidate_pcode->alias->type == AliasType1)) { + object = candidate_pcode->alias->object; + offset = candidate_pcode->alias->offset; + if (offset == 0 && candidate_pcode->alias->size == object->type->size) + flag24 = 1; + } else if (candidate_pcode->args[2].kind == PCOp_MEMORY) { + object = candidate_pcode->args[2].data.mem.obj; + if (candidate_pcode->op == PC_ADDIS) + offset = candidate_pcode->args[2].data.mem.offset << 16; + else + offset = candidate_pcode->args[2].data.mem.offset; + } else { + return 0; + } + +#line 478 + CError_ASSERT(object->otype == OT_OBJECT); + + if ((candidate_pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) && (candidate_pcode->flags & fPCodeFlag2000000)) { + reg = candidate_pcode->args[1].data.reg.reg; + offset = 0; + flag24 = 1; + } else if (candidate_pcode->op == PC_LWZ) { + if (object->datatype != DNONLAZYPTR) + return 0; + + object = object->u.var.realObj; +#line 495 + CError_ASSERT(object->otype == OT_OBJECT); + offset = 0; + } else if (candidate_pcode->op == PC_ADDI) { + if (!candidate_pcode->alias && object) + candidate_pcode->alias = make_alias(object, offset, 1); + } else if (candidate_pcode->op == PC_ADDIS) { + if (!candidate_pcode->alias && object) + candidate_pcode->alias = make_alias(object, offset, 1); + } else if (candidate_pcode->op == PC_ADD) { + offset = 0; + flag24 = 1; + } else { +#line 509 + CError_FATAL(); + } + + if ( + !(use_pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) && + use_pcode->op != PC_ADDI && + use_pcode->op != PC_ADD && + use_pcode->op != PC_ADDIS + ) { + if (object->datatype == DLOCAL && !is_safe_const(object)) + add_alias_member(worst_case, make_alias(object, 0, 0)); + return 1; + } + + if ( + (use_pcode->flags & (fPCodeFlag4 | fPCodeFlag40000)) && + use_pcode->args[0].kind == PCOp_REGISTER && + use_pcode->args[0].arg == RegClass_GPR && + use_pcode->args[0].data.reg.reg == reg && + object->datatype == DLOCAL && + !is_safe_const(object) + ) + add_alias_member(worst_case, make_alias(object, 0, 0)); + + if (use_pcode->argCount < 3) + return 1; + +#line 543 + CError_ASSERT(use_pcode->args[1].kind == PCOp_REGISTER); + + if (candidate_pcode->block == use_pcode->block && precedes(candidate_pcode, use_pcode)) { + for (scan = candidate_pcode->nextPCode; scan && scan != use_pcode; scan = scan->nextPCode) { + op = scan->args; + i = scan->argCount; + while (i--) { + if (op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) && + op->data.reg.reg == reg) + return 1; + op++; + } + } + } else { + if (!bitvectorgetbit(candidateID, propinfo[use_pcode->block->blockIndex].vec8)) { + if (bitvectorgetbit(candidate_pcode->defID, usedefinfo[use_pcode->block->blockIndex].defvec8)) { + for (scan = use_pcode->block->firstPCode; scan && scan != use_pcode; scan = scan->nextPCode) { + op = scan->args; + i = scan->argCount; + while (i--) { + if (op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) && + op->data.reg.reg == reg) + return 1; + op++; + } + } + } else { + return 1; + } + } + + for (scan = use_pcode->block->firstPCode; scan; scan = scan->nextPCode) { + if (scan == use_pcode) + break; + op = scan->args; + i = scan->argCount; + while (i--) { + if (op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) && + op->data.reg.reg == reg) + return 1; + op++; + } + } + } + +#line 598 + CError_ASSERT(object != NULL); + + if (use_pcode->op == PC_ADDI || use_pcode->op == PC_ADD || use_pcode->op == PC_ADDIS) { + if (use_pcode->args[0].data.reg.reg < n_real_registers[RegClass_GPR] && !is_safe_const(object)) + add_alias_member(worst_case, make_alias(object, 0, 0)); + } + + if (use_pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) + size = nbytes_loaded_or_stored_by(use_pcode); + + if (use_pcode->args[2].kind == PCOp_REGISTER) { + if (use_pcode->args[1].data.reg.reg == 0) { + if (use_pcode->args[2].data.reg.reg == reg) + alias = make_alias(object, offset, size); + } else { + if (use_pcode->args[1].data.reg.reg == reg) + reg2 = use_pcode->args[2].data.reg.reg; + else if (use_pcode->args[2].data.reg.reg == reg) + reg2 = use_pcode->args[1].data.reg.reg; + else + return 1; + + for (scan = use_pcode->prevPCode; scan; scan = scan->prevPCode) { + if (scan->op == PC_LI && scan->args[0].data.reg.reg == reg2) + break; + + for (i = 0; i < scan->argCount; i++) { + if (scan->args[i].kind == PCOp_REGISTER && + scan->args[i].arg == RegClass_GPR && + scan->args[i].data.reg.reg == reg2 && + (scan->args[i].data.reg.effect & EffectWrite)) { + scan = NULL; + break; + } + } + + if (!scan) + break; + } + + if (scan) { + offset += scan->args[1].data.mem.offset; + alias = make_alias(object, offset, size); + } else { + alias = make_alias(object, 0, 0); + } + } + } else { + if (use_pcode->args[1].kind != PCOp_REGISTER || + use_pcode->args[1].arg != RegClass_GPR || + use_pcode->args[1].data.reg.reg != reg) + return 1; + + if (use_pcode->args[1].data.reg.effect & EffectWrite) { + alias = make_alias(object, 0, 0); + } else if (use_pcode->args[2].kind == PCOp_IMMEDIATE) { + if (use_pcode->op == PC_ADDIS) { + offset += use_pcode->args[2].data.imm.value << 16; + alias = make_alias(object, offset, 1); + } else { + offset += use_pcode->args[2].data.imm.value; + alias = make_alias(object, offset, size); + } + } else { + return 1; + } + } + + if (flag24) + alias = make_alias(object, 0, 0); + + if (!alias) + return 1; + + if (!use_pcode->alias) { + if ( + use_pcode->op == PC_ADDI || + use_pcode->op == PC_ADD || + use_pcode->op == PC_ADDIS || + ((candidate_pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) && (candidate_pcode->flags & fPCodeFlag2000000)) + ) + recursive_propagation = 1; + } + + if (use_pcode->alias) { + if (use_pcode->alias == worst_case) { + add_alias_member(worst_case, make_alias(object, 0, 0)); + } else if (use_pcode->alias == alias) { + return 1; + } else if (use_pcode->alias->type == AliasType0 || use_pcode->alias->type == AliasType1) { + if (object == use_pcode->alias->object) { + use_pcode->alias = make_alias(object, 0, 0); + } else { + aliasSet = make_alias_set(); + if ( + use_pcode->op == PC_ADDI || + use_pcode->op == PC_ADD || + use_pcode->op == PC_ADDIS || + ((use_pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) && (use_pcode->flags & fPCodeFlag2000000)) + ) { + if (alias->type == AliasType2) + add_alias_member(worst_case, alias); + else + add_alias_member(worst_case, make_alias(use_pcode->alias->object, 0, 0)); + } + add_alias_member(aliasSet, use_pcode->alias); + add_alias_member(aliasSet, alias); + use_pcode->alias = aliasSet; + } + } else { + add_alias_member(use_pcode->alias, alias); + } + } else { + use_pcode->alias = alias; + } + + propagated_instructions = 1; + return 1; +} + +static void finishpropagatealiases(int id) { + propagated_instructions = 1; +} + +static Propagation alias_prop = { + &is_address_load, + &addresspropagatestouse, + &finishpropagatealiases, + "ALIAS", + "ALIASES", + "A%ld", + 1 +}; + +static void propagatealiasinfo(Object *proc) { + propagateinstructions(proc, &alias_prop, (copts.optimizationlevel >= 4) ? 4 : 1, 1); +} + +void gather_alias_info(void) { + UInt32 *myvec; // r31 + Alias *alias; // r22 + AliasMember *member; + AliasMember *member2; + PCodeBlock *block; // r21 + PCode *pcode; // r20 + PCodeArg *op; // r19 + RegUseOrDef *list; // r18 + int i; // r17 + Alias *alias_choice; // r16 + int aliases_idx; // r15 (helper in r23) + PCode *defpcode; // r14 + Alias *alias_array[3]; + UseOrDef *def; + int defID; + + if (coloring) { + propagatealiasinfo(gFunction); + myvec = oalloc(4 * ((number_of_Defs + 31) >> 5)); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + bitvectorcopy(myvec, usedefinfo[block->blockIndex].defvec8, number_of_Defs); + + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) { + if (!pcode->alias) { + pcode->alias = worst_case; + } else { + if ((pcode->alias->type == AliasType0 || pcode->alias->type == AliasType1) && + pcode->alias->size == nbytes_loaded_or_stored_by(pcode)) { + pcode->flags &= ~fPCodeFlag20; + } else { + pcode->flags |= fPCodeFlag20; + } + + if (pcode->alias != worst_case) { + aliases_idx = 0; + alias_choice = NULL; + op = pcode->args; + for (i = 0; i < pcode->argCount; i++, op++) { + if ( + (!(pcode->flags & (fPCodeFlag4 | fPCodeFlag40000)) || op != pcode->args) && + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectRead) + ) { + alias_array[aliases_idx] = NULL; + if (aliases_idx >= 2) { + alias_choice = worst_case; + break; + } + alias_array[aliases_idx] = pcode->alias; + + for (list = reg_Defs[RegClass_GPR][op->data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(list->id, myvec)) { + defpcode = Defs[list->id].pcode; + if (!defpcode->alias || !is_address_load(defpcode) || defpcode->alias == worst_case) { + alias_array[aliases_idx] = worst_case; + break; + } + } + } + + aliases_idx++; + } + } + + if (!alias_choice) { + if (aliases_idx > 0) { + alias_choice = alias_array[0]; + if (aliases_idx == 2) { + if (alias_array[0] != worst_case) { + if (alias_array[1] != worst_case) + alias_choice = worst_case; + } else if (alias_array[1] != worst_case) { + alias_choice = alias_array[1]; + } + } + } + + if (alias_choice == worst_case) { + pcode->flags |= fPCodeFlag20; + if (pcode->alias->type == AliasType2) + add_alias_member(worst_case, pcode->alias); + else + add_alias_member(worst_case, make_alias(pcode->alias->object, 0, 0)); + } + + if (alias_choice) + pcode->alias = alias_choice; + } + } + } + } else { + if ((pcode->flags & fPCodeFlag8) && !pcode->alias) + pcode->alias = worst_case; + } + + for (def = &Defs[defID = pcode->defID]; defID < number_of_Defs && def->pcode == pcode; defID++, def++) { + if (def->v.kind == PCOp_REGISTER && def->v.arg == RegClass_GPR) { + for (list = reg_Defs[RegClass_GPR][def->v.u.reg]; list; list = list->next) + bitvectorclearbit(list->id, myvec); + } + bitvectorsetbit(defID, myvec); + } + } + } + + freeoheap(); + } else { + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if ((pcode->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag8 | fPCodeFlag20000 | fPCodeFlag40000)) && !pcode->alias) + pcode->alias = worst_case; + } + } + } + + if (n_gathered_aliases != n_aliases) { + for (alias = aliases; alias; alias = alias->next) { + if (alias->type == AliasType2) { + alias->vec24 = lalloc(4 * ((n_aliases + 31) >> 35)); + bitvectorinitialize(alias->vec24, n_aliases, 0); + for (member = alias->parents; member; member = member->nextParent) { + bitvectorsetbit(member->child->index, alias->vec24); + for (member2 = member->child->parents; member2; member2 = member2->nextParent) + bitvectorsetbit(member2->child->index, alias->vec24); + } + } + } + n_gathered_aliases = n_aliases; + } +} + +static Boolean may_alias_alias(Alias *a, Alias *b) { + switch ((a->type * 3) + b->type) { + case (AliasType0 * 3) + AliasType0: + return a == b; + case (AliasType0 * 3) + AliasType1: + case (AliasType1 * 3) + AliasType0: + return a->object == b->object; + case (AliasType1 * 3) + AliasType1: + return (a->object == b->object) && aliases_overlap(a, b); + case (AliasType0 * 3) + AliasType2: + case (AliasType1 * 3) + AliasType2: + return bitvectorgetbit(a->index, b->vec24) != 0; + case (AliasType2 * 3) + AliasType0: + case (AliasType2 * 3) + AliasType1: + return bitvectorgetbit(b->index, a->vec24) != 0; + case (AliasType2 * 3) + AliasType2: + return (a == b) || !bitvectorintersectionisempty(a->vec24, b->vec24, n_aliases); + default: +#line 1054 + CError_FATAL(); + return 1; + } +} + +Boolean may_alias(PCode *a, PCode *b) { + return may_alias_alias(a->alias, b->alias); +} + +Boolean uniquely_aliases(PCode *a, PCode *b) { + if (may_alias_alias(a->alias, b->alias)) { + if ( + a->alias->type != AliasType2 && + b->alias->type != AliasType2 && + a->alias && + b->alias && + a->alias->size == nbytes_loaded_or_stored_by(a) && + b->alias->size == nbytes_loaded_or_stored_by(b) + ) + return 1; + } + + return 0; +} + +Boolean may_alias_worst_case(PCode *pcode) { + return may_alias_alias(pcode->alias, worst_case); +} + +Boolean may_alias_object(PCode *pcode, Object *object) { + return may_alias_alias(pcode->alias, make_alias(object, 0, 0)); +} + +void initialize_alias_values(void) { + Alias *alias; + + for (alias = aliases; alias; alias = alias->next) { + alias->valuenumber = nextvaluenumber++; + alias->valuepcode = NULL; + } +} + +void update_alias_value(Alias *alias, PCode *pcode) { + AliasMember *member; + AliasMember *member2; + AliasMember *member3; + + switch (alias->type) { + case AliasType0: + killmemory(alias, pcode); + for (member = alias->children; member; member = member->nextChild) { +#line 1152 + CError_ASSERT(member->parent->type == AliasType2); + killmemory(member->parent, NULL); + } + for (member = alias->parents; member; member = member->nextParent) { +#line 1157 + CError_ASSERT(member->child->type == AliasType1); + killmemory(member->child, NULL); + for (member2 = member->child->children; member2; member2 = member2->nextChild) { + if (member2->parent != alias) { +#line 1163 + CError_ASSERT(member2->parent->type == AliasType2); + killmemory(member2->parent, NULL); + } + } + } + break; + + case AliasType1: + killmemory(alias, pcode); + for (member = alias->children; member; member = member->nextChild) { + killmemory(member->parent, NULL); + if (member->parent->type == AliasType0) { + for (member2 = member->parent->parents; member2; member2 = member2->nextParent) { + if (member2->child != alias && aliases_overlap(alias, member2->child)) { + killmemory(member2->child, NULL); + } + } + } + } + break; + + case AliasType2: + killmemory(alias, NULL); + for (member = alias->parents; member; member = member->nextParent) { + killmemory(member->child, NULL); + for (member2 = member->child->children; member2; member2 = member2->nextChild) { + if (member2->parent != alias) + killmemory(member2->parent, NULL); + } + for (member3 = member->child->parents; member3; member3 = member3->nextParent) { + killmemory(member3->child, NULL); + for (member2 = member3->child->children; member2; member2 = member2->nextChild) { + if (member2->parent != member->child) + killmemory(member2->parent, NULL); + } + } + } + break; + } +} + +void update_all_alias_values(void) { + Alias *alias; + + for (alias = aliases; alias; alias = alias->next) + killmemory(alias, NULL); +} + diff --git a/compiler_and_linker/unsorted/BitVectors.c b/compiler_and_linker/unsorted/BitVectors.c index e69de29..3a928fd 100644 --- a/compiler_and_linker/unsorted/BitVectors.c +++ b/compiler_and_linker/unsorted/BitVectors.c @@ -0,0 +1,122 @@ +#include "compiler/BitVectors.h" + +void bitvectorcopy(UInt32 *dst, UInt32 *src, int len) { + int i = (len + 31) >> 5; + + while (i--) + *(dst++) = *(src++); +} + +int bitvectorchanged(UInt32 *dst, UInt32 *src, int len) { + int i = (len + 31) >> 5; + int flag = 0; + UInt32 v; + + while (i--) { + v = *src; + if (*dst != v) + flag = 1; + *dst = v; + dst++; + src++; + } + + return flag; +} + +void bitvectorinitialize(UInt32 *vec, int len, UInt32 initval) { + int i = (len + 31) >> 5; + + while (i--) + *(vec++) = initval; +} + +void bitvectorintersect(UInt32 *dst, UInt32 *src, int len) { + int i = (len + 31) >> 5; + + while (i--) + *(dst++) &= *(src++); +} + +void bitvectorunion(UInt32 *dst, UInt32 *src, int len) { + int i = (len + 31) >> 5; + + while (i--) + *(dst++) |= *(src++); +} + +void bitvectordifference(UInt32 *dst, UInt32 *src, int len) { + int i = (len + 31) >> 5; + + while (i--) + *(dst++) &= ~*(src++); +} + +void bitvectorcomplement(UInt32 *dst, UInt32 *src, int len) { + int i = (len + 31) >> 5; + + while (i--) + *(dst++) = ~*(src++); +} + +int bitvectorcount(UInt32 *vec, int len) { + static unsigned char nbits[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 + }; + + UInt32 v; + int i = (len + 31) >> 5; + int total = 0; + + while (i--) { + if ((v = *vec)) { + total += nbits[v & 0xFF]; + total += nbits[(v >> 8) & 0xFF]; + total += nbits[(v >> 16) & 0xFF]; + total += nbits[(v >> 24) & 0xFF]; + } + vec++; + } + + return total; +} + +int bitvectorisempty(UInt32 *vec, int len) { + int i = (len + 31) >> 5; + + while (i--) { + if (*vec) + return 0; + vec++; + } + + return 1; +} + +int bitvectorintersectionisempty(UInt32 *a, UInt32 *b, int len) { + int i = (len + 31) >> 5; + + while (i--) { + if (*a & *b) + return 0; + a++; + b++; + } + + return 1; +} diff --git a/compiler_and_linker/unsorted/COptimizer.c b/compiler_and_linker/unsorted/COptimizer.c index 38b203f..b7637c8 100644 --- a/compiler_and_linker/unsorted/COptimizer.c +++ b/compiler_and_linker/unsorted/COptimizer.c @@ -904,6 +904,8 @@ static COptBlock *newblock(void) { block->set1[i] = 0; block->set2[i] = 0; } + + return block; } static void MarkFollow(COptBlock *block) { @@ -1369,6 +1371,8 @@ static CLabel *finallabel(CLabel *label, Statement *stmt) { return label; } } + + return label; } static void optimizegoto(Statement *stmt) { @@ -1399,6 +1403,76 @@ static void removeif(Statement *stmt, Boolean flag) { } static void optimizeif(Statement *stmt) { + Statement *scan; + Statement *scan2; + Boolean flag; + + if (iszero(stmt->expr)) { + removeif(stmt, 0); + return; + } + if (isnotzero(stmt->expr)) { + removeif(stmt, 1); + return; + } + + for (scan = stmt->next, flag = 0; scan; scan = scan->next) { + if (scan->type > ST_LABEL) { + if (scan->type == ST_GOTO) { + if (scan->label == stmt->label) { + stmt->type = ST_EXPRESSION; + stmtchanged = 1; + return; + } + + if (!flag) { + for (scan2 = scan->next; scan2; scan2 = scan2->next) { + if (scan2->type > ST_LABEL) + break; + if (stmt->label->stmt == scan2) { + stmt->label = scan->label; + scan->type = ST_NOP; + if (stmt->type == ST_IFGOTO) + stmt->type = ST_IFNGOTO; + else + stmt->type = ST_IFGOTO; + stmtchanged = 1; + stmt->label = finallabel(stmt->label, stmt); + return; + } + } + } + } else if (scan->type == ST_RETURN && !scan->expr && !static_for_inlines && !flag) { + for (scan2 = scan->next; scan2; scan2 = scan2->next) { + if (scan2->type > ST_LABEL) + break; + if (stmt->label->stmt == scan2) { + stmt->label = cleanreturnlabel; + needs_cleanup = 1; + scan->type = ST_NOP; + if (stmt->type == ST_IFGOTO) + stmt->type = ST_IFNGOTO; + else + stmt->type = ST_IFGOTO; + stmtchanged = 1; + return; + } + } + } + break; + } + + if (scan->type == ST_LABEL) + flag = 1; + + if (stmt->label->stmt == scan) { + stmt->type = ST_EXPRESSION; + stmtchanged = 1; + return; + } + } + + stmt->label = finallabel(stmt->label, stmt); } static void optimizeswitch(Statement *stmt) { diff --git a/compiler_and_linker/unsorted/CodeMotion.c b/compiler_and_linker/unsorted/CodeMotion.c index e69de29..539748e 100644 --- a/compiler_and_linker/unsorted/CodeMotion.c +++ b/compiler_and_linker/unsorted/CodeMotion.c @@ -0,0 +1,916 @@ +#include "compiler/CodeMotion.h" +#include "compiler/Alias.h" +#include "compiler/BitVectors.h" +#include "compiler/LoopDetection.h" +#include "compiler/LoopOptimization.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/UseDefChains.h" +#include "compiler/RegisterInfo.h" + +int movedloopinvariantcode; +int unswitchedinvariantcode; + +static int isloopinvariant(PCode *pcode, Loop *loop, UInt32 *vec, int flag1, int flag2) { + PCodeArg *op; + RegUseOrDef *list; + int i; + + if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) { + if (pcode->alias) { + if (pcode->alias->type == AliasType2 || (pcode->flags & (fIsVolatile | fSideEffects))) + return 0; + + if (pcode->flags & fPCodeFlag2) { + for (list = findobjectusedef(pcode->alias->object)->defs; list; list = list->next) { + if ( + may_alias(pcode, Defs[list->id].pcode) && + bitvectorgetbit(list->id, vec) && + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 0; + } + } + + if (pcode->flags & fPCodeFlag4) { + for (list = findobjectusedef(pcode->alias->object)->uses; list; list = list->next) { + if ( + may_alias(pcode, Uses[list->id].pcode) && + bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 0; + } + } + } else { + return 0; + } + } + + if ((pcode->flags & fPCodeFlag4) && !bitvectorgetbit(pcode->block->blockIndex, loop->vec2C)) + return 0; + + op = pcode->args; + i = pcode->argCount; + while (i--) { + switch (op->kind) { + case PCOp_MEMORY: + if ((pcode->flags & fPCodeFlag2) && ((pcode->flags == 0) & 0x40)) { + for (list = findobjectusedef(op->data.mem.obj)->defs; list; list = list->next) { + if ( + may_alias(pcode, Defs[list->id].pcode) && + bitvectorgetbit(list->id, vec) && + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 0; + } + } + if (pcode->flags & fPCodeFlag4) { + for (list = findobjectusedef(op->data.mem.obj)->uses; list; list = list->next) { + if ( + may_alias(pcode, Uses[list->id].pcode) && + bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 0; + } + } + break; + case PCOp_REGISTER: + if (op->data.reg.effect & (EffectRead | EffectWrite)) { + if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { + if (op->data.reg.reg == _FP_) + break; + if (op->data.reg.reg == _CALLER_SP_) + break; + if (op->data.reg.reg == 2) + break; + } + if (op->data.reg.reg < n_real_registers[op->arg]) { + if (op->arg == RegClass_CRFIELD) { + if (!flag2 || (op->data.reg.effect & EffectRead)) + return 0; + } else if (op->arg == RegClass_SPR) { + if (!flag1) + return 0; + } else { + return 0; + } + } else if (op->data.reg.effect & EffectRead) { + if (flag1 && op->kind == PCOp_REGISTER && op->arg == RegClass_SPR) + break; + if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { + if (op->data.reg.reg == _FP_) + break; + if (op->data.reg.reg == _CALLER_SP_) + break; + if (op->data.reg.reg == 2) + break; + } + + for (list = reg_Defs[op->arg][op->data.reg.reg]; list; list = list->next) { + if ( + bitvectorgetbit(list->id, vec) && + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 0; + } + } + } + break; + } + op++; + } + + return 1; +} + +static int isuniquedefinition(PCode *pcode, Loop *loop) { + RegUseOrDef *list; + int defID; + UseOrDef *def; + + defID = pcode->defID; + def = &Defs[defID]; + if (defID >= number_of_Defs) + return 0; + if (def->pcode != pcode) + return 0; + if ((defID + 1) < number_of_Defs && def[1].pcode == pcode) + return 0; + + if (def->v.kind == PCOp_REGISTER) { + for (list = reg_Defs[(char) def->v.arg][def->v.u.reg]; list; list = list->next) { + if ( + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && + list->id != defID + ) + return 0; + } + } else if (def->v.kind == PCOp_MEMORY) { + for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { + if ( + may_alias(pcode, Defs[list->id].pcode) && + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && + list->id != defID + ) + return 0; + } + } else { +#line 292 + CError_FATAL(); + } + + return 1; +} + +static int uniquelyreachesuse(int defID, int useID) { + UseOrDef *def; + UseOrDef *use; + RegUseOrDef *list; + PCode *pcode; + + def = &Defs[defID]; + use = &Uses[useID]; + if (def->v.kind == PCOp_REGISTER) { + for (list = reg_Defs[(char) def->v.arg][def->v.u.reg]; list; list = list->next) { + if ( + list->id != defID && + bitvectorgetbit(list->id, usedefinfo[use->pcode->block->blockIndex].defvec8) + ) + break; + } + } else if (def->v.kind == PCOp_MEMORY) { + for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { + if ( + may_alias(def->pcode, Defs[list->id].pcode) && + list->id != defID && + bitvectorgetbit(list->id, usedefinfo[use->pcode->block->blockIndex].defvec8) + ) + break; + } + } + + if (!list) + return 1; + + if (def->pcode->block == use->pcode->block) { + for (pcode = use->pcode->prevPCode; pcode; pcode = pcode->prevPCode) { + if (pcode == def->pcode) + return 1; + } + } + + return 0; +} + +static int uniquelyreachesalluses(int defID, Loop *loop) { + UseOrDef *def; + RegUseOrDef *list; + + def = &Defs[defID]; + + if (def->v.kind == PCOp_REGISTER) { + for (list = reg_Uses[(char) def->v.arg][def->v.u.reg]; list; list = list->next) { + if ( + bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].usevec1C) || + (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) && !uniquelyreachesuse(defID, list->id)) + ) + return 0; + } + } else if (def->v.kind == PCOp_MEMORY) { + for (list = findobjectusedef(def->v.u.object)->uses; list; list = list->next) { + if (may_alias(def->pcode, Uses[list->id].pcode)) { + if ( + bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].usevec1C) || + (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) && !uniquelyreachesuse(defID, list->id)) + ) + return 0; + } + } + } else { +#line 382 + CError_FATAL(); + } + + return 1; +} + +static int isliveonexit(TinyValue *v, Loop *loop) { + RegUseOrDef *list; + UInt32 *vec; + + vec = usedefinfo[loop->preheader->blockIndex].usevec1C; + + if (v->kind == PCOp_REGISTER) { + for (list = reg_Uses[(char) v->arg][v->u.reg]; list; list = list->next) { + if ( + bitvectorgetbit(list->id, vec) && + !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 1; + } + } else if (v->kind == PCOp_MEMORY) { + for (list = findobjectusedef(v->u.object)->uses; list; list = list->next) { + if ( + bitvectorgetbit(list->id, vec) && + !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 1; + } + } + + return 0; +} + +static int dominatesallexits(PCode *pcode, Loop *loop) { + return bitvectorgetbit(pcode->block->blockIndex, loop->vec28) != 0; +} + +static int maymove(PCode *pcode, Loop *loop) { + short reg; + + if (!isuniquedefinition(pcode, loop)) + return 0; + if (!uniquelyreachesalluses(pcode->defID, loop)) + return 0; + if (!dominatesallexits(pcode, loop) && isliveonexit(&Defs[pcode->defID].v, loop)) + return 0; + + if (loop->bodySize > 25) { + switch (pcode->op) { + case PC_LI: + if ( + pcode->nextPCode && + pcode->nextPCode->op == PC_LVX && + (pcode->nextPCode->flags & fIsConst) + ) { + reg = pcode->args[0].data.reg.reg; + if (pcode->nextPCode->args[1].data.reg.reg == reg || + pcode->nextPCode->args[2].data.reg.reg == reg) + return 1; + } + case PC_VSPLTISB: + case PC_VSPLTISH: + case PC_VSPLTISW: + return 0; + default: + if (!bitvectorgetbit(pcode->block->blockIndex, loop->vec2C)) + return 0; + } + } + + return 1; +} + +static void moveinvariantcomputation(PCode *pcode, Loop *loop) { + ObjectUseDef *oud; + BlockList *blocklist; + RegUseOrDef *list; + UseOrDef *def; + int defID; + + defID = pcode->defID; + def = &Defs[defID]; + deletepcode(pcode); + insertpcodebefore(loop->preheader->lastPCode, pcode); + loop->bodySize--; + movedloopinvariantcode = 1; + + if (def->v.kind == PCOp_REGISTER) { + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + for (list = reg_Defs[(char) def->v.arg][def->v.u.reg]; list; list = list->next) + bitvectorclearbit(list->id, usedefinfo[blocklist->block->blockIndex].defvec8); + bitvectorsetbit(defID, usedefinfo[blocklist->block->blockIndex].defvec8); + } + } else if (def->v.kind == PCOp_MEMORY) { + oud = findobjectusedef(def->v.u.object); + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + for (list = oud->defs; list; list = list->next) { + if (uniquely_aliases(pcode, Defs[list->id].pcode)) + bitvectorclearbit(list->id, usedefinfo[blocklist->block->blockIndex].defvec8); + } + bitvectorsetbit(defID, usedefinfo[blocklist->block->blockIndex].defvec8); + } + } else { +#line 545 + CError_FATAL(); + } +} + +static int srawi_addze_maymove(PCode *pcode, Loop *loop) { + RegUseOrDef *list; + UseOrDef *def; + int defID; + int nextDefID; + + defID = pcode->defID; + nextDefID = pcode->nextPCode->defID; + + def = &Defs[defID]; + if (defID >= number_of_Defs) + return 0; + if (def->pcode != pcode) + return 0; + if ((defID + 1) < number_of_Defs && def[1].pcode == pcode) + return 0; + + if (def->v.kind == PCOp_REGISTER && def->v.arg == RegClass_GPR) { + for (list = reg_Defs[RegClass_GPR][def->v.u.reg]; list; list = list->next) { + if ( + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && + list->id != defID && + list->id != nextDefID + ) + return 0; + } + } else { +#line 582 + CError_FATAL(); + } + + if (!uniquelyreachesalluses(pcode->defID, loop)) + return 0; + if (!dominatesallexits(pcode, loop) && isliveonexit(&Defs[pcode->defID].v, loop)) + return 0; + if (!dominatesallexits(pcode->nextPCode, loop) && isliveonexit(&Defs[pcode->nextPCode->defID].v, loop)) + return 0; + + return 1; +} + +static int srawi_addze_isloopinvariant(PCode *pcode, Loop *loop, UInt32 *vec) { + static PCode *oldNextInstr; + PCode *nextInstr; + + nextInstr = pcode->nextPCode; + if ( + pcode->op == PC_ADDZE && + oldNextInstr == pcode + ) { + oldNextInstr = NULL; + return 1; + } else if ( + pcode->op == PC_SRAWI && + nextInstr && + nextInstr->op == PC_ADDZE && + pcode->args[0].data.reg.reg == nextInstr->args[0].data.reg.reg && + nextInstr->args[0].data.reg.reg == nextInstr->args[1].data.reg.reg && + !(pcode->flags & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects)) && + !(nextInstr->flags & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects)) && + isloopinvariant(pcode, loop, vec, 1, 0) && + srawi_addze_maymove(pcode, loop) + ) { + oldNextInstr = nextInstr; + return 1; + } else { + oldNextInstr = NULL; + return 0; + } +} + +static void removeblockfromloop(Loop *loop, PCodeBlock *block) { + BlockList *list; + BlockList **ptr; + + bitvectorclearbit(block->blockIndex, loop->memberblocks); + bitvectorclearbit(block->blockIndex, loop->vec24); + bitvectorclearbit(block->blockIndex, loop->vec28); + bitvectorclearbit(block->blockIndex, loop->vec2C); + loop->bodySize -= block->pcodeCount; + + ptr = &loop->blocks; + while ((list = *ptr)) { + if (list->block == block) + *ptr = list->next; + else + ptr = &list->next; + } +} + +static void changesuccessor(PCodeBlock *block, PCodeBlock *from, PCodeBlock *to) { + PCLink **ptr; + PCLink *link; + + for (link = block->successors; link; link = link->nextLink) { + if (link->block == from) + link->block = to; + } + + ptr = &from->predecessors; + while ((link = *ptr)) { + if (link->block == block) { + *ptr = link->nextLink; + link->nextLink = to->predecessors; + to->predecessors = link; + } else { + ptr = &link->nextLink; + } + } +} + +static void movesuccessor(PCodeBlock *to, PCodeBlock *from, PCodeBlock *block) { + PCLink **ptr; + PCLink *link; + + for (link = block->predecessors; link; link = link->nextLink) { + if (link->block == from) + link->block = to; + } + + ptr = &from->successors; + while ((link = *ptr)) { + if (link->block == block) { + *ptr = link->nextLink; + link->nextLink = to->successors; + to->successors = link; + } else { + ptr = &link->nextLink; + } + } +} + +static void movecmptopreheader(Loop *loop, PCodeBlock *block, PCode *pc1, PCode *pc2, PCodeArg *op) { + PCodeBlock *preheader; + PCode *pc3; + + preheader = loop->preheader; + if (PCODE_FLAG_SET_F(pc1) & fPCodeFlag20000000) { + moveinvariantcomputation(pc1, loop); + } else { + deletepcode(pc1); + insertpcodebefore(loop->preheader->lastPCode, pc1); + loop->bodySize--; + movedloopinvariantcode = 1; + } + loop->preheader = NULL; + + insertpreheaderblock(loop); + + pc3 = preheader->lastPCode; +#line 775 + CError_ASSERT(pc3->op == PC_B); + deletepcode(pc3); + deletepcode(pc2); + appendpcode(preheader, pc2); + movesuccessor(preheader, block, op->data.label.label->block); +} + +static PCodeBlock *appendheadercopy(Loop *loop, PCodeBlock *block1, PCodeBlock *block2, PCodeBlock *block3) { + PCodeBlock *newblock1; + PCodeBlock *newblock2; + PCLink *link; + PCode *scan; + + newblock1 = lalloc(sizeof(PCodeBlock)); + newblock2 = lalloc(sizeof(PCodeBlock)); + + newblock1->labels = NULL; + newblock1->predecessors = newblock1->successors = NULL; + newblock1->firstPCode = newblock1->lastPCode = NULL; + newblock1->pcodeCount = 0; + newblock1->loopWeight = loop->body->loopWeight; + newblock1->flags = 0; + newblock1->blockIndex = pcblockcount++; + + newblock2->labels = NULL; + newblock2->predecessors = newblock2->successors = NULL; + newblock2->firstPCode = newblock2->lastPCode = NULL; + newblock2->pcodeCount = 0; + newblock2->loopWeight = loop->body->loopWeight; + newblock2->flags = 0; + newblock2->blockIndex = pcblockcount++; + + newblock1->nextBlock = newblock2; + newblock2->prevBlock = newblock1; + newblock1->prevBlock = block1; + newblock2->nextBlock = block1->nextBlock; + block1->nextBlock = newblock1; + newblock2->nextBlock->prevBlock = newblock2; + + pclabel(newblock1, makepclabel()); + pclabel(newblock2, makepclabel()); + + changesuccessor(block1, block1->successors->block, newblock1); + + link = lalloc(sizeof(PCLink)); + link->block = newblock2; + link->nextLink = newblock1->successors; + newblock1->successors = link; + + link = lalloc(sizeof(PCLink)); + link->block = newblock1; + link->nextLink = newblock2->predecessors; + newblock2->predecessors = link; + + appendpcode(newblock2, makepcode(PC_B, block2->nextBlock->labels)); + pcbranch(newblock2, block2->nextBlock->labels); + pccomputepredecessors1(newblock2); + + for (scan = block2->firstPCode; scan; scan = scan->nextPCode) + appendpcode(newblock1, copypcode(scan)); + + pcbranch(newblock1, block3->labels); + + link = lalloc(sizeof(PCLink)); + link->block = newblock1; + link->nextLink = block3->predecessors; + block3->predecessors = link; + + addblocktoloop(loop, newblock1); + if (bitvectorgetbit(block2->blockIndex, loop->vec28)) + bitvectorsetbit(newblock1->blockIndex, loop->vec28); + if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) + bitvectorsetbit(newblock1->blockIndex, loop->vec2C); + + for (loop = loop->parent; loop; loop = loop->parent) { + addblocktoloop(loop, newblock1); + if (bitvectorgetbit(block2->blockIndex, loop->vec28)) + bitvectorsetbit(newblock1->blockIndex, loop->vec28); + if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) + bitvectorsetbit(newblock1->blockIndex, loop->vec2C); + + addblocktoloop(loop, newblock2); + if (bitvectorgetbit(block2->blockIndex, loop->vec28)) + bitvectorsetbit(newblock2->blockIndex, loop->vec28); + if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) + bitvectorsetbit(newblock2->blockIndex, loop->vec2C); + } + + return newblock1; +} + +static BlockList *findswitchpath(Loop *loop, PCodeBlock *block) { + BlockList *head; + BlockList *tail; + BlockList *node; + PCodeBlock *scan; + + head = NULL; + tail = NULL; + + for (scan = block; scan && scan != loop->body; scan = scan->successors->block) { + if (!bitvectorgetbit(scan->blockIndex, loop->memberblocks)) + return NULL; + if (scan->successors && scan->successors->nextLink) + return NULL; + + node = oalloc(sizeof(BlockList)); + node->block = scan; + node->next = NULL; + if (head) { + tail->next = node; + tail = node; + } else { + head = node; + tail = node; + } + } + + return head; +} + +static void simpleunswitchloop(Loop *loop) { + PCode *pc29; + PCodeArg *op27; + UInt32 *myvec; + PCodeBlock *block26; + PCode *pc25; // r25 + BlockList *path2_24; + PCodeArg *op23; + PCode *pc23; // r23 + BlockList *scanlist; // r23 + BlockList *bestpath1; // r23 + BlockList *bestpath2; // r22 + PCodeBlock *headercopy; // r22 + Loop *newloop; // r21 + PCodeBlock *preheader21; + BlockList *path20; + PCode *scan20; + PCode *lastpcode; + int i; + BlockList *pathiter1; + BlockList *pathiter2; + + if (!(lastpcode = loop->body->lastPCode)) + return; + if (lastpcode->op != PC_BT && lastpcode->op != PC_BF) + return; + if (lastpcode->args[2].kind != PCOp_LABEL) + return; + if (!bitvectorgetbit(lastpcode->args[2].data.label.label->block->blockIndex, loop->memberblocks)) + return; + if (loop->x57) + return; + if (loop->x4D) + return; + if (bitvectorgetbit(loop->body->nextBlock->blockIndex, loop->memberblocks)) + return; + + for (block26 = pcbasicblocks; block26; block26 = block26->nextBlock) { + if (bitvectorgetbit(block26->blockIndex, loop->memberblocks)) + break; + } + + if (!block26) + return; + + myvec = oalloc(4 * ((number_of_Defs + 31) >> 5)); + bitvectorcopy(myvec, usedefinfo[block26->blockIndex].defvec8, number_of_Defs); + for (pc25 = loop->preheader->nextBlock->firstPCode; pc25; pc25 = pc25->nextPCode) { + if (!(PCODE_FLAG_SET_F(pc25) & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects | fPCodeFlag20000000))) { + if (isloopinvariant(pc25, loop, myvec, 0, 1)) + break; + } + } + + if (!pc25 || pc25->argCount < 1) + return; + + if ( + pc25->argCount < 1 || + pc25->args[0].kind != PCOp_REGISTER || + pc25->args[0].arg != RegClass_CRFIELD + ) + return; + + pc29 = pc25->block->lastPCode; + if ( + !pc29 || + !(pc29->flags & fPCodeFlag1) || + pc29->args[0].kind != PCOp_REGISTER || + pc29->args[0].arg != RegClass_CRFIELD + ) + return; + + if (pc29->args[0].data.reg.reg != pc25->args[0].data.reg.reg) + return; + + op27 = NULL; + for (i = 0; i < pc29->argCount; i++) { + if (pc29->args[i].kind == PCOp_LABEL) + op27 = &pc29->args[i]; + } + + if (op27) { + preheader21 = loop->preheader; + + path20 = findswitchpath(loop, block26->nextBlock); + if (!path20) + return; + + path2_24 = findswitchpath(loop, op27->data.label.label->block); + if (!path2_24) + return; + + bestpath1 = NULL; + bestpath2 = NULL; + for (pathiter1 = path20; pathiter1; pathiter1 = pathiter1->next) { + for (pathiter2 = path2_24; pathiter2; pathiter2 = pathiter2->next) { + if (pathiter1->block == pathiter2->block) { + bestpath1 = pathiter1; + break; + } + } + if (bestpath1) + break; + bestpath2 = pathiter1; + } + +#line 1192 + CError_ASSERT(bestpath2->block); + + if (bestpath2->block->lastPCode && bestpath2->block->lastPCode->op == PC_B) + deletepcode(bestpath2->block->lastPCode); + + while (bestpath1) { + for (scan20 = bestpath1->block->firstPCode; scan20; scan20 = scan20->nextPCode) { + if (scan20->op != PC_B) + appendpcode(bestpath2->block, copypcode(scan20)); + } + bestpath1 = bestpath1->next; + } + + headercopy = appendheadercopy(loop, bestpath2->block, loop->body, block26); + movecmptopreheader(loop, block26, pc25, pc29, op27); + + if (block26->pcodeCount) { + if (path2_24->block->firstPCode) { + pc23 = path2_24->block->firstPCode; + for (scan20 = block26->firstPCode; scan20; scan20 = scan20->nextPCode) { + if (scan20->op != PC_B) + insertpcodebefore(pc23, copypcode(scan20)); + } + } else { + for (scan20 = block26->firstPCode; scan20; scan20 = scan20->nextPCode) { + if (scan20->op != PC_B) + appendpcode(path2_24->block, copypcode(scan20)); + } + } + } + + op23 = NULL; + for (i = 0; i < loop->body->lastPCode->argCount; i++) { + if (loop->body->lastPCode->args[i].kind == PCOp_LABEL) + op23 = &loop->body->lastPCode->args[i]; + } + +#line 1250 + CError_ASSERT(op23 != NULL); + + changesuccessor(loop->body, op23->data.label.label->block, path2_24->block); + op23->data.label.label = path2_24->block->labels; + + op23 = NULL; + for (i = 0; i < preheader21->lastPCode->argCount; i++) { + if (preheader21->lastPCode->args[i].kind == PCOp_LABEL) + op23 = &preheader21->lastPCode->args[i]; + } + +#line 1267 + CError_ASSERT(op23 != NULL); + + changesuccessor(preheader21, op23->data.label.label->block, loop->body); + op23->data.label.label = loop->body->labels; + + op23 = NULL; + for (i = 0; i < loop->preheader->lastPCode->argCount; i++) { + if (loop->preheader->lastPCode->args[i].kind == PCOp_LABEL) + op23 = &loop->preheader->lastPCode->args[i]; + } + +#line 1284 + CError_ASSERT(op23 != NULL); + + changesuccessor(loop->preheader, op23->data.label.label->block, headercopy); + op23->data.label.label = headercopy->labels; + + newloop = lalloc(sizeof(Loop)); + newloop->parent = loop->parent; + newloop->children = NULL; + newloop->nextSibling = loop->nextSibling; + loop->nextSibling = newloop; + newloop->body = loop->body; + newloop->preheader = NULL; + newloop->blocks = NULL; + newloop->basicInductionVars = NULL; + newloop->footer = NULL; + newloop->pc18 = NULL; + newloop->loopWeight = loop->loopWeight; + + bitvectorinitialize(newloop->memberblocks = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(newloop->vec24 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(newloop->vec28 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(newloop->vec2C = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + + removeblockfromloop(loop, newloop->body); + addblocktoloop(newloop, newloop->body); + + bitvectorsetbit(newloop->body->blockIndex, newloop->vec24); + bitvectorsetbit(newloop->body->blockIndex, newloop->vec2C); + bitvectorsetbit(newloop->body->blockIndex, newloop->vec28); + + for (scanlist = path2_24; scanlist; scanlist = scanlist->next) { + removeblockfromloop(loop, scanlist->block); + addblocktoloop(newloop, scanlist->block); + bitvectorsetbit(scanlist->block->blockIndex, newloop->vec2C); + } + + newloop->preheader = NULL; + insertpreheaderblock(newloop); + analyzeloop(newloop); + + loop->body = headercopy; + + for (scanlist = loop->blocks; scanlist; scanlist = scanlist->next) + bitvectorsetbit(scanlist->block->blockIndex, loop->vec2C); + + bitvectorsetbit(headercopy->blockIndex, loop->vec24); + analyzeloop(loop); + + unswitchedinvariantcode = 1; + } +} + +static void simpleunswitchloops(Loop *loop) { + while (loop) { + if (loop->children) + simpleunswitchloops(loop->children); + else if (!loop->x4F) + simpleunswitchloop(loop); + loop = loop->nextSibling; + } +} + +static void moveinvariantsfromloop(Loop *loop) { + RegUseOrDef *list; + BlockList *blocklist; + PCode *instr; + PCode *nextInstr; + UInt32 *myvec; + UseOrDef *def; + int defID; + int flag; + PCodeBlock *block; + + myvec = oalloc(4 * ((number_of_Defs + 31) >> 5)); + do { + flag = 0; + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + block = blocklist->block; + bitvectorcopy(myvec, usedefinfo[block->blockIndex].defvec8, number_of_Defs); + for (instr = block->firstPCode; instr; instr = nextInstr) { + nextInstr = instr->nextPCode; + if (!(instr->flags & fPCodeFlag1) && instr->argCount) { + if ( + !(instr->flags & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects)) && + isloopinvariant(instr, loop, myvec, 0, 0) && + maymove(instr, loop) + ) { + moveinvariantcomputation(instr, loop); + flag = 1; + } else if (srawi_addze_isloopinvariant(instr, loop, myvec)) { + moveinvariantcomputation(instr, loop); + flag = 1; + } + + for (def = &Defs[defID = instr->defID]; defID < number_of_Defs && def->pcode == instr; def++, defID++) { + if (def->v.kind == PCOp_REGISTER) { + for (list = reg_Defs[(char) def->v.arg][def->v.u.reg]; list; list = list->next) + bitvectorclearbit(list->id, myvec); + } else if (def->v.kind == PCOp_MEMORY) { + if ((char) def->v.arg == 0) { + for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { + if (uniquely_aliases(instr, Defs[list->id].pcode)) + bitvectorclearbit(list->id, myvec); + } + } + } else { +#line 1434 + CError_FATAL(); + } + + bitvectorsetbit(defID, myvec); + } + } + } + } + } while (flag); +} + +static void moveinvariantsfromloops(Loop *loop) { + while (loop) { + if (loop->children) + moveinvariantsfromloops(loop->children); + moveinvariantsfromloop(loop); + loop = loop->nextSibling; + } +} + +void moveloopinvariantcode(void) { + unswitchedinvariantcode = 0; + movedloopinvariantcode = 0; + if (loopsinflowgraph) { + moveinvariantsfromloops(loopsinflowgraph); + simpleunswitchloops(loopsinflowgraph); + } + freeoheap(); +} diff --git a/compiler_and_linker/unsorted/Coloring.c b/compiler_and_linker/unsorted/Coloring.c index e69de29..9ba3c28 100644 --- a/compiler_and_linker/unsorted/Coloring.c +++ b/compiler_and_linker/unsorted/Coloring.c @@ -0,0 +1,268 @@ +#include "compiler/Coloring.h" +#include "compiler/CFunc.h" +#include "compiler/CompilerTools.h" +#include "compiler/InterferenceGraph.h" +#include "compiler/PCode.h" +#include "compiler/PPCError.h" +#include "compiler/Registers.h" +#include "compiler/RegisterInfo.h" +#include "compiler/SpillCode.h" +#include "compiler/StackFrame.h" +#include "compiler/objects.h" + +char coloring_class; +static short used_regs_before_coloring; + +static void markspecialregisters(RegClass rclass) { + ObjectList *list; + Object *object; + VarInfo *vi; + UInt32 i; + + for (i = 0; i < n_real_registers[rclass]; i++) + interferencegraph[i]->x14 = i; + + for (list = arguments; list; list = list->next) { + object = list->object; + vi = Registers_GetVarInfo(object); + if ((vi->flags & VarInfoFlag2) && vi->rclass == rclass) { + interferencegraph[vi->reg]->spillTemporary = object; + if (vi->flags & VarInfoFlag4) { + interferencegraph[vi->reg]->flags |= fPairLow; + interferencegraph[vi->regHi]->flags |= fPairHigh; + interferencegraph[vi->regHi]->spillTemporary = object; + } + } + } + + for (list = locals; list; list = list->next) { + object = list->object; + vi = Registers_GetVarInfo(object); + if ((vi->flags & VarInfoFlag2) && vi->rclass == rclass) { + interferencegraph[vi->reg]->spillTemporary = object; + if (vi->flags & VarInfoFlag4) { + interferencegraph[vi->reg]->flags |= fPairLow; + interferencegraph[vi->regHi]->flags |= fPairHigh; + interferencegraph[vi->regHi]->spillTemporary = object; + } + } + } +} + +static IGNode *simplifygraph(void) { + int availableRegs; + IGNode *spilledNodes; + IGNode *pushedNodes; + IGNode *best; + IGNode *node; + UInt32 i; + UInt32 j; + int flag; + float bestScore; + float score; + + availableRegs = available_registers(coloring_class); + pushedNodes = NULL; + + do { + spilledNodes = NULL; + flag = 0; + for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) { + node = interferencegraph[i]; + if (!(node->flags & (fPushed | fCoalesced))) { + if (node->x12 < availableRegs) { + for (j = 0; j < node->arraySize; j++) + interferencegraph[node->array[j]]->x12--; + node->flags |= fPushed; + node->next = pushedNodes; + pushedNodes = node; + flag = 1; + } else { + node->next = spilledNodes; + spilledNodes = node; + } + } + } + } while (flag); + + if (spilledNodes) + estimatespillcosts(); + + while (spilledNodes) { + best = spilledNodes; + bestScore = (spilledNodes->x10 >= used_regs_before_coloring) ? FLT_MAX : ((float) spilledNodes->spillCost / (float) spilledNodes->x12); + + for (node = spilledNodes->next; node; node = node->next) { + score = (node->x10 >= used_regs_before_coloring) ? FLT_MAX : ((float) node->spillCost / (float) node->x12); + if (score < bestScore) { + best = node; + bestScore = score; + } + } + + for (i = 0; i < best->arraySize; i++) + interferencegraph[best->array[i]]->x12--; + + best->flags |= fPushed; + best->next = pushedNodes; + pushedNodes = best; + + do { + spilledNodes = NULL; + flag = 0; + for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) { + node = interferencegraph[i]; + if (!(node->flags & (fPushed | fCoalesced))) { + if (node->x12 < availableRegs) { + for (j = 0; j < node->arraySize; j++) + interferencegraph[node->array[j]]->x12--; + node->flags |= fPushed; + node->next = pushedNodes; + pushedNodes = node; + flag = 1; + } else { + node->next = spilledNodes; + spilledNodes = node; + } + } + } + } while (flag); + } + + return pushedNodes; +} + +static int colorgraph(IGNode *node) { + UInt32 volatileRegs; + int result; + IGNode *otherNode; + int reg; + UInt32 workingMask; + int i; + short *array; + + result = 1; + + reset_nonvolatile_registers(coloring_class); + volatileRegs = volatile_registers(coloring_class); + + while (node) { + workingMask = volatileRegs; + for (array = node->array, i = 0; i < node->arraySize; i++) { + otherNode = interferencegraph[*(array++)]; + reg = otherNode->x14; + if (reg != -1 && reg < n_real_registers[coloring_class]) + workingMask &= ~(1 << reg); + } + + if (workingMask) { + for (i = 0; i < n_real_registers[coloring_class]; i++) { + if (workingMask & (1 << i)) { + node->x14 = i; + break; + } + } + } else { + reg = obtain_nonvolatile_register(coloring_class); + if (reg != -1) { + volatileRegs |= 1 << (node->x14 = reg); + } else { + node->flags |= fSpilled; + result = 0; + } + } + + node = node->next; + } + + return result; +} + +static void rewritepcode(void) { + PCodeBlock *block; + PCode *instr; + PCodeArg *op; + UInt32 i; + IGNode *node; + int reg; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if (PC_OP_IS_ANY_REGISTER(op, coloring_class)) + op->data.reg.reg = interferencegraph[op->data.reg.reg]->x14; + op++; + } + + if ( + (instr->flags & fPCodeFlag10) && + ((char) instr->args[1].arg == coloring_class) && + instr->args[1].data.reg.reg == instr->args[0].data.reg.reg + ) + deletepcode(instr); + } + } + + for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) { + node = interferencegraph[i]; + if (node->spillTemporary && !(node->flags & fSpilled)) { + if (node->flags & fCoalesced) { + reg = node->x14; + while (reg >= n_real_registers[coloring_class]) { + reg = interferencegraph[reg]->x14; + if (reg < 0) + break; + } + node->x14 = reg; + } + + if (node->flags & fPairHigh) { + reg = node->x14; + Registers_GetVarInfo(node->spillTemporary)->regHi = reg; + } else { + reg = node->x14; + Registers_GetVarInfo(node->spillTemporary)->reg = reg; + } + } + } +} + +void colorinstructions(Object *proc) { + RegClass rclass; + int flag; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + coloring_class = rclass; + + if (rclass == RegClass_GPR) + check_dynamic_aligned_frame(); + + if (used_virtual_registers[rclass] > n_real_registers[rclass]) { + save_before_coloring_nonvolatile_registers(rclass); + used_regs_before_coloring = used_virtual_registers[rclass]; + if (!available_registers(rclass)) { + PPCError_Error(102, register_class_name[rclass]); + return; + } + + flag = 1; + while (flag && used_virtual_registers[rclass] > n_real_registers[rclass]) { + buildinterferencegraph(proc); + markspecialregisters(rclass); + flag = colorgraph(simplifygraph()) ? 0 : 1; + + if (flag) + insertspillcode(); + else + rewritepcode(); + freeoheap(); + } + } + + used_virtual_registers[rclass] = n_real_registers[rclass]; + } + + coloring = 0; +} diff --git a/compiler_and_linker/unsorted/ConstantPropagation.c b/compiler_and_linker/unsorted/ConstantPropagation.c index e69de29..4fe1d06 100644 --- a/compiler_and_linker/unsorted/ConstantPropagation.c +++ b/compiler_and_linker/unsorted/ConstantPropagation.c @@ -0,0 +1,643 @@ +#include "compiler/ConstantPropagation.h" +#include "compiler/Alias.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/UseDefChains.h" +#include "compiler/objects.h" + +int propagatedconstants; +static int changed; +static PCode **defininginstruction; +static PCode **vrdefininginstruction; + +static void computedefininginstructions(PCodeBlock *block) { + RegUseOrDef *list; + PCode *instr; + int i; + + for (i = 0; i < used_virtual_registers[RegClass_GPR]; i++) { + instr = NULL; + for (list = reg_Defs[RegClass_GPR][i]; list; list = list->next) { + if (bitvectorgetbit(list->id, usedefinfo[block->blockIndex].defvec8)) { + if (instr == NULL) { + instr = Defs[list->id].pcode; + } else { + instr = NULL; + break; + } + } + } + defininginstruction[i] = instr; + } + + for (i = 0; i < used_virtual_registers[RegClass_VR]; i++) { + instr = NULL; + for (list = reg_Defs[RegClass_VR][i]; list; list = list->next) { + if (bitvectorgetbit(list->id, usedefinfo[block->blockIndex].defvec8)) { + if (instr == NULL) { + instr = Defs[list->id].pcode; + } else { + instr = NULL; + break; + } + } + } + vrdefininginstruction[i] = instr; + } +} + +static PCode *isstackoperand(PCodeArg *op, SInt16 *resultValue, SInt16 addend) { + PCode *instr; + + if ((instr = defininginstruction[op->data.reg.reg]) && instr->op == PC_ADDI) { + if ( + instr->args[2].kind == PCOp_MEMORY && + (instr->args[1].data.reg.reg == _FP_ || instr->args[1].data.reg.reg == _CALLER_SP_) && + instr->args[2].data.mem.obj->datatype == DLOCAL + ) + { + if (can_add_displ_to_local(instr->args[2].data.mem.obj, addend)) { + *resultValue = instr->args[2].data.mem.offset; + return instr; + } else { + return NULL; + } + } else { + return NULL; + } + } else { + return NULL; + } +} + +static int isconstantoperand(PCodeArg *op, SInt16 *resultValue) { + PCode *instr; + + if ( + (instr = defininginstruction[op->data.reg.reg]) && + instr->op == PC_LI && + instr->args[1].kind == PCOp_IMMEDIATE + ) + { + *resultValue = instr->args[1].data.imm.value; + return 1; + } else { + return 0; + } +} + +static int isuint16constantoperand(PCodeArg *op, SInt16 *resultValue) { + PCode *instr; + + if ( + (instr = defininginstruction[op->data.reg.reg]) && + instr->op == PC_LI && + instr->args[1].kind == PCOp_IMMEDIATE && + FITS_IN_USHORT(instr->args[1].data.imm.value) + ) + { + *resultValue = instr->args[1].data.imm.value; + return 1; + } else { + return 0; + } +} + +static int isvectorconstantoperand(PCodeArg *op, SInt16 *resultValue, Opcode *resultNewOp) { + PCode *instr; + + if ( + (instr = vrdefininginstruction[op->data.reg.reg]) && + (instr->op == PC_VSPLTISB || instr->op == PC_VSPLTISH || instr->op == PC_VSPLTISW) && + instr->args[1].kind == PCOp_IMMEDIATE + ) + { + *resultValue = instr->args[1].data.imm.value; + *resultNewOp = instr->op; + return 1; + } else { + return 0; + } +} + +static int isunsignedloadoperand(PCodeArg *op) { + PCode *instr; + + if ((instr = defininginstruction[op->data.reg.reg])) { + if (instr->flags & fPCodeFlag2) { + if (instr->op >= PC_LHZ && instr->op <= PC_LHZUX) + return 2; + if (instr->op >= PC_LBZ && instr->op <= PC_LBZUX) + return 1; + } else if (instr->op == PC_RLWINM) { + int var3 = instr->args[3].data.imm.value; + int var4 = instr->args[4].data.imm.value; + if (var4 == 31) { + if (var3 == 24) + return 1; + if (var3 == 16) + return 2; + } + } + } + + return 0; +} + +static int ismaskedoperand(PCodeArg *op, UInt32 *resultMask) { + PCode *instr; + UInt32 mask; + + if ((instr = defininginstruction[op->data.reg.reg]) && instr->op == PC_RLWINM) { + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) { + mask = + ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) & + ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); + } else { + mask = + ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) | + ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); + } + *resultMask = mask; + return 1; + } + + return 0; +} + +static int issignedloadoperand(PCodeArg *op) { + PCode *instr; + + if ((instr = defininginstruction[op->data.reg.reg])) { + if (instr->flags & fPCodeFlag2) { + if (instr->op >= PC_LHA && instr->op <= PC_LHAUX) + return 2; + } else if (instr->op == PC_EXTSB) { + return 1; + } else if (instr->op == PC_EXTSH) { + return 2; + } + } + + return 0; +} + +static void propagateconstantstoblock(PCodeBlock *block) { + PCode *instr; + SInt16 immAddend; + SInt16 value1; + SInt16 valueU16; + Opcode newOpcode; + SInt16 value2; + UInt32 mask; + UInt32 mask2; + int loadSize; + PCodeArg *op; + int i; + + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + switch (instr->op) { + case PC_MR: + if (isconstantoperand(&instr->args[1], &value1)) { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value1; + instr->args[1].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } + break; + case PC_VMR: + if (isvectorconstantoperand(&instr->args[1], &value1, &newOpcode)) { + change_opcode(instr, newOpcode); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value1; + instr->args[1].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } + break; + case PC_RLWINM: + if ( + !(PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) && + instr->args[2].data.imm.value == 0 && + instr->args[4].data.imm.value == 31 + ) + { + if (isconstantoperand(&instr->args[1], &value1)) { + if ( + (instr->args[3].data.imm.value == 16 && value1 == (value1 & 0x7FFF)) || + (instr->args[3].data.imm.value == 24 && value1 == (value1 & 0xFF)) + ) + { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + break; + } + } + + loadSize = isunsignedloadoperand(&instr->args[1]); + if ( + (loadSize == 2 && instr->args[3].data.imm.value <= 16) || + (loadSize == 1 && instr->args[3].data.imm.value <= 24) + ) + { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + break; + } + + if (ismaskedoperand(&instr->args[1], &mask)) { + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) { + mask2 = + ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) & + ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); + } else { + mask2 = + ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) | + ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); + } + if (mask == (mask & mask2)) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + } + } + break; + + case PC_EXTSH: + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + break; + + if (isconstantoperand(&instr->args[1], &value1)) { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + break; + } + + loadSize = issignedloadoperand(&instr->args[1]); + if (loadSize == 1 || loadSize == 2) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + break; + + case PC_EXTSB: + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + break; + + if ( + isconstantoperand(&instr->args[1], &value1) && + value1 >= -128 && + value1 <= 127 + ) + { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + break; + } + + loadSize = issignedloadoperand(&instr->args[1]); + if (loadSize == 1) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + break; + + case PC_ADDI: + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + break; + + immAddend = instr->args[2].data.imm.value; + if ( + isconstantoperand(&instr->args[1], &value1) && + FITS_IN_SHORT(immAddend + value1) + ) + { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = immAddend + value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + break; + + case PC_ADD: + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + break; + + if (isconstantoperand(&instr->args[2], &value1)) { + if (value1 == 0) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + } else { + change_opcode(instr, PC_ADDI); + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = value1; + instr->args[2].data.imm.obj = NULL; + } + propagatedconstants = 1; + changed = 1; + immAddend = value1; + } + + if (isconstantoperand(&instr->args[1], &value1)) { + if (instr->op == PC_ADDI || instr->op == PC_MR) { + if (FITS_IN_SHORT(immAddend + value1)) { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = immAddend + value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + } else { + instr->args[1] = instr->args[2]; + if (value1 == 0) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + } else { + change_opcode(instr, PC_ADDI); + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = value1; + instr->args[2].data.imm.obj = NULL; + } + propagatedconstants = 1; + changed = 1; + } + } + + if (changed) { + if (instr->op == PC_MR) { + PCode *stackInstr; + if ((stackInstr = isstackoperand(&instr->args[1], &value1, 0))) { + change_opcode(instr, PC_ADDI); + instr->flags = stackInstr->flags; + instr->args[1] = stackInstr->args[1]; + instr->args[2] = stackInstr->args[2]; + change_num_operands(instr, 3); + propagatedconstants = 1; + changed = 1; + } + } else if (instr->op == PC_ADDI && instr->args[2].kind == PCOp_IMMEDIATE) { + PCode *stackInstr; + SInt16 addend = instr->args[2].data.imm.value; + if ((stackInstr = isstackoperand(&instr->args[1], &value1, addend))) { + change_opcode(instr, PC_ADDI); + instr->flags = stackInstr->flags; + instr->args[1] = stackInstr->args[1]; + instr->args[2] = stackInstr->args[2]; + instr->args[2].data.imm.value = value1 + addend; + if (instr->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) + instr->alias = make_alias(instr->args[2].data.imm.obj, instr->args[2].data.imm.value, 1); + propagatedconstants = 1; + changed = 1; + } + } + } + break; + + case PC_OR: + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + break; + + value1 = 0; + immAddend = 0; + if (isconstantoperand(&instr->args[2], &value1)) { + if (isuint16constantoperand(&instr->args[2], &valueU16)) { + if (valueU16 != 0) { + change_opcode(instr, PC_ORI); + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = valueU16; + instr->args[2].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } else { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + value1 = valueU16; + } else if (value1 == 0) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + immAddend = value1; + } + + if (isconstantoperand(&instr->args[1], &value1)) { + if (instr->op == PC_ORI || instr->op == PC_MR) { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = immAddend | value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } else if (isuint16constantoperand(&instr->args[1], &valueU16)) { + if (valueU16 != 0) { + change_opcode(instr, PC_ORI); + instr->args[1] = instr->args[2]; + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = valueU16; + instr->args[2].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } else { + change_opcode(instr, PC_MR); + instr->args[1] = instr->args[2]; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + } else if (value1 == 0) { + change_opcode(instr, PC_MR); + instr->args[1] = instr->args[2]; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + } + break; + + case PC_SUBF: + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + break; + + if (isconstantoperand(&instr->args[1], &value1) && FITS_IN_SHORT(-value1)) { + if (isconstantoperand(&instr->args[2], &value2) && FITS_IN_SHORT(value2 - value1)) { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value2 - value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + } else if (value1 == 0) { + change_opcode(instr, PC_MR); + instr->args[1] = instr->args[2]; + change_num_operands(instr, 2); + } else { + change_opcode(instr, PC_ADDI); + instr->args[1] = instr->args[2]; + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = -value1; + instr->args[2].data.imm.obj = NULL; + } + propagatedconstants = 1; + changed = 1; + value2 = value1; + } else if (isconstantoperand(&instr->args[2], &value1) && FITS_IN_SHORT(-value1)) { + if (value1 == 0) { + change_opcode(instr, PC_NEG); + change_num_operands(instr, 2); + } else { + instr->flags = opcodeinfo[PC_SUBFIC].flags | (instr->flags & ~opcodeinfo[PC_SUBF].flags); + change_opcode(instr, PC_SUBFIC); + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = value1; + instr->args[2].data.imm.obj = NULL; + instr->args[3].kind = PCOp_REGISTER; + instr->args[3].arg = RegClass_SPR; + instr->args[3].data.reg.reg = 0; + instr->args[3].data.reg.effect = EffectWrite; + change_num_operands(instr, 4); + } + propagatedconstants = 1; + changed = 1; + } + + break; + + case PC_LBZ: + case PC_LHZ: + case PC_LHA: + case PC_LWZ: + case PC_STB: + case PC_STH: + case PC_STW: + case PC_LFS: + case PC_LFD: + case PC_STFS: + case PC_STFD: + if (instr->args[2].kind == PCOp_IMMEDIATE) { + PCode *stackInstr; + SInt16 addend = instr->args[2].data.imm.value; + + if ((stackInstr = isstackoperand(&instr->args[1], &value1, addend))) { + instr->args[1] = stackInstr->args[1]; + instr->args[2] = stackInstr->args[2]; + instr->args[2].data.imm.value = value1 + addend; + if (instr->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) + instr->alias = make_alias(instr->args[2].data.imm.obj, instr->args[2].data.imm.value, + nbytes_loaded_or_stored_by(instr)); + propagatedconstants = 1; + changed = 1; + } + } + break; + + case PC_LBZX: + case PC_LHZX: + case PC_LHAX: + case PC_LWZX: + case PC_STBX: + case PC_STHX: + case PC_STWX: + case PC_LFSX: + case PC_LFDX: + case PC_STFSX: + case PC_STFDX: + if (isconstantoperand(&instr->args[2], &value1)) { + instr->op -= 2; + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = value1; + instr->args[2].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } else if (isconstantoperand(&instr->args[1], &value1)) { + instr->op -= 2; + instr->args[1] = instr->args[2]; + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = value1; + instr->args[2].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } + + break; + } + + for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) + ) + { + defininginstruction[op->data.reg.reg] = instr; + } + else if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_VR && + (op->data.reg.effect & EffectWrite) + ) + { + vrdefininginstruction[op->data.reg.reg] = instr; + } + } + } +} + +void propagateconstants(void) { + PCodeBlock *block; + int i; + + propagatedconstants = 0; + computeusedefchains(0); + defininginstruction = galloc(sizeof(PCode *) * used_virtual_registers[RegClass_GPR]); + vrdefininginstruction = galloc(sizeof(PCode *) * used_virtual_registers[RegClass_VR]); + + do { + changed = 0; + for (i = 0; i < pcblockcount; i++) { + if ((block = depthfirstordering[i])) { + computedefininginstructions(block); + propagateconstantstoblock(block); + } + } + } while (changed); + + freeoheap(); +} diff --git a/compiler_and_linker/unsorted/CopyPropagation.c b/compiler_and_linker/unsorted/CopyPropagation.c index e69de29..23583b1 100644 --- a/compiler_and_linker/unsorted/CopyPropagation.c +++ b/compiler_and_linker/unsorted/CopyPropagation.c @@ -0,0 +1,474 @@ +#include "compiler/CopyPropagation.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/UseDefChains.h" +#include "compiler/PCode.h" +#include "compiler/RegisterInfo.h" +#include "compiler/BitVectors.h" + +// TODO move me +extern void pclistblocks(char *, char *); + +int propagatedcopies; +int propagated_instructions; +int recursive_propagation; +int number_of_candidates; +Candidate *Candidates; +PropInfo *propinfo; +int *ncandidatesinblock; +int *firstcandidateinblock; +static int moreaggressiveoptimization; +static PropagateAndFinishFunc propagateandfinish; +static PropagatesToUseFunc propagatestouse; +static IsCandidateFunc is_candidate; + +static void precomputecanidatecounts(void) { + PCodeBlock *block; + PCode *pcode; + int count; + + ncandidatesinblock = oalloc(sizeof(int) * pcblockcount); + firstcandidateinblock = oalloc(sizeof(int) * pcblockcount); + number_of_candidates = 0; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + firstcandidateinblock[block->blockIndex] = number_of_candidates; + + count = 0; + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if (is_candidate(pcode)) { + number_of_candidates++; + count++; + } + } + ncandidatesinblock[block->blockIndex] = count; + } +} + +static void computecandidatelist(void) { + RegUseOrDef *list; // r23 + PCodeBlock *block; // r22 + PCode *pcode; // r21 + Candidate *candidate; // r20 + UInt32 *vec; // r19 + int reg; + RegUseOrDef *newlist; + UseOrDef *def; + UseOrDef *use; + int defID; + int useID; + + Candidates = oalloc(sizeof(Candidate) * number_of_candidates); + vec = oalloc(4 * ((number_of_Uses + 31) >> 5)); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (ncandidatesinblock[block->blockIndex]) { + bitvectorcopy(vec, usedefinfo[block->blockIndex].usevec1C, number_of_Uses); + candidate = &Candidates[firstcandidateinblock[block->blockIndex] + ncandidatesinblock[block->blockIndex] - 1]; + for (pcode = block->lastPCode; pcode; pcode = pcode->prevPCode) { + if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) { + if (is_candidate(pcode)) { + reg = pcode->args[0].data.reg.reg; + candidate->pcode = pcode; + candidate->list = NULL; + + for (list = reg_Uses[pcode->args[0].arg][reg]; list; list = list->next) { + if (bitvectorgetbit(list->id, vec)) { + newlist = oalloc(sizeof(RegUseOrDef)); + newlist->id = list->id; + newlist->next = candidate->list; + candidate->list = newlist; + } + } + + if ((pcode->flags & fPCodeFlag2 | fPCodeFlag4) && (pcode->flags & fPCodeFlag2000000)) { + for (list = reg_Uses[pcode->args[1].arg][pcode->args[1].data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(list->id, vec)) { + newlist = oalloc(sizeof(RegUseOrDef)); + newlist->id = list->id; + newlist->next = candidate->list; + candidate->list = newlist; + } + } + } + + candidate--; + } + + for (def = &Defs[defID = pcode->defID]; defID < number_of_Defs && def->pcode == pcode; def++, defID++) { + if (def->kind == PCOp_REGISTER) { + for (list = reg_Uses[def->arg][def->u.reg]; list; list = list->next) + bitvectorclearbit(list->id, vec); + } + } + for (use = &Uses[useID = pcode->useID]; useID < number_of_Uses && use->pcode == pcode; use++, useID++) { + if (use->kind == PCOp_REGISTER) + bitvectorsetbit(useID, vec); + } + } + } + } + } +} + +static void allocatepropinfo(void) { + PropInfo *info; + int i; + + propinfo = oalloc(sizeof(PropInfo) * pcblockcount); + for (i = 0, info = propinfo; i < pcblockcount; i++, info++) { + info->vec0 = oalloc(4 * ((number_of_candidates + 31) >> 5)); + info->vec4 = oalloc(4 * ((number_of_candidates + 31) >> 5)); + info->vec8 = oalloc(4 * ((number_of_candidates + 31) >> 5)); + info->vecC = oalloc(4 * ((number_of_candidates + 31) >> 5)); + } +} + +static void computelocalpropinfo(Boolean flag) { + PropInfo *info; + PCode *pcode; + PCodeBlock *block; + UInt32 *vec0; + UInt32 *vec4; + int index; + PCodeArg *op; + PCodeArg *candOp; + int i; + int j; + int cndi; + Candidate *candidate; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + info = &propinfo[block->blockIndex]; + vec0 = info->vec0; + vec4 = info->vec4; + bitvectorinitialize(vec0, number_of_candidates, 0); + bitvectorinitialize(vec4, number_of_candidates, 0); + index = firstcandidateinblock[block->blockIndex]; + + if (flag) { + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) { + i = pcode->argCount; + op = pcode->args; + while (i--) { + if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR && (op->data.reg.effect & EffectWrite)) { + for (cndi = 0, candidate = Candidates; cndi < number_of_candidates; cndi++, candidate++) { + for (j = 0; j < candidate->pcode->argCount; j++) { + candOp = candidate->pcode->args + j; + if (candOp->kind == PCOp_REGISTER && candOp->arg == RegClass_GPR && candOp->data.reg.reg == op->data.reg.reg) { + if (candidate->pcode->block == block) + bitvectorclearbit(cndi, vec0); + else + bitvectorsetbit(cndi, vec4); + break; + } + } + } + } + op++; + } + + if (is_candidate(pcode)) { + bitvectorsetbit(index, vec0); + index++; + } + } + } + } else { + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) { + i = pcode->argCount; + op = pcode->args; + while (i--) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) { + for (cndi = 0, candidate = Candidates; cndi < number_of_candidates; cndi++, candidate++) { + for (j = 0; j < candidate->pcode->argCount; j++) { + candOp = candidate->pcode->args + j; + if (candOp->kind == PCOp_REGISTER && candOp->arg == op->arg) { + if (candOp->data.reg.reg == op->data.reg.reg) { + if (candidate->pcode->block == block) + bitvectorclearbit(cndi, vec0); + else + bitvectorsetbit(cndi, vec4); + break; + } + } else { + if (j == 0) + break; + } + } + } + } + op++; + } + + if (is_candidate(pcode)) { + bitvectorsetbit(index, vec0); + index++; + } + } + } + } + } +} + +static void computeglobalpropinfo(void) { + PropInfo *info; + PCodeBlock *block; + int bitvecsize; + UInt32 *vec0; + UInt32 *vec4; + UInt32 *vec8; + UInt32 *vecC; + int i; + int j; + int flag; + PCLink *preds; + UInt32 val; + + bitvecsize = (number_of_candidates + 31) >> 5; + flag = 1; + info = &propinfo[pcbasicblocks->blockIndex]; + bitvectorinitialize(info->vec8, number_of_candidates, 0); + bitvectorcopy(info->vecC, info->vec0, number_of_candidates); + + for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) { + info = &propinfo[block->blockIndex]; + vecC = info->vecC; + vec4 = info->vec4; + for (i = 0; i < bitvecsize; vecC++, vec4++, i++) + *vecC = ~*vec4; + } + + while (flag) { + flag = 0; + for (i = 0; i < pcblockcount; i++) { + if (depthfirstordering[i]) { + info = &propinfo[depthfirstordering[i]->blockIndex]; + if ((preds = depthfirstordering[i]->predecessors)) { + vec8 = info->vec8; + bitvectorcopy(vec8, propinfo[preds->block->blockIndex].vecC, number_of_candidates); + for (preds = preds->nextLink; preds; preds = preds->nextLink) + bitvectorintersect(vec8, propinfo[preds->block->blockIndex].vecC, number_of_candidates); + } + + vecC = info->vecC; + vec8 = info->vec8; + vec0 = info->vec0; + vec4 = info->vec4; + for (j = 0; j < bitvecsize; j++) { + val = *vec0 | (*vec8 & ~*vec4); + if (val != *vecC) { + *vecC = val; + flag = 1; + } + vec8++; + vecC++; + vec4++; + vec0++; + } + } + } + } +} + +int precedes(PCode *a, PCode *b) { + PCode *scan; + + for (scan = a->nextPCode; scan; scan = scan->nextPCode) { + if (scan == b) + return 1; + } + + return 0; +} + +static int canidatepropagatestoalluses(int id) { + RegUseOrDef *list; + + if (PCODE_FLAG_SET_F(Candidates[id].pcode) & (fPCodeFlag20000000 | fSideEffects)) + return 0; + + for (list = Candidates[id].list; list; list = list->next) { + if (!propagatestouse(id, list->id)) + return 0; + } + + return 1; +} + +static void propagatecandidates(void) { + int i; + + for (i = 0; i < number_of_candidates; i++) { + if (canidatepropagatestoalluses(i)) + propagateandfinish(i); + } +} + +void propagateinstructions(Object *proc, Propagation *config, int passCount, Boolean localflag) { + char buf[64]; + + is_candidate = config->is_candidate; + propagatestouse = config->propagatestouse; + propagateandfinish = config->propagateandfinish; + propagated_instructions = 0; + + while (1) { + recursive_propagation = 0; + precomputecanidatecounts(); + if (number_of_candidates <= 0) { + freeoheap(); + if (config->computesUseDefChains) + computeusedefchains(0); + return; + } + + computeusedefchains(0); + computecandidatelist(); + allocatepropinfo(); + computelocalpropinfo(localflag); + computedepthfirstordering(); + computeglobalpropinfo(); + propagatecandidates(); + passCount--; + + if (propagated_instructions && copts.debuglisting) { + sprintf(buf, "AFTER %s PROPAGATION", config->name); + pclistblocks(CMangler_GetLinkName(proc)->name, buf); + } + + if (!passCount || !recursive_propagation) { + if (!config->computesUseDefChains) + freeoheap(); + return; + } + + freeoheap(); + } +} + +static int is_copy(PCode *pcode) { + return (pcode->flags & fPCodeFlag10) && (pcode->args[0].data.reg.reg >= n_real_registers[pcode->args[0].arg]); +} + +static int copypropagatestouse(int candidateID, int useID) { + UseOrDef *use; + short reg1; + short reg2; + char rclass; + PCode *pcode; + int i; + PCode *scan; + PCodeArg *op; + + pcode = Candidates[candidateID].pcode; + use = Uses + useID; + rclass = pcode->args[0].arg; + reg1 = pcode->args[0].data.reg.reg; + reg2 = pcode->args[1].data.reg.reg; + + if (use->pcode->flags & fPCodeFlag10) + return 0; + + if (rclass == RegClass_GPR && use->pcode->op == PC_RLWIMI && use->pcode->args[0].data.reg.reg == reg1) + return 0; + + if (pcode->block == use->pcode->block && precedes(pcode, use->pcode)) { + for (scan = pcode->nextPCode; scan && scan != use->pcode; scan = scan->nextPCode) { + op = scan->args; + i = scan->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == rclass && + (op->data.reg.effect & EffectWrite) && + op->data.reg.reg == reg2 + ) + return 0; + op++; + } + } + } else { + if (!bitvectorgetbit(candidateID, propinfo[use->pcode->block->blockIndex].vec8)) + return 0; + + for (scan = use->pcode->block->firstPCode; scan; scan = scan->nextPCode) { + op = scan->args; + i = scan->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == rclass && + (op->data.reg.effect & EffectWrite) && + op->data.reg.reg == reg2 + ) + return 0; + op++; + } + if (scan == use->pcode) + break; + } + } + + return 1; +} + +static void propagateandremovecopy(int id) { + Candidate *candidate; + unsigned char rclass; + short reg1; + short reg2; + RegUseOrDef *list; + int i; + PCodeArg *op; + + candidate = &Candidates[id]; + rclass = candidate->pcode->args[0].arg; + reg1 = candidate->pcode->args[0].data.reg.reg; + reg2 = candidate->pcode->args[1].data.reg.reg; + + if (rclass == RegClass_GPR && reg1 >= 32 && reg1 <= last_exception_register[RegClass_GPR]) + return; + + if (!moreaggressiveoptimization && reg2 < n_real_registers[(char) rclass]) + return; + + for (list = candidate->list; list; list = list->next) { + op = Uses[list->id].pcode->args; + i = Uses[list->id].pcode->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == (char) rclass && + op->data.reg.reg == reg1 && + (op->data.reg.effect & EffectRead) + ) + op->data.reg.reg = reg2; + op++; + } + } + + deletepcode(candidate->pcode); + propagated_instructions = 1; +} + +static Propagation copy_prop = { + &is_copy, + ©propagatestouse, + &propagateandremovecopy, + "COPY", + "COPIES", + "c%ld", + 0 +}; + +void propagatecopyinstructions(Object *proc, int flag) { + moreaggressiveoptimization = flag; + propagateinstructions(proc, ©_prop, 1, 0); + propagatedcopies = propagated_instructions; +} + diff --git a/compiler_and_linker/unsorted/IROUseDef.c b/compiler_and_linker/unsorted/IROUseDef.c index e69de29..943e557 100644 --- a/compiler_and_linker/unsorted/IROUseDef.c +++ b/compiler_and_linker/unsorted/IROUseDef.c @@ -0,0 +1,1448 @@ +#include "compiler/IROUseDef.h" +#include "compiler/IRODump.h" +#include "compiler/IROVars.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroMalloc.h" +#include "compiler/IroPointerAnalysis.h" +#include "compiler/IroTransform.h" +#include "compiler/IroUtil.h" +#include "compiler/CompilerTools.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmPPC.h" + +ENodeType IRO_NonAssignmentOp[MAXEXPR]; +typedef CInt64 (*AssignmentFoldingFunc)(CInt64, CInt64); +static AssignmentFoldingFunc AssignmentFoldingFunction[MAXEXPR]; +static SInt32 NumDefs; +static IRODef *FirstDef; +static IRODef *LastDef; +static SInt32 NumUses; +static BitVector *Reaches; +static BitVector *MightReachAnyUse; +static BitVector *alldefs; +static BitVector *alluses; +static BitVector *defset; +static BitVector *useset; +IROUse *IRO_FirstVarUse; +IROUse *IRO_LastVarUse; + +// forward decls +static void AddDefToRange(IRODef *def); + +static void MakeDef(VarRecord *var, IROLinear *linear, IRONode *node, Boolean flag) { + IRODef *def = oalloc(sizeof(IRODef)); + + def->index = NumDefs++; + def->node = node; + def->linear = linear; + def->var = var; + def->globalnext = NULL; + def->x18 = 0; + def->x1A = Inline_IsObjectData(var->object); + def->x1B = var->xB; + def->x1C = flag; + def->x1D = 0; + + if (FirstDef) + LastDef->globalnext = def; + else + FirstDef = def; + LastDef = def; + + def->varnext = var->defs; + var->defs = def; +} + +static void MakeUse(VarRecord *var, IROLinear *linear, IRONode *node) { + IROUse *use = oalloc(sizeof(IROUse)); + + use->index = NumUses++; + use->node = node; + use->linear = linear; + use->var = var; + use->globalnext = NULL; + use->x1C = 0; + + if (IRO_FirstVarUse) + IRO_LastVarUse->globalnext = use; + else + IRO_FirstVarUse = use; + IRO_LastVarUse = use; + + use->varnext = var->uses; + var->uses = use; +} + +static void FindDefsAndUses(void) { + VarRecord *var; + IROLinear *linear; + IRONode *node; + + NumDefs = 0; + NumUses = 0; + IRO_FirstVarUse = NULL; + FirstDef = NULL; + + for (var = IRO_FirstVar; var; var = var->next) { + var->defs = NULL; + var->uses = NULL; + var->xC = 0; + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + for (linear = node->first; linear; linear = linear->next) { + if (IS_LINEAR_ENODE(linear, EOBJREF)) { + Object *obj = linear->u.node->data.objref; + if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) { + if ((var = IRO_FindVar(obj, 0, 1))) + MakeUse(var, linear, node); + } + } + + if (IRO_IsAssignment(linear) && (var = IRO_FindAssigned(linear))) { + MakeDef( + var, + linear, + node, + (linear->rtype->size == var->object->type->size) && !IRO_IsBitField + ); + } + + if (linear->type == IROLinearAsm) { + IAEffects effects; + int i; + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + + for (i = 0; i < effects.numoperands; i++) { + var = IRO_FindVar(effects.operands[i].object, 0, 1); + switch (effects.operands[i].type) { + case IAEffect_0: + MakeUse(var, linear, node); + break; + case IAEffect_1: + MakeDef( + var, + linear, + node, + (effects.operands[i].offset == 0) && (effects.operands[i].size == var->object->type->size) + ); + break; + case IAEffect_2: + MakeDef(var, linear, node, 0); + break; + case IAEffect_4: + MakeUse(var, linear, node); + MakeDef( + var, + linear, + node, + (effects.operands[i].offset == 0) && (effects.operands[i].size == var->object->type->size) + ); + break; + } + } + } + + if (linear == node->last) + break; + } + } + + for (var = IRO_FirstVar; var; var = var->next) + MakeDef(var, NULL, NULL, 1); +} + +static void MarkUses(Object *obj) { + VarRecord *var; + IRODef *def; + + if ((var = IRO_FindVar(obj, 0, 1))) { + for (def = var->defs; def; def = def->varnext) { + if (Bv_IsBitSet(def->index, Reaches)) { + Bv_SetBit(def->index, MightReachAnyUse); + def->x18++; + } + } + + var->xC = 1; + } +} + +static Boolean IsIncOrDec(IROLinear *linear) { + switch (linear->type) { + case IROLinearOp1Arg: + if (linear->nodetype == EPOSTINC || linear->nodetype == EPOSTDEC || linear->nodetype == EPREINC || linear->nodetype == EPREDEC) { + if (!(linear->u.monadic->flags & IROLF_BitfieldIndirect)) + return 1; + } + break; + case IROLinearOp2Arg: + if (linear->nodetype == EADDASS || linear->nodetype == ESUBASS) { + if (IRO_IsIntConstant(linear->u.diadic.right) && !(linear->u.diadic.left->flags & IROLF_BitfieldIndirect)) + return 1; + } + break; + } + + return 0; +} + +static Boolean IsOtherSelfAssignment(IROLinear *linear) { + switch (linear->type) { + case IROLinearOp2Arg: + switch (linear->nodetype) { + case EMULASS: + case EDIVASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + if (IRO_IsIntConstant(linear->u.diadic.right)) + return 1; + break; + } + break; + } + + return 0; +} + +CInt64 IRO_GetSelfAssignmentVal(IROLinear *linear) { + CInt64 result; + + if (linear->type == IROLinearOp1Arg) { + switch (linear->nodetype) { + case EPOSTINC: + case EPREINC: + CInt64_SetLong(&result, 1); + break; + case EPOSTDEC: + case EPREDEC: + CInt64_SetLong(&result, -1); + break; + default: +#line 445 + CError_FATAL(); + } + + if (IS_TYPE_POINTER_ONLY(linear->rtype)) { + CInt64 mul; + CInt64_SetLong(&mul, TPTR_TARGET(linear->rtype)->size); + result = CInt64_Mul(result, mul); + } + } else if (linear->type == IROLinearOp2Arg) { + switch (linear->nodetype) { + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + result = linear->u.diadic.right->u.node->data.intval; + break; + case ESUBASS: + result = linear->u.diadic.right->u.node->data.intval; + result = CInt64_Neg(result); + break; + default: +#line 491 + CError_FATAL(); + } + } else { +#line 496 + CError_FATAL(); + } + + return result; +} + +static void UpdateUse(IROLinear *linear, CInt64 val, Type *type) { + IROLinear *father; + IROLinear *repl; + IROLinear *newdiadic; + + if ((father = IRO_LocateFather(linear))) { + switch (father->type) { + case IROLinearOp1Arg: + switch (father->nodetype) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + val = CInt64_Add(val, IRO_GetSelfAssignmentVal(father)); + father->nodetype = EADDASS; + father->type = IROLinearOp2Arg; + repl = IRO_NewIntConst(val, type); + father->u.diadic.right = repl; + IRO_PasteAfter(repl, repl, linear); + return; + } + break; + case IROLinearOp2Arg: + if (IRO_IsIntConstant(father->u.diadic.right)) { + switch (father->nodetype) { + case EADD: + case EADDASS: + father->u.diadic.right->u.node->data.intval = CInt64_Add( + father->u.diadic.right->u.node->data.intval, val); + return; + case ESUB: + case ESUBASS: + father->u.diadic.right->u.node->data.intval = CInt64_Sub( + father->u.diadic.right->u.node->data.intval, val); + return; + } + } + break; + } + } + + repl = IRO_NewIntConst(val, type); + newdiadic = IRO_NewLinear(IROLinearOp2Arg); + newdiadic->index = ++IRO_NumLinear; + newdiadic->nodetype = EADD; + newdiadic->u.diadic.left = linear; + newdiadic->u.diadic.right = repl; + newdiadic->rtype = linear->rtype; + repl->next = newdiadic; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(linear, newdiadic); + IRO_PasteAfter(repl, newdiadic, linear); +} + +void IRO_InitializeNonAssignmentOpArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + IRO_NonAssignmentOp[i] = MAXEXPR; + + IRO_NonAssignmentOp[EPOSTINC] = MAXEXPR; + IRO_NonAssignmentOp[EPOSTDEC] = MAXEXPR; + IRO_NonAssignmentOp[EPREINC] = MAXEXPR; + IRO_NonAssignmentOp[EPREDEC] = MAXEXPR; + IRO_NonAssignmentOp[EINDIRECT] = MAXEXPR; + IRO_NonAssignmentOp[EMONMIN] = MAXEXPR; + IRO_NonAssignmentOp[EBINNOT] = MAXEXPR; + IRO_NonAssignmentOp[ELOGNOT] = MAXEXPR; + IRO_NonAssignmentOp[EFORCELOAD] = MAXEXPR; + IRO_NonAssignmentOp[EMUL] = MAXEXPR; + IRO_NonAssignmentOp[EMULV] = MAXEXPR; + IRO_NonAssignmentOp[EDIV] = MAXEXPR; + IRO_NonAssignmentOp[EMODULO] = MAXEXPR; + IRO_NonAssignmentOp[EADDV] = MAXEXPR; + IRO_NonAssignmentOp[ESUBV] = MAXEXPR; + IRO_NonAssignmentOp[EADD] = MAXEXPR; + IRO_NonAssignmentOp[ESUB] = MAXEXPR; + IRO_NonAssignmentOp[ESHL] = MAXEXPR; + IRO_NonAssignmentOp[ESHR] = MAXEXPR; + IRO_NonAssignmentOp[ELESS] = MAXEXPR; + IRO_NonAssignmentOp[EGREATER] = MAXEXPR; + IRO_NonAssignmentOp[ELESSEQU] = MAXEXPR; + IRO_NonAssignmentOp[EGREATEREQU] = MAXEXPR; + IRO_NonAssignmentOp[EEQU] = MAXEXPR; + IRO_NonAssignmentOp[ENOTEQU] = MAXEXPR; + IRO_NonAssignmentOp[EAND] = MAXEXPR; + IRO_NonAssignmentOp[EXOR] = MAXEXPR; + IRO_NonAssignmentOp[EOR] = MAXEXPR; + IRO_NonAssignmentOp[ELAND] = MAXEXPR; + IRO_NonAssignmentOp[ELOR] = MAXEXPR; + IRO_NonAssignmentOp[EASS] = MAXEXPR; + IRO_NonAssignmentOp[EMULASS] = EMUL; + IRO_NonAssignmentOp[EDIVASS] = EDIV; + IRO_NonAssignmentOp[EMODASS] = EMODULO; + IRO_NonAssignmentOp[EADDASS] = EADD; + IRO_NonAssignmentOp[ESUBASS] = ESUB; + IRO_NonAssignmentOp[ESHLASS] = ESHL; + IRO_NonAssignmentOp[ESHRASS] = ESHR; + IRO_NonAssignmentOp[EANDASS] = EAND; + IRO_NonAssignmentOp[EXORASS] = EXOR; + IRO_NonAssignmentOp[EORASS] = EOR; + IRO_NonAssignmentOp[ECOMMA] = MAXEXPR; + IRO_NonAssignmentOp[EPMODULO] = MAXEXPR; + IRO_NonAssignmentOp[EROTL] = MAXEXPR; + IRO_NonAssignmentOp[EROTR] = MAXEXPR; + IRO_NonAssignmentOp[EBCLR] = MAXEXPR; + IRO_NonAssignmentOp[EBTST] = MAXEXPR; + IRO_NonAssignmentOp[EBSET] = MAXEXPR; + IRO_NonAssignmentOp[ETYPCON] = MAXEXPR; + IRO_NonAssignmentOp[EBITFIELD] = MAXEXPR; + IRO_NonAssignmentOp[EINTCONST] = MAXEXPR; + IRO_NonAssignmentOp[EFLOATCONST] = MAXEXPR; + IRO_NonAssignmentOp[ESTRINGCONST] = MAXEXPR; + IRO_NonAssignmentOp[ECOND] = MAXEXPR; + IRO_NonAssignmentOp[EFUNCCALL] = MAXEXPR; + IRO_NonAssignmentOp[EFUNCCALLP] = MAXEXPR; + IRO_NonAssignmentOp[EOBJREF] = MAXEXPR; + IRO_NonAssignmentOp[EMFPOINTER] = MAXEXPR; + IRO_NonAssignmentOp[ENULLCHECK] = MAXEXPR; + IRO_NonAssignmentOp[EPRECOMP] = MAXEXPR; + IRO_NonAssignmentOp[ETEMP] = MAXEXPR; + IRO_NonAssignmentOp[EARGOBJ] = MAXEXPR; + IRO_NonAssignmentOp[ELOCOBJ] = MAXEXPR; + IRO_NonAssignmentOp[ELABEL] = MAXEXPR; + IRO_NonAssignmentOp[ESETCONST] = MAXEXPR; + IRO_NonAssignmentOp[ENEWEXCEPTION] = MAXEXPR; + IRO_NonAssignmentOp[ENEWEXCEPTIONARRAY] = MAXEXPR; + IRO_NonAssignmentOp[EOBJLIST] = MAXEXPR; + IRO_NonAssignmentOp[EMEMBER] = MAXEXPR; + IRO_NonAssignmentOp[ETEMPLDEP] = MAXEXPR; + IRO_NonAssignmentOp[EINSTRUCTION] = MAXEXPR; + IRO_NonAssignmentOp[EDEFINE] = MAXEXPR; + IRO_NonAssignmentOp[EREUSE] = MAXEXPR; + IRO_NonAssignmentOp[EASSBLK] = MAXEXPR; + IRO_NonAssignmentOp[EVECTOR128CONST] = MAXEXPR; + IRO_NonAssignmentOp[ECONDASS] = MAXEXPR; +} + +void IRO_InitializeAssignmentFoldingFunctionArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + AssignmentFoldingFunction[i] = NULL; + + AssignmentFoldingFunction[EPOSTINC] = NULL; + AssignmentFoldingFunction[EPOSTDEC] = NULL; + AssignmentFoldingFunction[EPREINC] = NULL; + AssignmentFoldingFunction[EPREDEC] = NULL; + AssignmentFoldingFunction[EINDIRECT] = NULL; + AssignmentFoldingFunction[EMONMIN] = NULL; + AssignmentFoldingFunction[EBINNOT] = NULL; + AssignmentFoldingFunction[ELOGNOT] = NULL; + AssignmentFoldingFunction[EFORCELOAD] = NULL; + AssignmentFoldingFunction[EMUL] = NULL; + AssignmentFoldingFunction[EMULV] = NULL; + AssignmentFoldingFunction[EDIV] = NULL; + AssignmentFoldingFunction[EMODULO] = NULL; + AssignmentFoldingFunction[EADDV] = NULL; + AssignmentFoldingFunction[ESUBV] = NULL; + AssignmentFoldingFunction[EADD] = NULL; + AssignmentFoldingFunction[ESUB] = NULL; + AssignmentFoldingFunction[ESHL] = NULL; + AssignmentFoldingFunction[ESHR] = NULL; + AssignmentFoldingFunction[ELESS] = NULL; + AssignmentFoldingFunction[EGREATER] = NULL; + AssignmentFoldingFunction[ELESSEQU] = NULL; + AssignmentFoldingFunction[EGREATEREQU] = NULL; + AssignmentFoldingFunction[EEQU] = NULL; + AssignmentFoldingFunction[ENOTEQU] = NULL; + AssignmentFoldingFunction[EAND] = NULL; + AssignmentFoldingFunction[EXOR] = NULL; + AssignmentFoldingFunction[EOR] = NULL; + AssignmentFoldingFunction[ELAND] = NULL; + AssignmentFoldingFunction[ELOR] = NULL; + AssignmentFoldingFunction[EASS] = NULL; + AssignmentFoldingFunction[EMULASS] = CInt64_Mul; + AssignmentFoldingFunction[EDIVASS] = CInt64_Mul; + AssignmentFoldingFunction[EMODASS] = NULL; + AssignmentFoldingFunction[EADDASS] = CInt64_Add; + AssignmentFoldingFunction[ESUBASS] = CInt64_Add; + AssignmentFoldingFunction[ESHLASS] = CInt64_Add; + AssignmentFoldingFunction[ESHRASS] = CInt64_Add; + AssignmentFoldingFunction[EANDASS] = CInt64_And; + AssignmentFoldingFunction[EXORASS] = CInt64_Xor; + AssignmentFoldingFunction[EORASS] = CInt64_Or; + AssignmentFoldingFunction[ECOMMA] = NULL; + AssignmentFoldingFunction[EPMODULO] = NULL; + AssignmentFoldingFunction[EROTL] = NULL; + AssignmentFoldingFunction[EROTR] = NULL; + AssignmentFoldingFunction[EBCLR] = NULL; + AssignmentFoldingFunction[EBTST] = NULL; + AssignmentFoldingFunction[EBSET] = NULL; + AssignmentFoldingFunction[ETYPCON] = NULL; + AssignmentFoldingFunction[EBITFIELD] = NULL; + AssignmentFoldingFunction[EINTCONST] = NULL; + AssignmentFoldingFunction[EFLOATCONST] = NULL; + AssignmentFoldingFunction[ESTRINGCONST] = NULL; + AssignmentFoldingFunction[ECOND] = NULL; + AssignmentFoldingFunction[EFUNCCALL] = NULL; + AssignmentFoldingFunction[EFUNCCALLP] = NULL; + AssignmentFoldingFunction[EOBJREF] = NULL; + AssignmentFoldingFunction[EMFPOINTER] = NULL; + AssignmentFoldingFunction[ENULLCHECK] = NULL; + AssignmentFoldingFunction[EPRECOMP] = NULL; + AssignmentFoldingFunction[ETEMP] = NULL; + AssignmentFoldingFunction[EARGOBJ] = NULL; + AssignmentFoldingFunction[ELOCOBJ] = NULL; + AssignmentFoldingFunction[ELABEL] = NULL; + AssignmentFoldingFunction[ESETCONST] = NULL; + AssignmentFoldingFunction[ENEWEXCEPTION] = NULL; + AssignmentFoldingFunction[ENEWEXCEPTIONARRAY] = NULL; + AssignmentFoldingFunction[EOBJLIST] = NULL; + AssignmentFoldingFunction[EMEMBER] = NULL; + AssignmentFoldingFunction[ETEMPLDEP] = NULL; + AssignmentFoldingFunction[EINSTRUCTION] = NULL; + AssignmentFoldingFunction[EDEFINE] = NULL; + AssignmentFoldingFunction[EREUSE] = NULL; + AssignmentFoldingFunction[EASSBLK] = NULL; + AssignmentFoldingFunction[EVECTOR128CONST] = NULL; + AssignmentFoldingFunction[ECONDASS] = NULL; +} + +static void UpdateUseForOtherSelfAssignment(IROLinear *a, IROLinear *b, Type *type) { + CInt64 val; + IROLinear *father; + IROLinear *repl; + IROLinear *newdiadic; + + val = IRO_GetSelfAssignmentVal(b); + if ((father = IRO_LocateFather(a)) && father->type == IROLinearOp2Arg && IRO_IsIntConstant(father->u.diadic.right)) { + CInt64 var_30 = father->u.diadic.right->u.node->data.intval; + if (AssignmentFoldingFunction[b->nodetype] && ((father->nodetype == b->nodetype) || (father->nodetype == IRO_NonAssignmentOp[b->nodetype]))) { + CInt64 v; + CInt64 folded; + CInt64_SetLong(&v, b->rtype->size * 8); + folded = AssignmentFoldingFunction[b->nodetype](var_30, val); + if (b->nodetype == ESHRASS && !is_unsigned(b->rtype)) { + if (CInt64_LessU(var_30, v) && CInt64_LessU(val, v)) { + if (CInt64_GreaterEqualU(folded, v)) + folded = CInt64_Sub(v, cint64_one); + father->u.diadic.right->u.node->data.intval = folded; + return; + } + } else { + father->u.diadic.right->u.node->data.intval = folded; + return; + } + } else { + switch (b->nodetype) { + case EMULASS: + if (father->nodetype == ESHL || father->nodetype == ESHLASS) { + SInt32 powvalue; + if (IRO_IsPow2(b->u.diadic.right, &powvalue)) { + if (powvalue > 0) { + CInt64 v; + CInt64_SetLong(&v, powvalue); + father->u.diadic.right->u.node->data.intval = CInt64_Add(v, var_30); + } + } else { + father->nodetype = (father->nodetype == ESHL) ? EMUL : EMULASS; + var_30 = CInt64_Shl(cint64_one, var_30); + father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); + } + return; + } + break; + case EDIVASS: + if ((father->nodetype == ESHR || father->nodetype == ESHRASS) && is_unsigned(father->rtype)) { + SInt32 powvalue; + if (IRO_IsPow2(b->u.diadic.right, &powvalue)) { + if (powvalue > 0) { + CInt64 v; + CInt64_SetLong(&v, powvalue); + father->u.diadic.right->u.node->data.intval = CInt64_Add(v, var_30); + } + } else { + father->nodetype = (father->nodetype == ESHR) ? EDIV : EDIVASS; + var_30 = CInt64_Shl(cint64_one, var_30); + father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); + } + return; + } + break; + case ESHLASS: + if (father->nodetype == EMUL || father->nodetype == EMULASS) { + SInt32 powvalue; + if (IRO_IsPow2(father->u.diadic.right, &powvalue)) { + if (powvalue > 0) { + CInt64 v; + father->nodetype = (father->nodetype == EMUL) ? ESHL : ESHLASS; + CInt64_SetLong(&v, powvalue); + father->u.diadic.right->u.node->data.intval = CInt64_Add(v, val); + } + } else { + val = CInt64_Shl(cint64_one, val); + father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); + } + return; + } else if (father->nodetype == ESHR || father->nodetype == ESHRASS) { + if (CInt64_Equal(var_30, val) && is_unsigned(father->rtype)) { + father->nodetype = (father->nodetype == ESHR) ? EAND : EANDASS; + if (father->rtype->size < 8) { + CInt64 v; + CInt64_SetLong(&v, 64 - (father->rtype->size * 8)); + val = CInt64_Add(val, v); + } + father->u.diadic.right->u.node->data.intval = CInt64_ShrU(cint64_negone, val); + return; + } + } + break; + case ESHRASS: + if ((father->nodetype == EDIV || father->nodetype == EDIVASS) && is_unsigned(father->rtype)) { + SInt32 powvalue; + if (IRO_IsPow2(father->u.diadic.right, &powvalue)) { + if (powvalue > 0) { + CInt64 v; + father->nodetype = (father->nodetype == EDIV) ? ESHR : ESHRASS; + CInt64_SetLong(&v, powvalue); + father->u.diadic.right->u.node->data.intval = CInt64_Add(v, val); + } + } else { + val = CInt64_Shl(cint64_one, val); + father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); + } + return; + } else if (father->nodetype == ESHL || father->nodetype == ESHLASS) { + if (CInt64_Equal(var_30, val)) { + father->nodetype = (father->nodetype == ESHL) ? EAND : EANDASS; + father->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_negone, val); + return; + } + } + break; + } + } + } + + repl = IRO_NewIntConst(val, type); + newdiadic = IRO_NewLinear(IROLinearOp2Arg); + newdiadic->index = ++IRO_NumLinear; + newdiadic->nodetype = IRO_NonAssignmentOp[b->nodetype]; + newdiadic->u.diadic.left = a; + newdiadic->u.diadic.right = repl; + newdiadic->rtype = a->rtype; + repl->next = newdiadic; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(a, newdiadic); + IRO_PasteAfter(repl, newdiadic, a); +} + +static Boolean PropagateIncsAndDecs(void) { + IRODef *def; + Boolean result; + + result = 0; + def = FirstDef; + while (def) { + if ( + def->linear && + def->x1C && + IsIncOrDec(def->linear) && + !(def->linear->flags & IROLF_Reffed) && + (IS_TYPE_INT_OR_ENUM(def->linear->rtype) || IS_TYPE_POINTER_ONLY(def->linear->rtype)) && + IRO_TypesEqual(def->linear->rtype, def->var->object->type) && + !is_volatile_object(def->var->object) + ) { + IROUse *use; + IROUse *use2; + IROLinear *father; + CInt64 val; + SInt32 i; + Type *type; + + for (use = def->var->uses, i = 0; use; use = use->varnext) { + if (Bv_IsBitSet(def->index, use->x18)) { + if ( + use->x1C == 1 && + use->linear->type == IROLinearOperand && + (father = IRO_LocateFather(use->linear)) && + IRO_IsVariable(father) && + IRO_TypesEqual(def->linear->rtype, father->rtype) + ) { + if (use->linear->flags & IROLF_Assigned) { + if (!((father = IRO_LocateFather(father)) && IsIncOrDec(father) && !(father->flags & IROLF_Reffed))) + goto nextDef; + } + i++; + } else { + goto nextDef; + } + } + } + + if (i == def->x18) { + for (use = def->var->uses; use; use = use->varnext) { + if (Bv_IsBitSet(def->index, use->x18)) { + IRO_Dump("Propagating inc/dec from %d to %d\n", def->linear->index, use->linear->index); + father = IRO_LocateFather(use->linear); + val = IRO_GetSelfAssignmentVal(def->linear); + type = def->linear->rtype; + if (IS_TYPE_POINTER_ONLY(def->linear->rtype)) + type = TYPE(&stunsignedlong); + UpdateUse(father, val, type); + + result = 1; + for (use2 = def->var->uses; use2; use2 = use2->varnext) { + if (use2->linear == def->linear->u.monadic->u.diadic.left) { + use->x1C = use2->x1C; + Bv_Copy(use2->x18, use->x18); + break; + } + } + } + } + def->x18 = 0; + IRO_NopNonSideEffects(def->linear, -1); + def->linear->type = IROLinearNop; + IRO_Dump("Removing deadddd assignment %d\n", def->linear->index); + } + } + nextDef: + def = def->globalnext; + } + + return result; +} + +static Boolean PropagateOtherSelfAssignments(void) { + IRODef *def; + Boolean result; + + result = 0; + + def = FirstDef; + while (def) { + if ( + def->linear && + def->x1C && + IsOtherSelfAssignment(def->linear) && + !(def->linear->flags & IROLF_Reffed) && + IS_TYPE_INT_OR_ENUM(def->linear->rtype) && + IRO_TypesEqual(def->linear->rtype, def->var->object->type) && + !is_volatile_object(def->var->object) + ) + { + IROUse *use; + IROUse *use2; + IROLinear *father; + SInt32 i; + Type *type; + + for (use = def->var->uses, i = 0; use; use = use->varnext) { + if (Bv_IsBitSet(def->index, use->x18)) { + if ( + use->x1C == 1 && + use->linear->type == IROLinearOperand && + (father = IRO_LocateFather(use->linear)) && + IRO_IsVariable(father) && + IRO_TypesEqual(def->linear->rtype, father->rtype) + ) { + if (use->linear->flags & IROLF_Assigned) { + if (!((father = IRO_LocateFather(father)) && IsOtherSelfAssignment(father) && (father->nodetype == def->linear->nodetype) && !(father->flags & IROLF_Reffed))) + goto nextDef; + } + i++; + } else { + goto nextDef; + } + } + } + + if (i == def->x18) { + for (use = def->var->uses; use; use = use->varnext) { + if (Bv_IsBitSet(def->index, use->x18)) { + IRO_Dump("Propagating self assignment from %d to %d\n", def->linear->index, use->linear->index); + father = IRO_LocateFather(use->linear); + UpdateUseForOtherSelfAssignment(father, def->linear, def->linear->rtype); + + result = 1; + for (use2 = def->var->uses; use2; use2 = use2->varnext) { + if (use2->linear == def->linear->u.monadic->u.diadic.left) { + use->x1C = use2->x1C; + Bv_Copy(use2->x18, use->x18); + break; + } + } + } + } + def->x18 = 0; + IRO_NopNonSideEffects(def->linear, -1); + def->linear->type = IROLinearNop; + IRO_Dump("Removing deadddd assignment %d\n", def->linear->index); + } + } + nextDef: + def = def->globalnext; + } + + return result; +} + +static void MarkUsesByIndirect(IROLinear *linear, BitVector *a, BitVector *b) { + IROListNode *list; + IROLinear *nd; + Object *obj; + VarRecord *var; + Boolean foundObjRef; + IROListNode *scan; + IRODef *def; + Boolean found; + + found = 0; + + if (linear && copts.opt_pointer_analysis && linear->pointsToFunction && FunctionName) { + IROListNode *resultList; + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, linear, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + found = 1; + break; + } + + foundObjRef = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundObjRef = 1; + break; + } + } + + if (!foundObjRef) { + found = 1; + break; + } + } + + if (!found) { + while (list) { + for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + obj = nd->u.node->data.objref; +#line 1422 + CError_ASSERT(obj != NULL); + var = IRO_FindVar(obj, 1, 1); +#line 1424 + CError_ASSERT(var != NULL); + + for (def = var->defs; def; def = def->varnext) { + if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) { + def->x18++; + Bv_SetBit(def->index, MightReachAnyUse); + } + } + } + } + list = list->nextList; + } + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + found = 1; + } + } else { + found = 1; + } + + if (found) { + Bv_Copy(Reaches, a); + Bv_And(b, a); + Bv_Or(a, MightReachAnyUse); + for (def = FirstDef; def; def = def->globalnext) { + if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) + def->x18++; + } + } +} + +static void MarkUsesByFunctionCall(IROLinear *linear, BitVector *a, BitVector *b) { + ObjectList *olist; + IROLinear *funcnd; + IROListNode *list; + IROLinear *nd; + Object *obj; + VarRecord *var; + Boolean foundObjRef; + IROListNode *scan; + IRODef *def; + Boolean found; + + found = 0; + + if ((funcnd = linear->u.funccall.linear8) && copts.opt_pointer_analysis && funcnd->pointsToFunction && FunctionName) { + IROListNode *resultList; + ObjectList *depsList; + + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, funcnd, &resultList); + if (resultList) { + for (scan = resultList; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + found = 1; + break; + } + + foundObjRef = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = nd->u.node->data.objref; +#line 1522 + CError_ASSERT(obj != NULL); + + depsList = NULL; + PointerAnalysis_GetFunctionDependencies(obj, linear, &depsList); + for (olist = depsList; olist; olist = olist->next) { + if (!olist->object) { + found = 1; + break; + } + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + + if (found) + break; + } + } + + if (!foundObjRef) + found = 1; + if (found) + break; + } + + if (!found) { + for (list = resultList; list; list = list->nextList) { + for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + obj = nd->u.node->data.objref; + depsList = NULL; + PointerAnalysis_GetFunctionDependencies(obj, linear, &depsList); + + for (olist = depsList; olist; olist = olist->next) { + var = IRO_FindVar(olist->object, 1, 1); +#line 1573 + CError_ASSERT(var != NULL); + + for (def = var->defs; def; def = def->varnext) { + if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) { + def->x18++; + Bv_SetBit(def->index, MightReachAnyUse); + } + } + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + } + } + } + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + found = 1; + } + } else { + found = 1; + } + + if (found) { + Bv_Copy(Reaches, a); + Bv_And(b, a); + Bv_Or(a, MightReachAnyUse); + for (def = FirstDef; def; def = def->globalnext) { + if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) + def->x18++; + } + } + + if (linear->stmt && IRO_FunctionCallMightThrowException(linear)) + IRO_WalkExcActions(linear->stmt->dobjstack, MarkUses); +} + +static Boolean UseOfVarIsInsideASimpleDefOfVar(IROUse *use) { + VarRecord *var; + VarRecord *varAss; + IROLinear *nd; + IROLinear *nd2; + + if ((var = use->var)) { + if ((nd = use->linear) && (nd->flags & IROLF_4000)) + return 0; + + while (nd && (nd->flags & IROLF_Reffed)) + nd = nd->next; + + if ( + nd && + IRO_IsAssignment(nd) && + (varAss = IRO_FindAssigned(nd)) && + varAss == var && + !IRO_HasSideEffect((nd->type == IROLinearOp1Arg) ? nd->u.monadic : nd->u.diadic.left) && + (!(nd2 = (nd->type == IROLinearOp1Arg) ? NULL : nd->u.diadic.right) || !IRO_HasSideEffect(nd2)) + ) { + return 1; + } + } + + return 0; +} + +static Boolean AllLoopDefUsesAreInSimpleLoopDefs(IRODef *def) { + VarRecord *var; + IRODef *scan; + IROUse *use; + + if ((var = def->var)) { + for (scan = var->defs; scan; scan = scan->varnext) { + if (scan->node && scan->node->loopdepth) { + for (use = var->uses; use; use = use->varnext) { + if (Bv_IsBitSet(scan->index, use->x18)) { + if (!use->node || !use->node->loopdepth || !UseOfVarIsInsideASimpleDefOfVar(use)) + return 0; + } + } + } + } + return 1; + } else { + return 0; + } +} + +static void MarkRemovableLoopDefs(void) { + IRODef *def; + IRODef *scan; + + for (def = FirstDef; def; def = def->globalnext) { + if (!def->x1A && !def->x1B && def->node && def->node->loopdepth && !def->x1D && + AllLoopDefUsesAreInSimpleLoopDefs(def) && def->var) { + for (scan = def->var->defs; scan; scan = scan->varnext) { + if (scan->node && scan->node->loopdepth) + scan->x1D = 1; + } + } + } +} + +static Boolean EliminateReffedDeadStore(IRODef *def) { + Boolean isPostIncOrDec; + IROLinear *nd; + Boolean result; + + nd = def->linear; + isPostIncOrDec = (nd->type == IROLinearOp1Arg) && (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC); + + result = IRO_LocateFather(nd) != NULL; + if (result && IRO_IsAssignment(nd) && IRO_IsModifyOp[nd->nodetype]) + result = IRO_TransformSelfAssignmentToAssignment(nd); + result = result && (nd->type == IROLinearOp2Arg) && (nd->nodetype == EASS); + + if (result) { + def->x18 = 0; + IRO_Dump("Removing referenced dead assignment %d\n", nd->index); + + if (isPostIncOrDec) { + IRO_NopNonSideEffects(nd->u.diadic.right, 0); + nd->type = IROLinearNop; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, nd->u.diadic.left); + } else { + IRO_NopNonSideEffects(nd->u.diadic.left, 0); + nd->type = IROLinearNop; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, nd->u.diadic.right); + } + } + + return result; +} + +Boolean IRO_UseDef(Boolean optDeadAssignments, Boolean optPropagation) { + Boolean result; + IRODef *gdef; + IROUse *guse; + IRODef *def; + IROUse *use; + IRONode *node; + IROLinear *nd; + VarRecord *var; + Boolean flag; + BitVector *bv3; + BitVector *bv2; + BitVector *bv; + int i; + + FindDefsAndUses(); + + IRO_CheckForUserBreak(); + + for (use = IRO_FirstVarUse; use; use = use->globalnext) + Bv_AllocVector(&use->x18, NumDefs); + Bv_AllocVector(&MightReachAnyUse, NumDefs); + Bv_AllocVector(&bv, NumDefs); + + IRO_CheckForUserBreak(); + + for (def = FirstDef; def; def = def->globalnext) { + if (def->x1A || def->x1B) + Bv_SetBit(def->index, bv); + } + + Bv_AllocVector(&bv2, NumDefs); + gdef = FirstDef; + for (node = IRO_FirstNode; node; node = node->nextnode) { + Bv_AllocVector(&node->x16, NumDefs); + Bv_AllocVector(&node->x1E, NumDefs); + Bv_AllocVector(&node->x22, NumDefs); + Bv_AllocVector(&node->x1A, NumDefs); + + for (nd = node->first; nd; nd = nd->next) { + while (gdef && gdef->linear == nd) { + Bv_SetBit(gdef->index, node->x1E); + if (gdef->x1C) { + for (def = gdef->var->defs; def; def = def->varnext) { + if (def != gdef) { + Bv_SetBit(def->index, node->x22); + Bv_ClearBit(def->index, node->x1E); + } + } + } + gdef = gdef->globalnext; + } + if (nd == node->last) + break; + } + + if (node->numpred) + Bv_Set(node->x16); + Bv_Copy(node->x1E, node->x1A); + IRO_CheckForUserBreak(); + } + + Bv_AllocVector(&bv3, NumDefs); + + do { + flag = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + Bv_Clear(node->x16); + if (node->numpred) { + for (i = 0; i < node->numpred; i++) + Bv_Or(IRO_NodeTable[node->pred[i]]->x1A, node->x16); + } else if (node == IRO_FirstNode) { + for (var = IRO_FirstVar; var; var = var->next) + Bv_SetBit(var->defs->index, node->x16); + } + Bv_Copy(node->x16, bv3); + Bv_Minus(node->x22, bv3); + Bv_Or(node->x1E, bv3); + if (!Bv_Compare(bv3, node->x1A)) { + Bv_Copy(bv3, node->x1A); + flag = 1; + } + } + + IRO_CheckForUserBreak(); + } while (flag); + + gdef = FirstDef; + guse = IRO_FirstVarUse; + Bv_AllocVector(&Reaches, NumDefs); + + for (node = IRO_FirstNode; node; node = node->nextnode) { + Bv_Copy(node->x16, Reaches); + nd = node->first; + while (1) { + while (guse && guse->linear == nd) { + for (def = guse->var->defs; def; def = def->varnext) { + if (Bv_IsBitSet(def->index, Reaches)) { + Bv_SetBit(def->index, guse->x18); + Bv_SetBit(def->index, MightReachAnyUse); + def->x18++; + guse->x1C++; + } + } + guse = guse->globalnext; + } + + if (nd->type == IROLinearFunccall) { + MarkUsesByFunctionCall(nd, bv2, bv); + } else if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && !IRO_IsVariable(nd)) { + MarkUsesByIndirect(nd, bv2, bv); + } else if ((nd->type == IROLinearFunccall) || + (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && !IRO_IsVariable(nd))) { + Bv_Copy(Reaches, bv2); + Bv_And(bv, bv2); + Bv_Or(bv2, MightReachAnyUse); + for (def = FirstDef; def; def = def->globalnext) { + if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) + def->x18++; + } + if (nd->type == IROLinearFunccall && nd->stmt && IRO_FunctionCallMightThrowException(nd)) + IRO_WalkExcActions(nd->stmt->dobjstack, MarkUses); + } + + if (nd->type == IROLinearAsm) { + IAEffects effects; + CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects); + if (effects.x2) { + Bv_Copy(Reaches, bv2); + Bv_And(bv, bv2); + Bv_Or(bv2, MightReachAnyUse); + } + } + + if (nd->type == IROLinearReturn || nd->type == IROLinearEnd) { + for (def = FirstDef; def; def = def->globalnext) { + if (def->x1A && Bv_IsBitSet(def->index, Reaches)) { + Bv_SetBit(def->index, MightReachAnyUse); + def->x18++; + } + } + } + + while (gdef && gdef->linear == nd) { + if (gdef->x1C) { + for (def = gdef->var->defs; def; def = def->varnext) + Bv_ClearBit(def->index, Reaches); + } + Bv_SetBit(gdef->index, Reaches); + gdef = gdef->globalnext; + } + + if (nd == node->last) + break; + nd = nd->next; + } + } + + IRO_CheckForUserBreak(); + + result = 0; + + if (optDeadAssignments) { + MarkRemovableLoopDefs(); + for (def = FirstDef; def; def = def->globalnext) { + if (def->linear && + (!Bv_IsBitSet(def->index, MightReachAnyUse) || def->x1D) && + (copts.opt_pointer_analysis || !def->x1B) && + def->linear->type != IROLinearAsm && + (!def->linear->rtype || !CParser_IsVolatile(def->linear->rtype, def->linear->nodeflags & ENODE_FLAG_QUALS)) && + !is_volatile_object(def->var->object) + ) { + if (!(def->linear->flags & IROLF_Reffed)) { + def->x18 = 0; + IRO_NopNonSideEffects(def->linear, -1); + def->linear->type = IROLinearNop; + IRO_Dump("Removing dead assignment %d\n", def->linear->index); + result = 1; + } else { + result = EliminateReffedDeadStore(def); + } + } + } + } + + IRO_CheckForUserBreak(); + + if (optPropagation) { + while (1) { + if (PropagateIncsAndDecs() || PropagateOtherSelfAssignments()) + result = 1; + else + break; + } + } + + IRO_CheckForUserBreak(); + + return result; +} + +static IROLinear *GetOperand(IROLinear *nd) { + IROLinear *inner; + + if (nd->type == IROLinearOperand) + return nd; + + if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) { + inner = GetOperand(nd->u.diadic.left); + if (!inner) + inner = GetOperand(nd->u.diadic.right); + return inner; + } + + return NULL; +} + +static IROLinear *GetAssigned(IROLinear *nd) { + if (!nd) + return NULL; + + if (nd->type == IROLinearOp2Arg) { + nd = nd->u.diadic.left; + } else if (nd->type == IROLinearOp1Arg) { + nd = nd->u.monadic; + } else { +#line 2338 + CError_FATAL(); + } + + if (nd->type != IROLinearOp1Arg || nd->nodetype != EINDIRECT) { +#line 2351 + CError_FATAL(); + } + + nd = nd->u.monadic; + + if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) + nd = GetOperand(nd); + + return nd; +} + +static void AddUseToRange(IROUse *use) { + IRODef *def; + + Bv_SetBit(use->index, useset); + Bv_ClearBit(use->index, alluses); + + for (def = use->var->defs; def; def = def->varnext) { + if (Bv_IsBitSet(def->index, alldefs) && (Bv_IsBitSet(def->index, use->x18) || GetAssigned(def->linear) == use->linear)) + AddDefToRange(def); + } +} + +static void AddDefToRange(IRODef *def) { + IROUse *use; + IROLinear *assigned; + + Bv_SetBit(def->index, defset); + Bv_ClearBit(def->index, alldefs); + + for (use = def->var->uses, assigned = GetAssigned(def->linear); use; use = use->varnext) { + if (Bv_IsBitSet(use->index, alluses) && (Bv_IsBitSet(def->index, use->x18) || assigned == use->linear)) + AddUseToRange(use); + } +} + +static void ReplaceAssigned(IROLinear *nd, Object *from, Object *to) { + IROLinear *assigned; + + if ( + !(assigned = GetAssigned(nd)) || + assigned->type != IROLinearOperand || + assigned->u.node->type != EOBJREF || + assigned->u.node->data.objref != from + ) { +#line 2459 + CError_FATAL(); + } + + assigned->u.node->data.objref = to; +} + +static void ReplaceUsed(IROLinear *nd, Object *from, Object *to) { +#line 2482 + CError_ASSERT(nd->type == IROLinearOperand && nd->u.node->type == EOBJREF); + + if (nd->u.node->data.objref == from) { + nd->u.node->data.objref = to; + } else if (nd->u.node->data.objref != to) { +#line 2494 + CError_FATAL(); + } +} + +static void SplitOffRange(VarRecord *var) { + Object *newObj; + IRODef *def; + IROUse *use; + + IRO_Dump("Splitting range for variable: %d\n", var->index); + IRO_DumpBits("Def set: ", defset); + IRO_DumpBits("Use set: ", useset); + IRO_DumpBits("All defs: ", alldefs); + IRO_DumpBits("All uses: ", alluses); + + newObj = create_temp_object(var->object->type); + IRO_FindVar(newObj, 1, 1); + + for (def = var->defs; def; def = def->varnext) { + if (Bv_IsBitSet(def->index, defset) && def->linear) + ReplaceAssigned(def->linear, var->object, newObj); + } + + for (use = var->uses; use; use = use->varnext) { + if (Bv_IsBitSet(use->index, useset)) + ReplaceUsed(use->linear, var->object, newObj); + } +} + +void IRO_SplitLifetimes(void) { + VarRecord *var; + SInt32 numVars; + IRODef *def; + IROUse *use; + Boolean flag; + + Bv_AllocVector(&alldefs, NumDefs); + Bv_AllocVector(&alluses, NumUses); + Bv_AllocVector(&defset, NumDefs); + Bv_AllocVector(&useset, NumUses); + + var = IRO_FirstVar; + numVars = IRO_NumVars; + + while (var && var->index <= numVars) { + if (var->object->datatype == DLOCAL && !is_volatile_object(var->object) && !var->xC && !var->xB && !var->x1E) { + Bv_Clear(alldefs); + Bv_Clear(alluses); + + for (def = var->defs; def; def = def->varnext) { + if (def->linear && def->linear->type == IROLinearAsm) + goto skipThisVar; + Bv_SetBit(def->index, alldefs); + } + + for (use = var->uses; use; use = use->varnext) { + if (use->linear && use->linear->type == IROLinearAsm) + goto skipThisVar; + Bv_SetBit(use->index, alluses); + } + + flag = 1; + while (1) { + Bv_Clear(defset); + Bv_Clear(useset); + + def = var->defs; + while (def && !Bv_IsBitSet(def->index, alldefs)) + def = def->varnext; + + if (!def) + break; + + AddDefToRange(def); + if (Bv_IsEmpty(alldefs)) + break; + + if (!flag) + SplitOffRange(var); + flag = 0; + } + } + + skipThisVar: + var = var->next; + } + + IRO_CheckForUserBreak(); +} diff --git a/compiler_and_linker/unsorted/InlineAsmPPC.c b/compiler_and_linker/unsorted/InlineAsmPPC.c index ead84d7..e6e857b 100644 --- a/compiler_and_linker/unsorted/InlineAsmPPC.c +++ b/compiler_and_linker/unsorted/InlineAsmPPC.c @@ -22,11 +22,11 @@ #include "compiler/PCodeUtilities.h" #include "compiler/StackFrame.h" #include "compiler/CompilerTools.h" +#include "compiler/Alias.h" // TODO: move me extern int countexceptionactionregisters(ExceptionAction *); extern void noteexceptionactionregisters(ExceptionAction *, PCodeArg *); -extern void *make_alias(Object *obj, SInt32 offset, SInt32 size); char asm_alloc_flags[10]; unsigned char sm_section; @@ -2090,7 +2090,7 @@ static PCode *InlineAsm_TranslateIRtoPCodePPC(InlineAsm *ia, int argcount, UInt8 dest->data.mem.obj = src->u.obj.obj; dest->data.mem.offset = src->u.obj.offset; if (pc->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) { - pc->_18 = make_alias(dest->data.mem.obj, dest->data.mem.offset, nbytes_loaded_or_stored_by(pc)); + pc->alias = make_alias(dest->data.mem.obj, dest->data.mem.offset, nbytes_loaded_or_stored_by(pc)); if (is_volatile_object(dest->data.mem.obj)) pc->flags |= fIsVolatile; if (OBJ_GET_TARGET_CONST(dest->data.mem.obj)) diff --git a/compiler_and_linker/unsorted/InterferenceGraph.c b/compiler_and_linker/unsorted/InterferenceGraph.c index e69de29..942a5a0 100644 --- a/compiler_and_linker/unsorted/InterferenceGraph.c +++ b/compiler_and_linker/unsorted/InterferenceGraph.c @@ -0,0 +1,404 @@ +#include "compiler/InterferenceGraph.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/BitVectors.h" +#include "compiler/Coloring.h" +#include "compiler/LiveInfo.h" +#include "compiler/PCode.h" +#include "compiler/PCodeListing.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/Registers.h" +#include "compiler/RegisterInfo.h" +#include "compiler/CompilerTools.h" + +IGNode **interferencegraph; +static UInt32 *interferencematrix; +Boolean coalesced_nregisters; +static SInt16 *coalesced; + +static void makeinterfere(UInt32 a, UInt32 b) { + if (a < b) + bitvectorsetbit(((b * b) / 2) + a, interferencematrix); + else if (a > b) + bitvectorsetbit(((a * a) / 2) + b, interferencematrix); +} + +int interferes(UInt32 a, UInt32 b) { + if (a < b) + return bitvectorgetbit(((b * b) / 2) + a, interferencematrix) > 0; + else if (a > b) + return bitvectorgetbit(((a * a) / 2) + b, interferencematrix) > 0; + else + return 0; +} + +static void buildinterferencematrix(void) { + UInt32 regs; // r31 + PCodeBlock *block; // r30 + PCode *instr; // r29 + UInt32 *vec; // r28 + PCodeArg *op; + long reg; + UInt32 i; + UInt32 j; + + regs = used_virtual_registers[coloring_class]; + interferencematrix = oalloc(4 * ((((regs * regs) / 2) + 31) >> 5)); + bitvectorinitialize(interferencematrix, (regs * regs) / 2, 0); + + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) + if (i != j) + makeinterfere(i, j); + + vec = oalloc(4 * ((regs + 31) >> 5)); + for (block = pcbasicblocks; block; block = block->nextBlock) { + bitvectorcopy(vec, liveinfo[block->blockIndex].vecC, regs); + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + (char) op->arg == coloring_class && + (op->data.reg.effect & EffectWrite) + ) + { + reg = op->data.reg.reg; + bitvectorclearbit(reg, vec); + for (j = 0; j < regs; j++) { + if (bitvectorgetbit(j, vec)) { + if ( + (instr->flags & fPCodeFlag10) && + instr->args[0].kind == PCOp_REGISTER && + (char) instr->args[0].arg == coloring_class && + instr->args[1].data.reg.reg == j + ) + continue; + makeinterfere(reg, j); + } + } + } + op++; + } + + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + (char) op->arg == coloring_class && + (op->data.reg.effect & EffectRead) + ) + { + reg = op->data.reg.reg; + if (bitvectorgetbit(reg, vec) == 0) + op->data.reg.effect |= Effect4; + bitvectorsetbit(reg, vec); + } + op++; + } + + if (coloring_class == RegClass_GPR) { + if (PCODE_FLAG_SET_F(instr) & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag40000)) { + if (instr->args[1].data.reg.reg >= n_real_registers[coloring_class]) + makeinterfere(0, instr->args[1].data.reg.reg); + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag2000000) + makeinterfere(instr->args[0].data.reg.reg, instr->args[1].data.reg.reg); + } else { + switch (instr->op) { + case PC_DCBF: + case PC_DCBST: + case PC_DCBT: + case PC_DCBTST: + case PC_DCBZ: + case PC_DCBI: + case PC_ICBI: + case PC_DCCCI: + case PC_ICBT: + case PC_ICCCI: + case PC_ICREAD: + case PC_DCBA: + case PC_DST: + case PC_DSTT: + case PC_DSTST: + case PC_DSTSTT: + if (instr->args[0].data.reg.reg >= n_real_registers[coloring_class]) + makeinterfere(0, instr->args[0].data.reg.reg); + break; + } + } + } + + if (coloring_class == RegClass_GPR && (instr->flags & fPCodeFlag8)) { + i = branch_count_volatiles(); + op = instr->args; +#line 219 + CError_ASSERT(instr->argCount != 0); + + while (op->kind != PCOp_REGISTER && !(op->data.reg.effect & EffectWrite)) { + i++; + op++; +#line 226 + CError_ASSERT(i <= instr->argCount); + } + + op = instr->args + i; + while (i < instr->argCount) { + if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { + for (j = 0; j < n_scratch_registers[coloring_class]; j++) + makeinterfere(op->data.reg.reg, scratch_registers[coloring_class][j]); + } + op++; + } + } + } + } +} + +static short coalesced_path(short id) { + while (id != coalesced[id]) + id = coalesced[id]; + return id; +} + +static void coalescenodes(void) { + PCodeArg *op; + UInt32 regs; + PCodeBlock *block; + PCode *instr; + UInt32 i; + short path1; + short path2; + short node1; + short node2; + + regs = used_virtual_registers[coloring_class]; + coalesced = oalloc(sizeof(SInt16) * regs); + + for (i = 0; i < regs; i++) + coalesced[i] = i; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if ((instr->flags & fPCodeFlag10) && !(instr->flags & fSideEffects)) { + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) { +#line 309 + CError_FATAL(); + continue; + } + + if (instr->argCount > 2) { + if (instr->argCount != 3 || instr->args[2].kind != PCOp_PLACEHOLDEROPERAND) { +#line 316 + CError_FATAL(); + continue; + } + } + + if (instr->args[0].kind == PCOp_REGISTER && (char) instr->args[0].arg == coloring_class) { + path1 = coalesced_path(instr->args[0].data.reg.reg); + path2 = coalesced_path(instr->args[1].data.reg.reg); + if (path1 == path2) { + deletepcode(instr); + continue; + } + + if (!interferes(path1, path2)) { + if (path1 >= n_real_registers[coloring_class] && path2 >= n_real_registers[coloring_class]) { + if (path1 < first_fe_temporary_register[coloring_class]) + continue; + if (path1 > last_temporary_register[coloring_class]) + continue; + if (path2 < first_fe_temporary_register[coloring_class]) + continue; + if (path2 > last_temporary_register[coloring_class]) + continue; + } + + node1 = (path2 < path1) ? path2 : path1; + node2 = (path2 > path1) ? path2 : path1; + + if (coloring_class == RegClass_GPR && node2 == _CALLER_SP_) + continue; + + coalesced[node2] = node1; + for (i = 0; i < regs; i++) { + if (interferes(node2, i)) + makeinterfere(node1, i); + } + + deletepcode(instr); + } + } + } + } + } + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + (char) op->arg == coloring_class && + op->data.reg.reg != coalesced[op->data.reg.reg] + ) + op->data.reg.reg = coalesced_path(op->data.reg.reg); + op++; + } + } + } +} + +static void buildadjacencyvectors(void) { + IGNode *node; + UInt32 regs; + UInt32 i; + UInt32 counter; + short *array; + short *dest; + short *src; + UInt32 j; + + regs = used_virtual_registers[coloring_class]; + interferencegraph = oalloc(sizeof(IGNode *) * regs); + array = oalloc(sizeof(short) * regs); + + for (i = 0; i < regs; i++) { + counter = 0; + for (j = 0; j < regs; j++) { + if (interferes(i, j)) + array[counter++] = j; + } + + node = interferencegraph[i] = oalloc(sizeof(IGNode) + sizeof(short) * (counter - 1)); + memclrw(node, sizeof(IGNode) + sizeof(short) * (counter - 1)); + + node->x10 = i; + node->x14 = -1; + node->arraySize = counter; + node->x12 = counter; + + dest = node->array; + src = array; + for (j = 0; j < counter; j++) + *(dest++) = *(src++); + + if (i != coalesced[i]) { + node->flags |= fCoalesced; + j = coalesced_path(i); + interferencegraph[j]->flags |= fCoalescedInto; + node->x14 = j; + } + } +} + +static void eliminatedeadcode(void) { + UInt32 regs; + PCodeBlock *block; + PCode *instr; + UInt32 *vec; + UInt32 i; + PCodeArg *op; + + regs = used_virtual_registers[coloring_class]; + vec = oalloc(4 * ((regs + 31) >> 5)); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + bitvectorcopy(vec, liveinfo[block->blockIndex].vecC, regs); + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + if (dead(instr, coloring_class, vec)) { + deletepcode(instr); + continue; + } + + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + (char) op->arg == coloring_class && + (op->data.reg.effect & EffectWrite) + ) + bitvectorclearbit(op->data.reg.reg, vec); + op++; + } + + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + (char) op->arg == coloring_class && + (op->data.reg.effect & EffectRead) + ) + { + int reg = op->data.reg.reg; + if (!bitvectorgetbit(reg, vec)) + op->data.reg.effect |= Effect4; + bitvectorsetbit(reg, vec); + } + op++; + } + } + } +} + +static void findrematerializations(void) { + UInt32 regs; + UInt32 i; + PCodeBlock *block; + PCode *instr; + PCodeArg *op; + IGNode *node; + + regs = used_virtual_registers[coloring_class]; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + (char) op->arg == coloring_class && + (op->data.reg.effect & EffectWrite) && + op->data.reg.reg >= n_real_registers[coloring_class] && + !(interferencegraph[op->data.reg.reg]->flags & (fPairLow | fPairHigh)) && + !(interferencegraph[op->data.reg.reg]->flags & fIGNode40) + ) + { + node = interferencegraph[op->data.reg.reg]; + if (!node->instr8) { + node->instr8 = instr; + } else { + node->instr8 = NULL; + node->flags |= fIGNode40; + } + } + op++; + } + } + } + + for (i = 0; i < regs; i++) { + node = interferencegraph[i]; + if (node->instr8 && !is_location_independent(node->instr8)) + node->instr8 = NULL; + } +} + +void buildinterferencegraph(Object *proc) { + int regs = used_virtual_registers[coloring_class]; + + computelivevariables(proc); + eliminatedeadcode(); + buildinterferencematrix(); + if (copts.debuglisting) + pclistinterferences(register_class_format[coloring_class], regs); + coalescenodes(); + buildadjacencyvectors(); + findrematerializations(); +} diff --git a/compiler_and_linker/unsorted/IrOptimizer.c b/compiler_and_linker/unsorted/IrOptimizer.c index e69de29..462adf3 100644 --- a/compiler_and_linker/unsorted/IrOptimizer.c +++ b/compiler_and_linker/unsorted/IrOptimizer.c @@ -0,0 +1,45 @@ +#include "compiler/IrOptimizer.h" +#include "compiler/CParser.h" + +Boolean DoScalarize; +Boolean DoLinearize; +Boolean EarlyReturn; +Boolean IRO_CPFirstTime; +Boolean VectorPhaseCalledFromUnroll; +Boolean IRO_Log; +static Boolean stIsSetup; + +static void CountRefToObject() { +} + +static void CountARef() { +} + +static void CountDoubleInd() { +} + +static void CountUsage() { +} + +Statement *IRO_Optimizer(Object *obj, Statement *stmt) { +} + +void IRO_Setup(void) { + static Boolean ENodeArraysHaveBeenInitialized; +} + +void IRO_Cleanup(void) { +} + +void CodeGen_UpdateOptimizerOptions(void) { + copts.opt_dead_code = copts.optimizationlevel > 0; + copts.opt_propagation = copts.optimizationlevel > 1; + copts.opt_common_subs = copts.optimizationlevel > 1; + copts.opt_vectorize_loops = copts.optimizationlevel > 2; + copts.opt_unroll_loops = copts.optimizationlevel > 2; + copts.opt_dead_assignments = copts.optimizationlevel > 2; + copts.opt_lifetimes = copts.optimizationlevel > 2; + copts.opt_strength_reduction = copts.optimizationlevel > 2; + copts.opt_loop_invariants = copts.optimizationlevel > 2; + copts._B4 = copts.optimizationlevel > 3; +} diff --git a/compiler_and_linker/unsorted/IroBitVect.c b/compiler_and_linker/unsorted/IroBitVect.c index ecaea04..f243238 100644 --- a/compiler_and_linker/unsorted/IroBitVect.c +++ b/compiler_and_linker/unsorted/IroBitVect.c @@ -1,4 +1,4 @@ -#include "compiler/IroBitVect.h" +#include "compiler/BitVector.h" #include "compiler/CompilerTools.h" void Bv_AllocVector(BitVector **bv, UInt32 size) { diff --git a/compiler_and_linker/unsorted/IroCSE.c b/compiler_and_linker/unsorted/IroCSE.c index e69de29..e7ad16f 100644 --- a/compiler_and_linker/unsorted/IroCSE.c +++ b/compiler_and_linker/unsorted/IroCSE.c @@ -0,0 +1,1039 @@ +#include "compiler/IroCSE.h" +#include "compiler/IroDump.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroMalloc.h" +#include "compiler/IroPointerAnalysis.h" +#include "compiler/IroSubable.h" +#include "compiler/IroUtil.h" +#include "compiler/IroVars.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" + +BitVector *IRO_Depends; +Boolean IRO_NotSubable; +Boolean IRO_IsVolatile; +Boolean IRO_CouldError; +IROExpr *IRO_FirstExpr; +IROExpr *IRO_LastExpr; +SInt32 IRO_NumExprs; +static Boolean HasVectorOperand; + +// forward decls +static void IRO_DependsOnForDataFlow(IROLinear *linear, Boolean flag); + +static void GetDependsOfIndirect(IROLinear *nd) { + IROListNode *resultList; + IROListNode *next; + IROListNode *list; + IROListNode *scan; + IROLinear *scannd; + Object *obj; + VarRecord *var; + int index; + Boolean result; + Boolean foundObjRef; + + result = 0; + + if (nd && copts.opt_pointer_analysis && nd->pointsToFunction && FunctionName) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, nd, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + break; + } + } + + if (!foundObjRef) { + result = 1; + break; + } + } + + if (!result) { + while (list) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; +#line 119 + CError_ASSERT(obj != NULL); + var = IRO_FindVar(obj, 1, 1); +#line 121 + CError_ASSERT(var != NULL); + index = var->index; +#line 123 + CError_ASSERT(index != 0); + + if (is_volatile_object(obj)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + Bv_SetBit(index, IRO_Depends); + } + } + list = list->nextList; + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) { + nd = nd->u.monadic; + if (nd->type == IROLinearOp1Arg && nd->nodetype == EBITFIELD) + nd = nd->u.monadic; + + if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) { + IRO_BaseTerms = 0; + IRO_VarTerms = 0; + IRO_DecomposeAddressExpression_Cheap(nd); + if (IRO_BaseTerms != 1) { + IRO_CouldError = 1; + Bv_SetBit(0, IRO_Depends); + Bv_Or(IRO_FuncKills, IRO_Depends); + } + if (IRO_VarTerms) + IRO_CouldError = 1; + } else { + IRO_CouldError = 1; + Bv_SetBit(0, IRO_Depends); + Bv_Or(IRO_FuncKills, IRO_Depends); + } + } +} + +static void GetDependsOfFunctionCallForDataFlow(IROLinear *nd) { + IROLinear *innernd; + IROListNode *resultList; + IROListNode *next; + IROListNode *list; + IROListNode *scan; + IROLinear *scannd; + Object *obj; + VarRecord *var; + int index; + Boolean result; + Boolean foundObjRef; + ObjectList *olist; + ObjectList *depsList; + + result = 0; + innernd = nd->u.funccall.linear8; + + if (innernd && copts.opt_pointer_analysis && innernd->pointsToFunction && FunctionName) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, innernd, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = scannd->u.node->data.objref; +#line 234 + CError_ASSERT(obj != NULL); + + depsList = NULL; + PointerAnalysis_GetFunctionDependencies(obj, nd, &depsList); + + for (olist = depsList; olist; olist = olist->next) { + if (!olist->object) { + result = 1; + break; + } + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + + if (result) + break; + } + } + + if (!foundObjRef) + result = 1; + if (result) + break; + } + + if (!result) { + for (list = resultList; list; list = list->nextList) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; + + depsList = NULL; + PointerAnalysis_GetFunctionDependencies(obj, nd, &depsList); + + for (olist = depsList; olist; olist = olist->next) { + var = IRO_FindVar(olist->object, 1, 1); +#line 285 + CError_ASSERT(var != NULL); + index = var->index; +#line 287 + CError_ASSERT(index != 0); + + if (is_volatile_object(olist->object)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + Bv_SetBit(index, IRO_Depends); + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + } + } + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) { + IRO_DependsOnForDataFlow(nd->u.funccall.linear8, 0); + Bv_Or(IRO_FuncKills, IRO_Depends); + + for (index = nd->u.funccall.argCount - 1; index >= 0; index--) + IRO_DependsOnForDataFlow(nd->u.funccall.args[index], 0); + } +} + +static void IRO_DependsOn(IROLinear *linear, Boolean flag) { + VarRecord *var; + IROLinear *inner; + + if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + + if (!IRO_NotSubable) { + switch (linear->type) { + case IROLinearOperand: + if (flag && linear->u.node->type == EOBJREF) { + if ((var = IRO_FindVar(linear->u.node->data.objref, 0, 1))) { + if (is_volatile_object(var->object)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + Bv_SetBit(var->index, IRO_Depends); + } else { + IRO_NotSubable = 1; + } + } + break; + case IROLinearOp1Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + IRO_NotSubable = 1; + } else { + inner = linear->u.monadic; + if (linear->nodetype == EINDIRECT) { + if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) + inner = inner->u.monadic; + if (inner->type != IROLinearOperand || inner->u.node->type != EOBJREF) + GetDependsOfIndirect(linear); + } + + IRO_DependsOn(inner, linear->nodetype == EINDIRECT); + } + break; + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + IRO_NotSubable = 1; + } else { + if (linear->nodetype == EDIV || linear->nodetype == EMODULO) { + if (IRO_IsIntConstant(linear->u.diadic.right)) { + if (CInt64_Equal(linear->u.diadic.right->u.node->data.intval, cint64_zero)) + IRO_CouldError = 1; + } else { + IRO_CouldError = 1; + } + } + + IRO_DependsOn(linear->u.diadic.left, flag); + IRO_DependsOn(linear->u.diadic.right, flag); + } + break; + case IROLinearOp3Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + IRO_NotSubable = 1; + } else { + IRO_DependsOn(linear->u.args3.a, flag); + IRO_DependsOn(linear->u.args3.b, flag); + IRO_DependsOn(linear->u.args3.c, flag); + } + break; + case IROLinearFunccall: + IRO_NotSubable = 1; + break; + default: +#line 479 + CError_FATAL(); + } + } +} + +static void IRO_DependsOnForDataFlow(IROLinear *linear, Boolean flag) { + VarRecord *var; + IROLinear *inner; + + if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + + switch (linear->type) { + case IROLinearOperand: + if (flag && linear->u.node->type == EOBJREF) { + if ((var = IRO_FindVar(linear->u.node->data.objref, 0, 1))) { + if (is_volatile_object(var->object)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + Bv_SetBit(var->index, IRO_Depends); + } else { + IRO_NotSubable = 1; + } + } + break; + case IROLinearOp1Arg: + if (IRO_IsAssignOp[linear->nodetype]) + IRO_NotSubable = 1; + + inner = linear->u.monadic; + if (linear->nodetype == EINDIRECT) { + if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) + inner = inner->u.monadic; + if (inner->type != IROLinearOperand || inner->u.node->type != EOBJREF) + GetDependsOfIndirect(linear); + } + + IRO_DependsOnForDataFlow(inner, linear->nodetype == EINDIRECT); + break; + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) + IRO_NotSubable = 1; + + if (linear->nodetype == EDIV || linear->nodetype == EMODULO) { + if (IRO_IsIntConstant(linear->u.diadic.right)) { + if (CInt64_Equal(linear->u.diadic.right->u.node->data.intval, cint64_zero)) + IRO_CouldError = 1; + } else { + IRO_CouldError = 1; + } + } + + IRO_DependsOnForDataFlow(linear->u.diadic.left, flag); + IRO_DependsOnForDataFlow(linear->u.diadic.right, flag); + break; + case IROLinearOp3Arg: + if (IRO_IsAssignOp[linear->nodetype]) + IRO_NotSubable = 1; + + IRO_DependsOnForDataFlow(linear->u.args3.a, flag); + IRO_DependsOnForDataFlow(linear->u.args3.b, flag); + IRO_DependsOnForDataFlow(linear->u.args3.c, flag); + break; + case IROLinearFunccall: + IRO_NotSubable = 1; + GetDependsOfFunctionCallForDataFlow(linear); + break; + default: +#line 650 + CError_FATAL(); + } +} + +void IRO_FindDepends_NoAlloc(IROLinear *linear) { + Bv_Clear(IRO_Depends); + IRO_CouldError = 0; + IRO_NotSubable = 0; + IRO_IsVolatile = 0; + IRO_DependsOnForDataFlow(linear, 0); +} + +void IRO_FindDepends(IROLinear *linear) { + Bv_AllocVector(&IRO_Depends, IRO_NumVars + 1); + IRO_CouldError = 0; + IRO_NotSubable = 0; + IRO_DependsOn(linear, 0); +} + +static void VecAct(IROLinear *linear, Boolean isFirst) { + if (!isFirst && (linear->flags & IROLF_VecOpBase)) + HasVectorOperand = 1; +} + +static Boolean IRO_DoesNotHaveVectorOperand(IROLinear *linear) { + HasVectorOperand = 0; + IRO_WalkTree(linear, VecAct); + return HasVectorOperand == 0; +} + +static void IRO_AddExpression(IROLinear *linear, IRONode *node, Boolean flag) { + IROExpr *expr; + + if ((linear->flags & IROLF_Reffed) && IRO_IsSubableExpression(linear) && IRO_DoesNotHaveVectorOperand(linear)) { + expr = oalloc(sizeof(IROExpr)); + expr->x0 = 0; + expr->index = ++IRO_NumExprs; + expr->linear = linear; + expr->x8 = NULL; + expr->node = node; + IRO_FindDepends(linear); + expr->depends = IRO_Depends; + expr->notSubable = IRO_NotSubable; + expr->couldError = IRO_CouldError; + expr->next = NULL; + expr->x14 = NULL; + if (IRO_FirstExpr) + IRO_LastExpr->next = expr; + else + IRO_FirstExpr = expr; + IRO_LastExpr = expr; + linear->expr = expr; + } +} + +void IRO_FindExpressions(BitVector *bv, Boolean flag) { + IROLinear *nd; + IRONode *fnode; + + IRO_FirstExpr = IRO_LastExpr = NULL; + IRO_NumExprs = 0; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (!bv || Bv_IsBitSet(fnode->index, bv)) { + for (nd = fnode->first; nd; nd = nd->next) { + nd->expr = NULL; + IRO_AddExpression(nd, fnode, flag); + if (nd == fnode->last) + break; + } + } else { + for (nd = fnode->first; nd; nd = nd->next) { + nd->expr = NULL; + if (nd == fnode->last) + break; + } + } + } + + IRO_CheckForUserBreak(); +} + +void IRO_RemoveExpr(IROExpr *expr) { + IROExpr *prev; + IROExpr *scan; + + scan = IRO_FirstExpr; + prev = NULL; + while (scan != expr) { + prev = scan; + scan = scan->next; +#line 809 + CError_ASSERT(scan); + } + + expr->linear->expr = NULL; + if (prev) + prev->next = expr->next; + else + IRO_FirstExpr = expr->next; +} + +static void GetExprKillsByIndirectAssignment(IROLinear *linear) { + IROLinear *inner; + IROListNode *resultList; + IROListNode *next; + IROListNode *list; + IROListNode *scan; + IROLinear *scannd; + Object *obj; + VarRecord *var; + int index; + Boolean result; + Boolean foundObjRef; + IROExpr *expr; + + result = 0; + if (linear->type == IROLinearOp2Arg) + linear = linear->u.diadic.left; + else + linear = linear->u.monadic; + + if ( + linear && + linear->type == IROLinearOp1Arg && + linear->nodetype == EINDIRECT && + (inner = linear->u.monadic) && + copts.opt_pointer_analysis && + inner->pointsToFunction && + FunctionName + ) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + break; + } + } + + if (!foundObjRef) { + result = 1; + break; + } + } + + if (!result) { + while (list) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; +#line 893 + CError_ASSERT(obj != NULL); + var = IRO_FindVar(obj, 1, 1); +#line 895 + CError_ASSERT(var != NULL); + index = var->index; + + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_IsBitSet(index, expr->depends)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + } + } + list = list->nextList; + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) { + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_BitsInCommon(expr->depends, IRO_FuncKills)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + } +} + +static void GetExprKillsByFunctionCall(IROLinear *funccall) { + IROLinear *innernd; + IROListNode *resultList; + IROListNode *next; + IROListNode *list; + IROListNode *scan; + IROLinear *scannd; + Object *obj; + VarRecord *var; + int index; + Boolean result; + Boolean foundObjRef; + ObjectList *olist; + ObjectList *depsList; + IROExpr *expr; + + result = 0; + innernd = funccall->u.funccall.linear8; + + if (innernd && copts.opt_pointer_analysis && innernd->pointsToFunction && FunctionName) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, innernd, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = scannd->u.node->data.objref; +#line 991 + CError_ASSERT(obj != NULL); + + depsList = NULL; + PointerAnalysis_GetFunctionKills(obj, funccall, &depsList); + + for (olist = depsList; olist; olist = olist->next) { + if (!olist->object) { + result = 1; + break; + } + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + + if (result) + break; + } + } + + if (!foundObjRef) + result = 1; + if (result) + break; + } + + if (!result) { + for (list = resultList; list; list = list->nextList) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; + + depsList = NULL; + PointerAnalysis_GetFunctionKills(obj, funccall, &depsList); + + for (olist = depsList; olist; olist = olist->next) { + var = IRO_FindVar(olist->object, 1, 1); +#line 1042 + CError_ASSERT(var != NULL); + index = var->index; +#line 1044 + CError_ASSERT(index != 0); + + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_IsBitSet(index, expr->depends)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + } + } + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) { + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_BitsInCommon(expr->depends, IRO_FuncKills)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + } +} + +static void IRO_GetExprKills(IROLinear *linear) { + Bv_Clear(IRO_ExprKills); + switch (linear->type) { + case IROLinearOp1Arg: + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + VarRecord *var; + int index; + + var = IRO_FindAssigned(linear); + index = 0; + if (var) + index = var->index; + if (!index) { + GetExprKillsByIndirectAssignment(linear); + } else { + IROExpr *expr; + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_IsBitSet(index, expr->depends)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + } + } + break; + case IROLinearAsm: { + IROExpr *expr; + IRO_GetKills(linear); + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_BitsInCommon(expr->depends, IRO_VarKills)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + break; + } + case IROLinearFunccall: + GetExprKillsByFunctionCall(linear); + break; + } +} + +void IRO_ComputeAvail(void) { + IRONode *node; + IROLinear *linear; + SInt32 counter; + BitVector *bv; + Boolean flag; + + counter = 0; + node = IRO_FirstNode; + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + Bv_AllocVector(&IRO_ExprKills, IRO_NumExprs + 1); + + while (node) { + Bv_AllocVector(&node->x16, IRO_NumExprs); + if (node->numpred) + Bv_Set(node->x16); + Bv_AllocVector(&node->x22, IRO_NumExprs); + Bv_AllocVector(&node->x1E, IRO_NumExprs); + Bv_AllocVector(&node->x1A, IRO_NumExprs); + + for (linear = node->first; linear; linear = linear->next) { + if (linear->expr) + Bv_SetBit(linear->expr->index, node->x1E); + IRO_GetExprKills(linear); + Bv_Or(IRO_ExprKills, node->x22); + Bv_Minus(IRO_ExprKills, node->x1E); + if (linear == node->last) + break; + + if (counter > 250) { + IRO_CheckForUserBreak(); + counter = 0; + } else { + counter++; + } + } + + Bv_Copy(node->x16, node->x1A); + Bv_Minus(node->x22, node->x1A); + Bv_Or(node->x1E, node->x1A); + node = node->nextnode; + } + + IRO_CheckForUserBreak(); + + Bv_AllocVector(&bv, IRO_NumExprs); + do { + flag = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (!node->numpred) { + Bv_Clear(bv); + } else { + UInt16 i; + Bv_Set(bv); + for (i = 0; i < node->numpred; i++) + Bv_And(IRO_NodeTable[node->pred[i]]->x1A, bv); + } + + if (!Bv_Compare(bv, node->x16)) { + flag = 1; + Bv_Copy(bv, node->x16); + } + + Bv_Copy(node->x16, node->x1A); + Bv_Minus(node->x22, node->x1A); + Bv_Or(node->x1E, node->x1A); + } + IRO_CheckForUserBreak(); + } while (flag); +} + +static void IRO_MakeReplacementEmbedded(IROExpr *expr) { + IROLinear *opnd; + IROLinear *ind; + IROLinear *ass; + + IRO_GetTemp(expr); + + opnd = IRO_NewLinear(IROLinearOperand); + opnd->u.node = create_objectrefnode(expr->x8); + opnd->rtype = opnd->u.node->data.objref->type; + opnd->index = ++IRO_NumLinear; + opnd->flags |= IROLF_Reffed | IROLF_Assigned | IROLF_Ind; + + ind = IRO_NewLinear(IROLinearOp1Arg); + ind->nodetype = EINDIRECT; + ind->rtype = expr->linear->rtype; + ind->u.monadic = opnd; + ind->index = ++IRO_NumLinear; + ind->flags |= IROLF_Reffed | IROLF_Assigned; + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->nodetype = EASS; + ass->u.diadic.left = ind; + ass->u.diadic.right = expr->linear; + ass->rtype = expr->linear->rtype; + ass->index = ++IRO_NumLinear; + + opnd->next = ind; + ind->next = ass; + IRO_ReplaceReferenceWithNode(expr->linear, ass); + IRO_PasteAfter(opnd, ass, expr->linear); +} + +static void IRO_ActUnmarkSubExpressions(IROLinear *linear, Boolean isFirst) { + if (isFirst) + linear->flags &= ~IROLF_8; +} + +static void CheckCommonSub(IROLinear *linear) { + IROExpr *expr; + + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (expr->linear != linear && !expr->x14) { + if (Bv_IsBitSet(expr->index, IRO_Avail) && !expr->notSubable && IRO_ExprsSame(linear, expr->linear)) { + IRO_WalkTree(linear, IRO_ActUnmarkSubExpressions); + linear->flags |= IROLF_8; + linear->expr->x14 = expr; + break; + } + } + } +} + +static void MoveCommonSub(IROExpr *expr) { + SInt32 best; + SInt32 sz1; + SInt32 sz2; + SInt32 i1; + SInt32 i2; + IROLinear *scan; + IROLinear *array1[64]; + IROLinear *array2[64]; + IROExpr *scanexpr; + + sz1 = 0; + scan = expr->linear; + do { + scan = IRO_LocateFather(scan); + if (scan) { + if (sz1 == 64) + return; + array1[sz1++] = scan; + } + } while (scan); + + best = -1; + for (scanexpr = IRO_FirstExpr; scanexpr; scanexpr = scanexpr->next) { + if (scanexpr->x14 == expr) { + sz2 = 0; + scan = scanexpr->linear; + do { + scan = IRO_LocateFather(scan); + if (scan) { + if (sz2 == 64) + return; + array2[sz2++] = scan; + } + } while (scan); + + i1 = sz1; + i2 = sz2; + while (i1 && i2 && array1[sz1 - 1] == array2[sz2 - 1]) { + i1--; + i2--; + } + + if (i1 != sz1 && i1 > best) + best = i1; + } + } + + if (best < 0) { + IRO_MakeReplacementEmbedded(expr); + } else { + IROLinear *start; + IROLinear *comma; + IRO_Dump("Moving common sub from node %d to %d\n", expr->linear->index, array1[best]->index); + start = IRO_FindStart(array1[best]); + IRO_GetTemp(expr); + IRO_ReplaceReference(expr->linear, expr->x8, expr->linear); + IRO_MoveExpression(expr, start); + + comma = IRO_NewLinear(IROLinearOp2Arg); + comma->nodetype = ECOMMA; + comma->rtype = array1[best]->rtype; + comma->u.diadic.left = IRO_AssignToTemp(expr); + comma->u.diadic.right = array1[best]; + comma->stmt = array1[best]->stmt; + IRO_ReplaceReferenceWithNode(array1[best], comma); + IRO_PasteAfter(comma, comma, array1[best]); + } +} + +static void ReplaceCommonSub(IROLinear *linear) { + IROExpr *expr = linear->expr->x14; + if (!expr->x8) { + MoveCommonSub(expr); + if (!expr->x8) + return; + } + + IRO_Dump("Replacing common sub at %d with %d\n", linear->index, expr->linear->index); + IRO_ReplaceReference(linear, expr->x8, linear); + IRO_RemoveExpr(linear->expr); + IRO_NopOut(linear); +} + +void IRO_CommonSubs(void) { + IRONode *node; + IROLinear *linear; + SInt32 counter; + + counter = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + IRO_Avail = node->x16; + linear = node->first; + while (1) { + if (!linear) + break; + if (linear->expr && !linear->expr->notSubable) + CheckCommonSub(linear); + if (linear->expr) + Bv_SetBit(linear->expr->index, IRO_Avail); + IRO_GetExprKills(linear); + Bv_Minus(IRO_ExprKills, IRO_Avail); + if (linear == node->last) + break; + if (counter > 250) { + IRO_CheckForUserBreak(); + counter = 0; + } else { + counter++; + } + linear = linear->next; + } + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + for (linear = node->first; linear; linear = linear->next) { + if (linear->expr && (linear->flags & IROLF_8) && !IRO_HasSideEffect(linear)) + ReplaceCommonSub(linear); + if (linear == node->last) + break; + if (counter > 250) { + IRO_CheckForUserBreak(); + counter = 0; + } else { + counter++; + } + } + } + + IRO_CheckForUserBreak(); +} + +static Boolean CountThisSubableOperandUse() { +} + +static void GetSubableOperandUseCount() { +} + +static void IRO_MakeTopLevelExprForSubableOperand(IROLinear *linear) { + IROLinear *copy = IRO_NewLinear(IROLinearOperand); + memcpy(copy, linear, sizeof(IROLinear)); + copy->index = ++IRO_NumLinear; + + if (IRO_FirstLinear && IRO_FirstLinear->type == IROLinearNop) + IRO_PasteAfter(copy, copy, IRO_FirstLinear); + else + IRO_Paste(copy, copy, IRO_FirstLinear); +} + +void IRO_GenerateTopLevelExprsForSubableOperands(void) { + IROLinear *nd; + IRONode *fnode; + VarRecord *var; + BitVector *bv; + + Bv_AllocVector(&bv, IRO_NumVars + 1); + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + for (nd = fnode->first; nd; nd = nd->next) { + nd->expr = NULL; + if ((nd->flags & IROLF_Reffed) && IRO_IsSubableExpression(nd) && IRO_DoesNotHaveVectorOperand(nd)) { + if (nd->type == IROLinearOperand && nd->u.node && nd->u.node->type == EOBJREF) { + if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 1))) { + if (!Bv_IsBitSet(var->index, bv)) { + IRO_MakeTopLevelExprForSubableOperand(nd); + Bv_SetBit(var->index, bv); + } + } + } + } + + if (nd == fnode->last) + break; + } + } +} diff --git a/compiler_and_linker/unsorted/IroDump.c b/compiler_and_linker/unsorted/IroDump.c index e69de29..9472a0f 100644 --- a/compiler_and_linker/unsorted/IroDump.c +++ b/compiler_and_linker/unsorted/IroDump.c @@ -0,0 +1,652 @@ +#include "compiler/IroDump.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroPropagate.h" +#include "compiler/IroUtil.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/objects.h" +#include "compiler/IroVars.h" +#include "compiler/IroCSE.h" + +static FILE *DumpFile; +static char *nodenames[MAXEXPR]; + +char *IRO_NodeName(ENodeType nodetype) { + return nodenames[nodetype]; +} + +void IRO_InitializeNodeNamesArray(void) { + int i; + for (i = 0; i < MAXEXPR; i++) + nodenames[i] = ""; + + nodenames[EPOSTINC] = "EPOSTINC"; + nodenames[EPOSTDEC] = "EPOSTDEC"; + nodenames[EPREINC] = "EPREINC"; + nodenames[EPREDEC] = "EPREDEC"; + nodenames[EINDIRECT] = "EINDIRECT"; + nodenames[EMONMIN] = "EMONMIN"; + nodenames[EBINNOT] = "EBINNOT"; + nodenames[ELOGNOT] = "ELOGNOT"; + nodenames[EFORCELOAD] = "EFORCELOAD"; + nodenames[EMUL] = "EMUL"; + nodenames[EMULV] = "EMULV"; + nodenames[EDIV] = "EDIV"; + nodenames[EMODULO] = "EMODULO"; + nodenames[EADDV] = "EADDV"; + nodenames[ESUBV] = "ESUBV"; + nodenames[EADD] = "EADD"; + nodenames[ESUB] = "ESUB"; + nodenames[ESHL] = "ESHL"; + nodenames[ESHR] = "ESHR"; + nodenames[ELESS] = "ELESS"; + nodenames[EGREATER] = "EGREATER"; + nodenames[ELESSEQU] = "ELESSEQU"; + nodenames[EGREATEREQU] = "EGREATEREQU"; + nodenames[EEQU] = "EEQU"; + nodenames[ENOTEQU] = "ENOTEQU"; + nodenames[EAND] = "EAND"; + nodenames[EXOR] = "EXOR"; + nodenames[EOR] = "EOR"; + nodenames[ELAND] = "ELAND"; + nodenames[ELOR] = "ELOR"; + nodenames[EASS] = "EASS"; + nodenames[EMULASS] = "EMULASS"; + nodenames[EDIVASS] = "EDIVASS"; + nodenames[EMODASS] = "EMODASS"; + nodenames[EADDASS] = "EADDASS"; + nodenames[ESUBASS] = "ESUBASS"; + nodenames[ESHLASS] = "ESHLASS"; + nodenames[ESHRASS] = "ESHRASS"; + nodenames[EANDASS] = "EANDASS"; + nodenames[EXORASS] = "EXORASS"; + nodenames[EORASS] = "EORASS"; + nodenames[ECOMMA] = "ECOMMA"; + nodenames[EPMODULO] = "EPMODULO"; + nodenames[EROTL] = "EROTL"; + nodenames[EROTR] = "EROTR"; + nodenames[EBCLR] = "EBCLR"; + nodenames[EBTST] = "EBTST"; + nodenames[EBSET] = "EBSET"; + nodenames[ETYPCON] = "ETYPCON"; + nodenames[EBITFIELD] = "EBITFIELD"; + nodenames[EINTCONST] = "EINTCONST"; + nodenames[EFLOATCONST] = "EFLOATCONST"; + nodenames[ESTRINGCONST] = "ESTRINGCONST"; + nodenames[ECOND] = "ECOND"; + nodenames[EFUNCCALL] = "EFUNCCALL"; + nodenames[EFUNCCALLP] = "EFUNCCALLP"; + nodenames[EOBJREF] = "EOBJREF"; + nodenames[EMFPOINTER] = "EMFPOINTER"; + nodenames[ENULLCHECK] = "ENULLCHECK"; + nodenames[EPRECOMP] = "EPRECOMP"; + nodenames[ETEMP] = "ETEMP"; + nodenames[EARGOBJ] = "EARGOBJ"; + nodenames[ELOCOBJ] = "ELOCOBJ"; + nodenames[ELABEL] = "ELABEL"; + nodenames[ESETCONST] = "ESETCONST"; + nodenames[ENEWEXCEPTION] = "ENEWEXCEPTION"; + nodenames[ENEWEXCEPTIONARRAY] = "ENEWEXCEPTIONARRAY"; + nodenames[EOBJLIST] = "EOBJLIST"; + nodenames[EMEMBER] = "EMEMBER"; + nodenames[ETEMPLDEP] = "ETEMPLDEP"; + nodenames[EINSTRUCTION] = "EINSTRUCTION"; + nodenames[EDEFINE] = "EDEFINE"; + nodenames[EREUSE] = "EREUSE"; + nodenames[EASSBLK] = "EASSBLK"; + nodenames[EVECTOR128CONST] = "EVECTOR128CONST"; + nodenames[ECONDASS] = "ECONDASS"; +} + +static void DumpENode(ENode *enode) { + char buf[64]; + + if (IRO_Log) { + switch (enode->type) { + case EOBJREF: + fprintf(DumpFile, "%s", enode->data.objref->name->name); + break; + case EINTCONST: + CInt64_PrintDec(buf, enode->data.intval); + fprintf(DumpFile, "%s", buf); + break; + case EFLOATCONST: + fprintf(DumpFile, "%g", enode->data.floatval.value); + break; + case EVECTOR128CONST: + fprintf(DumpFile, "%.8lX%.8lX%.8lX%.8lX", + enode->data.vector128val.ul[0], + enode->data.vector128val.ul[1], + enode->data.vector128val.ul[2], + enode->data.vector128val.ul[3] + ); + break; + } + } +} + +static void DumpLinearNode(IROLinear *linear) { + int i; + + if (IRO_Log) { + fprintf(DumpFile, "%4d: ", linear->index); + switch (linear->type) { + case IROLinearNop: + fprintf(DumpFile, "Nop"); + break; + case IROLinearOperand: + fprintf(DumpFile, "Operand "); + DumpENode(linear->u.node); + break; + case IROLinearOp1Arg: + fprintf(DumpFile, "%s %d", nodenames[linear->nodetype], linear->u.monadic->index); + break; + case IROLinearOp2Arg: + fprintf(DumpFile, "%s %d %d", nodenames[linear->nodetype], linear->u.diadic.left->index, linear->u.diadic.right->index); + break; + case IROLinearGoto: + fprintf(DumpFile, "Goto %s", linear->u.label.label->name->name); + break; + case IROLinearIf: + fprintf(DumpFile, "If %d %s", linear->u.label.x4->index, linear->u.label.label->name->name); + break; + case IROLinearIfNot: + fprintf(DumpFile, "IfNot %d %s", linear->u.label.x4->index, linear->u.label.label->name->name); + break; + case IROLinearReturn: + fprintf(DumpFile, "Return "); + if (linear->u.monadic) + fprintf(DumpFile, "%d", linear->u.monadic->index); + break; + case IROLinearLabel: + fprintf(DumpFile, "Label %s", linear->u.label.label->name->name); + break; + case IROLinearSwitch: + fprintf(DumpFile, "Switch %d", linear->u.swtch.x4->index); + break; + case IROLinearOp3Arg: + fprintf(DumpFile, "%s %d %d %d", + nodenames[linear->nodetype], + linear->u.args3.a->index, + linear->u.args3.b->index, + linear->u.args3.c->index); + break; + case IROLinearFunccall: + fprintf(DumpFile, "Funccall %d(", linear->u.funccall.linear8->index); + for (i = 0; i < linear->u.funccall.argCount; i++) { + fprintf(DumpFile, "%d", linear->u.funccall.args[i]->index); + if (i < (linear->u.funccall.argCount - 1)) + fprintf(DumpFile, ","); + } + fprintf(DumpFile, ")"); + break; + case IROLinearBeginCatch: + fprintf(DumpFile, "BeginCatch %d", linear->u.ctch.linear->index); + break; + case IROLinearEndCatch: + fprintf(DumpFile, "EndCatch %d", linear->u.monadic->index); + break; + case IROLinearEndCatchDtor: + fprintf(DumpFile, "EndCatchDtor %d", linear->u.monadic->index); + break; + case IROLinearEnd: + fprintf(DumpFile, "End"); + break; + } + + if (linear->flags & IROLF_Assigned) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Used) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Ind) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Subs) fprintf(DumpFile, " "); + if (linear->flags & IROLF_LoopInvariant) fprintf(DumpFile, " "); + if (linear->flags & IROLF_BeginLoop) fprintf(DumpFile, " "); + if (linear->flags & IROLF_EndLoop) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Ris) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Immind) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Reffed) fprintf(DumpFile, " "); + if (linear->flags & IROLF_VecOp) fprintf(DumpFile, " "); + if (linear->flags & IROLF_VecOpBase) fprintf(DumpFile, " "); + if (linear->flags & IROLF_CounterLoop) fprintf(DumpFile, " "); + if (linear->flags & IROLF_BitfieldIndirect) fprintf(DumpFile, " "); + if (linear->flags & IROLF_CouldError) fprintf(DumpFile, " "); + + if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) + fprintf(DumpFile, " "); + + if (IS_LINEAR_ENODE(linear, EOBJREF)) { + VarRecord *var = IRO_FindVar(linear->u.node->data.objref, 0, 1); + if (var && is_volatile_object(var->object)) + fprintf(DumpFile, " "); + } + + fprintf(DumpFile, "\n"); + } +} + +static void DumpAct(IROLinear *linear, Boolean isFirst) { + if (!isFirst) + DumpLinearNode(linear); +} + +void IRO_DumpIntTree(IROLinear *linear) { + IRO_WalkTree(linear, DumpAct); +} + +void IRO_DumpLinearList(IROLinear *linear) { + if (!IRO_Log) + return; + + while (linear) { + DumpLinearNode(linear); + linear = linear->next; + } + fprintf(DumpFile, "\n"); +} + +static void DumpList(int num, UInt16 *list) { + int i; + + if (IRO_Log) { + for (i = 0; i < num; i++) + fprintf(DumpFile, "%d ", list[i]); + fprintf(DumpFile, "\n"); + } +} + +void IRO_DumpBits(char *name, BitVector *bv) { + SInt32 i; + SInt32 rangeStart; + Boolean inRange = 0; + Boolean isFirst = 1; + + if (!IRO_Log) + return; + + fprintf(DumpFile, name); + if (!bv) { + fprintf(DumpFile, "NULL"); + } else { + for (i = 0; i < (bv->size * 32); i++) { + if (Bv_IsBitSet(i, bv)) { + if (!inRange) { + if (!isFirst) + fputc(',', DumpFile); + isFirst = 0; + fprintf(DumpFile, "%d", i); + inRange = 1; + rangeStart = i; + } + } else { + if (inRange) { + inRange = 0; + if (i != (rangeStart + 1)) + fprintf(DumpFile, "-%d", i - 1); + } + } + } + + if (inRange && i != (rangeStart + 1)) + fprintf(DumpFile, "-%d", i - 1); + } + + fprintf(DumpFile, "\n"); +} + +void IRO_DumpAfterPhase(char *str, Boolean flag) { + if (flag) { + IRO_Dump("Dumping function %s after %s \n", FunctionName ? FunctionName->name->name : "Init-code", str); + IRO_Dump("--------------------------------------------------------------------------------\n"); + IRO_DumpFlowgraph(); + } +} + +void IRO_LogForFunction(char *name) { + if (FunctionName) { + if (!strcmp(FunctionName->name->name, name)) + IRO_Log = 1; + else + IRO_Log = 0; + } +} + +void IRO_DumpFlowgraph(void) { + IRONode *node; + IROLinear *linear; + + if (IRO_Log && DumpFile) { + fprintf(DumpFile, "\nFlowgraph\n"); + for (node = IRO_FirstNode; node; node = node->nextnode) { + fprintf(DumpFile, "Flowgraph node %d First=%d, Last=%d\n", node->index, node->first->index, node->last->index); + + fprintf(DumpFile, "Succ = "); + DumpList(node->numsucc, node->succ); + fprintf(DumpFile, "Pred = "); + DumpList(node->numpred, node->pred); + + fprintf(DumpFile, "MustReach = %d, MustReach1=%d\n", node->mustreach, node->mustreach1); + fprintf(DumpFile, "LoopDepth = %d\n", node->loopdepth); + + IRO_DumpBits("Dom: ", node->dom); + if ((linear = node->first)) { + while (1) { + DumpLinearNode(linear); + if (linear == node->last) + break; + linear = linear->next; + } + } + + fprintf(DumpFile, "\n\n"); + } + fprintf(DumpFile, "\n"); + fflush(DumpFile); + } +} + +void IRO_DumpNode(IRONode *node) { + IROLinear *linear; + + if (IRO_Log) { + if (!DumpFile) + return; + + while (node) { + fprintf(DumpFile, "Flowgraph node %d First=%d, Last=%d\n", node->index, node->first->index, + node->last->index); + + fprintf(DumpFile, "Succ = "); + DumpList(node->numsucc, node->succ); + fprintf(DumpFile, "Pred = "); + DumpList(node->numpred, node->pred); + + fprintf(DumpFile, "MustReach = %d MustReach1 = %d\n", node->mustreach, node->mustreach1); + fprintf(DumpFile, "LoopDepth = %d\n", node->loopdepth); + + IRO_DumpBits("Dom: ", node->dom); + if ((linear = node->first)) { + while (1) { + DumpLinearNode(linear); + if (linear == node->last) + break; + linear = linear->next; + } + } + + fprintf(DumpFile, "\n\n"); + node = node->nextnode; + } + + fprintf(DumpFile, "\n"); + fflush(DumpFile); + } +} + +void IRO_DumpAssignments(void) { + IROAssign *assign; + + if (IRO_Log) { + fprintf(DumpFile, "\nAssignments\n\n"); + for (assign = IRO_FirstAssign; assign; assign = assign->next) { + fprintf(DumpFile, "%5d ", assign->index); + DumpLinearNode(assign->linear); + fprintf(DumpFile, "\n"); + } + fprintf(DumpFile, "\n"); + } +} + +void IRO_DumpVars(void) { + VarRecord *var; + + if (IRO_Log) { + fprintf(DumpFile, "\nVariables\n"); + for (var = IRO_FirstVar; var; var = var->next) { + fprintf(DumpFile, "%5d %s %s\n", var->index, var->object->name->name, var->xB ? "" : ""); + } + fprintf(DumpFile, "\n"); + } +} + +void IRO_DumpDf(void) { + IRONode *node; + + if (IRO_Log) { + for (node = IRO_FirstNode; node; node = node->nextnode) { + fprintf(DumpFile, "Node %d\n", node->index); + if (node->x16) IRO_DumpBits("In: ", node->x16); + if (node->x1E) IRO_DumpBits("Gen: ", node->x1E); + if (node->x22) IRO_DumpBits("Kill: ", node->x22); + if (node->x1A) IRO_DumpBits("Out: ", node->x1A); + if (node->x2A) IRO_DumpBits("AA: ", node->x2A); + fprintf(DumpFile, "\n"); + } + fprintf(DumpFile, "\n"); + } +} + +void IRO_DumpExprs(void) { + IROExpr *expr; + + if (IRO_Log) { + fprintf(DumpFile, "Expressions\n\n"); + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + fprintf(DumpFile, "%4d: %d FN:%d CE:%d NS:%d ", expr->index, expr->linear->index, expr->node->index, expr->couldError, expr->notSubable); + IRO_DumpBits("Depends: ", expr->depends); + fprintf(DumpFile, "\n"); + } + fprintf(DumpFile, "\n"); + } +} + +void IRO_SetupDump(void) { + if (IRO_Log) { + if ((DumpFile = fopen("OPT.LOG", "wt")) == NULL) + IRO_Log = 0; + } +} + +void IRO_CleanupDump(void) { + if (DumpFile) + fclose(DumpFile); +} + +void IRO_Dump(char *format, ...) { + va_list va; + if (IRO_Log) { + va_start(va, format); + vfprintf(DumpFile, format, va); + va_end(va); + } +} + +void IRO_DumpAddr(IROAddrRecord *rec) { + IROElmList *list; + + if (IRO_Log && DumpFile) { + fprintf(DumpFile, "\n"); + fprintf(DumpFile, "Address :\n"); + IRO_DumpIntTree(rec->linear); + fprintf(DumpFile, "\n"); + fprintf(DumpFile, "BaseTerms:\n"); + for (list = rec->objRefs; list; list = list->next) { + IRO_DumpIntTree(list->element); + fprintf(DumpFile, "\n"); + } + fprintf(DumpFile, "VarTerms:\n"); + for (list = rec->misc; list; list = list->next) { + IRO_DumpIntTree(list->element); + fprintf(DumpFile, "\n"); + } + fprintf(DumpFile, "ConstTerms:\n"); + for (list = rec->ints; list; list = list->next) { + IRO_DumpIntTree(list->element); + fprintf(DumpFile, "\n"); + } + } +} + +static void IRO_DumpType(Type *type) { + char buf[256]; + IRO_SpellType(type, buf); + fprintf(DumpFile, " (%s)", buf); +} + +void IRO_SpellType(Type *type, char *buf) { + char mybuf[256]; + char mybuf2[256]; + + switch (type->type) { + case TYPEVOID: + strcpy(buf, "void"); + break; + case TYPEINT: + switch (TYPE_INTEGRAL(type)->integral) { + case IT_BOOL: + strcpy(buf, "bool"); + break; + case IT_CHAR: + strcpy(buf, "char"); + break; + case IT_WCHAR_T: + strcpy(buf, "wchar_t"); + break; + case IT_SCHAR: + strcpy(buf, "signed char"); + break; + case IT_UCHAR: + strcpy(buf, "unsigned char"); + break; + case IT_SHORT: + strcpy(buf, "short"); + break; + case IT_USHORT: + strcpy(buf, "unsigned short"); + break; + case IT_INT: + strcpy(buf, "int"); + break; + case IT_UINT: + strcpy(buf, "unsigned int"); + break; + case IT_LONG: + strcpy(buf, "long"); + break; + case IT_ULONG: + strcpy(buf, "unsigned long"); + break; + case IT_LONGLONG: + strcpy(buf, "long long"); + break; + case IT_ULONGLONG: + strcpy(buf, "unsigned long long"); + break; + } + break; + case TYPEFLOAT: + switch (TYPE_INTEGRAL(type)->integral) { + case IT_FLOAT: + strcpy(buf, "float"); + break; + case IT_SHORTDOUBLE: + strcpy(buf, "short double"); + break; + case IT_DOUBLE: + strcpy(buf, "double"); + break; + case IT_LONGDOUBLE: + strcpy(buf, "long double"); + break; + } + break; + case TYPEENUM: + strcpy(buf, "enum "); + if (TYPE_ENUM(type)->enumname) + strcat(buf, TYPE_ENUM(type)->enumname->name); + break; + case TYPESTRUCT: + if (IS_TYPESTRUCT_VECTOR(type)) { + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_TYPE_4: + strcpy(buf, "vector unsigned char "); + break; + case STRUCT_TYPE_5: + strcpy(buf, "vector signed char "); + break; + case STRUCT_TYPE_6: + strcpy(buf, "vector bool char "); + break; + case STRUCT_TYPE_7: + strcpy(buf, "vector unsigned short "); + break; + case STRUCT_TYPE_8: + strcpy(buf, "vector signed short "); + break; + case STRUCT_TYPE_9: + strcpy(buf, "vector bool short "); + break; + case STRUCT_TYPE_A: + strcpy(buf, "vector unsigned long "); + break; + case STRUCT_TYPE_B: + strcpy(buf, "vector signed long "); + break; + case STRUCT_TYPE_C: + strcpy(buf, "vector bool long "); + break; + case STRUCT_TYPE_D: + strcpy(buf, "vector float "); + break; + case STRUCT_TYPE_E: + strcpy(buf, "vector pixel "); + break; + } + } else { + strcpy(buf, "struct "); + } + if (TYPE_STRUCT(type)->name) + strcat(buf, TYPE_STRUCT(type)->name->name); + break; + case TYPECLASS: + strcpy(buf, "class "); + if (TYPE_CLASS(type)->classname) + strcat(buf, TYPE_CLASS(type)->classname->name); + break; + case TYPEFUNC: + IRO_SpellType(TYPE_FUNC(type)->functype, mybuf); + strcpy(buf, "freturns("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEBITFIELD: + IRO_SpellType(TYPE_BITFIELD(type)->bitfieldtype, mybuf); + sprintf(buf, "bitfield(%s){%d:%d}", mybuf, TYPE_BITFIELD(type)->unkA, TYPE_BITFIELD(type)->unkB); + break; + case TYPELABEL: + strcpy(buf, "label"); + break; + case TYPEPOINTER: + IRO_SpellType(TPTR_TARGET(type), mybuf); + strcpy(buf, "pointer("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEARRAY: + IRO_SpellType(TPTR_TARGET(type), mybuf); + strcpy(buf, "array("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEMEMBERPOINTER: + IRO_SpellType(TYPE_MEMBER_POINTER(type)->ty2, mybuf); + IRO_SpellType(TYPE_MEMBER_POINTER(type)->ty1, mybuf2); + strcpy(buf, "memberpointer("); + strcat(buf, mybuf); + strcat(buf, ","); + strcat(buf, mybuf2); + strcat(buf, ")"); + break; + } +} + diff --git a/compiler_and_linker/unsorted/IroEmptyLoop.c b/compiler_and_linker/unsorted/IroEmptyLoop.c index e69de29..1a63f84 100644 --- a/compiler_and_linker/unsorted/IroEmptyLoop.c +++ b/compiler_and_linker/unsorted/IroEmptyLoop.c @@ -0,0 +1,567 @@ +#include "compiler/IroEmptyLoop.h" +#include "compiler/IroDump.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroLoop.h" +#include "compiler/IroUtil.h" +#include "compiler/IroVars.h" +#include "compiler/CInt64.h" + +// forward decls +static Boolean EmptyLoop(IRONode *fnode); +static int CanRemoveRedundantLoop(IROLoop *loop); +static int CanRemoveRedundantLoop1(IROLoop *loop); +static int RedundantLoopCheck(IROLoop *loop); +static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2); +static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2); + +void IRO_FindEmptyLoops(void) { + IRONode *fnode; + IRONode *pred; + UInt16 i; + UInt16 x; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + x = 0; + for (i = 0; i < fnode->numpred; i++) { + pred = IRO_NodeTable[fnode->pred[i]]; + if (Bv_IsBitSet(fnode->index, pred->dom)) { + if (!x) { + Bv_AllocVector(&InLoop, IRO_NumNodes + 1); + Bv_Clear(InLoop); + Bv_SetBit(fnode->index, InLoop); + } + x = 1; + Bv_SetBit(pred->index, InLoop); + if (pred != fnode) + AddPreds(pred); + } + } + + if (x) { + IRO_Dump("IRO_FindEmptyLoops:Found loop with header %d\n", fnode->index); + IRO_DumpBits("Loop includes: ", InLoop); + EmptyLoop(fnode); + IRO_UpdateFlagsOnInts(); + } + } + + IRO_CheckForUserBreak(); +} + +static Boolean EmptyLoop(IRONode *fnode) { + VarRecord *var; + IRONode *bestpred; + IRONode *pred; + UInt16 i; + int flag2; + IRONode *r24; + Boolean flag; + int counter; + int j; + IRONode *succ; + IRONode *bestsucc; + int counter2; + UInt32 counter3; + IROLoop *loop; + IRONode *r21; + IRONode *r20; + IROLinear *constnd; + Type *type20; + ENode *enode; + IROLinear *save; + + flag = 0; + counter = 0; + LoopNode = fnode; + FindMustReach(); + + for (var = IRO_FirstVar; var; var = var->next) + var->xA = 1; + + ComputeLoopKills(); + ComputeLoopInvariance(); + ComputeLoopInduction(); + + LoopNode = fnode; + ConditionalHeaderAtBottom = 0; + + bestpred = NULL; + flag2 = 0; + for (i = 0; i < LoopNode->numpred; i++) { + pred = IRO_NodeTable[LoopNode->pred[i]]; + if (!Bv_IsBitSet(pred->index, InLoop)) { + flag2 = 1; + if (pred->nextnode == fnode) { +#line 173 + CError_ASSERT(!bestpred || pred == bestpred); + bestpred = pred; + } + } + } + + if (!flag2) { + IRO_Dump("No predecessor outside the loop\n"); + return 0; + } + + bestsucc = NULL; + for (i = 0; i < LoopNode->numsucc; i++) { + succ = IRO_NodeTable[LoopNode->succ[i]]; + if (Bv_IsBitSet(succ->index, InLoop)) { + bestsucc = succ; + counter++; + } + } + + if (LoopNode == bestsucc && counter == 1) + flag = 1; + + if (LoopNode->last->type != IROLinearIf || LoopNode->last->type != IROLinearIfNot || flag) { + counter2 = 0; + for (j = 0; j < LoopNode->numpred; j++) { + if (Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) { + r21 = IRO_NodeTable[LoopNode->pred[j]]; + counter2++; + } + } + + r24 = NULL; + counter3 = 0; + for (j = 0; j < LoopNode->numpred; j++) { + if (!Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) { + r24 = IRO_NodeTable[LoopNode->pred[j]]; + counter3++; + } + } + + if (counter2 == 1 && counter3 == 1) { + if (r21->last->type == IROLinearIf) { + if ((Bv_IsBitSet(LoopNode->nextnode->index, InLoop) && !Bv_IsBitSet(r21->nextnode->index, InLoop)) || flag) { + IRO_Dump("Standard while loop layout\n"); + loop = ExtractLoopInfo(r21); + if (flag) + loop->flags |= LoopFlags_20000; + FindAssignmenttoInductionVar(loop, r24); + r20 = r24; + while (r20 && !loop->nd14 && r20->numpred == 1 && IRO_NodeTable[r20->pred[0]]->numsucc == 1) { + FindAssignmenttoInductionVar(loop, IRO_NodeTable[r20->pred[0]]); + r20 = IRO_NodeTable[r20->pred[0]]; + } + + if (CanRemoveRedundantLoop(loop)) { + IRO_Dump("EmptyLoop: # of iterations =%ld, FinalStoreVal=%ld\n", CInt64_GetULong(&loop->x28), CInt64_GetULong(&loop->x30)); + IRO_NopOut(r21->last->u.label.x4); + r21->last->type = IROLinearNop; + type20 = loop->induction->nd->rtype; + constnd = IRO_NewLinear(IROLinearOperand); + constnd->index = ++IRO_NumLinear; + enode = IRO_NewENode(EINTCONST); + enode->rtype = type20; + enode->data.intval = loop->x30; + constnd->u.node = enode; + constnd->rtype = type20; + + if (loop->induction->nd->type == IROLinearOp1Arg) { + save = loop->induction->nd->u.monadic; + loop->induction->nd->type = IROLinearOp2Arg; + loop->induction->nd->nodetype = EASS; + loop->induction->nd->u.diadic.left = save; + loop->induction->nd->u.diadic.right = constnd; + IRO_Paste(constnd, constnd, loop->induction->nd); + } else if (loop->induction->nd->type == IROLinearOp2Arg) { + loop->induction->nd->nodetype = EASS; + IRO_NopOut(loop->induction->nd->u.diadic.right); + loop->induction->nd->u.diadic.right = constnd; + IRO_Paste(constnd, constnd, loop->induction->nd); + } + } else if (CanRemoveRedundantLoop1(loop)) { + IRO_Dump("EmptyLoop: self recursive dowhile(--n ) loop\n"); + + r21->last->type = IROLinearNop; + type20 = loop->induction->nd->rtype; + constnd = IRO_NewLinear(IROLinearOperand); + constnd->index = ++IRO_NumLinear; + enode = IRO_NewENode(EINTCONST); + enode->rtype = type20; + enode->data.intval = cint64_zero; + constnd->u.node = enode; + constnd->rtype = type20; + + save = loop->induction->nd->u.monadic; + loop->induction->nd->type = IROLinearOp2Arg; + loop->induction->nd->nodetype = EASS; + loop->induction->nd->u.diadic.left = save; + loop->induction->nd->u.diadic.right = constnd; + IRO_Paste(constnd, constnd, loop->induction->nd); + } + } else { + IRO_Dump("NonStandard while loop layout\n"); + } + } else { + IRO_Dump("NonStandard while loop layout\n"); + } + } else { + IRO_Dump("Cannot handle Do While Loop with multiple tails\n"); + } + } + + return 0; +} + +static int CanRemoveRedundantLoop(IROLoop *loop) { + IROLinear *inner; + + if (loop->flags & LoopFlags_10000) { + IRO_Dump("CanRemoveRedundantLoop:No because detection of dowhile(n--) loop not supported\n"); + return 0; + } + + if (loop->flags & LP_LOOP_HAS_ASM) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_ASM \n"); + return 0; + } + + if (loop->flags & LP_IFEXPR_NON_CANONICAL) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_IFEXPR_NON_CANONICAL \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HAS_CALLS) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CALLS \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CNTRLFLOW \n"); + return 0; + } + + if (loop->flags & LP_INDUCTION_NOT_FOUND) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_INDUCTION_NOT_FOUND \n"); + return 0; + } + + if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_HAS_MULTIPLE_INDUCTIONS \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n"); + return 0; + } + + if (!(loop->flags & LoopFlags_200)) { + IRO_Dump("CanRemoveRedundantLoop:No because header does not follow induction update \n"); + return 0; + } + + if (!(loop->flags & LoopFlags_10000)) { + inner = loop->nd18->u.diadic.right; + if (!IRO_IsIntConstant(inner) && !(inner->flags & IROLF_LoopInvariant)) { + IRO_Dump("CanRemoveRedundantLoop:No because Loop Upper Bound is Variant in the loop\n"); + return 0; + } + + if (!loop->nd14) { + IRO_Dump("CanRemoveRedundantLoop:No because there is no initialization of loop index in PreHeader\n"); + return 0; + } + + if (!IRO_IsVariable(loop->nd14->u.diadic.left)) { + IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction stored thru pointer\n"); + return 0; + } + + if (!IRO_IsUnsignedType(loop->nd14->rtype)) { + if (IRO_IsIntConstant(loop->nd14->u.diadic.right)) { + if (!CInt64_GreaterEqual(loop->nd14->u.diadic.right->u.node->data.intval, cint64_zero)) { + IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed but < 0\n"); + return 0; + } + } else { + IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed and not constant\n"); + return 0; + } + } + + if (!(loop->flags & LP_LOOP_STEP_ISPOS) && !(loop->flags & LP_LOOP_STEP_ISNEG)) { + IRO_Dump("CanRemoveRedundantLoop:No because LP_LOOP_STEP_ISPOS/LP_LOOP_STEP_ISNEG is not set\n"); + return 0; + } + + if ((loop->flags & LP_LOOP_STEP_ISPOS) && CheckStepOverFlow1_EmptyLoop(loop, &loop->x28, &loop->x30)) { + IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n"); + return 0; + } + + if ((loop->flags & LP_LOOP_STEP_ISNEG) && CheckStepOverFlow2_EmptyLoop(loop, &loop->x28, &loop->x30)) { + IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n"); + return 0; + } + } + + return RedundantLoopCheck(loop) != 0; +} + +static int CanRemoveRedundantLoop1(IROLoop *loop) { + if ((loop->flags & LoopFlags_10000) && (loop->flags & LoopFlags_20000)) { + if (loop->flags & LP_LOOP_HAS_ASM) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_ASM \n"); + return 0; + } + + if (loop->flags & LP_IFEXPR_NON_CANONICAL) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_IFEXPR_NON_CANONICAL \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HAS_CALLS) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CALLS \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CNTRLFLOW \n"); + return 0; + } + + if (loop->flags & LP_INDUCTION_NOT_FOUND) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_INDUCTION_NOT_FOUND \n"); + return 0; + } + + if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_HAS_MULTIPLE_INDUCTIONS \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n"); + return 0; + } + + if (!(loop->flags & LoopFlags_200)) { + IRO_Dump("CanRemoveRedundantLoop1:No because header does not follow induction update \n"); + return 0; + } + + if (loop->induction->nd->type == IROLinearOp1Arg && loop->induction->nd->nodetype == EPREDEC) { + if (IRO_IsUnsignedType(loop->induction->nd->rtype)) + return 1; + IRO_Dump("CanRemoveRedundantLoop1:No because induction not of the right type \n"); + return 0; + } + + IRO_Dump("CanRemoveRedundantLoop1:No because induction operator not a predec \n"); + return 0; + } else { + return 0; + } +} + +static int RedundantLoopCheck(IROLoop *loop) { + IRONode *fnode; + IROLinear *nd; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop) && fnode != loop->fnode && (nd = fnode->first)) { + while (1) { + if ((nd->index < loop->index20 || nd->index > loop->index24) && nd->type != IROLinearNop && nd->type != IROLinearLabel) { + if (IS_LINEAR_DIADIC(nd, EASS)) { + if (!(nd->flags & IROLF_Reffed)) { + if (IS_LINEAR_MONADIC(nd->u.diadic.left, EINDIRECT)) { + if (nd->u.diadic.left->rtype && CParser_IsVolatile(nd->u.diadic.left->rtype, nd->u.diadic.left->nodeflags & ENODE_FLAG_QUALS)) { + IRO_Dump(" EASS at %d fail as store to volatile memory \n", nd->index); + return 0; + } + + if ((nd->u.diadic.left->u.monadic->flags & IROLF_LoopInvariant) && (nd->u.diadic.right->flags & IROLF_LoopInvariant)) { + IRO_Dump(" EASS at %d pass\n", nd->index); + } else { + IRO_Dump(" EASS at %d fail, either LHS address or RHS is variant \n", nd->index); + return 0; + } + } else { + IRO_Dump("Found EASS nodes whose lhs root is not a EINDIRECT node\n"); + return 0; + } + } else { + IRO_Dump("Found EASS node that is referenced i.e embedded assignment\n"); + return 0; + } + } else { + if (!(nd->flags & IROLF_Reffed)) { + IRO_Dump("Found non EASS top level node in the loop\n"); + return 0; + } + } + } + + if (nd == fnode->last) + break; + nd = nd->next; + } + } + } + + return 1; +} + +static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) { + Boolean isUnsigned; + IROLinear *nd2; + IROLinear *nd1; + CInt64 nd2value; + CInt64 nd1value; + CInt64 addConst; + CInt64 work; + CInt64 neg1; + + nd2 = loop->nd14->u.diadic.right; + nd1 = loop->nd18->u.diadic.right; + isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype); + + if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) { + nd2value = nd2->u.node->data.intval; + nd1value = nd1->u.node->data.intval; + if (isUnsigned) { + if (CInt64_LessEqualU(nd1value, nd2value)) + return 1; + } else { + if (CInt64_LessEqual(nd1value, nd2value)) + return 1; + } + + CInt64_SetLong(&addConst, loop->induction->addConst); + CInt64_SetLong(&neg1, -1); + *val1 = CInt64_Sub(nd1value, nd2value); + *val1 = CInt64_Add(*val1, addConst); + if (IS_LINEAR_DIADIC(loop->nd18, ELESS)) + *val1 = CInt64_Add(*val1, neg1); + +#line 855 + CError_ASSERT(!CInt64_IsZero(&addConst)); + + if (isUnsigned) + *val1 = CInt64_DivU(*val1, addConst); + else + *val1 = CInt64_Div(*val1, addConst); + + if (CInt64_Equal(*val1, cint64_zero)) + return 1; + + if (isUnsigned) { + if (CInt64_LessEqualU(*val1, cint64_zero)) { +#line 877 + CError_FATAL(); + } + } else { + if (CInt64_LessEqual(*val1, cint64_zero)) { +#line 886 + CError_FATAL(); + } + } + + if (isUnsigned) { + *val2 = CInt64_MulU(*val1, addConst); + *val2 = CInt64_Add(*val2, nd2value); + } else { + *val2 = CInt64_Mul(*val1, addConst); + *val2 = CInt64_Add(*val2, nd2value); + } + } else { + return 1; + } + + CInt64_SetLong(&addConst, loop->induction->addConst); + work = CInt64_Add(nd1value, addConst); + + if (isUnsigned) { + if (CInt64_LessU(work, nd1value)) + return 1; + } else { + if (CInt64_Less(work, nd1value)) + return 1; + } + + return 0; +} + +static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) { + Boolean isUnsigned; + IROLinear *nd2; + IROLinear *nd1; + CInt64 nd2value; + CInt64 nd1value; + CInt64 addConst; + CInt64 work; + CInt64 neg1; + + nd1 = loop->nd14->u.diadic.right; + nd2 = loop->nd18->u.diadic.right; + isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype); + + if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) { + nd2value = nd2->u.node->data.intval; + nd1value = nd1->u.node->data.intval; + if (isUnsigned) { + if (CInt64_LessEqualU(nd1value, nd2value)) + return 1; + } else { + if (CInt64_LessEqual(nd1value, nd2value)) + return 1; + } + + CInt64_SetLong(&addConst, loop->induction->addConst); + CInt64_SetLong(&neg1, -1); + *val1 = CInt64_Sub(nd1value, nd2value); + *val1 = CInt64_Add(*val1, addConst); + if (IS_LINEAR_DIADIC(loop->nd18, EGREATER)) + *val1 = CInt64_Add(*val1, neg1); + +#line 995 + CError_ASSERT(!CInt64_IsZero(&addConst)); + + if (isUnsigned) + *val1 = CInt64_DivU(*val1, addConst); + else + *val1 = CInt64_Div(*val1, addConst); + + if (CInt64_Equal(*val1, cint64_zero)) + return 1; + + if (isUnsigned) { + if (CInt64_LessEqualU(*val1, cint64_zero)) + return 0; + } else { + if (CInt64_LessEqual(*val1, cint64_zero)) + return 0; + } + + if (isUnsigned) { + *val2 = CInt64_MulU(*val1, addConst); + *val2 = CInt64_Sub(nd1value, *val2); + } else { + *val2 = CInt64_Mul(*val1, addConst); + *val2 = CInt64_Sub(nd1value, *val2); + } + } else { + return 1; + } + + CInt64_SetLong(&addConst, loop->induction->addConst); + work = CInt64_Sub(nd2value, addConst); + + if (isUnsigned) { + if (CInt64_GreaterU(work, nd2value)) + return 1; + } else { + if (CInt64_Greater(work, nd1value)) + return 1; + } + + return 0; +} + diff --git a/compiler_and_linker/unsorted/IroExprRegeneration.c b/compiler_and_linker/unsorted/IroExprRegeneration.c index e69de29..074510b 100644 --- a/compiler_and_linker/unsorted/IroExprRegeneration.c +++ b/compiler_and_linker/unsorted/IroExprRegeneration.c @@ -0,0 +1,1531 @@ +#include "compiler/IroExprRegeneration.h" +#include "compiler/IroCSE.h" +#include "compiler/IroDump.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroSubable.h" +#include "compiler/IroTransform.h" +#include "compiler/IROUseDef.h" +#include "compiler/IroUtil.h" +#include "compiler/IroVars.h" +#include "compiler/CDecl.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/objects.h" + +// forward decls +static void GetExprUses(IROLinear *linear, Boolean isEntry); +static void RebuildPossibleCondExpression(IRONode *fnode); +static void AddNodeAndSuccessorsRecursively(IRONodes *nodes, IRONode *fnode1, IRONode *fnode2); + +static Boolean FindFlowgraphNodeThatStartsWithLabel(CLabel *label, IRONode **result1, IRONode **result2) { + IRONode *prev; + IRONode *iter; + + prev = IRO_FirstNode; + if (prev != NULL) + iter = prev->nextnode; + + while (iter) { + if (iter->first->type == IROLinearLabel && iter->first->u.label.label == label) { + *result1 = iter; + *result2 = prev; + return 1; + } + + prev = iter; + iter = iter->nextnode; + } + + return 0; +} + +static IROLinear *FindLastDiadicTopLevelAssignmentInFlowgraphNode(IRONode *fnode) { + IROLinear *scan; + IROLinear *result; + + result = NULL; + + for (scan = fnode->first; scan != fnode->last->next; scan = scan->next) { + if (scan->type == IROLinearOp2Arg && scan->nodetype == EASS && !(scan->flags & IROLF_Reffed)) + result = scan; + } + + return result; +} + +static Boolean RewriteUse(IROUse *use, ENode *enode, IROLinear *nd, Boolean flag) { + IROLinear *father; + IROLinear *father2; + + if ( + use && + use->x1C && + use->linear && + use->linear->type == IROLinearOperand && + use->linear->u.node->type == EOBJREF && + use->linear->u.node->data.objref == enode->data.objref && + (father = IRO_LocateFather(use->linear)) && + father->type == IROLinearOp1Arg && + father->nodetype == EINDIRECT && + father->rtype == nd->rtype && + (father2 = IRO_LocateFather(father)) && + ((father2->type != IROLinearOp1Arg && father2->type != IROLinearOp2Arg) || !IRO_IsModifyOp[father2->nodetype]) + ) { + if (flag) + IRO_LocateFather_Cut_And_Paste(father, nd); + return 1; + } + + return 0; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +static struct { + jmp_buf buf; + UInt16 index; + Boolean flag; +} scuai; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void StatementContainsUseAction(IROLinear *linear, Boolean isFirst) { + if (isFirst && linear->index == scuai.index) { + scuai.flag = 1; + longjmp(scuai.buf, 1); + } +} + +static Boolean StatementContainsUse(IROLinear *a, IROLinear *b) { + memset(&scuai, 0, sizeof(scuai)); + scuai.index = b->index; + scuai.flag = 0; + + if (!setjmp(scuai.buf)) + IRO_WalkInts(a, a, StatementContainsUseAction); + + return scuai.flag; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +static struct { + jmp_buf buf; + Boolean flag; +} scseai; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void StatementContainsSideEffectAction(IROLinear *linear, Boolean isFirst) { + if (isFirst) { + switch (linear->type) { + case IROLinearOperand: + case IROLinearOp1Arg: + case IROLinearOp2Arg: + case IROLinearOp3Arg: + case IROLinearFunccall: + case IROLinearAsm: + if (IRO_HasSideEffect(linear)) { + scseai.flag = 1; + longjmp(scseai.buf, 1); + } + break; + } + } +} + +static Boolean StatementContainsSideEffect(IROLinear *linear) { + memset(&scseai, 0, sizeof(scseai)); + scseai.flag = 0; + + if (!setjmp(scseai.buf)) + IRO_WalkInts(linear, linear, StatementContainsSideEffectAction); + + return scseai.flag; +} + +static Boolean HasSideEffectsBeforeUse(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd, Boolean flag) { + IRONode *fnode; + IROLinear *scannd; + UInt16 i; + + if (fnode1 != fnode3) { + if (flag) { + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) + fnode->x3C = 0; + } else if (fnode1->x3C) { + return 0; + } + fnode1->x3C = 1; + } + + for (scannd = fnode1->first; scannd && scannd != fnode1->last->next; scannd = scannd->next) { + if (!(scannd->flags & IROLF_Reffed)) { + if (StatementContainsUse(scannd, nd)) + return 0; + if (StatementContainsSideEffect(scannd)) + return 1; + } + } + + if (fnode1 != fnode3) { + for (i = 0; i < fnode1->numsucc; i++) { + if (HasSideEffectsBeforeUse(IRO_NodeTable[fnode1->succ[i]], fnode2, fnode3, nd, 0)) + return 1; + } + } + + return 0; +} + +static Boolean UsesAKilledVarBeforeUse(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd, BitVector *bv, Boolean flag) { + IRONode *fnode; + UInt16 i; + IROLinear *scannd; + + if (fnode1 != fnode3) { + if (flag) { + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) + fnode->x3C = 0; + } else if (fnode1->x3C) { + return 0; + } + fnode1->x3C = 1; + } + + for (scannd = fnode1->first; scannd && scannd != fnode1->last->next; scannd = scannd->next) { + if (!(scannd->flags & IROLF_Reffed)) { + if (StatementContainsUse(scannd, nd)) + return 0; + Bv_Clear(IRO_VarKills); + IRO_WalkInts(scannd, scannd, GetExprUses); + if (Bv_BitsInCommon(bv, IRO_VarKills)) + return 1; + } + } + + if (fnode1 != fnode3) { + for (i = 0; i < fnode1->numsucc; i++) { + if (UsesAKilledVarBeforeUse(IRO_NodeTable[fnode1->succ[i]], fnode2, fnode3, nd, bv, 0)) + return 1; + } + } + + return 0; +} + +static void GetExprUses(IROLinear *linear, Boolean isEntry) { + Object *obj; + VarRecord *var; + + if (isEntry) { + if (linear->type == IROLinearOperand && linear->u.node->type == EOBJREF) { + obj = linear->u.node->data.objref; + if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) { + if ((var = IRO_FindVar(obj, 0, 1))) + Bv_SetBit(var->index, IRO_VarKills); + } + } + } +} + +static void GetExprKills(IROLinear *linear, Boolean isEntry) { + if (isEntry) + IRO_GetKills(linear); +} + +static void CheckUnorderedRegionForSideEffectsAndUses(IROLinear *nd, BitVector *bv1, BitVector *bv2, Boolean *result) { + if (IRO_HasSideEffect(nd)) { + *result = 1; + } else { + Bv_Clear(bv2); + Bv_Clear(IRO_VarKills); + IRO_WalkTree(nd, GetExprUses); + Bv_Or(IRO_VarKills, bv2); + + if (Bv_BitsInCommon(bv1, bv2)) + *result = 1; + } +} + +static void CheckUnorderedRegionsForSideEffectsAndUses(IROLinear *nd1, IROLinear *nd2, BitVector *bv1, BitVector *bv2, Boolean *result) { + int i; + + switch (nd1->type) { + case IROLinearOp2Arg: + if (nd1->nodetype != ELAND && nd1->nodetype != ELOR && nd1->nodetype != ECOMMA) { + if (nd1->u.diadic.left != nd2) + CheckUnorderedRegionForSideEffectsAndUses(nd1->u.diadic.left, bv1, bv2, result); + if (nd1->u.diadic.right != nd2) + CheckUnorderedRegionForSideEffectsAndUses(nd1->u.diadic.right, bv1, bv2, result); + } + break; + case IROLinearFunccall: + if (nd1->u.funccall.linear8 != nd2) + CheckUnorderedRegionForSideEffectsAndUses(nd1->u.funccall.linear8, bv1, bv2, result); + for (i = 0; !*result && i < nd1->u.funccall.argCount; i++) { + if (nd1->u.funccall.args[i] != nd2) + CheckUnorderedRegionForSideEffectsAndUses(nd1->u.funccall.args[i], bv1, bv2, result); + } + break; + } +} + +static Boolean CheckThenOrElseBranch(IRONode *fnode1, IRONode *fnode2, IROLinear *nd, Boolean flag) { + IRONode *fnode; + IROLinear *scannd; + IRONodes nodes; + Boolean result; + + IROFlowgraph_sub_4C2140(&nodes); + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) + fnode->x3C = 0; + AddNodeAndSuccessorsRecursively(&nodes, fnode1, fnode2); + + while (IROFlowgraph_sub_4C2040(&nodes)) { + fnode = IRO_NodeTable[IROFlowgraph_sub_4C2100(&nodes)]; + if (fnode) { + if (!Bv_IsBitSet(fnode1->index, fnode->dom)) { + result = 0; + goto done; + } + + for (scannd = fnode->first; scannd && scannd != fnode->last->next; scannd = scannd->next) { + if (!nd || scannd != nd) { + if (!flag || (scannd->type != IROLinearReturn)) { + if (fnode->numpred == 2 && scannd->type == IROLinearLabel) + RebuildPossibleCondExpression(fnode); + + if (scannd->type != IROLinearNop && + scannd->type != IROLinearLabel && + scannd->type != IROLinearGoto && + !(scannd->flags & IROLF_Reffed)) { + result = 0; + goto done; + } + } + } + } + } + } + + result = 1; +done: + IROFlowgraph_sub_4C20E0(&nodes); + return result; +} + +static void RebuildPossibleCondExpression(IRONode *fnode) { + IRONode *pred1; + IRONode *pred2; + IRONode *r30; + IROLinear *leftAss; + IROLinear *rightAss; + IROLinear *r27; + IROLinear *r13; + IROLinear *var_58; + IRONode *left; + IRONode *right; + IRONode *r24; + ENode *r23; + IRODef *r22; + IRODef *r21; + IRODef *def; + IROUse *use; + UInt32 r20; + UInt32 r19; + Boolean r18; + Boolean r17; + UInt32 i; + Boolean compareType; + Type *var_60; + IROLinear copy1; + IROLinear copy2; + IROLinear copy3; + + if ( + !fnode || + fnode->numpred != 2 || + !fnode->first || + fnode->first->type != IROLinearLabel + ) + return; + + pred1 = IRO_NodeTable[fnode->pred[0]]; + pred2 = IRO_NodeTable[fnode->pred[1]]; + if ( + !pred1 || !pred2 || + pred1->numsucc != 1 || pred2->numsucc != 1 + ) + return; + + r24 = NULL; + for (i = 0; i < IRO_NumNodes; i++) { + if ( + Bv_IsBitSet(i, fnode->dom) && + (r24 = IRO_NodeTable[i]) && + r24->last && + (r24->last->type == IROLinearIf || r24->last->type == IROLinearIfNot) && + r24->last->u.label.label && + r24->numsucc == 2 + ) { + if (Bv_IsBitSet(r24->succ[0], pred1->dom) && + !Bv_IsBitSet(r24->succ[0], pred2->dom) && + Bv_IsBitSet(r24->succ[1], pred2->dom) && + !Bv_IsBitSet(r24->succ[1], pred1->dom)) + break; + + if (Bv_IsBitSet(r24->succ[0], pred2->dom) && + !Bv_IsBitSet(r24->succ[0], pred1->dom) && + Bv_IsBitSet(r24->succ[1], pred1->dom) && + !Bv_IsBitSet(r24->succ[1], pred2->dom)) + break; + } + } + + if (i >= IRO_NumNodes) + return; + + /*if ( + (r30 = IRO_NodeTable[r24->succ[0]]) && + r30->numpred == 1 && + r30->first && + r30->first->type == IROLinearLabel && + r30->first->u.label.label == r24->last->u.label.label + ) { + goto ok; + } else if ( + (r30 = IRO_NodeTable[r24->succ[1]]) && + r30->numpred == 1 && + r30->first && + r30->first->type == IROLinearLabel && + r30->first->u.label.label == r24->last->u.label.label + ) { + goto ok; + } else { + return; + }*/ + /*if ( + (!(r30 = IRO_NodeTable[r24->succ[0]]) || + r30->numpred != 1 || + !r30->first || + r30->first->type != IROLinearLabel || + r30->first->u.label.label != r24->last->u.label.label) + && + (!(r30 = IRO_NodeTable[r24->succ[1]]) || + r30->numpred != 1 || + !r30->first || + r30->first->type != IROLinearLabel || + r30->first->u.label.label != r24->last->u.label.label) + ) + return;*/ + r30 = IRO_NodeTable[r24->succ[0]]; + if ( + r30 && + r30->numpred == 1 && + r30->first && + r30->first->type == IROLinearLabel && + r30->first->u.label.label == r24->last->u.label.label + ) { + (void)0; + } else { + r30 = IRO_NodeTable[r24->succ[1]]; + if ( + r30 && + r30->numpred == 1 && + r30->first && + r30->first->type == IROLinearLabel && + r30->first->u.label.label == r24->last->u.label.label + ) { + } else { + return; + } + } + +ok: + if (Bv_IsBitSet(r30->index, pred1->dom)) { + left = pred2; + right = pred1; + } else { + left = pred1; + right = pred2; + } + + leftAss = FindLastDiadicTopLevelAssignmentInFlowgraphNode(left); + if ( + !leftAss || + leftAss->type != IROLinearOp2Arg || + !leftAss->u.diadic.left || + leftAss->u.diadic.left->type != IROLinearOp1Arg || + leftAss->u.diadic.left->nodetype != EINDIRECT || + !leftAss->u.diadic.left->u.monadic || + leftAss->u.diadic.left->u.monadic->type != IROLinearOperand || + !(r23 = leftAss->u.diadic.left->u.monadic->u.node) || + !r23->rtype || + !IS_TYPE_POINTER_ONLY(r23->rtype) || + !r23->data.objref || + is_volatile_object(r23->data.objref) || + r23->data.objref->datatype != DLOCAL + ) + r23 = NULL; + + if (r23) { + rightAss = FindLastDiadicTopLevelAssignmentInFlowgraphNode(right); + if ( + !rightAss || + rightAss->type != IROLinearOp2Arg || + !rightAss->u.diadic.left || + rightAss->u.diadic.left->type != IROLinearOp1Arg || + rightAss->u.diadic.left->nodetype != EINDIRECT || + !rightAss->u.diadic.left->u.monadic || + rightAss->u.diadic.left->u.monadic->type != IROLinearOperand || + !rightAss->u.diadic.left->u.monadic->u.node || + !rightAss->u.diadic.left->u.monadic->u.node->rtype || + !IS_TYPE_POINTER_ONLY(rightAss->u.diadic.left->u.monadic->u.node->rtype) || + rightAss->u.diadic.left->u.monadic->u.node->type != EOBJREF || + rightAss->u.diadic.left->u.monadic->u.node->data.objref != r23->data.objref || + rightAss->rtype != leftAss->rtype + ) + r23 = NULL; + } + + if (r23) { + if (!CheckThenOrElseBranch(r24->nextnode, left, leftAss, 0) || !CheckThenOrElseBranch(r30, right, rightAss, 0)) + return; + + r19 = 0; + r20 = 0; + r18 = 0; + r17 = 0; + if (!r23->data.objref->varptr || !r23->data.objref->varptr->uses || !r23->data.objref->varptr->defs) { + r23 = NULL; + } else { + r21 = NULL; + r22 = NULL; + for (def = r23->data.objref->varptr->defs; def && (!r22 || !r21); def = def->varnext) { + if (def->x18 && def->linear == leftAss) + r22 = def; + else if (def->x18 && def->linear == rightAss) + r21 = def; + } + + if (!r22 || !r21) { + r23 = NULL; + } else { + for (use = r23->data.objref->varptr->uses; r23 && use; use = use->varnext) { + if (use->x1C) { + r20++; + if (Bv_IsBitSet(r22->index, use->x18) && Bv_IsBitSet(r21->index, use->x18)) { + for (i = 0; r23 && i < use->x18->size; i++) { + if (i != r22->index && i != r21->index && Bv_IsBitSet(i, use->x18)) + r23 = NULL; + } + + if (r23 && !Bv_IsBitSet(fnode->index, use->node->dom)) + r23 = NULL; + + if (r23) { + if (RewriteUse(use, r23, rightAss, 0)) + r19++; + else + r23 = NULL; + } + + if (r23 && !r17) + r17 = HasSideEffectsBeforeUse(fnode, fnode, use->node, use->linear, 1); + + if (r23 && !r18 && (IRO_HasSideEffect(r24->last->u.label.x4) || IRO_HasSideEffect(leftAss->u.label.x4) || + IRO_HasSideEffect(rightAss->u.label.x4))) + r18 = 1; + } else if (Bv_IsBitSet(r22->index, use->x18) || Bv_IsBitSet(r21->index, use->x18)) { + r23 = NULL; + } + } + } + } + } + } + + if (!r23) + return; + + compareType = r24->last->type == IROLinearIf; + r27 = r24->last->u.label.x4; + r13 = leftAss->u.label.x4; + var_58 = rightAss->u.label.x4; + var_60 = rightAss->rtype; + memcpy(©1, r13, sizeof(IROLinear)); + memcpy(©2, rightAss, sizeof(IROLinear)); + + r24->last->type = IROLinearNop; + r24->last->expr = NULL; + r30->first->type = IROLinearNop; + r30->first->expr = NULL; + fnode->first->type = IROLinearNop; + fnode->first->expr = NULL; + if (left->last->type == IROLinearGoto) { + left->last->type = IROLinearNop; + left->last->expr = NULL; + } + if (right->last->type == IROLinearGoto) { + right->last->type = IROLinearNop; + right->last->expr = NULL; + } + + if (r23) { + IRO_NopOut(leftAss->u.diadic.left); + leftAss->type = IROLinearNop; + leftAss->expr = NULL; + } + + memcpy(rightAss, ©1, sizeof(IROLinear)); + rightAss->type = IROLinearOp3Arg; + rightAss->nodetype = ECOND; + rightAss->index = copy2.index; + rightAss->u.args3.a = r27; + rightAss->rtype = var_60; + rightAss->next = copy2.next; + if (compareType) { + rightAss->u.args3.b = var_58; + rightAss->u.args3.c = r13; + } else { + rightAss->u.args3.b = r13; + rightAss->u.args3.c = var_58; + } + rightAss->flags |= IROLF_Reffed; + + if (r19 == 1 && !r17 && !r18 && !r23->data.objref->varptr->xB) { + for (use = r23->data.objref->varptr->uses; use; use = use->varnext) { + if (use->x1C && Bv_IsBitSet(r22->index, use->x18) && Bv_IsBitSet(r21->index, use->x18)) { + RewriteUse(use, r23, rightAss, 1); + if ((r18 = (use->linear->flags & IROLF_4000) && IRO_HasSideEffect(r27))) { + IROLinear *tmp; + Object *obj; + + tmp = IRO_NewLinear(IROLinearOperand); + memcpy(tmp, copy2.u.diadic.left->u.monadic, sizeof(IROLinear)); + tmp->index = IRO_NumLinear++; + tmp->rtype = r27->rtype; + if (r20 == 1) { + tmp->u.node->data.objref->type = r27->rtype; + tmp->u.node->rtype = CDecl_NewPointerType(r27->rtype); + } else { + obj = create_temp_object(tmp->rtype); + IRO_FindVar(obj, 1, 1); + tmp->u.node = create_objectrefnode(obj); + } + IRO_PasteAfter(tmp, tmp, r27); + + tmp = IRO_NewLinear(IROLinearOp1Arg); + memcpy(tmp, copy2.u.diadic.left, sizeof(IROLinear)); + tmp->index = IRO_NumLinear++; + tmp->u.monadic = r27->next; + tmp->rtype = r27->rtype; + IRO_PasteAfter(tmp, tmp, r27->next); + + tmp = IRO_NewLinear(IROLinearOp2Arg); + memcpy(tmp, ©2, sizeof(IROLinear)); + tmp->index = IRO_NumLinear++; + tmp->u.diadic.right = r27; + tmp->u.diadic.left = r27->next->next; + tmp->rtype = r27->rtype; + IRO_PasteAfter(tmp, tmp, r27->next->next); + + if (r20 != 1) { + tmp = copy2.u.diadic.left->u.monadic; + tmp->u.node = create_objectrefnode(obj); + } + + rightAss->u.args3.a = copy2.u.diadic.left; + rightAss->u.args3.a->rtype = r27->rtype; + + if (r20 == 1) { + r21->linear = r27->next->next; + if (Bv_IsBitSet(r21->index, right->x1A)) { + Bv_ClearBit(r21->index, right->x1A); + Bv_SetBit(r21->index, r24->x1A); + } + if (Bv_IsBitSet(r21->index, right->x1E)) { + Bv_ClearBit(r21->index, right->x1E); + Bv_SetBit(r21->index, r24->x1E); + } + if (Bv_IsBitSet(r21->index, right->x22)) { + Bv_ClearBit(r21->index, right->x22); + Bv_SetBit(r21->index, r24->x22); + } + } + } + } + } + + if (!r18) { + if (r20 == 1 && r23->data.objref->u.var.info) { + r23->data.objref->u.var.info->usage = 0; + r23->data.objref->u.var.info->used = 0; + } + r22->x18 = 0; + IRO_NopOut(copy2.u.diadic.left); + r21->x18 = 0; + } + } else { + memcpy(©3, fnode->first, sizeof(IROLinear)); + memcpy(fnode->first, ©2, sizeof(IROLinear)); + + fnode->first->index = copy3.index; + fnode->first->u.diadic.right = rightAss; + fnode->first->next = copy3.next; + r22->x18 = 0; + r21->linear = fnode->first; + if (Bv_IsBitSet(r21->index, right->x1A)) { + Bv_ClearBit(r21->index, right->x1A); + Bv_SetBit(r21->index, fnode->x1A); + } + if (Bv_IsBitSet(r21->index, right->x1E)) { + Bv_ClearBit(r21->index, right->x1E); + Bv_SetBit(r21->index, fnode->x1E); + } + if (Bv_IsBitSet(r21->index, right->x22)) { + Bv_ClearBit(r21->index, right->x22); + Bv_SetBit(r21->index, fnode->x22); + } + } +} + +static void RebuildPossibleReturnCondExpression(IRONode *fnode) { + IRONode *succ1; + IRONode *succ2; + IROLinear *node1; + IROLinear *node2; + IROLinear *node3; + IRONode *r27; + Boolean isIf; + Type *type; + IROList list; + + if ( + !fnode || + fnode->numsucc != 2 || + !fnode->last || + (fnode->last->type != IROLinearIf && fnode->last->type != IROLinearIfNot) + ) + return; + + succ1 = IRO_NodeTable[fnode->succ[0]]; + succ2 = IRO_NodeTable[fnode->succ[1]]; + if ( + !succ1 || !succ2 || + succ1->numsucc != 0 || succ1->numpred != 1 || + succ2->numsucc != 0 || succ2->numpred != 1 + ) + return; + + if (succ1->first && succ1->first->type == IROLinearLabel && succ1->first->u.label.label == fnode->last->u.label.label) { + r27 = succ1; + } else if (succ2->first && succ2->first->type == IROLinearLabel && succ2->first->u.label.label == fnode->last->u.label.label) { + r27 = succ2; + } else { + return; + } + + if (r27->numpred != 1) + return; + + if (!CheckThenOrElseBranch(fnode->nextnode, fnode->nextnode, NULL, 1) || !CheckThenOrElseBranch(r27, r27, NULL, 1)) + return; + + if ( + !fnode->nextnode->last || + fnode->nextnode->last->type != IROLinearReturn || + !fnode->nextnode->last->u.monadic || + !r27->last || + r27->last->type != IROLinearReturn || + !r27->last->u.monadic || + !IRO_TypesEqual(fnode->nextnode->last->u.monadic->rtype, r27->last->u.monadic->rtype) + ) + return; + + isIf = fnode->last->type == IROLinearIf; + node1 = fnode->last->u.diadic.right; + node2 = fnode->nextnode->last->u.diadic.left; + node3 = r27->last->u.diadic.left; + type = node2->rtype; + + fnode->last->type = IROLinearNop; + fnode->last->expr = NULL; + r27->last->type = IROLinearNop; + r27->last->expr = NULL; + r27->first->type = IROLinearNop; + r27->first->expr = NULL; + + if (IRO_IsIntConstant(node2) && IRO_IsIntConstant(node3) && + ((IRO_IsConstantOne(node2) && IRO_IsConstantZero(node3)) || + (IRO_IsConstantZero(node2) && IRO_IsConstantOne(node3)))) { + if (!(node1->type == IROLinearOp1Arg && node1->nodetype == ELOGNOT && node1->rtype == type)) { + IROLinear *tmp1; + IROLinear *tmp2; + + tmp1 = IRO_NewLinear(IROLinearOp1Arg); + memcpy(tmp1, node2, sizeof(IROLinear)); + tmp1->type = IROLinearOp1Arg; + tmp1->nodetype = ELOGNOT; + tmp1->index = IRO_NumLinear++; + tmp1->u.monadic = node1; + + tmp1->next = tmp2 = IRO_NewLinear(IROLinearOp1Arg); + memcpy(tmp2, node2, sizeof(IROLinear)); + tmp2->type = IROLinearOp1Arg; + tmp2->nodetype = ELOGNOT; + tmp2->index = IRO_NumLinear++; + tmp2->u.monadic = tmp1; + + IRO_PasteAfter(tmp1, tmp2, node1); + node1 = tmp2; + } + + if ((IRO_IsConstantZero(node2) && !isIf) || (IRO_IsConstantOne(node2) && isIf)) { + if (node1->type == IROLinearOp1Arg && node1->nodetype == ELOGNOT && node1->rtype == node1->u.monadic->rtype) { + IROLinear *tmp = node1; + node1 = node1->u.monadic; + tmp->type = IROLinearNop; + tmp->expr = NULL; + } else { + IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg); + memcpy(tmp, node2, sizeof(IROLinear)); + tmp->type = IROLinearOp1Arg; + tmp->nodetype = ELOGNOT; + tmp->index = IRO_NumLinear++; + tmp->u.monadic = node1; + IRO_PasteAfter(tmp, tmp, node1); + node1 = tmp; + } + } + + node2->type = IROLinearNop; + node2->expr = NULL; + node3->type = IROLinearNop; + node3->expr = NULL; + fnode->nextnode->last->u.monadic = node1; + } else { + IROLinear *tmp1; + IROLinear *tmp2; + + IRO_InitList(&list); + tmp1 = IRO_DuplicateExpr(node3, &list); + IRO_NopOut(node3); + IRO_Paste(list.head, list.tail, fnode->nextnode->last); + + tmp2 = IRO_NewLinear(IROLinearOp3Arg); + memcpy(tmp2, node2, sizeof(IROLinear)); + tmp2->type = IROLinearOp3Arg; + tmp2->nodetype = ECOND; + tmp2->index = IRO_NumLinear++; + tmp2->u.args3.a = node1; + tmp2->rtype = type; + IRO_Paste(tmp2, tmp2, fnode->nextnode->last); + + if (isIf) { + tmp2->u.args3.b = tmp1; + tmp2->u.args3.c = node2; + } else { + tmp2->u.args3.b = node2; + tmp2->u.args3.c = tmp1; + } + + fnode->nextnode->last->u.monadic = tmp2; + } +} + +static void RebuildCondExpressions(void) { + IRONode *fnode; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (fnode->numpred == 2) { + if (fnode->first && fnode->first->type == IROLinearLabel) + RebuildPossibleCondExpression(fnode); + } else if (fnode->numsucc == 2) { + if (fnode->last && (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot)) + RebuildPossibleReturnCondExpression(fnode); + } + } + + IRO_CheckForUserBreak(); +} + +static Boolean IsLogicalExpressionAssign(IROLinear *nd) { + IROLinear *right; + IROLinear *left; + + return ( + nd->type == IROLinearOp2Arg && + nd->nodetype == EASS && + (left = nd->u.diadic.left) && + (right = nd->u.diadic.right) && + right->type == IROLinearOperand && + right->u.node && + right->u.node->type == EINTCONST && + (CInt64_Equal(right->u.node->data.intval, cint64_one) || CInt64_Equal(right->u.node->data.intval, cint64_zero)) && + left->type == IROLinearOp1Arg && + left->nodetype == EINDIRECT && + left->u.monadic && + IS_TYPE_POINTER_ONLY(left->u.monadic->rtype) && + left->u.monadic->type == IROLinearOperand && + left->u.monadic->u.node && + left->u.monadic->u.node->type == EOBJREF && + left->u.monadic->u.node->data.objref && + left->u.monadic->u.node->data.objref->datatype == DLOCAL); +} + +static Boolean IsPossibleLogicalExpressionStart(IRONode *fnode, IROLinear *nd) { + return + fnode->numsucc == 2 && + fnode->last && + (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot) && + IsLogicalExpressionAssign(nd); +} + +static Boolean CheckForTopLevelExpressions(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd1, IROLinear *nd2, Boolean flag) { + IRONode *fnode; + IROLinear *nd; + UInt16 i; + + if (fnode1 != fnode3) { + if (!Bv_IsBitSet(fnode2->index, fnode1->dom)) + return 0; + + if (flag) { + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) + fnode->x3C = 0; + } else if (fnode1->x3C) { + return 1; + } + fnode1->x3C = 1; + + for (i = 0; i < fnode1->numsucc; i++) { + fnode = IRO_NodeTable[fnode1->succ[i]]; + if (!CheckForTopLevelExpressions(fnode, fnode2, fnode3, fnode->first, nd2, 0)) + return 0; + } + } + + for (nd = nd1; nd && nd != fnode1->last->next; nd = nd->next) { + if (nd == nd2) + return 1; + + if (nd->type != IROLinearNop && nd->type != IROLinearLabel && !(nd->flags & IROLF_Reffed)) + return 0; + } + + return 1; +} + +static void AddNodeAndSuccessorsRecursively(IRONodes *nodes, IRONode *fnode1, IRONode *fnode2) { + UInt16 i; + + if (fnode1 && !fnode1->x3C) { + fnode1->x3C = 1; + IROFlowgraph_sub_4C3880(nodes, fnode1->index); + if (fnode1 != fnode2) { + for (i = 0; i < fnode1->numsucc; i++) + AddNodeAndSuccessorsRecursively(nodes, IRO_NodeTable[fnode1->succ[i]], fnode2); + } + } +} + +static Boolean RebuildPossibleLogicalExpression(IRONode *fnode, IROLinear *nd) { + IROUse *use; + IROLinear *nd2; + IROLinear *left; + IROLinear *right; + IRONode *r25; + IRONode *r24; + ENode *objnode; + IRODef *def1; + IRODef *def2; + UInt32 useCount; + UInt32 rewrittenUseCount; + Boolean sideEffectFlag; + IROLinearType compareType; + CLabel *somelab; + IRONode *var_68; + IRONode *var_6C; + CInt64 compareVal; + Boolean killedFlag; + BitVector *bv1; + BitVector *bv2; + + IROLinear *father; + IROLinear *iter; + IRODef *def; + UInt32 i; + IROLinear *newlin; + + objnode = nd->u.diadic.left->u.monadic->u.node; + if (!objnode->data.objref->varptr) + return 0; + + if (CInt64_Equal(nd->u.diadic.right->u.node->data.intval, cint64_zero)) { + compareType = IROLinearIfNot; + compareVal = cint64_one; + } else { + compareType = IROLinearIf; + compareVal = cint64_zero; + } + + var_68 = NULL; + def1 = NULL; + for (def = objnode->data.objref->varptr->defs; def && !def1; def = def->varnext) { + if (def->x18 && def->linear == nd) + def1 = def; + } + + if (def1) { + for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) { + if (use->x1C == 2 && Bv_IsBitSet(def1->index, use->x18)) { + if (!var_68) { + var_68 = use->node; + } else if (Bv_IsBitSet(use->node->index, var_68->dom)) { + var_68 = use->node; + } + } + } + + if (var_68) { + for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) { + if (use->node != var_68 && use->x1C == 2 && Bv_IsBitSet(def1->index, use->x18) && !Bv_IsBitSet(var_68->index, use->node->dom)) { + var_68 = NULL; + break; + } + } + } + } + + if ( + !var_68 || + !var_68->first || + var_68->first->type != IROLinearLabel || + !(somelab = var_68->first->u.label.label) || + var_68->numpred != 3 + ) + return 0; + + r25 = IRO_NodeTable[var_68->pred[0]]; + if (Bv_IsBitSet(IRO_NodeTable[var_68->pred[1]]->index, r25->dom)) { + r25 = IRO_NodeTable[var_68->pred[1]]; + } else if (!Bv_IsBitSet(r25->index, IRO_NodeTable[var_68->pred[1]]->dom)) { + return 0; + } + + if (Bv_IsBitSet(IRO_NodeTable[var_68->pred[2]]->index, r25->dom)) { + r25 = IRO_NodeTable[var_68->pred[2]]; + } else if (!Bv_IsBitSet(r25->index, IRO_NodeTable[var_68->pred[2]]->dom)) { + return 0; + } + + if ( + !r25 || + !(left = r25->last) || + left->type != compareType || + left->u.label.label != somelab + ) + return 0; + + if ( + !FindFlowgraphNodeThatStartsWithLabel(left->u.label.label, &var_68, &var_6C) || + !var_6C || + var_6C->numpred != 1 || + !(r24 = IRO_NodeTable[var_6C->pred[0]]) || + !(right = r24->last) || + right->type != compareType || + right->u.label.label != left->u.label.label || + !(nd2 = FindLastDiadicTopLevelAssignmentInFlowgraphNode(var_6C)) || + !IsLogicalExpressionAssign(nd2) || + nd2->u.diadic.left->u.monadic->u.node->data.objref != objnode->data.objref || + !CInt64_Equal(compareVal, nd2->u.diadic.right->u.node->data.intval) || + nd2->rtype != nd->rtype + ) + return 0; + + if ( + !CheckForTopLevelExpressions(fnode, fnode, r25, nd->next, left, 1) || + !CheckForTopLevelExpressions(r25->nextnode, r25->nextnode, r24, r25->nextnode->first, right, 1) || + !CheckForTopLevelExpressions(r24->nextnode, r24->nextnode, var_6C, right->next, nd2, 1) || + !CheckForTopLevelExpressions(var_6C, var_6C, var_6C, nd2->next, var_68->first, 1) + ) + return 0; + + rewrittenUseCount = 0; + useCount = 0; + killedFlag = 0; + sideEffectFlag = 0; + if (!objnode->data.objref->varptr || !(objnode->data.objref->varptr->uses) || !(objnode->data.objref->varptr->defs)) { + objnode = NULL; + } else { + def1 = def2 = NULL; + for (def = objnode->data.objref->varptr->defs; def && (!def1 || !def2); def = def->varnext) { + if (def->x18 && def->linear == nd) + def1 = def; + else if (def->x18 && def->linear == nd2) + def2 = def; + } + + if (!def1 || !def2) { + objnode = NULL; + } else { + for (use = objnode->data.objref->varptr->uses; objnode && use; use = use->varnext) { + if (use->x1C) { + useCount++; + if (Bv_IsBitSet(def1->index, use->x18) && Bv_IsBitSet(def2->index, use->x18)) { + for (i = 0; objnode && i < use->x18->size; i++) { + if (i != def1->index && i != def2->index && Bv_IsBitSet(i, use->x18)) + objnode = NULL; + } + + if (objnode && !Bv_IsBitSet(var_68->index, use->node->dom)) + objnode = NULL; + + if (objnode) { + if (RewriteUse(use, objnode, nd2, 0)) + rewrittenUseCount++; + else + objnode = NULL; + } + + if (objnode) { + if (!sideEffectFlag) + sideEffectFlag = HasSideEffectsBeforeUse(var_68, var_68, use->node, use->linear, 1); + + if (!killedFlag && (IRO_HasSideEffect(left->u.label.x4) || IRO_HasSideEffect(right->u.label.x4))) { + iter = use->linear; + if ((father = IRO_LocateFather(use->linear))) { + Bv_AllocVector(&bv1, IRO_NumVars + 1); + Bv_AllocVector(&bv2, IRO_NumVars + 1); + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + IRO_WalkTree(left->u.label.x4, GetExprKills); + IRO_WalkTree(right->u.label.x4, GetExprKills); + Bv_Or(IRO_VarKills, bv1); + while (father && !killedFlag) { + CheckUnorderedRegionsForSideEffectsAndUses(father, iter, bv1, bv2, &killedFlag); + iter = father; + father = IRO_LocateFather(father); + } + } + + if (!killedFlag) + killedFlag = UsesAKilledVarBeforeUse(var_68, var_68, use->node, use->linear, bv1, 1); + } + } + } else if (Bv_IsBitSet(def1->index, use->x18) || Bv_IsBitSet(def2->index, use->x18)) + objnode = NULL; + } + } + } + } + + if (!objnode) + return 0; + + left->type = right->type = IROLinearNop; + left->expr = right->expr = NULL; + + IRO_NopOut(nd); + + newlin = IRO_NewLinear(IROLinearOp2Arg); + memcpy(newlin, nd2, sizeof(IROLinear)); + newlin->nodetype = (compareType == IROLinearIf) ? ELOR : ELAND; + newlin->index = IRO_NumLinear++; + newlin->u.diadic.left = left->u.label.x4; + newlin->u.diadic.right = right->u.label.x4; + newlin->flags |= IROLF_Reffed; + IRO_Paste(newlin, newlin, nd2); + + if (rewrittenUseCount == 1 && !sideEffectFlag && !killedFlag && !objnode->data.objref->varptr->xB) { + for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) { + if (use->x1C && Bv_IsBitSet(def1->index, use->x18) && Bv_IsBitSet(def2->index, use->x18)) + RewriteUse(use, objnode, newlin, 1); + } + + if (useCount == 1 && objnode->data.objref->u.var.info) { + objnode->data.objref->u.var.info->usage = 0; + objnode->data.objref->u.var.info->used = 0; + } + IRO_NopOut(nd2); + def1->x18 = 0; + def2->x18 = 0; + } else { + IRO_NopOut(nd2->u.label.x4); + nd2->u.label.x4 = newlin; + def1->x18 = 0; + } + + if (r24->numpred == 1 && IRO_NodeTable[r24->pred[0]] == r25 && IRO_MergeFlowGraphNodes(r25, r24)) + r24 = r25; + if (var_6C->numpred == 1 && IRO_NodeTable[var_6C->pred[0]] == r24 && IRO_MergeFlowGraphNodes(r24, var_6C)) + var_6C = r24; + if (var_68->numpred == 1 && r24 == r25 && var_6C == r24) + IRO_MergeFlowGraphNodes(var_6C, var_68); + return 1; +} + +static void RebuildLogicalExpressions(void) { + IRONode *fnode; + IROLinear *nd; + Boolean flag; + + flag = 1; + while (flag) { + flag = 0; + for (fnode = IRO_FirstNode; fnode && fnode->last; fnode = fnode->nextnode) { + for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) { + if (IsPossibleLogicalExpressionStart(fnode, nd) && RebuildPossibleLogicalExpression(fnode, nd)) + flag = 1; + } + } + } + + IRO_CheckForUserBreak(); +} + +static Boolean IsPossibleCondAssStart(IRONode *fnode) { + return (fnode->numsucc == 2) && fnode->last && (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot); +} + +static Type *logicalType(void) { + if (copts.cplusplus && copts.booltruefalse) + return TYPE(&stbool); + else + return TYPE(&stsignedint); +} + +static Boolean GeneratePossibleCondAss(IRONode *fnode) { + IROLinear *r31; + IRONode *node2; + IRONode *r29; + Boolean r28; + IRONode *node1; + IROLinear *r24; + Boolean r23; + IROLinear *r19; + Boolean r18; + IROLinear *r20; + Boolean r19flag; + IROLinear *r18nd; + IROLinear *ass; + IROLinear *cond; + IROLinear *r16; + IROLinear *r15; + BitVector *saveVarKills; + IROList list; + Object *obj; + IROLinear *r14; + + if (!fnode || fnode->numsucc != 2 || !fnode->last || (fnode->last->type != IROLinearIf && fnode->last->type != IROLinearIfNot)) + return 0; + + if (IRO_NodeTable[fnode->succ[0]] && + IRO_NodeTable[fnode->succ[0]]->first && + IRO_NodeTable[fnode->succ[0]]->first->type == IROLinearLabel && + IRO_NodeTable[fnode->succ[0]]->first->u.label.label == fnode->last->u.label.label) { + node1 = IRO_NodeTable[fnode->succ[0]]; + node2 = IRO_NodeTable[fnode->succ[1]]; + } else { + node1 = IRO_NodeTable[fnode->succ[1]]; + if (node1 && node1->first && node1->first->type == IROLinearLabel && node1->first->u.label.label == fnode->last->u.label.label) { + node2 = IRO_NodeTable[fnode->succ[0]]; + } else { + return 0; + } + } + + if (!node2 || node2->numpred != 1 || node2->numsucc != 1 || node2->last->next != node1->first) + return 0; + + if (IRO_NodeTable[node2->succ[0]] == node1 && Bv_IsBitSet(fnode->index, node1->dom)) { + r28 = 0; + } else if ( + node1->numpred == 1 && node1->numsucc == 1 && + node2->succ[0] == node1->succ[0] && + (r29 = IRO_NodeTable[node2->succ[0]]) && + Bv_IsBitSet(fnode->index, r29->dom) && + node1->last->next == r29->first + ) { + r28 = 1; + } else { + return 0; + } + + r24 = NULL; + if (node2->last) { + for (r19 = node2->first; r19 && r19 != node2->last->next; r19 = r19->next) { + if (IRO_IsAssignment(r19) && !(r19->flags & IROLF_Reffed) && !r24) { + r24 = r19; + } else if (r19->type != IROLinearNop && r19->type != IROLinearLabel && r19->type != IROLinearGoto && !(r19->flags & IROLF_Reffed)) { + return 0; + } + } + } + + if ( + !r24 || + (r24->nodetype != EASS && !IRO_TransformSelfAssignmentToAssignment(r24)) || + !r24->u.diadic.left || + r24->u.diadic.left->type != IROLinearOp1Arg || + r24->u.diadic.left->nodetype != EINDIRECT || + !r24->u.diadic.left->u.monadic || + r24->u.diadic.left->u.monadic->type != IROLinearOperand || + !r24->u.diadic.left->u.monadic->u.node || + !r24->u.diadic.left->u.monadic->u.node->rtype || + !IS_TYPE_POINTER_ONLY(r24->u.diadic.left->u.monadic->u.node->rtype) || + !r24->u.diadic.left->u.monadic->u.node->data.monadic + ) + return 0; + + if (r28) { + r31 = NULL; + if (node1->last) { + for (r19 = node1->first; r19 && r19 != node1->last->next; r19 = r19->next) { + if (IRO_IsAssignment(r19) && !(r19->flags & IROLF_Reffed) && !r31) { + r31 = r19; + } else if (r19->type != IROLinearNop && r19->type != IROLinearLabel && r19->type != IROLinearGoto && !(r19->flags & IROLF_Reffed)) { + return 0; + } + } + } + + if ( + !r31 || + (r31->nodetype != EASS && !IRO_TransformSelfAssignmentToAssignment(r31)) || + !r31->u.diadic.left || + r31->u.diadic.left->type != IROLinearOp1Arg || + r31->u.diadic.left->nodetype != EINDIRECT || + !r31->u.diadic.left->u.monadic || + r31->u.diadic.left->u.monadic->type != IROLinearOperand || + !r31->u.diadic.left->u.monadic->u.node || + !r31->u.diadic.left->u.monadic->u.node->rtype || + !IS_TYPE_POINTER_ONLY(r31->u.diadic.left->u.monadic->u.node->rtype) || + !r31->u.diadic.left->u.monadic->u.node->data.monadic + ) + return 0; + + r18 = IRO_ExprsSame(r24->u.diadic.left, r31->u.diadic.left); + } + + r23 = fnode->last->type == IROLinearIf; + r20 = fnode->last->u.diadic.right; + r19flag = 0; + if (r28 && copts.opt_common_subs && IRO_IsSubableExpression(r20)) + r19flag = 1; + + if (r19flag) { + IRO_FindDepends(r20); + r19flag = !IRO_NotSubable; + } + + if (r28) { + if (r18) { + r19flag = 0; + } else if (IRO_HasSideEffect(r20)) { + r19flag = 1; + } else { + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + IRO_WalkTree(r20, GetExprUses); + saveVarKills = IRO_VarKills; + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + IRO_WalkTree(r20, GetExprKills); + if (Bv_BitsInCommon(IRO_VarKills, saveVarKills)) + r19flag = 1; + } + + if (r19flag && !copts.opt_common_subs) + return 0; + } + + if (r19flag) { + IRO_InitList(&list); + obj = create_temp_object(r20->rtype); + IRO_FindVar(obj, 1, 1); + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->u.diadic.left = IRO_TempReference(obj, &list); + ass->rtype = r20->rtype; + ass->nodetype = EASS; + ass->index = ++IRO_NumLinear; + ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.right = r20; + IRO_AddToList(ass, &list); + IRO_PasteAfter(list.head, list.tail, r20); + } + + r16 = r24->u.diadic.left; + r15 = r24->u.diadic.right; + fnode->last->type = IROLinearNop; + fnode->last->expr = NULL; + if (node2->last->type == IROLinearGoto) { + node2->last->type = IROLinearNop; + node2->last->expr = NULL; + } + if (r28 || node1->numpred == 2) { + node1->first->type = IROLinearNop; + node1->first->expr = NULL; + } + + if (r28 && r18) { + if (node1->last->type == IROLinearGoto) { + node1->last->type = IROLinearNop; + node1->last->expr = NULL; + } + if (r29->numpred == 2) { + r29->first->type = IROLinearNop; + r29->first->expr = NULL; + } + + cond = IRO_NewLinear(IROLinearOp3Arg); + memcpy(cond, r24, sizeof(IROLinear)); + cond->type = IROLinearOp3Arg; + cond->nodetype = ECOND; + cond->index = ++IRO_NumLinear; + cond->rtype = r16->rtype; + cond->flags |= IROLF_Reffed; + if (r19flag) { + IRO_InitList(&list); + r14 = IRO_TempReference(obj, &list); + IRO_Paste(list.head, list.tail, r31); + } else { + r14 = r20; + } + cond->u.args3.a = r14; + + if (r23) { + cond->u.args3.b = r31->u.diadic.right; + cond->u.args3.c = r15; + } else { + cond->u.args3.b = r15; + cond->u.args3.c = r31->u.diadic.right; + } + + r24->type = IROLinearNop; + r24->expr = NULL; + IRO_NopOut(r24->u.diadic.left); + IRO_Paste(cond, cond, r31); + r31->u.diadic.right = cond; + } else { + r24->type = IROLinearOp3Arg; + r24->nodetype = ECONDASS; + if (r19flag) { + IRO_InitList(&list); + r20 = IRO_TempReference(obj, &list); + IRO_Paste(list.head, list.tail, r24); + } + cond = r20; + if (r23) { + r18nd = IRO_NewLinear(IROLinearOp1Arg); + memcpy(r18nd, r20, sizeof(IROLinear)); + r18nd->type = IROLinearOp1Arg; + r18nd->nodetype = ELOGNOT; + r18nd->index = ++IRO_NumLinear; + r18nd->rtype = logicalType(); + r18nd->u.monadic = r20; + r18nd->flags |= IROLF_Reffed; + IRO_Paste(r18nd, r18nd, r24); + r20 = r18nd; + } + r24->u.args3.a = r20; + r24->u.args3.b = r16; + r24->u.args3.c = r15; + if (r28) { + r15 = r31->u.diadic.left; + r16 = r31->u.diadic.right; + if (node1->last->type == IROLinearGoto) { + node1->last->type = IROLinearNop; + node1->last->expr = NULL; + } + if (r29->numpred == 2) { + r29->first->type = IROLinearNop; + r29->first->expr = NULL; + } + r31->type = IROLinearOp3Arg; + r31->nodetype = ECONDASS; + if (r19flag) { + IRO_InitList(&list); + cond = IRO_TempReference(obj, &list); + IRO_Paste(list.head, list.tail, r31); + } else { + IRO_InitList(&list); + cond = IRO_DuplicateExpr(cond, &list); + IRO_Paste(list.head, list.tail, r31); + } + if (!r23) { + r14 = IRO_NewLinear(IROLinearOp1Arg); + memcpy(r14, cond, sizeof(IROLinear)); + r14->type = IROLinearOp1Arg; + r14->nodetype = ELOGNOT; + r14->index = ++IRO_NumLinear; + r14->rtype = logicalType(); + r14->u.monadic = cond; + r14->flags |= IROLF_Reffed; + IRO_Paste(r14, r14, r31); + cond = r14; + } + r31->u.args3.a = cond; + r31->u.args3.b = r15; + r31->u.args3.c = r16; + } + } + + if (IRO_MergeFlowGraphNodes(fnode, node2)) + node2 = fnode; + if ((r28 || node1->numpred == 1) && IRO_MergeFlowGraphNodes(node2, node1)) + node1 = node2; + if (r28 && r29->numpred == 1) + IRO_MergeFlowGraphNodes(node1, r29); + return 1; +} + +static void GenerateCondAssignments(void) { + IRONode *fnode; + + fnode = IRO_FirstNode; + while (fnode && fnode->last) { + if (IsPossibleCondAssStart(fnode)) { + if (!GeneratePossibleCondAss(fnode)) + fnode = fnode->nextnode; + } else { + fnode = fnode->nextnode; + } + } + + IRO_CheckForUserBreak(); +} + +void IRO_RegenerateExpressions(void) { + IRO_UpdateFlagsOnInts(); + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + IRO_UseDef(0, 0); + + if (copts.optimizationlevel > 0) { + IRO_Dump("Rebuilding ELORs and ELANDs\n"); + RebuildLogicalExpressions(); + IRO_DumpAfterPhase("RebuildLogicalExpressions", 0); + } + + if (copts.optimizationlevel > 0) { + IRO_Dump("Rebuilding ECONDs\n"); + RebuildCondExpressions(); + IRO_DumpAfterPhase("RebuildCondExpressions", 0); + } + + if (copts.optimizationlevel > 0) { + IRO_Dump("Generating ECONDASSes\n"); + GenerateCondAssignments(); + IRO_DumpAfterPhase("GenerateCondAssignments", 0); + } +} diff --git a/compiler_and_linker/unsorted/IroFlowgraph.c b/compiler_and_linker/unsorted/IroFlowgraph.c index e69de29..7b6aa3a 100644 --- a/compiler_and_linker/unsorted/IroFlowgraph.c +++ b/compiler_and_linker/unsorted/IroFlowgraph.c @@ -0,0 +1,336 @@ +#include "compiler/IroFlowgraph.h" +#include "compiler/IroCSE.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroPropagate.h" +#include "compiler/IROUseDef.h" +#include "compiler/IroUtil.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/InlineAsmPPC.h" + +UInt16 IRO_NumNodes; +IRONode *IRO_FirstNode; +IRONode *IRO_LastNode; +IRONode *IRO_EndNode; +IRONode **IRO_NodeTable; +BitVector *IRO_VarKills; +BitVector *IRO_Avail; +BitVector *IRO_FuncKills; +BitVector *IRO_ExprKills; + +static IRONode *StartNode(IROLinear *linear) { + IRONode *node = oalloc(sizeof(IRONode)); + + node->index = IRO_NumNodes; + node->numsucc = 0; + node->succ = NULL; + node->numpred = 0; + node->pred = NULL; + node->first = linear; + node->last = linear; + node->x16 = NULL; + node->x1A = NULL; + node->x1E = NULL; + node->x22 = NULL; + node->x26 = 0; + node->x2A = NULL; + node->dom = NULL; + node->nextnode = NULL; + node->x36 = 0; + node->x37 = 0; + node->mustreach = 0; + node->x39 = 0; + node->loopdepth = 0; + node->x3C = 0; + node->addressed = NULL; + + IRO_NumNodes++; + if (!IRO_FirstNode) + IRO_FirstNode = node; + else + IRO_LastNode->nextnode = node; + IRO_LastNode = node; + return node; +} + +static void AddSucc(IRONode *a, IRONode *b) { + a->succ[a->numsucc++] = b->index; + b->numpred++; +} + +static void AddLabelSucc(IRONode *node, CLabel *label) { + IRONode *targetnode = (IRONode *) label->stmt; + if (targetnode) { + AddSucc(node, targetnode); + targetnode->x39 = 1; + } else { +#line 126 + CError_FATAL(); + } +} + +static void AddSwitchSucc(IRONode *node) { + SwitchInfo *info = node->last->u.swtch.info; + SwitchCase *curcase = info->cases; + SInt32 i = 1; + + while (curcase) { + curcase = curcase->next; + i++; + } + + node->succ = oalloc(sizeof(UInt16) * i); + for (curcase = info->cases; curcase; curcase = curcase->next) + AddLabelSucc(node, curcase->label); + AddLabelSucc(node, info->defaultlabel); +} + +static void AddPred(UInt32 a, UInt16 b) { + IRONode *node = IRO_NodeTable[a]; + node->pred[node->numpred++] = b; +} + +void IRO_ComputeSuccPred(void) { + CLabel *label; + IRONode *node; + SInt32 count; + IROLinear *linear; + ExceptionAction *action; + IAEffects effects; + UInt16 i; + + for (label = Labels; label; label = label->next) + label->stmt = NULL; + + for (node = IRO_FirstNode; node; node = node->nextnode) { + node->x39 = 0; + node->numsucc = 0; + node->numpred = 0; + node->x36 = 0; + node->x37 = 0; + if (node->first && node->first->type == IROLinearLabel) + node->first->u.label.label->stmt = (Statement *) node; + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (!node->first) { + if (node->nextnode) { + node->succ = oalloc(sizeof(UInt16)); + AddSucc(node, node->nextnode); + } + } else { + linear = node->last; + next_linear: + switch (linear->type) { + case IROLinearReturn: + case IROLinearEnd: + break; + case IROLinearGoto: + node->succ = oalloc(sizeof(UInt16)); + AddLabelSucc(node, linear->u.label.label); + break; + case IROLinearIf: + case IROLinearIfNot: + node->succ = oalloc(sizeof(UInt16) * 2); + AddSucc(node, node->nextnode); + AddLabelSucc(node, linear->u.label.label); + break; + case IROLinearSwitch: + AddSwitchSucc(node); + break; + case IROLinearFunccall: + count = 1; + if (IRO_FunctionCallMightThrowException(linear)) { + for (action = linear->stmt->dobjstack; action; action = action->prev) { + if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION) + count++; + } + } + node->succ = oalloc(sizeof(UInt16) * count); + AddSucc(node, node->nextnode); + if (IRO_FunctionCallMightThrowException(linear)) { + for (action = linear->stmt->dobjstack; action; action = action->prev) { + if (action->type == EAT_CATCHBLOCK) + AddLabelSucc(node, action->data.catch_block.catch_label); + else if (action->type == EAT_SPECIFICATION) + AddLabelSucc(node, action->data.specification.unexp_label); + } + } + break; + case IROLinearAsm: + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + node->succ = oalloc(sizeof(UInt16) * (!effects.x5 + effects.numlabels)); + if (!effects.x5) + AddSucc(node, node->nextnode); + for (i = 0; i < effects.numlabels; i++) + AddLabelSucc(node, effects.labels[i]); + break; + case IROLinearOp2Arg: + if (linear->nodetype == ECOMMA) { + linear = linear->u.diadic.right; + goto next_linear; + } + default: + if (node->nextnode) { + node->succ = oalloc(sizeof(UInt16)); + AddSucc(node, node->nextnode); + } + } + } + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->numpred) + node->pred = oalloc(sizeof(UInt16) * node->numpred); + else + node->pred = NULL; + node->numpred = 0; + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + for (i = 0; i < node->numsucc; i++) + AddPred(node->succ[i], node->index); + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first && node->first->type == IROLinearLabel) { + IROLinear *linear = node->first; + do { + if (linear->type == IROLinearBeginCatch || linear->type == IROLinearEndCatch || linear->type == IROLinearEndCatchDtor) { + node->x39 = 1; + break; + } + } while (linear != node->last && (linear = linear->next)); + } + } +} + +void IRO_ComputeDom(void) { + IRONode *node; + BitVector *bv; + SInt32 i; + int repeat; + + Bv_AllocVector(&IRO_FirstNode->dom, IRO_NumNodes); + Bv_SetBit(IRO_FirstNode->index, IRO_FirstNode->dom); + for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) { + Bv_AllocVector(&node->dom, IRO_NumNodes); + Bv_Set(node->dom); + } + + Bv_AllocVector(&bv, IRO_NumNodes); + + do { + repeat = 0; + for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) { + if (node->numpred) { + Bv_Set(bv); + for (i = 0; i < node->numpred; i++) { + Bv_And(IRO_NodeTable[node->pred[i]]->dom, bv); + } + Bv_SetBit(node->index, bv); + } else { + Bv_Clear(bv); + Bv_SetBit(node->index, bv); + } + + if (!Bv_Compare(bv, node->dom)) { + Bv_Copy(bv, node->dom); + repeat = 1; + } + } + } while (repeat); +} + +void IRO_BuildFlowgraph(IROLinear *linear) { + IROLinear *scan; + CLabel *label; + ExceptionAction *action; + IAEffects effects; + IRONode *node; + SInt32 i; + int flag; + + for (label = Labels; label; label = label->next) + label->stmt = NULL; + + scan = linear; + IRO_NumNodes = 0; + IRO_FirstNode = IRO_LastNode = IRO_EndNode = NULL; + while (scan) { + StartNode(scan); + if (scan->type == IROLinearLabel) + scan->u.label.label->stmt = (Statement *) IRO_LastNode; + + flag = 0; + while (!flag && scan->next && !(scan->next->flags & IROLF_1)) { + switch (scan->type) { + case IROLinearGoto: + case IROLinearReturn: + case IROLinearEntry: + case IROLinearExit: + case IROLinearEnd: + flag = 1; + break; + case IROLinearIf: + case IROLinearIfNot: + case IROLinearSwitch: + flag = 1; + skip: + if (scan->next->type == IROLinearLabel) { + IROLinear *nw = IRO_NewLinear(IROLinearNop); + nw->index = ++IRO_NumLinear; + nw->next = scan->next; + scan->next = nw; + } + break; + case IROLinearFunccall: + if (IRO_FunctionCallMightThrowException(scan)) { + for (action = scan->stmt->dobjstack; action; action = action->prev) { + if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION) { + flag = 1; + goto skip; + } + } + } + break; + case IROLinearAsm: + CodeGen_GetAsmEffects(scan->u.asm_stmt, &effects); + if (effects.numlabels) + flag = 1; + break; + } + if (!flag) + scan = scan->next; + } + + if (scan->type == IROLinearEnd) + IRO_EndNode = IRO_LastNode; + IRO_LastNode->last = scan; + scan = scan->next; + } + + IRO_NodeTable = oalloc(IRO_NumNodes * sizeof(IRONode *)); + memset(IRO_NodeTable, 0, IRO_NumNodes * sizeof(IRONode *)); + for (node = IRO_FirstNode, i = 0; node; node = node->nextnode) + IRO_NodeTable[i++] = node; + + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + IRO_CheckForUserBreak(); +} + +IRONode *IRO_NewFlowGraphNode(void) { + IRONode *node = oalloc(sizeof(IRONode)); + memset(node, 0, sizeof(IRONode)); + node->index = IRO_NumNodes; + IRO_NumNodes++; + node->nextnode = NULL; + return node; +} + +IRONode *IRO_MergeFlowGraphNodes(IRONode *a, IRONode *b) { + // TODO +} diff --git a/compiler_and_linker/unsorted/IroJump.c b/compiler_and_linker/unsorted/IroJump.c index e69de29..e39e3f0 100644 --- a/compiler_and_linker/unsorted/IroJump.c +++ b/compiler_and_linker/unsorted/IroJump.c @@ -0,0 +1,267 @@ +#include "compiler/IroJump.h" +#include "compiler/IroDump.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroUtil.h" +#include "compiler/CFunc.h" +#include "compiler/Exceptions.h" + +static Boolean CheckChain(CLabel **labelptr) { + IRONode *node; + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first && node->first->type == IROLinearLabel && node->first->u.label.label == *labelptr) { + IROLinear *linear; + CLabel *lab; + for (linear = node->first->next, lab = NULL; linear && (linear->type == IROLinearLabel || linear->type == IROLinearNop); linear = linear->next) { + if (linear->type == IROLinearLabel) + lab = linear->u.label.label; + } + + if (linear->type == IROLinearGoto && *labelptr != linear->u.label.label) { + *labelptr = linear->u.label.label; + IRO_Dump("Chaining goto at %d\n", linear->index); + return 1; + } + + if (lab && *labelptr != lab) + *labelptr = lab; + return 0; + } + } + + return 0; +} + +Boolean IRO_DoJumpChaining(void) { + IRONode *node; + IROLinear *linear; + Boolean flag; + SwitchInfo *info; + SwitchCase *curcase; + Boolean result; + + result = 0; + do { + flag = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first) { + linear = node->last; + switch (linear->type) { + case IROLinearGoto: + if (CheckChain(&linear->u.label.label)) + flag = 1; + break; + case IROLinearIf: + case IROLinearIfNot: + if (CheckChain(&linear->u.label.label)) + flag = 1; + break; + case IROLinearSwitch: + info = linear->u.swtch.info; + for (curcase = info->cases; curcase; curcase = curcase->next) { + if (CheckChain(&curcase->label)) + flag = 1; + } + if (CheckChain(&info->defaultlabel)) + flag = 1; + break; + } + } + } + result |= flag; + IRO_CheckForUserBreak(); + } while (flag); + + return result; +} + +void IRO_MakeReachable(IRONode *node) { + UInt16 i; + Boolean flag; + + node->x36 = 1; + do { + flag = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->x36 && !node->x37) { + for (i = 0; i < node->numsucc; i++) { + if (!IRO_NodeTable[node->succ[i]]->x36) { + flag = 1; + IRO_NodeTable[node->succ[i]]->x36 = 1; + } + } + node->x37 = 1; + } + } + } while (flag); +} + +Boolean IRO_RemoveUnreachable(void) { + IRONode *node2; + IRONode *node1; + IROLinear *scan; + IROLinear *linear; + Boolean result; + ExceptionAction **actptr; + ExceptionAction *act; + + result = 0; + IRO_ComputeSuccPred(); + IRO_MakeReachable(IRO_FirstNode); + node1 = IRO_FirstNode; + for (node2 = IRO_FirstNode->nextnode; node2; node2 = node2->nextnode) { + if (node2->first && !node2->x36) { + IRO_Dump("Removing unreachable code at: %d\n", node2->index); + node1->nextnode = node2->nextnode; + node1->last->next = node2->last->next; + result = 1; + for (linear = node2->first; linear && linear->type == IROLinearLabel && linear != node2->last->next; linear = linear->next) { + for (scan = IRO_FirstLinear; scan; scan = scan->next) { + if (scan->stmt) + scan->stmt->marked = 0; + } + + for (scan = IRO_FirstLinear; scan; scan = scan->next) { + if (scan->stmt && !scan->stmt->marked) { + scan->stmt->marked = 1; + for (actptr = &scan->stmt->dobjstack; (act = *actptr); actptr = &act->prev) { + if ( + (act->type == EAT_CATCHBLOCK && act->data.catch_block.catch_label == linear->u.label.label) || + (act->type == EAT_SPECIFICATION && act->data.specification.unexp_label == linear->u.label.label)) { + *actptr = act->prev; + } + } + } + } + } + if (node2 == IRO_LastNode) + IRO_LastNode = node1; + } else { + node1 = node2; + } + } + + if (result) { + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } + + IRO_CheckForUserBreak(); + return result; +} + +Boolean IRO_RemoveRedundantJumps(void) { + IRONode *node; + IROLinear *linear; + IROLinear *scan; + IROLinear *scan2; + SwitchInfo *info; + SwitchCase *curcase; + Boolean result; + + result = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first) { + linear = node->last; + switch (linear->type) { + case IROLinearGoto: + scan = linear->next; + while (scan && ((scan->type == IROLinearNop) || (scan->type == IROLinearLabel && scan->u.label.label != linear->u.label.label))) + scan = scan->next; + while (1) { + if (!scan) break; + if (scan->type != IROLinearLabel) break; + if (scan->u.label.label == linear->u.label.label) { + IRO_Dump("Removing goto next at %d\n", linear->index); + linear->type = IROLinearNop; + result = 1; + break; + } + scan = scan->next; + } + break; + + case IROLinearIf: + case IROLinearIfNot: + scan = linear->next; + while (scan && scan->type == IROLinearNop) + scan = scan->next; + if (scan && scan->type == IROLinearGoto) { + scan2 = scan->next; + while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label))) + scan2 = scan2->next; + + if (scan2 && scan2->type == IROLinearLabel && scan2->u.label.label == linear->u.label.label) { + if (linear->type == IROLinearIf) + linear->type = IROLinearIfNot; + else + linear->type = IROLinearIf; + + linear->u.label.label = scan->u.label.label; + scan->type = IROLinearNop; + IRO_Dump("Removing branch around goto at %d\n", linear->index); + result = 1; + } + } + + scan2 = linear->next; + while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label))) + scan2 = scan2->next; + while (1) { + if (!scan2) break; + if (scan2->type != IROLinearLabel) break; + if (scan2->u.label.label == linear->u.label.label) { + IRO_Dump("Removing If/IfNot_Goto next at %d\n", linear->index); + linear->type = IROLinearNop; + IRO_CheckSideEffect(linear->u.label.x4); + result = 1; + break; + } + scan2 = scan2->next; + } + break; + + case IROLinearSwitch: + info = linear->u.swtch.info; + curcase = info->cases; + while (curcase && curcase->label == info->defaultlabel) + curcase = curcase->next; + if (!curcase) { + IRO_Dump("Removing Switch next at %d\n", linear->index); + IRO_CheckSideEffect(linear->u.swtch.x4); + linear->type = IROLinearGoto; + linear->u.label.label = info->defaultlabel; + result = 1; + } + break; + } + } + } + + if (result) { + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } + + IRO_CheckForUserBreak(); + return result; +} + +Boolean IRO_RemoveLabels(void) { + Boolean result; + IRONode *node; + + result = 0; + IRO_ComputeSuccPred(); + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first && node->first->type == IROLinearLabel && !node->x39) { + node->first->type = IROLinearNop; + node->first->flags &= ~IROLF_1; + result = 1; + } + } + + IRO_CheckForUserBreak(); + return result; +} diff --git a/compiler_and_linker/unsorted/IroLinearForm.c b/compiler_and_linker/unsorted/IroLinearForm.c index e69de29..8b8e305 100644 --- a/compiler_and_linker/unsorted/IroLinearForm.c +++ b/compiler_and_linker/unsorted/IroLinearForm.c @@ -0,0 +1,1831 @@ +#include "compiler/IroLinearForm.h" +#include "compiler/IroDump.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroUtil.h" +#include "compiler/IroVars.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/CompilerTools.h" +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/types.h" + +typedef struct NullCheckListNode { + SInt32 precompid; + Object *tempobj; + struct NullCheckListNode *next; +} NullCheckListNode; + +IROLinear *IRO_FirstLinear; +IROLinear *IRO_LastLinear; +UInt32 IRO_NumLinear; +Statement *CurStat; +static NullCheckListNode *NullCheckList; +static Statement *CurrStmt; +static Statement *PrevStmt; + +static void LinkLinear(IROLinear *linear) { + linear->index = IRO_NumLinear++; + if (IRO_FirstLinear) + IRO_LastLinear->next = linear; + else + IRO_FirstLinear = linear; + IRO_LastLinear = linear; +} + +IROLinear *IRO_NewLinear(IROLinearType type) { + IROLinear *linear = oalloc(sizeof(IROLinear)); + memset(linear, 0, sizeof(IROLinear)); + linear->stmt = CurStat; + linear->nodetype = EPOSTINC; + linear->next = NULL; + linear->type = type; + linear->rtype = NULL; + linear->flags = 0; + linear->nodeflags = 0; + linear->expr = NULL; + linear->x16 = 0; + return linear; +} + +static void MarkAssigned(IROLinear *linear, Boolean flag) { + IROLinear *inner; + IROAddrRecord *rec; + + if (IS_LINEAR_MONADIC(linear, EINDIRECT) && IS_LINEAR_MONADIC(linear->u.monadic, EBITFIELD)) { + linear->flags |= IROLF_Assigned; + inner = linear->u.monadic->u.monadic; + if (inner->type == IROLinearOperand) { + inner->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + inner->flags |= IROLF_Used; + } + } + + if (IS_LINEAR_DIADIC(inner, EADD)) { + if (IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + if (IS_LINEAR_ENODE(inner->u.diadic.right, EINTCONST)) + inner->u.diadic.left->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + inner->u.diadic.left->flags |= IROLF_Used; + } + } + + rec = IRO_InitAddrRecordPointer(inner); + IRO_DecomposeAddressExpression(inner, rec); + if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + rec->objRefs->element->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + rec->objRefs->element->flags |= IROLF_Used; + } + } + } + } + + if (IS_LINEAR_MONADIC(linear, EINDIRECT)) { + linear->flags |= IROLF_Assigned; + if (linear->u.monadic->type == IROLinearOperand) { + linear->u.monadic->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + linear->u.monadic->flags |= IROLF_Used; + } + } + } + + if (IS_LINEAR_MONADIC(linear, EINDIRECT)) { + linear->flags |= IROLF_Assigned; + inner = linear->u.monadic; + + if (IS_LINEAR_DIADIC(inner, EADD)) { + if (IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + if (IS_LINEAR_ENODE(inner->u.diadic.right, EINTCONST)) + inner->u.diadic.left->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + inner->u.diadic.left->flags |= IROLF_Used; + } + } + + rec = IRO_InitAddrRecordPointer(inner); + IRO_DecomposeAddressExpression(inner, rec); + if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + rec->objRefs->element->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + rec->objRefs->element->flags |= IROLF_Used; + } + } + } + } +} + +static void MarkSubscript(IROLinear *linear) { + linear->flags |= IROLF_Subs; + if (IS_LINEAR_DIADIC(linear, EADD)) { + if (IRO_IsAddressMultiply(linear->u.diadic.left) || IS_LINEAR_MONADIC(linear->u.diadic.left, EINDIRECT)) + linear->u.diadic.left->flags |= IROLF_Subs; + if (IRO_IsAddressMultiply(linear->u.diadic.right) || IS_LINEAR_MONADIC(linear->u.diadic.right, EINDIRECT)) + linear->u.diadic.right->flags |= IROLF_Subs; + + if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) + MarkSubscript(linear->u.diadic.left); + if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) + MarkSubscript(linear->u.diadic.right); + } +} + +static void MarkArgs(IROLinear *linear) { + int i; + linear->flags |= IROLF_4000; + + switch (linear->type) { + case IROLinearEnd: + break; + case IROLinearOp1Arg: + case IROLinearBeginCatch: + case IROLinearEndCatch: + case IROLinearEndCatchDtor: + MarkArgs(linear->u.monadic); + break; + case IROLinearOp2Arg: + MarkArgs(linear->u.diadic.left); + MarkArgs(linear->u.diadic.right); + break; + case IROLinearIf: + case IROLinearIfNot: + MarkArgs(linear->u.label.x4); + break; + case IROLinearReturn: + if (linear->u.monadic) + MarkArgs(linear->u.monadic); + break; + case IROLinearSwitch: + MarkArgs(linear->u.swtch.x4); + break; + case IROLinearOp3Arg: + MarkArgs(linear->u.args3.a); + MarkArgs(linear->u.args3.b); + MarkArgs(linear->u.args3.c); + break; + case IROLinearFunccall: + MarkArgs(linear->u.funccall.linear8); + for (i = 0; i < linear->u.funccall.argCount; i++) + MarkArgs(linear->u.funccall.args[i]); + break; + } +} + +// assumed name, position +static inline void MarkSubExpr(IROLinear *linear) { + int i; + + switch (linear->type) { + case IROLinearNop: + case IROLinearOperand: + case IROLinearGoto: + case IROLinearLabel: + case IROLinearEntry: + case IROLinearExit: + case IROLinearAsm: + case IROLinearEnd: + break; + case IROLinearOp1Arg: + case IROLinearBeginCatch: + case IROLinearEndCatch: + case IROLinearEndCatchDtor: + linear->u.monadic->flags |= IROLF_Reffed; + break; + case IROLinearOp2Arg: + linear->u.diadic.left->flags |= IROLF_Reffed; + linear->u.diadic.right->flags |= IROLF_Reffed; + break; + case IROLinearIf: + case IROLinearIfNot: + linear->u.label.x4->flags |= IROLF_Reffed; + break; + case IROLinearReturn: + if (linear->u.monadic) + linear->u.monadic->flags |= IROLF_Reffed; + break; + case IROLinearSwitch: + linear->u.swtch.x4->flags |= IROLF_Reffed; + break; + case IROLinearOp3Arg: + linear->u.args3.a->flags |= IROLF_Reffed; + linear->u.args3.b->flags |= IROLF_Reffed; + linear->u.args3.c->flags |= IROLF_Reffed; + break; + case IROLinearFunccall: + linear->u.funccall.linear8->flags |= IROLF_Reffed; + for (i = 0; i < linear->u.funccall.argCount; i++) + linear->u.funccall.args[i]->flags |= IROLF_Reffed; + break; + default: +#line 368 + CError_FATAL(); + } +} + +static void MarkSubs1(IROLinear *linear) { + IROAddrRecord *rec; + + if (IS_LINEAR_MONADIC(linear, EBITFIELD)) { + linear = linear->u.monadic; + if (IS_LINEAR_ENODE(linear, EOBJREF)) + linear->flags |= IROLF_Ind; + } + + if (IS_LINEAR_DIADIC(linear, EADD)) { + if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF) && IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) + linear->u.diadic.left->flags |= IROLF_Ind; + + rec = IRO_InitAddrRecordPointer(linear); + IRO_DecomposeAddressExpression(linear, rec); + if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) + rec->objRefs->element->flags |= IROLF_Ind; + } +} + +static void MakeLeftChildAsAssignment(ENode *enode) { + Statement *stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = enode->data.diadic.left; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void AssignCommaRToTemp(ENode *enode, Boolean flag) { + Statement *stmt; + + if (!IS_TYPE_VOID(enode->rtype) && !flag) { + Object *obj = create_temp_object(enode->rtype); + ENode *indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(obj); + + if (!IS_TYPE_VOID(enode->rtype)) { + indnode->rtype = enode->rtype; + } else { +#line 548 + CError_FATAL(); + } + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.diadic.right; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(obj); +#line 580 + CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); + } else { + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = enode->data.diadic.right; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINTCONST; + enode->data.intval = cint64_zero; + } +} + +static void AssignDangerousArgumentToTemp(ENode *enode) { + Statement *stmt; + Object *obj; + ENode *indnode; + ENode *rightnode; + + obj = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(obj); + + if (!IS_TYPE_VOID(enode->rtype)) { + indnode->rtype = enode->rtype; + } else { +#line 627 + CError_FATAL(); + } + + rightnode = IRO_NewENode(enode->type); + memcpy(rightnode, enode, sizeof(ENode)); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(obj); +} + +static void CreateTempAssignmentToZero(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) { + indnode->rtype = enode->rtype; + } else { +#line 678 + CError_FATAL(); + } + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_zero; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void CreateTempAssignmentToOne(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) { + indnode->rtype = enode->rtype; + } else { +#line 720 + CError_FATAL(); + } + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_one; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateCondExpression(ENode *enode, CLabel **label) { + Statement *stmt; + + *label = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = enode->data.cond.cond; + stmt->label = *label; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateGoToStmt(ENode *enode, CLabel **label) { + Statement *stmt; + + *label = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_GOTO; + stmt->label = *label; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void PutTempOnNullCheckList(ENode *expr, Object *obj) { + NullCheckListNode *n = lalloc(sizeof(NullCheckListNode)); + n->precompid = expr->data.nullcheck.precompid; + n->tempobj = obj; + n->next = NULL; + if (NullCheckList) { + n->next = NullCheckList; + NullCheckList = n; + } else { + NullCheckList = n; + } +} + +static Object *GetTempFromtheList(ENode *expr) { + NullCheckListNode *n; + + for (n = NullCheckList; n; n = n->next) { + if (n->precompid == expr->data.precompid) + break; + } + +#line 839 + CError_ASSERT(n); + return n->tempobj; +} + +static void GenerateNullcheckExprTempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) + *objptr = create_temp_object(enode->rtype); + else + *objptr = create_temp_object(enode->data.nullcheck.nullcheckexpr->rtype); + + PutTempOnNullCheckList(enode, *objptr); + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + indnode->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.nullcheck.nullcheckexpr; + if (!IS_TYPE_VOID(enode->rtype)) + stmt->expr->rtype = enode->rtype; + else + stmt->expr->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateExpr1TempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) { + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + indnode->rtype = enode->rtype; +#line 905 + CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); + } + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + if (!IS_TYPE_VOID(enode->rtype)) { + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.cond.expr1; + stmt->expr->rtype = enode->rtype; + } else { + stmt->expr = enode->data.cond.expr1; + } + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateExpr2TempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) { + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + indnode->rtype = enode->rtype; +#line 953 + CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); + } + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + if (!IS_TYPE_VOID(enode->rtype)) { + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.cond.expr2; + stmt->expr->rtype = enode->rtype; + } else { + stmt->expr = enode->data.cond.expr2; + } + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateForceLoadTempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) { + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + indnode->rtype = enode->rtype; +#line 1003 + CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); + } + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + if (!IS_TYPE_VOID(enode->rtype)) { + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.monadic; + stmt->expr->rtype = enode->rtype; + } else { + stmt->expr = enode->data.monadic; + } + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateLabel(CLabel **labelptr) { + Statement *stmt; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_LABEL; + stmt->label = *labelptr; + stmt->label->stmt = stmt; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateIfNotTemp(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + ENode *indnode; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + indnode->rtype = enode->data.monadic->rtype; + + *labelptr = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = indnode; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateNullcheckCondExpr(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + indnode->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.nullcheck.condexpr; + if (!IS_TYPE_VOID(enode->rtype)) + stmt->expr->rtype = enode->rtype; + else + stmt->expr->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void TransformLogicalAndLHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + + *labelptr = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = enode->data.diadic.left; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void TransformLogicalAndRHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = enode->data.diadic.right; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) { + indnode->rtype = enode->rtype; + } else { +#line 1225 + CError_FATAL(); + } + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_one; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_LABEL; + stmt->label = *labelptr; + stmt->label->stmt = stmt; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(*objptr); +#line 1276 + CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); +} + +static void TransformLogicalOrLHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + + *labelptr = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFGOTO; + stmt->expr = enode->data.diadic.left; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void TransformLogicalOrRHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFGOTO; + stmt->expr = enode->data.diadic.right; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) { + indnode->rtype = enode->rtype; + } else { +#line 1354 + CError_FATAL(); + } + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_zero; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_LABEL; + stmt->label = *labelptr; + stmt->label->stmt = stmt; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(*objptr); +#line 1405 + CError_ASSERT(!IS_TYPE_VOID(enode->rtype)); +} + +static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) { + switch (a->type) { + ENODE_CASE_MONADIC + LinearizeExpr1(a->data.monadic, a, 0, 0); + if (a->type == EFORCELOAD) { + Object *obj; + GenerateForceLoadTempAssignment(a, &obj); + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(obj); +#line 1428 + CError_ASSERT(!IS_TYPE_VOID(a->rtype)); + } + break; + ENODE_CASE_DIADIC_1 + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBTST: + if (a->type == ECOMMA) { + LinearizeExpr1(a->data.diadic.left, a, 1, 0); + MakeLeftChildAsAssignment(a); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + AssignCommaRToTemp(a, flag); + } else if (a->data.diadic.right->cost >= a->data.diadic.left->cost) { + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + } else { + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + } + break; + ENODE_CASE_ASSIGN + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + break; + case ELAND: + case ELOR: + if (a->type == ELAND) { + CLabel *label; + Object *obj; + CreateTempAssignmentToZero(a, &obj); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + TransformLogicalAndLHS(a, &obj, &label); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + TransformLogicalAndRHS(a, &obj, &label); + } else if (a->type == ELOR) { + CLabel *label; + Object *obj; + CreateTempAssignmentToOne(a, &obj); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + TransformLogicalOrLHS(a, &obj, &label); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + TransformLogicalOrRHS(a, &obj, &label); + } + break; + case ECOND: { + CLabel *label1, *label2; + Object *obj; + LinearizeExpr1(a->data.cond.cond, a, 0, 0); + GenerateCondExpression(a, &label1); + LinearizeExpr1(a->data.cond.expr1, a, 0, 0); + GenerateExpr1TempAssignment(a, &obj); + GenerateGoToStmt(a, &label2); + GenerateLabel(&label1); + LinearizeExpr1(a->data.cond.expr2, a, 0, 0); + GenerateExpr2TempAssignment(a, &obj); + GenerateLabel(&label2); + if (!IS_TYPE_VOID(a->rtype)) { + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(obj); +#line 1596 + CError_ASSERT(!IS_TYPE_VOID(a->rtype)); + } else { + a->type = EINTCONST; + a->data.intval = cint64_zero; + } + break; + } + case EPRECOMP: { + Object *temp = GetTempFromtheList(a); + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(temp); +#line 1614 + CError_ASSERT(!IS_TYPE_VOID(a->rtype)); + break; + } + case ENULLCHECK: { + CLabel *label; + Object *obj; + LinearizeExpr1(a->data.nullcheck.nullcheckexpr, a, 0, 0); + GenerateNullcheckExprTempAssignment(a, &obj); + GenerateIfNotTemp(a, &obj, &label); + LinearizeExpr1(a->data.nullcheck.condexpr, a, 0, 0); + GenerateNullcheckCondExpr(a, &obj); + GenerateLabel(&label); + if (!IS_TYPE_VOID(a->rtype)) { + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(obj); +#line 1639 + CError_ASSERT(!IS_TYPE_VOID(a->rtype)); + } else { + a->type = EINTCONST; + a->data.intval = cint64_zero; + } + break; + } + case EFUNCCALL: + case EFUNCCALLP: { + SInt32 count; + SInt32 i; + ENodeList *list; + ENode **arr; + SInt16 *arr2; + + IRO_IsLeafFunction = 0; + + list = a->data.funccall.args; + count = 0; + while (list) { + list = list->next; + count++; + } + + if (count) { + arr = oalloc(sizeof(ENode *) * count); + list = a->data.funccall.args; + count = 0; + while (list) { + arr[count] = list->node; + list = list->next; + count++; + } + + arr2 = oalloc(sizeof(SInt16) * count); + for (i = 0; i < count; i++) + arr2[i] = count - i - 1; + + for (i = 0; i < count; i++) + LinearizeExpr1(arr[arr2[i]], a, 0, 0); + } + + LinearizeExpr1(a->data.funccall.funcref, a, 0, 0); + break; + } + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case ESETCONST: + case EVECTOR128CONST: + break; + + default: +#line 1723 + CError_FATAL(); + } +} + +static IROLinear *LinearizeExpr(ENode *enode) { + IROLinear *linear = NULL; + + switch (enode->type) { + ENODE_CASE_MONADIC + linear = IRO_NewLinear(IROLinearOp1Arg); + linear->u.monadic = LinearizeExpr(enode->data.monadic); + linear->nodetype = enode->type; + linear->rtype = enode->rtype; + linear->nodeflags = enode->flags; + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.monadic, 1); + if (linear->nodetype == EINDIRECT) { + MarkSubs1(linear->u.monadic); + linear->u.monadic->flags |= IROLF_Immind | IROLF_Ind; + if (IS_LINEAR_DIADIC(linear->u.monadic, EADD)) + MarkSubscript(linear->u.monadic); + } + break; + ENODE_CASE_DIADIC_1 + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBTST: + linear = IRO_NewLinear(IROLinearOp2Arg); + linear->nodeflags = enode->flags; + if (!ENODE_IS(enode, ECOMMA) && enode->data.diadic.right->cost >= enode->data.diadic.left->cost) { + linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); + linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); + linear->flags |= IROLF_8000; + } else { + linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); + linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); + } + linear->nodetype = enode->type; + linear->rtype = enode->rtype; + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); + break; + ENODE_CASE_ASSIGN + linear = IRO_NewLinear(IROLinearOp2Arg); + linear->nodeflags = enode->flags; + linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); + linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); + linear->flags |= IROLF_8000; + linear->nodetype = enode->type; + linear->rtype = enode->rtype; + MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); + break; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EVECTOR128CONST: + linear = IRO_NewLinear(IROLinearOperand); + linear->nodeflags = enode->flags; + linear->u.node = enode; + linear->rtype = enode->rtype; + break; + case EFUNCCALL: + case EFUNCCALLP: { + SInt32 count; + SInt32 i; + ENodeList *list; + ENode **arr; + SInt16 *arr2; + + linear = IRO_NewLinear(IROLinearFunccall); + linear->nodeflags = enode->flags; + linear->u.funccall.ispascal = enode->type == EFUNCCALLP; + + list = enode->data.funccall.args; + count = 0; + while (list) { + list = list->next; + count++; + } + + arr = NULL; + if (count) { + arr = oalloc(sizeof(ENode *) * count); + list = enode->data.funccall.args; + count = 0; + while (list) { + arr[count] = list->node; + list = list->next; + count++; + } + + arr2 = oalloc(sizeof(SInt16) * count); + for (i = 0; i < count; i++) + arr2[i] = count - i - 1; + + for (i = 0; i < count; i++) { + arr[arr2[i]] = (ENode *) LinearizeExpr(arr[arr2[i]]); + MarkArgs((IROLinear *) arr[arr2[i]]); + } + } + + linear->u.funccall.argCount = count; + linear->u.funccall.args = (IROLinear **) arr; + linear->u.funccall.linear8 = LinearizeExpr(enode->data.funccall.funcref); + linear->u.funccall.functype = enode->data.funccall.functype; + linear->rtype = enode->rtype; + break; + } + default: +#line 1943 + CError_FATAL(); + } + + if (linear) + LinkLinear(linear); + return linear; +} + +void IRO_PreLinearize(Statement *stmt) { + IRO_FirstLinear = IRO_LastLinear = NULL; + IRO_NumLinear = 0; + CurrStmt = PrevStmt = NULL; + + while (stmt) { + CurStat = stmt; + CurrStmt = stmt; + NullCheckList = NULL; + + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + break; + case ST_OVF: +#line 1989 + CError_FATAL(); + case ST_EXPRESSION: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_SWITCH: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_IFGOTO: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_IFNGOTO: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_RETURN: + if (stmt->expr) + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_BEGINCATCH: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_ENDCATCH: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_ENDCATCHDTOR: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + + case ST_EXIT: + case ST_ENTRY: + case ST_ASM: + break; + + default: +#line 2038 + CError_FATAL(); + } + + PrevStmt = stmt; + stmt = stmt->next; + } + + IRO_CheckForUserBreak(); +} + +static void MarkAllSubExprs(IROLinear *linear) { + IROLinear *scan; + int i; + + for (scan = linear; scan; scan = scan->next) + scan->flags &= ~IROLF_Reffed; + + for (scan = linear; scan; scan = scan->next) + MarkSubExpr(scan); +} + +void IRO_Linearize(Statement *stmt) { + IROLinear *linear; + + IRO_FirstLinear = IRO_LastLinear = NULL; + IRO_NumLinear = 0; + + while (stmt) { + CurStat = stmt; + linear = NULL; + + switch (stmt->type) { + case ST_NOP: + linear = IRO_NewLinear(IROLinearNop); + break; + case ST_LABEL: + linear = IRO_NewLinear(IROLinearLabel); + linear->u.label.label = stmt->label; + linear->flags |= IROLF_1; + break; + case ST_GOTO: + linear = IRO_NewLinear(IROLinearGoto); + linear->u.label.label = stmt->label; + break; + case ST_EXPRESSION: + LinearizeExpr(stmt->expr); + break; + case ST_SWITCH: + linear = IRO_NewLinear(IROLinearSwitch); + linear->u.swtch.x4 = LinearizeExpr(stmt->expr); + linear->u.swtch.info = (SwitchInfo *) stmt->label; + break; + case ST_IFGOTO: + linear = IRO_NewLinear(IROLinearIf); + linear->u.label.x4 = LinearizeExpr(stmt->expr); + linear->u.label.label = stmt->label; + break; + case ST_IFNGOTO: + linear = IRO_NewLinear(IROLinearIfNot); + linear->u.label.x4 = LinearizeExpr(stmt->expr); + linear->u.label.label = stmt->label; + break; + case ST_RETURN: + IRO_FunctionHasReturn = 1; + linear = IRO_NewLinear(IROLinearReturn); + if (stmt->expr) + linear->u.monadic = LinearizeExpr(stmt->expr); + else + linear->u.monadic = NULL; + break; + case ST_OVF: +#line 2143 + CError_FATAL(); + break; + case ST_EXIT: + linear = IRO_NewLinear(IROLinearExit); + linear->u.label.label = stmt->label; + break; + case ST_ENTRY: + linear = IRO_NewLinear(IROLinearEntry); + linear->u.label.label = stmt->label; + linear->flags |= IROLF_1; + break; + case ST_BEGINCATCH: + linear = IRO_NewLinear(IROLinearBeginCatch); + linear->u.ctch.linear = LinearizeExpr(stmt->expr); + linear->u.ctch.x4 = 0; + linear->u.ctch.x8 = 0; + break; + case ST_ENDCATCH: + linear = IRO_NewLinear(IROLinearEndCatch); + linear->u.monadic = LinearizeExpr(stmt->expr); + break; + case ST_ENDCATCHDTOR: + linear = IRO_NewLinear(IROLinearEndCatchDtor); + linear->u.monadic = LinearizeExpr(stmt->expr); + break; + case ST_ASM: + linear = IRO_NewLinear(IROLinearAsm); + linear->u.asm_stmt = stmt; + if (copts.optimizewithasm) { + IAEffects effects; + CodeGen_GetAsmEffects(stmt, &effects); + if (effects.x0 || effects.x3) + DisableDueToAsm = 1; + } else { + DisableDueToAsm = 1; + } + break; + default: +#line 2194 + CError_FATAL(); + } + + if (linear) + LinkLinear(linear); + stmt = stmt->next; + } + + linear = IRO_NewLinear(IROLinearEnd); + linear->flags |= IROLF_1; + LinkLinear(linear); + + MarkAllSubExprs(IRO_FirstLinear); + IRO_CheckForUserBreak(); +} + +static Statement *NewStatement(IROLinear *linear, StatementType sttype) { + Statement *stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = sttype; + stmt->value = 1; + if (linear->stmt) { + stmt->dobjstack = linear->stmt->dobjstack; + stmt->sourceoffset = linear->stmt->sourceoffset; + stmt->sourcefilepath = linear->stmt->sourcefilepath; + stmt->value = linear->stmt->value; + stmt->flags = linear->stmt->flags; + } else { + stmt->sourceoffset = -1; + stmt->sourcefilepath = NULL; + } + return stmt; +} + +ENode *IRO_NewENode(ENodeType nodetype) { + ENode *enode = lalloc(sizeof(ENode)); + memset(enode, 0, sizeof(ENode)); + enode->type = nodetype; + return enode; +} + +static ENode *BuildExpr(IROLinear *linear) { + ENode *enode; + + switch (linear->type) { + case IROLinearOperand: + enode = IRO_NewENode(linear->u.node->type); + enode->flags = linear->nodeflags; + *enode = *linear->u.node; + break; + case IROLinearOp1Arg: + enode = IRO_NewENode(linear->nodetype); + enode->flags = linear->nodeflags; + enode->data.monadic = BuildExpr(linear->u.monadic); + enode->rtype = linear->rtype; + enode->cost = enode->data.monadic->cost; + if (!enode->cost) + enode->cost = 1; + break; + case IROLinearOp2Arg: + enode = IRO_NewENode(linear->nodetype); + enode->flags = linear->nodeflags; + enode->data.diadic.left = BuildExpr(linear->u.diadic.left); + enode->data.diadic.right = BuildExpr(linear->u.diadic.right); + + enode->cost = enode->data.diadic.left->cost; + if (enode->data.diadic.right->cost > enode->cost) + enode->cost = enode->data.diadic.right->cost; + else if (enode->data.diadic.right->cost == enode->cost) + enode->cost += 1; + + if (ENODE_IS4(enode, ESHL, ESHR, EDIV, EMODULO)) + enode->cost += 2; + if (enode->cost > 200) + enode->cost = 200; + + enode->rtype = linear->rtype; + break; + case IROLinearOp3Arg: + enode = IRO_NewENode(linear->nodetype); + enode->flags = linear->nodeflags; + enode->data.cond.cond = BuildExpr(linear->u.args3.a); + enode->data.cond.expr1 = BuildExpr(linear->u.args3.b); + enode->data.cond.expr2 = BuildExpr(linear->u.args3.c); + enode->rtype = linear->rtype; + + enode->cost = enode->data.cond.cond->cost; + if (enode->data.cond.expr1->cost > enode->cost) + enode->cost = enode->data.cond.expr1->cost; + if (enode->data.cond.expr2->cost > enode->cost) + enode->cost = enode->data.cond.expr2->cost; + enode->cost += 1; + + if (enode->cost > 200) + enode->cost = 200; + + break; + + case IROLinearFunccall: { + int i; + enode = IRO_NewENode(linear->u.funccall.ispascal ? EFUNCCALLP : EFUNCCALL); + enode->flags = linear->nodeflags; + enode->data.funccall.funcref = BuildExpr(linear->u.funccall.linear8); + enode->data.funccall.functype = linear->u.funccall.functype; + enode->data.funccall.args = NULL; + enode->cost = 200; + for (i = linear->u.funccall.argCount - 1; i >= 0; i--) { + ENodeList *list = lalloc(sizeof(ENodeList)); + list->node = BuildExpr(linear->u.funccall.args[i]); + list->next = enode->data.funccall.args; + enode->data.funccall.args = list; + } + enode->rtype = linear->rtype; + break; + } + + default: + IRO_Dump("Oh, oh, bad expression type in BuildExpr at: %d\n", linear->index); +#line 2390 + CError_FATAL(); + } + + enode->pointsTo = linear->pointsToFunction; + return enode; +} + +Statement *IRO_Delinearize(IRONode *node, IROLinear *linear) { + IROLinear *scanlin; + Statement *firstStmt; + Statement *lastStmt; + IRONode *scan; + Statement *stmt; + IRONode mynode; + + firstStmt = lastStmt = NULL; + + if (node) { + scan = node; + MarkAllSubExprs(IRO_FirstLinear); + } else { + memset(&mynode, 0, sizeof(IRONode)); + mynode.first = linear; + scan = &mynode; + MarkAllSubExprs(linear); + } + + while (scan) { + for (scanlin = scan->first; scanlin; scanlin = scanlin->next) { + stmt = NULL; + if (!(scanlin->flags & IROLF_Reffed)) { + switch (scanlin->type) { + case IROLinearNop: + if (scan == node) + stmt = NewStatement(scanlin, ST_NOP); + else + stmt = NULL; + break; + case IROLinearOperand: + case IROLinearOp1Arg: + case IROLinearOp2Arg: + case IROLinearOp3Arg: + case IROLinearFunccall: + stmt = NewStatement(scanlin, ST_EXPRESSION); + stmt->expr = BuildExpr(scanlin); + break; + case IROLinearGoto: + stmt = NewStatement(scanlin, ST_GOTO); + stmt->label = scanlin->u.label.label; + break; + case IROLinearExit: + stmt = NewStatement(scanlin, ST_EXIT); + stmt->label = scanlin->u.label.label; + break; + case IROLinearIf: + case IROLinearIfNot: + stmt = NewStatement(scanlin, (scanlin->type == IROLinearIf) ? ST_IFGOTO : ST_IFNGOTO); + stmt->label = scanlin->u.label.label; + stmt->expr = BuildExpr(scanlin->u.label.x4); + break; + case IROLinearReturn: + stmt = NewStatement(scanlin, ST_RETURN); + if (scanlin->u.monadic) + stmt->expr = BuildExpr(scanlin->u.monadic); + break; + case IROLinearLabel: + stmt = NewStatement(scanlin, ST_LABEL); + stmt->label = scanlin->u.label.label; + stmt->label->stmt = stmt; + break; + case IROLinearEntry: + stmt = NewStatement(scanlin, ST_ENTRY); + stmt->label = scanlin->u.label.label; + stmt->label->stmt = stmt; + break; + case IROLinearSwitch: + stmt = NewStatement(scanlin, ST_SWITCH); + stmt->expr = BuildExpr(scanlin->u.swtch.x4); + stmt->label = (CLabel *) scanlin->u.swtch.info; + break; + case IROLinearBeginCatch: + stmt = NewStatement(scanlin, ST_BEGINCATCH); + stmt->expr = BuildExpr(scanlin->u.ctch.linear); + break; + case IROLinearEndCatch: + stmt = NewStatement(scanlin, ST_ENDCATCH); + stmt->expr = BuildExpr(scanlin->u.monadic); + break; + case IROLinearEndCatchDtor: + stmt = NewStatement(scanlin, ST_ENDCATCHDTOR); + stmt->expr = BuildExpr(scanlin->u.monadic); + break; + case IROLinearAsm: + stmt = scanlin->u.asm_stmt; + break; + case IROLinearEnd: + stmt = NULL; + break; + default: +#line 2685 + CError_FATAL(); + } + + if (stmt) { + if (LoopOptimizerRun) { + SInt32 i; + SInt32 value = 1; + for (i = 0; i < scan->loopdepth; i++) { + value = (value < 4096) ? (value * 8) : (value + 1); + } + stmt->value = value; + } + if (firstStmt) + lastStmt->next = stmt; + else + firstStmt = stmt; + lastStmt = stmt; + } + } + if (scanlin == scan->last) + break; + } + scan = scan->nextnode; + } + + return firstStmt; +} + +void IRO_RenumberInts(void) { + IROLinear *linear = IRO_FirstLinear; + IRO_NumLinear = 0; + while (linear) { + linear->index = IRO_NumLinear++; + linear = linear->next; + } +} + +static void TravExprToUpdateFlags(IROLinear *linear) { + int i; + + linear->flags &= ~(IROLF_Assigned | IROLF_8 | IROLF_Used | IROLF_Ind | IROLF_Subs | IROLF_LoopInvariant | IROLF_Ris | IROLF_Immind | IROLF_CouldError); + switch (linear->type) { + case IROLinearNop: + case IROLinearOperand: + break; + case IROLinearOp1Arg: + TravExprToUpdateFlags(linear->u.monadic); + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.monadic, 1); + if (linear->nodetype == EINDIRECT) { + MarkSubs1(linear->u.monadic); + linear->u.monadic->flags |= IROLF_Immind | IROLF_Ind; + if (IS_LINEAR_DIADIC(linear->u.monadic, EADD)) + MarkSubscript(linear->u.monadic); + } + break; + case IROLinearOp2Arg: + TravExprToUpdateFlags(linear->u.diadic.left); + TravExprToUpdateFlags(linear->u.diadic.right); + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); + break; + case IROLinearOp3Arg: + TravExprToUpdateFlags(linear->u.args3.a); + TravExprToUpdateFlags(linear->u.args3.b); + TravExprToUpdateFlags(linear->u.args3.c); + break; + case IROLinearFunccall: + TravExprToUpdateFlags(linear->u.funccall.linear8); + for (i = linear->u.funccall.argCount - 1; i >= 0; i--) + TravExprToUpdateFlags(linear->u.funccall.args[i]); + break; + default: + IRO_Dump("Oh, oh, bad expression type in TravExprToUpdateFlags at: %d\n", linear->index); +#line 2853 + CError_FATAL(); + } +} + +void IRO_UpdateFlagsOnInts(void) { + IROLinear *linear; + IRONode *node; + + MarkAllSubExprs(IRO_FirstLinear); + + for (node = IRO_FirstNode; node; node = node->nextnode) { + for (linear = node->first; linear; linear = linear->next) { + if (!(linear->flags & IROLF_Reffed)) { + switch (linear->type) { + case IROLinearOperand: + case IROLinearOp1Arg: + case IROLinearOp2Arg: + case IROLinearOp3Arg: + case IROLinearFunccall: + TravExprToUpdateFlags(linear); + break; + case IROLinearIf: + case IROLinearIfNot: + TravExprToUpdateFlags(linear->u.label.x4); + break; + case IROLinearReturn: + if (linear->u.monadic) + TravExprToUpdateFlags(linear->u.monadic); + break; + case IROLinearSwitch: + TravExprToUpdateFlags(linear->u.swtch.x4); + break; + case IROLinearBeginCatch: + TravExprToUpdateFlags(linear->u.ctch.linear); + break; + case IROLinearEndCatch: + TravExprToUpdateFlags(linear->u.monadic); + break; + case IROLinearEndCatchDtor: + TravExprToUpdateFlags(linear->u.monadic); + break; + case IROLinearNop: + case IROLinearGoto: + case IROLinearLabel: + case IROLinearEntry: + case IROLinearExit: + case IROLinearAsm: + case IROLinearEnd: + break; + default: +#line 2931 + CError_FATAL(); + } + } + if (linear == node->last) + break; + } + } +} + +void IRO_SaveLinearIR(IROLinearIRSave *save) { + save->firstLinear = IRO_FirstLinear; + save->lastLinear = IRO_LastLinear; + save->numLinear = IRO_NumLinear; + save->curStat = CurStat; + save->disableDueToAsm = DisableDueToAsm; + save->isLeafFunction = IRO_IsLeafFunction; + save->functionHasReturn = IRO_FunctionHasReturn; + save->nullCheckList = NullCheckList; + save->currStmt = CurrStmt; + save->prevStmt = PrevStmt; +} + +void IRO_RestoreLinearIR(IROLinearIRSave *save) { + IRO_FirstLinear = save->firstLinear; + IRO_LastLinear = save->lastLinear; + IRO_NumLinear = save->numLinear; + CurStat = save->curStat; + DisableDueToAsm = save->disableDueToAsm; + IRO_IsLeafFunction = save->isLeafFunction; + IRO_FunctionHasReturn = save->functionHasReturn; + NullCheckList = save->nullCheckList; + CurrStmt = save->currStmt; + PrevStmt = save->prevStmt; +} + diff --git a/compiler_and_linker/unsorted/IroLoop.c b/compiler_and_linker/unsorted/IroLoop.c index e69de29..7f207e6 100644 --- a/compiler_and_linker/unsorted/IroLoop.c +++ b/compiler_and_linker/unsorted/IroLoop.c @@ -0,0 +1,2335 @@ +#include "compiler/IroLoop.h" +#include "compiler/IroCSE.h" +#include "compiler/IroDump.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroPropagate.h" +#include "compiler/IroSubable.h" +#include "compiler/IroUtil.h" +#include "compiler/IroVars.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +IRONode *LoopNode; +Boolean ConditionalHeaderAtBottom; +IROLoopInd *FirstInd; +BitVector *InLoop; +IROList IRO_InitLList; +BitVector *InLoop_Exits; +BitVector *InLoop_Tails; +UInt32 LoopExitNumber; +UInt32 LoopTailNum; +IRONode *LoopExitSuccessor; +IRONode *LoopTail; +IROLoopMemRef *IRO_LoopMemRefFirst; +IROLoopMemRef *IRO_LoopMemRefCurrent; +static IROExpr *RisList; +static BitVector *AllKills; +static Boolean KnownBounds; +static SInt32 Times; +static IROLinear *PredInt; +static IROElmList *FirstAddendLinear; +static IROElmList *LastAddendLinear; +static int NoSubableSubs; + +// forward decls +static void MyHandleLoop_Vector(IRONode *fnode); +static void MyHandleLoop_Motion(IRONode *fnode); +static void CheckAllLoopAddresses(IRONode *fnode, BitVector *bv, Boolean *resultFlag); +static void MakeLoopEntry(IROLinear *nd, IROAddrRecord *rec, Boolean mustreach1, Boolean flag2); +static void MoveInvarianceInAddressExpr(void); +static IROLinear *RearrangeInvarianceInAddressExpr(IROLinear *nd, IROList *list); +static UInt32 IsAssignmentReductionCandidate(IROLinear *nd); + +void FindMustReach(void) { + IRONode *fnode; + IRONode *fnode2; + IRONode *pred; + int i; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + fnode->mustreach = 0; + if (Bv_IsBitSet(fnode->index, InLoop)) { + fnode->mustreach = 1; + + for (i = 0; i < LoopNode->numpred; i++) { + pred = IRO_NodeTable[LoopNode->pred[i]]; + if (Bv_IsBitSet(pred->index, InLoop) && !Bv_IsBitSet(fnode->index, pred->dom)) { + fnode->mustreach = 0; + break; + } + } + + for (fnode2 = IRO_FirstNode; fnode2; fnode2 = fnode2->nextnode) { + if (Bv_IsBitSet(fnode2->index, InLoop)) { + for (i = 0; i < fnode2->numsucc; i++) { + if (!Bv_IsBitSet(fnode2->succ[i], InLoop) && !Bv_IsBitSet(fnode->index, fnode2->dom)) { + fnode->mustreach = 0; + break; + } + } + + if (!fnode->mustreach) + break; + } + } + } + } +} + +void FindMustReach1(IRONode *checkfnode) { + IRONode *fnode; + IRONode *fnode2; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop)) { + fnode->mustreach1 = 1; + for (fnode2 = IRO_FirstNode; fnode2; fnode2 = fnode2->nextnode) { + if (Bv_IsBitSet(fnode2->index, InLoop)) { + if (Bv_IsBitSet(fnode2->index, InLoop_Tails) && !Bv_IsBitSet(fnode->index, fnode2->dom)) + fnode->mustreach1 = 0; + + if (Bv_IsBitSet(fnode2->index, InLoop_Exits) && fnode2 != checkfnode && !Bv_IsBitSet(fnode->index, fnode2->dom)) + fnode->mustreach1 = 0; + + if (!fnode->mustreach1) + break; + } + } + } + } +} + +static void IRO_FindLoopTailsAndExits(IRONode *fnode) { + IRONode *scan; + IRONode *succ; + int i; + + for (scan = IRO_FirstNode; scan; scan = scan->nextnode) { + if (Bv_IsBitSet(scan->index, InLoop)) { + for (i = 0; i < scan->numsucc; i++) { + succ = IRO_NodeTable[scan->succ[i]]; + if (succ == fnode) { + Bv_SetBit(scan->index, InLoop_Tails); + LoopTail = scan; + LoopTailNum++; + } + if (!Bv_IsBitSet(succ->index, InLoop)) { + LoopExitNumber++; + LoopExitSuccessor = succ; + Bv_SetBit(scan->index, InLoop_Exits); + } + } + } + } + + IRO_Dump("IRO_FindLoopTailsAndExits:For header %d, Loop exits and loop tails are \n", fnode->index); + IRO_DumpBits("Loop Exits: ", InLoop_Exits); + IRO_DumpBits("Loop Tails: ", InLoop_Tails); + IRO_Dump("LoopExitNum=%d: \n", LoopExitNumber); + if (LoopExitSuccessor) + IRO_Dump("LoopExitSuccessor node =%d: \n", LoopExitSuccessor->index); +} + +static int IsSafeTypcon(IROLinear *nd) { + Type *srcType; + Type *destType; + SInt32 srcSize; + SInt32 destSize; + Boolean srcUnsigned; + Boolean destUnsigned; + + srcType = nd->u.monadic->rtype; + destType = nd->rtype; + if (!IS_TYPE_INT(srcType) || !IS_TYPE_INT(destType)) + return 0; + + srcSize = srcType->size; + destSize = destType->size; + srcUnsigned = IRO_IsUnsignedType(srcType); + destUnsigned = IRO_IsUnsignedType(destType); + + if (srcUnsigned == destUnsigned && destSize >= srcSize) + return 1; + if (srcUnsigned == 1 && destUnsigned == 0 && destSize > srcSize) + return 1; + return 0; +} + +static int Reducable(IROLinear *nd, IROLinear **resultNd1, IROLinear **resultNd2, VarRecord **resultVar) { + IROLinear *indirect; + IROLinear *left; + IROLinear *right; + Boolean leftInvariant; + Boolean rightInvariant; + Boolean leftTypcon; + Boolean rightTypcon; + Object *obj; + ENode *enode; + IROLoopInd *ind; + CInt64 val64; + SInt32 val; + SInt32 div; + + leftInvariant = 0; + rightInvariant = 0; + leftTypcon = 0; + rightTypcon = 0; + + if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD && (IS_TYPE_INT(nd->rtype) || IS_TYPE_POINTER_ONLY(nd->rtype))) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON) { + leftTypcon = 1; + leftInvariant = (left->flags & IROLF_LoopInvariant) != 0; + left = left->u.monadic; + } + if (right->type == IROLinearOp1Arg && right->nodetype == ETYPCON) { + rightTypcon = 1; + rightInvariant = (right->flags & IROLF_LoopInvariant) != 0; + right = right->u.monadic; + } + + if (((left->flags & IROLF_LoopInvariant) || leftInvariant) && IRO_IsVariable(right)) { + if (leftInvariant || ((!(obj = IRO_IsVariable(left)) || !IRO_IsRegable(obj)) && !IRO_IsConstant(left))) { + if ( + left->type == IROLinearOp2Arg && + left->nodetype == EADD && + (obj = IRO_IsVariable(left->u.diadic.left)) && + IRO_IsRegable(obj) && + IRO_IsConstant(left->u.diadic.right) + ) + return 0; + + if (rightTypcon) { + if (!IsSafeTypcon(nd->u.diadic.right)) + return 0; + *resultNd2 = nd->u.diadic.right; + } else { + *resultNd2 = right; + } + + indirect = right; + *resultNd1 = IRO_NewLinear(IROLinearOperand); + + enode = IRO_NewENode(EINTCONST); + enode->data.intval = cint64_one; + enode->rtype = nd->u.diadic.right->rtype; + (*resultNd1)->rtype = nd->u.diadic.right->rtype; + (*resultNd1)->u.node = enode; + } else { + return 0; + } + } else if ( + ((left->flags & IROLF_LoopInvariant) || leftInvariant) && + right->type == IROLinearOp2Arg && + !rightTypcon && + (right->nodetype == EMUL || right->nodetype == ESHL) + ) { + if (IRO_IsConstant(right->u.diadic.right)) { + if (right->nodetype == ESHL) { + right->nodetype = EMUL; + right->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_one, right->u.diadic.right->u.node->data.intval); + } + if (right->u.diadic.left->type == IROLinearOp1Arg) { + if (IRO_IsVariable(right->u.diadic.left)) { + *resultNd2 = right->u.diadic.left; + indirect = right->u.diadic.left; + *resultNd1 = right->u.diadic.right; + } else if (right->u.diadic.left->nodetype == ETYPCON && IRO_IsVariable(right->u.diadic.left->u.monadic)) { + if (!IsSafeTypcon(right->u.diadic.left)) + return 0; + *resultNd2 = right->u.diadic.left; + indirect = right->u.diadic.left->u.monadic; + *resultNd1 = right->u.diadic.right; + } else { + return 0; + } + } else { + return 0; + } + } else { + return 0; + } + } else if ( + ((right->flags & IROLF_LoopInvariant) || rightInvariant) && + left->type == IROLinearOp2Arg && + !leftTypcon && + (left->nodetype == EMUL || left->nodetype == ESHL) + ) { + if (IRO_IsConstant(left->u.diadic.right)) { + if (left->nodetype == ESHL) { + left->nodetype = EMUL; + left->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_one, left->u.diadic.right->u.node->data.intval); + } + if (left->u.diadic.left->type == IROLinearOp1Arg) { + if (IRO_IsVariable(left->u.diadic.left)) { + *resultNd2 = left->u.diadic.left; + indirect = left->u.diadic.left; + *resultNd1 = left->u.diadic.right; + } else if (left->u.diadic.left->nodetype == ETYPCON && IRO_IsVariable(left->u.diadic.left->u.monadic)) { + if (!IsSafeTypcon(left->u.diadic.left)) + return 0; + *resultNd2 = left->u.diadic.left; + indirect = left->u.diadic.left->u.monadic; + *resultNd1 = left->u.diadic.right; + } else { + return 0; + } + } else { + return 0; + } + } else { + return 0; + } + } else if ( + ((right->flags & IROLF_LoopInvariant) || rightInvariant) && + IRO_IsVariable(left) + ) { + if (rightInvariant || ((!(obj = IRO_IsVariable(right)) || !IRO_IsRegable(obj)) && !IRO_IsConstant(right))) { + if ( + right->type == IROLinearOp2Arg && + right->nodetype == EADD && + (obj = IRO_IsVariable(right->u.diadic.left)) && + IRO_IsRegable(obj) && + IRO_IsConstant(right->u.diadic.right) + ) + return 0; + + if (leftTypcon) { + if (!IsSafeTypcon(nd->u.diadic.left)) + return 0; + *resultNd2 = nd->u.diadic.left; + } else { + *resultNd2 = left; + } + + indirect = left; + *resultNd1 = IRO_NewLinear(IROLinearOperand); + + enode = IRO_NewENode(EINTCONST); + enode->data.intval = cint64_one; + enode->rtype = nd->u.diadic.left->rtype; + (*resultNd1)->rtype = nd->u.diadic.left->rtype; + (*resultNd1)->u.node = enode; + } else { + return 0; + } + } else { + return 0; + } + } else if (nd->type == IROLinearOp2Arg && (nd->nodetype == EMUL || nd->nodetype == ESHL) && nd->rtype->size <= 4 && (IS_TYPE_INT(nd->rtype) || IS_TYPE_POINTER_ONLY(nd->rtype))) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + + if (IRO_IsConstant(right) && IRO_IsVariable(left)) { + *resultNd2 = left; + indirect = left; + *resultNd1 = right; + } else if (IRO_IsConstant(nd->u.diadic.right) && left->type == IROLinearOp1Arg && left->nodetype == ETYPCON && + IRO_IsVariable(left->u.monadic)) { + if (!IsSafeTypcon(left)) + return 0; + *resultNd2 = left; + indirect = left->u.monadic; + *resultNd1 = right; + } else { + if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHL) + return 0; + + if (nd->u.diadic.right->flags & IROLF_LoopInvariant) { + if (IRO_IsVariable(left)) { + *resultNd2 = left; + indirect = left; + *resultNd1 = right; + } else if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON && IRO_IsVariable(left->u.monadic)) { + if (!IsSafeTypcon(left)) + return 0; + *resultNd2 = left; + indirect = left->u.monadic; + *resultNd1 = right; + } else { + return 0; + } + } else if (nd->u.diadic.left->flags & IROLF_LoopInvariant) { + if (IRO_IsVariable(right)) { + *resultNd2 = right; + indirect = right; + *resultNd1 = left; + } else if (right->type == IROLinearOp1Arg && right->nodetype == ETYPCON && IRO_IsVariable(right->u.monadic) && nd->type == IROLinearOp2Arg && nd->nodetype == EMUL) { + if (!IsSafeTypcon(right)) + return 0; + *resultNd2 = right; + indirect = right->u.monadic; + *resultNd1 = left; + } else { + return 0; + } + } else { + return 0; + } + } + } else if (nd->type == IROLinearOp2Arg && (nd->nodetype == EDIV || nd->nodetype == ESHR) && nd->rtype->size <= 4 && IS_TYPE_INT(nd->rtype)) { + if (IRO_IsVariable(nd->u.diadic.left) && IRO_IsConstant(nd->u.diadic.right)) { + val64 = nd->u.diadic.right->u.node->data.intval; + if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHR) { + CInt64_GetULong(&val64); + if (CInt64_GetULong(&val64) > 32 || CTool_EndianReadWord32(&val64.hi)) + return 0; + val64 = CInt64_Shl(cint64_one, val64); + } + *resultNd2 = nd->u.diadic.left; + indirect = nd->u.diadic.left; + } else { + return 0; + } + } else { + return 0; + } + + if ( + nd->type == IROLinearOp2Arg && + nd->nodetype == ESHL && + ( + !IRO_IsConstant(*resultNd1) || + (SInt32) CInt64_GetULong(&(*resultNd1)->u.node->data.intval) < 0 || + (SInt32) CInt64_GetULong(&(*resultNd1)->u.node->data.intval) > 32 || + CTool_EndianReadWord32(&(*resultNd1)->u.node->data.intval.hi) + ) + ) + return 0; + +#line 802 + CError_ASSERT(indirect->u.monadic->u.node != NULL); + *resultVar = IRO_FindVar(indirect->u.monadic->u.node->data.objref, 0, 1); + if (!*resultVar || (*resultVar)->xA != 2) + return 0; + + if (copts.ANSI_strict || copts.opt_strength_reduction_strict) { + Type *type = (*resultVar)->object->type; + if (IRO_IsUnsignedType(type) && type->size < stunsignedlong.size) + return 0; + } + + if (nd->type == IROLinearOp2Arg && (nd->nodetype == ESHR || nd->nodetype == EDIV)) { + ind = FirstInd; + while (ind && ind->var != *resultVar) + ind = ind->next; + +#line 845 + CError_ASSERT(ind != NULL); + + if (ind->addNode == NULL) { + if (ind->addConst < (val = CInt64_GetULong(&val64))) + return 0; + if ((div = ind->addConst / val) <= 0) + return 0; + + *resultNd1 = IRO_NewLinear(IROLinearOperand); + enode = IRO_NewENode(EINTCONST); + CInt64_SetULong(&enode->data.intval, div); + enode->rtype = nd->u.diadic.left->rtype; + (*resultNd1)->rtype = nd->u.diadic.left->rtype; + (*resultNd1)->u.node = enode; + } else { + return 0; + } + } + + return 1; +} + +static void IRO_RemoveExpr_Action(IROLinear *linear, Boolean isFirst) { + if (isFirst && linear->expr) + IRO_RemoveExpr(linear->expr); +} + +static void IRO_ActUnmarkRISCandidate(IROLinear *linear, Boolean isFirst) { + if (isFirst && linear->expr) + linear->flags &= ~IROLF_Ris; +} + +static IROExpr *CreateRIS(IROExpr *expr, IROLinear *nd1, IROLinear *nd2, IROLoopInd *induction, int unk) { + Object *tempObj; + Type *type; + Boolean flag23; + Object *tempObj2; + IROLinear *firstnode; + IROLinear *fourthnode; + IROLinear *fifthnode; + IROLinear *secondnode; + IROLinear *thirdnode; + IROLinear *tmp; + ENode *enode; + IROList list1; + IROList list2; + + flag23 = 0; + type = expr->linear->rtype; + tempObj = create_temp_object(type); + IRO_FindVar(tempObj, 1, 1); + IRO_InitList(&list1); + + if (IS_LINEAR_DIADIC(expr->linear, EADD)) { + firstnode = IRO_DuplicateExpr(expr->linear, &list1); + } else if (IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR)) { + firstnode = IRO_DuplicateExpr(expr->linear, &list1); + } else { + firstnode = IRO_NewLinear(IROLinearOp2Arg); + firstnode->index = ++IRO_NumLinear; + firstnode->rtype = type; + firstnode->nodetype = EMUL; + firstnode->u.diadic.left = IRO_DuplicateExpr(nd1, &list1); + if (unk) + firstnode->u.diadic.right = IRO_DuplicateExpr(nd1, &list1); + else + firstnode->u.diadic.right = IRO_DuplicateExpr(nd2, &list1); + IRO_AddToList(firstnode, &list1); + } + + secondnode = IRO_NewLinear(IROLinearOp2Arg); + secondnode->index = ++IRO_NumLinear; + secondnode->rtype = type; + secondnode->nodetype = EASS; + secondnode->u.diadic.left = IRO_TempReference(tempObj, &list1); + secondnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; + secondnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; + secondnode->u.diadic.right = firstnode; + IRO_AddToList(secondnode, &list1); + IRO_Paste(list1.head, list1.tail, PredInt); + if ( + !IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR) && + induction->addConst != 1 && + (induction->addNode || !IRO_IsConstant(nd2)) + ) { + flag23 = 1; + IRO_InitList(&list1); + thirdnode = IRO_NewLinear(IROLinearOp2Arg); + thirdnode->index = ++IRO_NumLinear; + thirdnode->rtype = nd2->rtype; + thirdnode->nodetype = EMUL; + + if (!induction->addNode) { + thirdnode->u.diadic.left = IRO_DuplicateExpr(nd2, &list1); + thirdnode->u.diadic.right = IRO_NewLinear(IROLinearOperand); + thirdnode->u.diadic.right->index = ++IRO_NumLinear; + enode = IRO_NewENode(EINTCONST); + enode->rtype = nd2->rtype; + thirdnode->u.diadic.right->rtype = nd2->rtype; + CInt64_SetLong(&enode->data.intval, induction->addConst); + thirdnode->u.diadic.right->u.node = enode; + IRO_AddToList(thirdnode->u.diadic.right, &list1); + } else { + thirdnode->u.diadic.left = IRO_DuplicateExpr(nd2, &list1); + thirdnode->u.diadic.right = IRO_DuplicateExpr(induction->addNode, &list1); + if (nd2->rtype != induction->addNode->rtype) { + tmp = IRO_NewLinear(IROLinearOp1Arg); + tmp->nodetype = ETYPCON; + tmp->index = ++IRO_NumLinear; + tmp->rtype = nd2->rtype; + tmp->u.monadic = thirdnode->u.diadic.right; + IRO_AddToList(tmp, &list1); + thirdnode->u.diadic.right = tmp; + } + } + IRO_AddToList(thirdnode, &list1); + + tempObj2 = create_temp_object(nd2->rtype); + + fourthnode = IRO_NewLinear(IROLinearOp2Arg); + fourthnode->index = ++IRO_NumLinear; + fourthnode->rtype = nd2->rtype; + fourthnode->nodetype = EASS; + fourthnode->u.diadic.left = IRO_TempReference(tempObj2, &list1); + fourthnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; + fourthnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; + fourthnode->u.diadic.right = thirdnode; + IRO_AddToList(fourthnode, &list1); + IRO_Paste(list1.head, list1.tail, PredInt); + } + + IRO_InitList(&list2); + fifthnode = IRO_NewLinear(IROLinearOp2Arg); + fifthnode->index = ++IRO_NumLinear; + fifthnode->rtype = type; + if (induction->nd->type == IROLinearOp2Arg) { + if (induction->nd->nodetype == EASS && IS_LINEAR_DIADIC(induction->nd->u.diadic.right, EADD)) + fifthnode->nodetype = EADDASS; + else if (induction->nd->nodetype == EASS && IS_LINEAR_DIADIC(induction->nd->u.diadic.right, ESUB)) + fifthnode->nodetype = ESUBASS; + else + fifthnode->nodetype = induction->nd->nodetype; + } else { + if (induction->nd->nodetype == EPREINC || induction->nd->nodetype == EPOSTINC) + fifthnode->nodetype = EADDASS; + else + fifthnode->nodetype = ESUBASS; + } + + fifthnode->u.diadic.left = IRO_TempReference(tempObj, &list2); + fifthnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Used | IROLF_Assigned; + fifthnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Used | IROLF_Assigned; + if (!unk) { + if (!flag23) { + if (induction->addConst == 1 || IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR)) { + fifthnode->u.diadic.right = IRO_DuplicateExpr(nd2, &list2); + } else { + fifthnode->u.diadic.right = IRO_NewLinear(IROLinearOperand); + fifthnode->u.diadic.right->index = ++IRO_NumLinear; + enode = IRO_NewENode(EINTCONST); + enode->rtype = nd2->rtype; + fifthnode->u.diadic.right->rtype = nd2->rtype; + CInt64_SetLong(&enode->data.intval, induction->addConst * CInt64_GetULong(&nd2->u.node->data.intval)); + fifthnode->u.diadic.right->u.node = enode; + IRO_AddToList(fifthnode->u.diadic.right, &list2); + } + } else { + fifthnode->u.diadic.right = IRO_TempReference(tempObj2, &list2); + fifthnode->u.diadic.right->flags |= IROLF_Used; + } + } + + fifthnode->index = ++IRO_NumLinear; + IRO_AddToList(fifthnode, &list2); + IRO_Paste(list2.head, list2.tail, IRO_FindStart(induction->nd)); + IRO_WalkTree(expr->linear, IRO_RemoveExpr_Action); + expr->x8 = tempObj; + expr->next = RisList; + RisList = expr; + return expr; +} + +static IRONode *CreatePreHeader(IRONode *fnode1, IRONode *fnode2) { + IROLinear *labelnode; + IRONode *newfnode; + IRONode *iter; + CLabel *oldlabel; + CLabel *newlabel; + SwitchInfo *swinfo; + SwitchCase *swcase; + + newfnode = oalloc(sizeof(IRONode)); + memset(newfnode, 0, sizeof(IRONode)); + newfnode->index = IRO_NumNodes; + IRO_NumNodes++; + + labelnode = IRO_NewLinear(IROLinearLabel); + labelnode->index = IRO_NumLinear++; + labelnode->next = NULL; + labelnode->u.label.label = IRO_NewLabel(); + labelnode->flags |= IROLF_1; + labelnode->u.label.label->stmt = (Statement *) newfnode; + newfnode->first = labelnode; + newfnode->last = labelnode; + + if (fnode2) { + fnode2->last->next = labelnode; + labelnode->next = IRO_NewLinear(IROLinearNop); + labelnode->next->next = fnode1->first; + fnode2->nextnode = newfnode; + newfnode->nextnode = fnode1; + } else { +#line 1254 + CError_ASSERT(fnode1->first->type == IROLinearLabel); + labelnode->next = IRO_NewLinear(IROLinearGoto); + labelnode->next->u.label.label = fnode1->first->u.label.label; + IRO_LastNode->last->next = labelnode; + IRO_LastNode->nextnode = newfnode; + IRO_LastNode = newfnode; + IRO_LastLinear = labelnode->next; + } + + newfnode->last = labelnode->next; + + IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes); + memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes); + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) + IRO_NodeTable[iter->index] = iter; + + if (fnode1->first->type == IROLinearLabel) { + oldlabel = fnode1->first->u.label.label; + newlabel = newfnode->first->u.label.label; + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) { + if (!Bv_IsBitSet(iter->index, InLoop) && iter != newfnode) { + switch (iter->last->type) { + case IROLinearGoto: + if (iter->last->u.label.label == oldlabel) + iter->last->u.label.label = newlabel; + break; + case IROLinearIf: + case IROLinearIfNot: + if (iter->last->u.label.label == oldlabel) + iter->last->u.label.label = newlabel; + break; + case IROLinearSwitch: + swinfo = iter->last->u.swtch.info; + for (swcase = swinfo->cases; swcase; swcase = swcase->next) { + if (swcase->label == oldlabel) + swcase->label = newlabel; + } + if (swinfo->defaultlabel == oldlabel) + swinfo->defaultlabel = newlabel; + break; + } + } + } + } + + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + return newfnode; +} + +static IRONode *CreateNewLoopExitSuccessor(IRONode *fnode1) { + IROLinear *labelnode; + IRONode *fnode2; + IRONode *newfnode; + Boolean flag; + IRONode *iter; + CLabel *oldlabel; + CLabel *newlabel; + SwitchInfo *swinfo; + SwitchCase *swcase; + UInt16 i; + +#line 1355 + CError_ASSERT(fnode1 != NULL && LoopExitNumber == 1); + + fnode2 = NULL; + flag = 0; + + for (i = 0; i < fnode1->numpred; i++) { + iter = IRO_NodeTable[fnode1->pred[i]]; + if (Bv_IsBitSet(iter->index, InLoop_Exits)) { +#line 1366 + CError_ASSERT(fnode2 == NULL); + fnode2 = iter; + if (!flag) { + if ( + !iter->last || + !fnode1->first || + fnode1->first->type != IROLinearLabel || + ( + (iter->last->type == IROLinearIf || iter->last->type == IROLinearIfNot) && + iter->last->u.label.label != fnode1->first->u.label.label + )) + flag = 1; + } + } + } + +#line 1382 + CError_ASSERT(fnode2 != NULL); + + newfnode = oalloc(sizeof(IRONode)); + memset(newfnode, 0, sizeof(IRONode)); + newfnode->index = IRO_NumNodes; + IRO_NumNodes++; + + labelnode = IRO_NewLinear(IROLinearLabel); + labelnode->index = IRO_NumLinear++; + labelnode->next = NULL; + labelnode->u.label.label = IRO_NewLabel(); + labelnode->flags |= IROLF_1; + labelnode->u.label.label->stmt = (Statement *) newfnode; + newfnode->first = labelnode; + newfnode->last = labelnode; + + if (flag) { + fnode2->last->next = labelnode; + labelnode->next = IRO_NewLinear(IROLinearNop); + labelnode->next->next = fnode1->first; + fnode2->nextnode = newfnode; + newfnode->nextnode = fnode1; + } else { +#line 1422 + CError_ASSERT(fnode1->first->type == IROLinearLabel); + labelnode->next = IRO_NewLinear(IROLinearGoto); + labelnode->next->u.label.label = fnode1->first->u.label.label; + IRO_LastNode->last->next = labelnode; + IRO_LastNode->nextnode = newfnode; + IRO_LastNode = newfnode; + IRO_LastLinear = labelnode->next; + } + + newfnode->last = labelnode->next; + + IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes); + memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes); + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) + IRO_NodeTable[iter->index] = iter; + + if (fnode1->first->type == IROLinearLabel) { + oldlabel = fnode1->first->u.label.label; + newlabel = newfnode->first->u.label.label; + switch (fnode2->last->type) { + case IROLinearGoto: + if (fnode2->last->u.label.label == oldlabel) + fnode2->last->u.label.label = newlabel; + break; + case IROLinearIf: + case IROLinearIfNot: + if (fnode2->last->u.label.label == oldlabel) + fnode2->last->u.label.label = newlabel; + break; + case IROLinearSwitch: + swinfo = fnode2->last->u.swtch.info; + for (swcase = swinfo->cases; swcase; swcase = swcase->next) { + if (swcase->label == oldlabel) + swcase->label = newlabel; + } + if (swinfo->defaultlabel == oldlabel) + swinfo->defaultlabel = newlabel; + break; + } + } + + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + return newfnode; +} + +void AddPreds(IRONode *fnode) { + IRONode *pred; + int i; + + for (i = 0; i < fnode->numpred; i++) { + pred = IRO_NodeTable[fnode->pred[i]]; + if (!Bv_IsBitSet(pred->index, InLoop)) { + Bv_SetBit(pred->index, InLoop); + AddPreds(pred); + } + } +} + +static void RemoveNoopsFromExprList(void) { + IROExpr *expr; + IROExpr *prev; + + expr = IRO_FirstExpr; + prev = NULL; + while (expr) { + if (expr->linear->type == IROLinearNop) { + if (prev) + prev->next = expr->next; + else + IRO_FirstExpr = expr->next; + expr = expr->next; + } else { + prev = expr; + expr = expr->next; + } + } +} + +void IncLoopDepth(void) { + IRONode *fnode; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop)) + fnode->loopdepth++; + } +} + +void IRO_SetLoopDepth(void) { + IRONode *fnode; + IRONode *pred; + UInt16 i; + UInt16 flag; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) + fnode->loopdepth = 0; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + flag = 0; + + for (i = 0; i < fnode->numpred; i++) { + pred = IRO_NodeTable[fnode->pred[i]]; + if (Bv_IsBitSet(fnode->index, pred->dom)) { + if (!flag) { + Bv_AllocVector(&InLoop, IRO_NumNodes + 1); + Bv_Clear(InLoop); + Bv_SetBit(fnode->index, InLoop); + } + flag = 1; + Bv_SetBit(pred->index, InLoop); + if (pred != fnode) + AddPreds(pred); + } + } + + if (flag) + IncLoopDepth(); + } + + IRO_CheckForUserBreak(); +} + +static void InsertBranchAroundLoopPreheaders(void) { + IRONode *fnode; + CLabel *label; + IRONode *iter; + IROLinear *endnode; + IROLinear *labelnode; + + if (IRO_EndNode && IRO_EndNode->last && IRO_EndNode->last->type == IROLinearEnd) { + label = IRO_NewLabel(); + fnode = IRO_NewFlowGraphNode(); + IRO_LastNode->nextnode = fnode; + label->stmt = (Statement *) fnode; + + IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes); + memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes); + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) + IRO_NodeTable[iter->index] = iter; + + labelnode = IRO_NewLinear(IROLinearLabel); + labelnode->index = ++IRO_NumLinear; + labelnode->u.label.label = label; + labelnode->flags |= IROLF_1; + fnode->first = labelnode; + IRO_LastLinear->next = labelnode; + + endnode = IRO_NewLinear(IROLinearEnd); + memcpy(endnode, IRO_EndNode->last, sizeof(IROLinear)); + endnode->index = ++IRO_NumLinear; + endnode->next = NULL; + fnode->last = endnode; + labelnode->next = endnode; + IRO_LastLinear = endnode; + + IRO_EndNode->last->type = IROLinearGoto; + IRO_EndNode->last->u.label.label = label; + IRO_LastNode = fnode; + IRO_EndNode = fnode; + + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } +} + +void IRO_FindLoops(void) { + IRONode *fnode; + IRONode *pred; + UInt16 i; + UInt16 flag; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + flag = 0; + + for (i = 0; i < fnode->numpred; i++) { + pred = IRO_NodeTable[fnode->pred[i]]; + if (Bv_IsBitSet(fnode->index, pred->dom)) { + if (!flag) { + Bv_AllocVector(&InLoop, IRO_NumNodes + 1); + Bv_Clear(InLoop); + Bv_SetBit(fnode->index, InLoop); + } + flag = 1; + Bv_SetBit(pred->index, InLoop); + if (pred != fnode) + AddPreds(pred); + } + } + + if (flag) { + IncLoopDepth(); + IRO_Dump("IRO_FindLoops:Found loop with header %d\n", fnode->index); + IRO_DumpBits("Loop includes: ", InLoop); + MyHandleLoop_Motion(fnode); + IRO_UpdateFlagsOnInts(); + MyHandleLoop_Vector(fnode); + RemoveNoopsFromExprList(); + IRO_UpdateFlagsOnInts(); + IRO_UpdateVars(); + } + } + + if (!IRO_FunctionHasReturn && IRO_EndNode != IRO_LastNode) + InsertBranchAroundLoopPreheaders(); +} + +static void CheckSubableSub(IROLinear *linear, Boolean isFirst) { + if (isFirst && IRO_IsSubableExpression(linear)) { + IRO_Dump("Subable Expression is %d\n", linear->index); + NoSubableSubs = 0; + } +} + +static int NoSubableSubExprs(IROLinear *nd) { + NoSubableSubs = 1; + IRO_WalkTree(nd, CheckSubableSub); + return NoSubableSubs; +} + +void ComputeLoopKills(void) { + IRONode *fnode; + IROLinear *nd; + + Bv_AllocVector(&AllKills, IRO_NumVars + 1); + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { + Bv_AllocVector(&fnode->x16, IRO_NumVars + 1); + Bv_AllocVector(&fnode->x1E, IRO_NumVars + 1); + while (1) { + Bv_Clear(IRO_VarKills); + IRO_GetKills(nd); + Bv_Or(IRO_VarKills, AllKills); + if (nd == fnode->last) + break; + nd = nd->next; + } + } + } +} + +void ComputeLoopInvariance(void) { + IRONode *fnode; + IROLinear *nd; + + IRO_Depends = IRO_VarKills; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { + nd->flags &= ~IROLF_LoopInvariant; + while (1) { + if ((nd->flags & IROLF_Reffed) && nd->type != IROLinearNop) { + IRO_FindDepends_NoAlloc(nd); + if (!IRO_IsVolatile && !Bv_BitsInCommon(IRO_Depends, AllKills)) + nd->flags |= IROLF_LoopInvariant; + + if (IRO_CouldError) + nd->flags |= IROLF_CouldError; + else + nd->flags &= ~IROLF_CouldError; + } + + if (nd == fnode->last) + break; + nd = nd->next; + } + } + } +} + +void ComputeLoopInduction(void) { + IRONode *fnode; + IROLinear *nd; + Boolean flag; + Object *obj; + Object *obj2; + Object *obj3; + VarRecord *var; + IROLinear *tmpnd; + IROLoopInd *ind; + Boolean isUnsigned; + + Bv_AllocVector(&AllKills, IRO_NumVars + 1); + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { + while (1) { + Bv_Clear(IRO_VarKills); + IRO_GetKills(nd); + Bv_Or(IRO_VarKills, AllKills); + flag = 0; + if ( + ( + nd->type == IROLinearOp2Arg && + nd->rtype->size <= 4 && + (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) && + (obj = IRO_IsVariable(nd->u.diadic.left)) && + obj->type->size == nd->rtype->size && + IS_TYPE_INT(obj->type) && + ( + (IRO_IsIntConstant(nd->u.diadic.right) && CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval)) + || + (nd->u.diadic.right->flags & IROLF_LoopInvariant) + ) + ) + || + ( + nd->type == IROLinearOp1Arg && + nd->rtype->size <= 4 && + (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC || nd->nodetype == EPREINC || nd->nodetype == EPREDEC) && + (obj = IRO_IsVariable(nd->u.monadic)) && + obj->type->size == nd->rtype->size && + IS_TYPE_INT(obj->type) + ) + ) + { + flag = 1; + } + else if ( + nd->type == IROLinearOp2Arg && + nd->rtype->size <= 4 && + nd->nodetype == EASS && + (obj = IRO_IsVariable(nd->u.diadic.left)) && + obj->type->size == nd->rtype->size && + IS_TYPE_INT(obj->type) && + nd->u.diadic.right->type == IROLinearOp2Arg && + (nd->u.diadic.right->nodetype == EADD || nd->u.diadic.right->nodetype == ESUB) + ) + { + if (nd->u.diadic.right->nodetype == EADD) { + obj2 = IRO_IsVariable(nd->u.diadic.right->u.diadic.left); + obj3 = IRO_IsVariable(nd->u.diadic.right->u.diadic.right); + if (obj2 == obj && obj3 != obj && (nd->u.diadic.right->u.diadic.right->flags & IROLF_LoopInvariant)) + flag = 1; + + if (obj3 == obj && obj2 != obj && (nd->u.diadic.right->u.diadic.left->flags & IROLF_LoopInvariant)) { + flag = 1; + tmpnd = nd->u.diadic.right->u.diadic.left; + nd->u.diadic.right->u.diadic.left = nd->u.diadic.right->u.diadic.right; + nd->u.diadic.right->u.diadic.right = tmpnd; + } + } else { + obj2 = IRO_IsVariable(nd->u.diadic.right->u.diadic.left); + obj3 = IRO_IsVariable(nd->u.diadic.right->u.diadic.right); + if (obj2 == obj && obj3 != obj && (nd->u.diadic.right->u.diadic.right->flags & IROLF_LoopInvariant)) + flag = 1; + } + } + + if (flag) { + if ((var = IRO_FindAssigned(nd))) { + if (var->xA == 2) + var->xA = 0; + else if (var->xA == 1) + var->xA = 2; + } + } else { + for (var = IRO_FirstVar; var; var = var->next) { + if (Bv_IsBitSet(var->index, IRO_VarKills)) + var->xA = 0; + } + } + + if (nd == fnode->last) + break; + nd = nd->next; + } + } + } + + IRO_DumpBits("Killed in loop: ", AllKills); + + for (fnode = IRO_FirstNode, FirstInd = NULL; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { + while (1) { + if ( + ( + nd->type == IROLinearOp2Arg && + (nd->nodetype == EADDASS || nd->nodetype == ESUBASS || nd->nodetype == EASS) + ) + || + ( + nd->type == IROLinearOp1Arg && + (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC || nd->nodetype == EPREINC || nd->nodetype == EPREDEC) + ) + ) { + if ((var = IRO_FindAssigned(nd)) && var->xA == 2 && var->object->type->size <= 4) { + ind = oalloc(sizeof(IROLoopInd)); + ind->fnode = fnode; + ind->var = var; + ind->nd = nd; + ind->next = FirstInd; + ind->addNode = NULL; + ind->addConst = 0; + ind->flags = 0; + + if (nd->type == IROLinearOp2Arg) { + isUnsigned = IRO_IsUnsignedType(nd->rtype); + if (IRO_IsIntConstant(nd->u.diadic.right)) { + CInt64 val = nd->u.diadic.right->u.node->data.intval; + if (IS_LINEAR_DIADIC(nd, EADDASS) && CInt64_Less(val, cint64_zero)) { + nd->nodetype = ESUBASS; + nd->u.diadic.right->u.node->data.intval = CInt64_Neg(val); + } + if (isUnsigned) { + CInt64_ConvertUInt32(&nd->u.diadic.right->u.node->data.intval); + ind->addConst = CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval); + } else { + CInt64_ConvertInt32(&nd->u.diadic.right->u.node->data.intval); + ind->addConst = CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval); + } + ind->addNode = NULL; + } else if (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) { + ind->addNode = nd->u.diadic.right; + } else if (nd->nodetype == EASS) { + ind->addNode = nd->u.diadic.right->u.diadic.right; + } + } else { + if (IS_TYPE_POINTER_ONLY(nd->rtype)) + ind->addConst = TPTR_TARGET(nd->rtype)->size; + else + ind->addConst = 1; + ind->addNode = NULL; + } + + FirstInd = ind; + + if (IS_LINEAR_DIADIC_2(nd, EADDASS, ESUBASS)) { + if (nd->u.diadic.right->flags & IROLF_LoopInvariant) + IRO_Dump("Found induction variable the new way: %s\n", var->object->name->name); + else + IRO_Dump("Found induction variable the old way: %s\n", var->object->name->name); + } else if (nd->type == IROLinearOp2Arg && (nd->u.diadic.right->nodetype == EADD || nd->u.diadic.right->nodetype == ESUB)) { + IRO_Dump("Found induction variable the new way: %s\n", var->object->name->name); + } else { + IRO_Dump("Found induction variable the old way: %s\n", var->object->name->name); + } + } + } + + if (nd == fnode->last) + break; + nd = nd->next; + } + } + } +} + +static void IRO_ActUnmarkLoopInvariance(IROLinear *linear, Boolean isFirst) { + if (isFirst) + linear->flags &= ~IROLF_LoopInvariant; +} + +static void UnmarkSubexpressionsOfInvariantExpressions(void) { + IROExpr *expr; + + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if ( + Bv_IsBitSet(expr->node->index, InLoop) && + !expr->notSubable && + (!expr->couldError || expr->node->mustreach) && + (expr->linear->flags & IROLF_LoopInvariant) + ) { + IRO_WalkTree(expr->linear, IRO_ActUnmarkLoopInvariance); + expr->linear->flags |= IROLF_LoopInvariant; + } + } +} + +static void MyHandleLoop_Vector(IRONode *fnode) { + IRONode *pred; + UInt16 i; + IROExpr *expr; + IROExpr *removedExprs; + IROExpr *exprnext; + IROLoopInd *induction; + IROExpr *exprinner; + Boolean flag24; + IRONode *v2; + IRONode *node22; + int flag21; + IRONode *iter; + IROExpr *searchris; + IROLinear *reduceNd1; + VarRecord *var; + IROLinear *reduceNd2; + + IRO_FirstExpr = NULL; + LoopNode = fnode; + FindMustReach(); + + for (var = IRO_FirstVar; var; var = var->next) + var->xA = 1; + + ComputeLoopKills(); + ComputeLoopInvariance(); + ComputeLoopInduction(); + LoopNode = fnode; + ConditionalHeaderAtBottom = 0; + + v2 = NULL; + flag21 = 0; + node22 = NULL; + for (i = 0; i < LoopNode->numpred; i++) { + pred = IRO_NodeTable[LoopNode->pred[i]]; + if (!Bv_IsBitSet(pred->index, InLoop)) { + if (flag21) + node22 = NULL; + else + node22 = pred; + flag21 = 1; + if (pred->nextnode == fnode) { +#line 2880 + CError_ASSERT(v2 == NULL || pred == v2); + v2 = pred; + } + } + } + + if (!flag21) { + IRO_Dump("No predecessor outside the loop\n"); + return; + } + + if (!node22 || node22->last->type != IROLinearGoto) + node22 = CreatePreHeader(fnode, v2); + PredInt = node22->last; + + if (PredInt->type == IROLinearGoto && PredInt->u.label.label != LoopNode->first->u.label.label) { + if (!KnownBounds || !Times) { + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) + iter->mustreach = 0; + } else { + PredInt->u.label.label = LoopNode->first->u.label.label; + IRO_ComputeSuccPred(); + } + } + + if (copts.opt_loop_invariants || copts.opt_strength_reduction) { + MoveInvarianceInAddressExpr(); + IRO_DumpAfterPhase("MoveInvarianceInAddressExpr", 0); + IRO_FindExpressions(InLoop, 1); + IRO_DumpExprs(); + } + + if (copts.opt_loop_invariants) + UnmarkSubexpressionsOfInvariantExpressions(); + + if (!copts.optimize_for_size && copts.opt_strength_reduction) { + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if ( + !(expr->x0 & 4) && + Bv_IsBitSet(expr->node->index, InLoop) && + !expr->notSubable && + (!expr->couldError || expr->node->mustreach) && + Reducable(expr->linear, &reduceNd1, &reduceNd2, &var) + ) { + IRO_WalkTree(expr->linear, IRO_ActUnmarkRISCandidate); + expr->linear->flags |= IROLF_Ris; + expr->x1A = reduceNd1; + expr->x1E = var; + expr->x22 = reduceNd2; + } + } + } + + if (!copts.optimize_for_size && copts.opt_strength_reduction) { + RisList = NULL; + for (expr = IRO_FirstExpr; expr; expr = exprnext) { + exprnext = expr->next; + if (!(expr->x0 & 4) && (expr->linear->flags & IROLF_Ris)) { + reduceNd1 = expr->x1A; + var = expr->x1E; + reduceNd2 = expr->x22; + + induction = FirstInd; + while (induction && induction->var != var) + induction = induction->next; +#line 3529 + CError_ASSERT(induction != NULL); + + IRO_FindDepends(reduceNd1); + if (!Bv_BitsInCommon(IRO_Depends, AllKills)) { + IRO_Dump("Found reduction in strength: %d\n", expr->linear->index); + if (IS_LINEAR_DIADIC(expr->linear, ESHL)) { + expr->linear->nodetype = EMUL; + CInt64_SetULong(&reduceNd1->u.node->data.intval, 1 << CInt64_GetULong(&reduceNd1->u.node->data.intval)); + reduceNd1->u.node->rtype = expr->linear->rtype; + } + + searchris = RisList; + while (1) { + if (!searchris) + break; + if (IRO_ExprsSame(expr->linear, searchris->linear)) + break; + searchris = searchris->next; + } + + if (searchris) { + IRO_Dump("Using existing RIS: %d\n", searchris->linear->index); + IRO_WalkTree(expr->linear, IRO_RemoveExpr_Action); + } else { + searchris = CreateRIS(expr, reduceNd2, reduceNd1, induction, 0); + } + IRO_ReplaceReference(expr->linear, searchris->x8, expr->linear); + IRO_ClipExpr(expr); + } + } + } + } + + RisList = NULL; + + expr = IRO_FirstExpr; + removedExprs = NULL; + if (copts.opt_loop_invariants) { + while (expr) { + exprnext = expr->next; + flag24 = 0; + + if ( + Bv_IsBitSet(expr->node->index, InLoop) && + !expr->notSubable && + (!expr->couldError || expr->node->mustreach) && + (expr->linear->flags & IROLF_LoopInvariant) && + !(expr->x0 & 4) + ) { + IRO_Dump("Found loop invariant: %d\n", expr->linear->index); + + for (exprinner = removedExprs; exprinner; exprinner = exprinner->next) { + if (IRO_ExprsSame(exprinner->linear, expr->linear)) { + IRO_ReplaceReference(expr->linear, exprinner->x8, expr->linear); + IRO_NopOut(expr->linear); + IRO_Dump("Using already removed expr: %d\n", exprinner->linear->index); + IRO_RemoveExpr(expr); + flag24 = 1; + } + } + + if (!flag24 && !expr->x8) { + IRO_GetTemp(expr); + IRO_ReplaceReference(expr->linear, expr->x8, expr->linear); + IRO_MoveExpression(expr, PredInt); + IRO_AssignToTemp(expr); + IRO_RemoveExpr(expr); + expr->next = removedExprs; + removedExprs = expr; + } + } + + expr = exprnext; + } + } +} + +static void MyHandleLoop_Motion(IRONode *fnode) { + IROLoopMemRef *memref; + IRONode *pred; + UInt16 i; + IRONode *v2; + IRONode *node21; + Object *tempobj; + int flag20; + IRONode *iter; + IROLinear *ass; + VarRecord *var; + Boolean checkflag; + IROLoop *loop; + IROList list; + IROElmList *refiter; + + IRO_FirstExpr = NULL; + LoopNode = fnode; + FindMustReach(); + + for (var = IRO_FirstVar; var; var = var->next) + var->xA = 1; + + ComputeLoopKills(); + ComputeLoopInvariance(); + ComputeLoopInduction(); + LoopNode = fnode; + ConditionalHeaderAtBottom = 0; + + v2 = NULL; + flag20 = 0; + node21 = NULL; + for (i = 0; i < LoopNode->numpred; i++) { + pred = IRO_NodeTable[LoopNode->pred[i]]; + if (!Bv_IsBitSet(pred->index, InLoop)) { + if (flag20) + node21 = NULL; + else + node21 = pred; + flag20 = 1; + if (pred->nextnode == fnode) { +#line 3880 + CError_ASSERT(v2 == NULL || pred == v2); + v2 = pred; + } + } + } + + if (!flag20) { + IRO_Dump("No predecessor outside the loop\n"); + return; + } + + if (!node21 || node21->last->type != IROLinearGoto) + node21 = CreatePreHeader(fnode, v2); + PredInt = node21->last; + + if (PredInt->type == IROLinearGoto && PredInt->u.label.label != LoopNode->first->u.label.label) { + if (!KnownBounds || !Times) { + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) + iter->mustreach = 0; + } else { + PredInt->u.label.label = LoopNode->first->u.label.label; + IRO_ComputeSuccPred(); + } + } + + if (copts.opt_loop_invariants || copts.opt_strength_reduction) { + MoveInvarianceInAddressExpr(); + IRO_DumpAfterPhase("MoveInvarianceInAddressExpr", 0); + IRO_FindExpressions(InLoop, 0); + IRO_DumpExprs(); + } + + if (copts.opt_loop_invariants) + UnmarkSubexpressionsOfInvariantExpressions(); + + checkflag = 1; + Bv_AllocVector(&InLoop_Exits, IRO_NumNodes + 1); + Bv_AllocVector(&InLoop_Tails, IRO_NumNodes + 1); + LoopExitNumber = 0; + LoopExitSuccessor = NULL; + LoopTailNum = 0; + LoopTail = NULL; + IRO_FindLoopTailsAndExits(fnode); + FindMustReach1(fnode); + + loop = NULL; + if (LoopTailNum == 1) { + if (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot) + loop = ExtractLoopInfo(fnode); + else if (LoopTail->last->type == IROLinearIf || LoopTail->last->type == IROLinearIfNot) + loop = ExtractLoopInfo(LoopTail); + } + + if (loop && !(loop->flags & LP_IFEXPR_NON_CANONICAL) && LoopExitNumber == 1) { + IRO_LoopMemRefFirst = NULL; + IRO_LoopMemRefCurrent = NULL; + CheckAllLoopAddresses(IRO_FirstNode, InLoop, &checkflag); + CheckAllLoopAddresses(IRO_FirstNode, InLoop, &checkflag); + if (checkflag) { + for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) { + if (memref->flags & LoopMemRef_10) + memref->flags |= LoopMemRef_8; + } + + for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) { + IRO_Dump("Loop Motion Candidate:: Int= %d", memref->nd->index); + if (memref->flags & LoopMemRef_8) + IRO_Dump(""); + if (memref->flags & LoopMemRef_1) + IRO_Dump(""); + if (memref->flags & LoopMemRef_2) + IRO_Dump(""); + IRO_Dump("\n"); + + if (!(memref->flags & LoopMemRef_8)) { + tempobj = create_temp_object(memref->nd->rtype); + IRO_FindVar(tempobj, 1, 1); + if (IRO_FindVar(((IROLinear *) memref->rec->objRefs->element)->u.node->data.objref, 0, 1)) { + IRO_InitList(&list); + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->rtype = memref->nd->rtype; + ass->nodetype = EASS; + ass->u.diadic.left = IRO_TempReference(tempobj, &list); + ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.right = IRO_DuplicateExpr(memref->nd, &list); + IRO_AddToList(ass, &list); + IRO_Paste(list.head, list.tail, PredInt); + } else { +#line 4123 + CError_FATAL(); + } + + if (LoopExitSuccessor->numpred != 1) + LoopExitSuccessor = CreateNewLoopExitSuccessor(LoopExitSuccessor); + + IRO_InitList(&list); + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->rtype = memref->nd->rtype; + ass->nodetype = EASS; + ass->u.diadic.left = IRO_DuplicateExpr(memref->nd, &list); + ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.right = IRO_TempReference(tempobj, &list); + IRO_AddToList(ass, &list); + + if (LoopExitSuccessor->first->type == IROLinearLabel) + IRO_PasteAfter(list.head, list.tail, LoopExitSuccessor->first); + else + IRO_Paste(list.head, list.tail, LoopExitSuccessor->first); + + for (refiter = memref->list; refiter; refiter = refiter->next) { + IRO_Dump("Loop Motion Candidate Reference at Int= %d\n", ((IROLinear *) refiter->element)->index); + IRO_InitList(&list); + IRO_TempReference(tempobj, &list); + IRO_Paste(list.head, list.tail, refiter->element); + IRO_LocateFather_Cut_And_Paste(refiter->element, list.tail); + } + } + } + } + } + + IRO_DumpAfterPhase("After Motion", 0); +} + +static Boolean CheckLoopAddress(IROLinear *nd, Boolean mustreach1) { + IROLoopMemRef *memref; + IROAddrRecord *rec; + IROAddrRecord *otherrec; + IROLinear *inner; + IROElmList *list; + Boolean flag; + + inner = nd->u.monadic; + rec = IRO_InitAddrRecordPointer(inner); + if (IS_LINEAR_ENODE(inner, EOBJREF)) { + rec->numObjRefs++; + IRO_AddElmToList(inner, &rec->objRefs); + } else if (IS_LINEAR_DIADIC(inner, EADD)) { + IRO_DecomposeAddressExpression(inner, rec); + } else { + return 0; + } + + if (rec->numObjRefs != 1) + return 0; + + flag = (nd->flags & IROLF_CouldError) || !(nd->flags & IROLF_Reffed); + if (!IRO_LoopMemRefFirst) { + MakeLoopEntry(nd, rec, mustreach1, flag); + } else { + for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) { + otherrec = memref->rec; + if (((IROLinear *) rec->objRefs->element)->u.node->data.objref == ((IROLinear *) otherrec->objRefs->element)->u.node->data.objref) { + if (IRO_ExprsSame(inner, otherrec->linear)) { + list = oalloc(sizeof(IROElmList)); + list->element = nd; + list->next = NULL; + if (!memref->list) { + memref->list = list; + } else { + list->next = memref->list; + memref->list = list; + } + } else { + memref->flags |= LoopMemRef_8; + } + + if (!mustreach1 && flag) + memref->flags |= LoopMemRef_8; + if (mustreach1 || flag) + memref->flags &= ~LoopMemRef_10; + break; + } + } + + if (!memref) + MakeLoopEntry(nd, rec, mustreach1, flag); + } + + return 1; +} + +static void CheckAllLoopAddresses(IRONode *fnode, BitVector *bv, Boolean *resultFlag) { + IROLinear *nd; + Boolean flag; + + flag = *resultFlag; + while (fnode) { + if (Bv_IsBitSet(fnode->index, bv) && (nd = fnode->first)) { + while (flag) { + if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT) + flag = CheckLoopAddress(nd, fnode->mustreach1); + else if (nd->type == IROLinearFunccall) + flag = 0; + + if (nd == fnode->last) + break; + nd = nd->next; + } + + if (!flag) + break; + } + fnode = fnode->nextnode; + } + *resultFlag = flag; +} + +static void MakeLoopEntry(IROLinear *nd, IROAddrRecord *rec, Boolean mustreach1, Boolean flag2) { + IROElmList *list; + + if (!IRO_IsRegable(((IROLinear *) rec->objRefs->element)->u.node->data.objref) && + (nd->u.monadic->flags & IROLF_LoopInvariant) && + !IRO_HasSideEffect(nd)) { + if (!IRO_LoopMemRefFirst) { + IRO_LoopMemRefCurrent = IRO_LoopMemRefFirst = oalloc(sizeof(IROLoopMemRef)); + } else { + IRO_LoopMemRefCurrent->next = oalloc(sizeof(IROLoopMemRef)); + IRO_LoopMemRefCurrent = IRO_LoopMemRefCurrent->next; + } + IRO_LoopMemRefCurrent->flags = LoopMemRef_10; + IRO_LoopMemRefCurrent->nd = nd; + IRO_LoopMemRefCurrent->rec = rec; + IRO_LoopMemRefCurrent->next = NULL; + IRO_LoopMemRefCurrent->list = NULL; + + list = oalloc(sizeof(IROElmList)); + list->element = nd; + list->next = NULL; + if (!IRO_LoopMemRefCurrent->list) { + IRO_LoopMemRefCurrent->list = list; + } else { + list->next = IRO_LoopMemRefCurrent->list; + IRO_LoopMemRefCurrent->list = list; + } + + if (((IROLinear *) rec->objRefs->element)->flags & IROLF_Assigned) { + IRO_LoopMemRefCurrent->flags |= LoopMemRef_2; + if (((IROLinear *) rec->objRefs->element)->flags & IROLF_Used) + IRO_LoopMemRefCurrent->flags |= LoopMemRef_1; + } else { + IRO_LoopMemRefCurrent->flags |= LoopMemRef_1; + } + + if (!mustreach1 && flag2) + IRO_LoopMemRefCurrent->flags |= LoopMemRef_8; + + if (mustreach1 || flag2) + IRO_LoopMemRefCurrent->flags &= ~LoopMemRef_10; + } +} + +void FindAssignmenttoInductionVar(IROLoop *loop, IRONode *fnode) { + IROLinear *nd; + UInt32 index; + + if (!loop->induction) { + loop->nd14 = NULL; + } else { + index = loop->induction->var->index; + for (nd = fnode->first; nd; nd = nd->next) { + Bv_Clear(IRO_VarKills); + IRO_GetKills(nd); + if (Bv_IsBitSet(index, IRO_VarKills)) + loop->nd14 = nd; + + if (nd == fnode->last) + break; + } + + if (loop->nd14 && loop->nd14->type != IROLinearOp2Arg) + loop->nd14 = NULL; + } +} + +static void ComputeIntWeight(IROLoop *loop, IROLinear *Int) { + loop->sizeBySomeMeasurement++; +} + +static IROLinear *IsTypconVar(IROLinear *nd) { + if (IS_LINEAR_MONADIC(nd, ETYPCON) && IRO_IsVariable(nd->u.monadic)) + return nd->u.monadic; + else + return NULL; +} + +IROLoop *ExtractLoopInfo(IRONode *fnode) { + Boolean flag30; + Boolean flag29; + Boolean flag28; + UInt32 counter27; + IROLoopInd *ind23; + Object *obj; + IROLinear *nd21; + IRONode *scanfnode; + IROLinear *left19; + IROLinear *right18; + IROLinear *tmp18; + IROLinear *scannd; + IROLinear *tmp; + VarRecord *var; + IROLoopInd *scanind; + IROLinear *left; + IROLinear *right; + UInt32 counter2; + UInt32 i; + IROLoop *loop; + + flag30 = 0; + flag29 = 0; + flag28 = 0; + counter27 = 0; + LoopNode = fnode; + + loop = oalloc(sizeof(IROLoop)); + loop->fnode = fnode; + nd21 = LoopNode->last->u.label.x4; + loop->nd18 = nd21; + loop->flags = 0; + loop->x8 = 0; + loop->nd14 = NULL; + loop->induction = NULL; + loop->index20 = -1; + loop->index24 = -1; + loop->sizeBySomeMeasurement = 0; + + if (nd21->type == IROLinearOp2Arg && IS_TYPE_INT(nd21->rtype)) { + ind23 = NULL; + left19 = nd21->u.diadic.left; + right18 = nd21->u.diadic.right; + if (IRO_IsVariable(left19) || (left19 = IsTypconVar(left19))) { + if ((var = IRO_FindVar(left19->u.monadic->u.node->data.objref, 0, 1))) { + scanind = FirstInd; + while (scanind && scanind->var != var) + scanind = scanind->next; + if (scanind) { + ind23 = scanind; + loop->flags |= LoopFlags_1; + loop->induction = scanind; + } + } + } + + if (IRO_IsVariable(right18) || (right18 = IsTypconVar(right18))) { + if ((var = IRO_FindVar(right18->u.monadic->u.node->data.objref, 0, 1))) { + scanind = FirstInd; + while (scanind && scanind->var != var) + scanind = scanind->next; + if (scanind) { + ind23 = scanind; + loop->flags &= ~LoopFlags_1; + loop->induction = scanind; + } + } + } + + if (ind23 && ind23->addConst > 0) { + if (loop->flags & LoopFlags_1) { + if ( + loop->nd18->type != IROLinearOp2Arg || + !(loop->nd18->nodetype == ELESS || loop->nd18->nodetype == EGREATER || loop->nd18->nodetype == ELESSEQU || loop->nd18->nodetype == EGREATEREQU) || + !loop->nd18->u.diadic.left || + !loop->nd18->u.diadic.left->rtype || + !IS_TYPE_INT(loop->nd18->u.diadic.left->rtype) || + !loop->nd18->u.diadic.right || + !loop->nd18->u.diadic.right->rtype || + !IS_TYPE_INT(loop->nd18->u.diadic.right->rtype) + ) { + loop->flags |= LP_IFEXPR_NON_CANONICAL; + return loop; + } + } else { + if ( + loop->nd18->type == IROLinearOp2Arg && + (loop->nd18->nodetype == EGREATER || loop->nd18->nodetype == EGREATEREQU) && + (left = loop->nd18->u.diadic.left) && + left->rtype && + IS_TYPE_INT(left->rtype) && + (right = loop->nd18->u.diadic.right) && + right->rtype && + IS_TYPE_INT(right->rtype) + ) { + loop->nd18->u.diadic.left = right; + loop->nd18->u.diadic.right = left; + if (loop->nd18->nodetype == EGREATER) + loop->nd18->nodetype = ELESS; + else if (loop->nd18->nodetype == EGREATEREQU) + loop->nd18->nodetype = ELESSEQU; + loop->flags |= LoopFlags_1; + } else if ( + loop->nd18->type == IROLinearOp2Arg && + (loop->nd18->nodetype == ELESS || loop->nd18->nodetype == ELESSEQU) && + (left = loop->nd18->u.diadic.left) && + left->rtype && + IS_TYPE_INT(left->rtype) && + (right = loop->nd18->u.diadic.right) && + right->rtype && + IS_TYPE_INT(right->rtype) + ) { + loop->nd18->u.diadic.left = right; + loop->nd18->u.diadic.right = left; + if (loop->nd18->nodetype == ELESS) + loop->nd18->nodetype = EGREATER; + else if (loop->nd18->nodetype == ELESSEQU) + loop->nd18->nodetype = EGREATEREQU; + loop->flags |= LoopFlags_1; + } else { + loop->flags |= LP_IFEXPR_NON_CANONICAL; + return loop; + } + } + } else { + loop->flags |= LP_INDUCTION_NOT_FOUND; + return loop; + } + } else if (nd21->type == IROLinearOp1Arg && IS_TYPE_INT(nd21->rtype)) { + if (nd21->nodetype == EPREINC || nd21->nodetype == EPOSTINC || nd21->nodetype == EPREDEC || nd21->nodetype == EPOSTDEC) { + if (IRO_IsVariable(nd21->u.monadic)) { + if ((var = IRO_FindVar(nd21->u.monadic->u.monadic->u.node->data.objref, 0, 1))) { + scanind = FirstInd; + while (scanind && scanind->var != var) + scanind = scanind->next; + if (scanind) { + ind23 = scanind; + loop->flags |= LoopFlags_10000; + loop->induction = scanind; + } else { + loop->flags |= LP_INDUCTION_NOT_FOUND; + return loop; + } + } else { + loop->flags |= LP_INDUCTION_NOT_FOUND; + return loop; + } + } else { + loop->flags |= LP_INDUCTION_NOT_FOUND; + return loop; + } + } else { + loop->flags |= LP_INDUCTION_NOT_FOUND; + return loop; + } + } else { + loop->flags |= LP_IFEXPR_NON_CANONICAL; + return loop; + } + + counter2 = 0; + scanind = FirstInd; + while (scanind) { + scanind = scanind->next; + counter2++; + } + + if (counter2 > 1) + loop->flags |= LP_HAS_MULTIPLE_INDUCTIONS; + + if ((scanind = loop->induction)) { + nd21 = scanind->nd; + if (nd21->type == IROLinearOp2Arg) { + if (IS_LINEAR_DIADIC_2(loop->nd18, ELESS, ELESSEQU)) { + if (nd21->nodetype == EADDASS) { + if (scanind->addConst == 1) + loop->flags |= LoopFlags_100; + if (scanind->addConst > 0) + loop->flags |= LP_LOOP_STEP_ISPOS; + } else if (nd21->nodetype == EASS && + IS_LINEAR_DIADIC(nd21->u.diadic.right, EADD) && + IRO_IsIntConstant(tmp18 = nd21->u.diadic.right->u.diadic.right) && + CTool_EndianReadWord32(&tmp18->u.node->data.intval.hi) == 0) { + if (CInt64_GetULong(&tmp18->u.node->data.intval) == 1) + loop->flags |= LoopFlags_100; + if (CInt64_GetULong(&tmp18->u.node->data.intval) > 0) + loop->flags |= LP_LOOP_STEP_ISPOS; + } + } + } else if (nd21->type == IROLinearOp1Arg) { + if (nd21->nodetype == EPREINC || nd21->nodetype == EPOSTINC) { + if (scanind->addConst == 1) + loop->flags |= LoopFlags_100; + if (scanind->addConst > 0) + loop->flags |= LP_LOOP_STEP_ISPOS; + } + if (nd21->nodetype == EPREDEC || nd21->nodetype == EPOSTDEC) { + if (scanind->addConst == 1) + loop->flags |= LoopFlags_2000; + if (scanind->addConst > 0) + loop->flags |= LP_LOOP_STEP_ISNEG; + } + } + loop->index24 = nd21->index; + loop->index20 = IRO_FindStart(nd21)->index; + } + + if (ind23) { + tmp = IRO_FindStart(fnode->last->u.diadic.right); + loop->flags |= LoopFlags_200; + if (loop->flags & LoopFlags_10000) { + for (scannd = loop->fnode->first; scannd && scannd != tmp; scannd = scannd->next) { + if (scannd->type != IROLinearLabel && scannd->type != IROLinearNop) + loop->flags &= ~LoopFlags_200; + } + } else { + for (scannd = ind23->nd->next; scannd && scannd != tmp; scannd = scannd->next){ + if (scannd->type != IROLinearLabel && scannd->type != IROLinearNop) + loop->flags &= ~LoopFlags_200; + } + for (scannd = loop->fnode->first; scannd && scannd != tmp; scannd = scannd->next){ + if ((scannd->index < loop->index20 || scannd->index > loop->index24) && scannd->type != IROLinearLabel && scannd->type != IROLinearNop) + loop->flags &= ~LoopFlags_200; + } + } + } + + for (scanfnode = IRO_FirstNode; scanfnode; scanfnode = scanfnode->nextnode) { + if (Bv_IsBitSet(scanfnode->index, InLoop) && scanfnode != fnode && (scannd = scanfnode->first)) { + while (1) { + if (scannd->type == IROLinearFunccall) + flag30 = 1; + if (scannd->type == IROLinearGoto) + flag28++; + if (flag28 >= 1) + flag29 = 1; + if (scannd->type == IROLinearIf || scannd->type == IROLinearIfNot || scannd->type == IROLinearSwitch || scannd->type == IROLinearReturn) + flag29 = 1; + + if (scannd->type == IROLinearAsm) + loop->flags |= LP_LOOP_HAS_ASM; + + if (!(scannd->flags & IROLF_Reffed) && scannd->type != IROLinearNop && scannd->type != IROLinearLabel) { + if (!IRO_IsAssignOp[scannd->nodetype]) { + loop->flags |= LoopFlags_8; + } else if (scannd->index < loop->index20 || scannd->index > loop->index24) { + counter27++; + if (IsAssignmentReductionCandidate(scannd) && counter27 == 1) + loop->flags |= LoopFlags_40000; + if (counter27 > 1) + loop->flags &= ~LoopFlags_40000; + } + } + + if (scannd->index < loop->index20 || scannd->index > loop->index24) { + if (IS_LINEAR_ENODE(scannd, EOBJREF)) { + obj = scannd->u.node->data.objref; + if ((scannd->flags & IROLF_Ind) && obj && obj == loop->induction->var->object) { + if (!(scannd->flags & IROLF_Assigned) && (scannd->flags & IROLF_Used)) { + IRO_Dump("Induction Used in loop\n"); + loop->flags |= LoopFlags_800; + } + } + } + + if (IS_LINEAR_DIADIC(scannd, ESHR) && + (obj = IRO_IsVariable(scannd->u.diadic.left)) && + IRO_IsConstant(scannd->u.diadic.right)) { + for (scanind = FirstInd; scanind; scanind = scanind->next) { + if (scanind->var->object == obj) { + IRO_Dump("Induction has DIV: %s\n", obj->name->name); + scanind->flags |= LoopInd_2; + } + } + } + + if (IS_LINEAR_DIADIC(scannd, EAND) && + (obj = IRO_IsVariable(scannd->u.diadic.left)) && + IRO_IsConstant(scannd->u.diadic.right)) { + for (scanind = FirstInd; scanind && obj; scanind = scanind->next) { + if (scanind->var->object == obj) { + IRO_Dump("Induction has MOD: %s\n", obj->name->name); + scanind->flags |= LoopInd_1; + } + } + } + } + + ComputeIntWeight(loop, scannd); + if (scannd == scanfnode->last) + break; + scannd = scannd->next; + } + } + + if (flag30) + loop->flags |= LP_LOOP_HAS_CALLS; + if (flag29) + loop->flags |= LP_LOOP_HAS_CNTRLFLOW; + + for (i = 0; i < scanfnode->numsucc && scanfnode != fnode; i++) { + if (Bv_IsBitSet(scanfnode->index, InLoop) && !Bv_IsBitSet(scanfnode->succ[i], InLoop)) { + IRO_Dump("Node %d has an out of loop successor %d\n", scanfnode->index, scanfnode->succ[i]); + IRO_DumpBits("Loop includes: ", InLoop); + IRO_Dump("loop has multiple exits\n"); + loop->flags |= LoopFlags_1000; + } + } + } + + return loop; +} + +CLabel *BuildLabel(IROList *list) { + IROLinear *nd; + + nd = IRO_NewLinear(IROLinearLabel); + nd->index = IRO_NumLinear++; + nd->u.label.label = IRO_NewLabel(); + nd->flags |= IROLF_1; + IRO_AddToList(nd, list); + return nd->u.label.label; +} + +static void MoveInvarianceInAddressExpr(void) { + IRONode *fnode; + IROLinear *nd; + IROLinear *start; + IROList list; + + IRO_FirstExpr = IRO_LastExpr = NULL; + IRO_NumExprs = 0; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop)) { + for (nd = fnode->first; nd; nd = nd->next) { + if (nd->type == IROLinearOp1Arg && + (nd->nodetype == EINDIRECT || nd->nodetype == EINDIRECT) && + IS_LINEAR_DIADIC(nd->u.monadic, EADD)) { + RearrangeInvarianceInAddressExpr(nd->u.monadic, &list); + start = IRO_FindStart(nd->u.monadic); + IRO_LocateFather_Cut_And_Paste(nd->u.monadic, list.tail); + IRO_Paste(list.head, list.tail, start); + } + + if (nd == fnode->last) + break; + } + } + } + + IRO_UpdateFlagsOnInts(); +} + +static void AddAddendLinear(IROLinear *nd) { + IROElmList *list; + + if (IS_LINEAR_DIADIC(nd, EADD)) { + AddAddendLinear(nd->u.diadic.left); + AddAddendLinear(nd->u.diadic.right); + } else { + list = oalloc(sizeof(IROElmList)); + list->element = nd; + list->next = NULL; + if (FirstAddendLinear) + LastAddendLinear->next = list; + else + FirstAddendLinear = list; + LastAddendLinear = list; + } +} + +static IROLinear *RearrangeInvarianceInAddressExpr(IROLinear *nd, IROList *list) { + IROLinear *result; + IROElmList *scanlist; + IROElmList *elist; + IROLinear *scannd; + + IRO_InitList(list); + FirstAddendLinear = LastAddendLinear = NULL; + AddAddendLinear(nd->u.diadic.left); + AddAddendLinear(nd->u.diadic.right); + + elist = NULL; + result = NULL; + for (scanlist = FirstAddendLinear; scanlist; scanlist = scanlist->next) { + scannd = scanlist->element; + if (!IRO_IsIntConstant(scannd) && (scannd->flags & IROLF_LoopInvariant)) { + if (result) { + IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg); + tmp->index = ++IRO_NumLinear; + tmp->nodetype = EADD; + tmp->u.diadic.left = result; + tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list); + IRO_AddToList(tmp, list); + tmp->flags |= IROLF_LoopInvariant; + tmp->flags |= IROLF_Reffed; + tmp->rtype = result->rtype; + result = tmp; + } else { + result = IRO_DuplicateExpr(scannd, list); + } + + if (elist) + elist->next = scanlist->next; + else + FirstAddendLinear = scanlist->next; + } else { + elist = scanlist; + } + } + + for (scanlist = FirstAddendLinear, elist = NULL; scanlist; scanlist = scanlist->next) { + scannd = scanlist->element; + if (!IRO_IsIntConstant(scannd)) { + if (result) { + IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg); + tmp->index = ++IRO_NumLinear; + tmp->nodetype = EADD; + tmp->u.diadic.left = result; + tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list); + IRO_AddToList(tmp, list); + tmp->flags |= IROLF_Reffed; + tmp->rtype = result->rtype; + result = tmp; + } else { + result = IRO_DuplicateExpr(scannd, list); + } + + if (elist) + elist->next = scanlist->next; + else + FirstAddendLinear = scanlist->next; + } else { + elist = scanlist; + } + } + + for (scanlist = FirstAddendLinear; scanlist; scanlist = scanlist->next) { + scannd = scanlist->element; + if (result) { + IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg); + tmp->index = ++IRO_NumLinear; + tmp->nodetype = EADD; + tmp->u.diadic.left = result; + tmp->u.diadic.right = scannd; + tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list); + IRO_AddToList(tmp, list); + tmp->flags |= IROLF_Reffed; + tmp->rtype = result->rtype; + result = tmp; + } else { + result = IRO_DuplicateExpr(scannd, list); + } + } + + return result; +} + +static IROLinear *FindAddendForReductionPattern(IROLinear *a, IROLinear *b, Boolean *resultFlag) { + IROLinear *left; + IROLinear *right; + IROLinear *node28; + Boolean subflag; + + left = b->u.diadic.left; + right = b->u.diadic.right; + if (b->nodetype == EADD || b->nodetype == ESUB) { + node28 = left; + while (IS_LINEAR_MONADIC(node28, ETYPCON)) + node28 = node28->u.monadic; + + if (IS_LINEAR_MONADIC(node28, EINDIRECT) && (node28->u.monadic->flags & IROLF_LoopInvariant) && IRO_ExprsSame(a, node28)) { + *resultFlag = 1; + return left; + } + + if (IS_LINEAR_DIADIC_2(node28, EADD, ESUB)) { + if ((node28 = FindAddendForReductionPattern(a, node28, &subflag))) { + *resultFlag = 1; + return node28; + } + } + } + + *resultFlag = 0; + if (b->nodetype == EADD) { + node28 = right; + while (IS_LINEAR_MONADIC(node28, ETYPCON)) + node28 = node28->u.monadic; + + if (IS_LINEAR_MONADIC(node28, EINDIRECT) && (node28->u.monadic->flags & IROLF_LoopInvariant) && IRO_ExprsSame(a, node28)) { + return right; + } + + if (IS_LINEAR_DIADIC_2(node28, EADD, ESUB)) { + if ((node28 = FindAddendForReductionPattern(a, node28, &subflag))) { + return node28; + } + } + } + + return NULL; +} + +static void ReorderOperandsForReductionPattern(IROLinear *a, IROLinear *b) { + IROLinear *left; + IROLinear *right; + IROLinear *addend; + IROLinear *tmp; + Boolean flag; + + left = b->u.diadic.left; + right = b->u.diadic.right; + + if (b->nodetype == EADD && (addend = FindAddendForReductionPattern(a, b, &flag)) && addend != left) { + if (flag && IS_LINEAR_DIADIC_2(left, EADD, ESUB) && addend->rtype == right->rtype) { + tmp = left; + b->u.diadic.left = right; + left = right; + b->u.diadic.right = tmp; + right = tmp; + flag = 0; + } + + if (!flag && IS_LINEAR_DIADIC_2(right, EADD, ESUB) && addend->rtype == left->rtype) { + if (IRO_LocateFather_Cut_And_Paste_Without_Nopping(addend, left)) + b->u.diadic.left = addend; + } + } +} + +static UInt32 IsAssignmentReductionCandidate(IROLinear *nd) { + IROLinear *left; + IROLinear *right; + IROLinear *tmp; + + if (nd->type == IROLinearOp2Arg) { + if (nd->nodetype == EASS) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + if (IS_LINEAR_MONADIC(left, EINDIRECT) && (left->u.monadic->flags & IROLF_LoopInvariant)) { + if (IS_LINEAR_MONADIC(right, ETYPCON) && + right->rtype->type == right->u.monadic->rtype->type && + IS_TYPE_INT(right->rtype) && + right->rtype->size < right->u.monadic->rtype->size) + right = right->u.monadic; + + if (IS_LINEAR_DIADIC_2(right, EADD, ESUB)) { + ReorderOperandsForReductionPattern(left, right); + tmp = right->u.diadic.left; + if (IS_LINEAR_MONADIC(tmp, ETYPCON)) + tmp = tmp->u.monadic; + if (IS_LINEAR_MONADIC(tmp, EINDIRECT) && + (tmp->u.monadic->flags & IROLF_LoopInvariant) && + IRO_ExprsSame(left, tmp) && + right->u.diadic.right->type == IROLinearOp2Arg) { + if (right->u.diadic.right->nodetype == EADD) + return 1; + if (right->u.diadic.right->nodetype == ESUB) + return 1; + if (right->u.diadic.right->nodetype == EMUL) + return 1; + if (right->u.diadic.right->nodetype == EDIV) + return 1; + } + } + } + } else if (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + + if (IS_LINEAR_MONADIC(right, ETYPCON) && + right->rtype->type == right->u.monadic->rtype->type && + IS_TYPE_INT(right->rtype) && + right->rtype->size < right->u.monadic->rtype->size) + right = right->u.monadic; + + if (IS_LINEAR_MONADIC(left, EINDIRECT) && + (left->u.monadic->flags & IROLF_LoopInvariant) && + right->type == IROLinearOp2Arg) { + if (right->nodetype == EADD) + return 1; + if (right->nodetype == ESUB) + return 1; + if (right->nodetype == EMUL) + return 1; + if (right->nodetype == EDIV) + return 1; + } + } + } + + return 0; +} + diff --git a/compiler_and_linker/unsorted/IroMalloc.c b/compiler_and_linker/unsorted/IroMalloc.c index e69de29..8928ba9 100644 --- a/compiler_and_linker/unsorted/IroMalloc.c +++ b/compiler_and_linker/unsorted/IroMalloc.c @@ -0,0 +1,564 @@ +#include "compiler/IroMalloc.h" +#include "compiler/CompilerTools.h" + +#define FLAGMASK 0xF + +typedef struct Block { + struct Block *prev; + struct Block *next; + void *x8; + void *xC; + size_t remain; + size_t x14; +} Block; + +typedef struct SubBlockBase { + size_t x0; + Block *block; +} SubBlockBase; + +typedef struct SubBlock { + size_t x0; + Block *block; + struct SubBlock *x8; + struct SubBlock *xC; +} SubBlock; + +typedef struct SubBlockTail { + size_t x0copy; +} SubBlockTail; + +typedef struct BlockTail { + size_t x14copy; + SubBlock *unk; +} BlockTail; + +typedef struct FixStart { + struct FixBlock *a; + struct FixSubBlock *b; + long count; +} FixStart; + +typedef struct FixBlock { + struct FixBlock *prev; + struct FixBlock *next; + size_t entrysize; +} FixBlock; + +typedef struct FixSubBlockBase { + FixBlock *fixblock; +} FixSubBlockBase; + +typedef struct FixSubBlock { + FixBlock *fixblock; + struct FixSubBlock *next; +} FixSubBlock; + +static const size_t fix_pool_sizes[] = {0xC, 0x1C, 0x2C, 0x4C}; +static Block *start_; +static FixStart fix_start[4]; +static int initialized; + +// forward decls +static void Block_link(Block *block, SubBlock *subblock); +static void Block_unlink(Block *block, SubBlock *subblock); +static void SubBlock_construct(SubBlock *subblock, size_t size, Block *block, int flag1, int flag2); +static SubBlock *SubBlock_split(SubBlock *subblock, size_t pos); +static SubBlock *SubBlock_merge_prev(SubBlock *subblock, SubBlock **sbptr); +static void SubBlock_merge_next(SubBlock *subblock, SubBlock **sbptr); + +#define BLOCK_TAIL(block) ((BlockTail *) ((long) (block) + ((block)->x14 & ~FLAGMASK) - sizeof(BlockTail))) + +#define BUF_LOCATOR(buf) (*((size_t *) ((long) (buf) - sizeof(size_t)))) +#define SBB_BLOCK(sbb) ((Block *) ((long) ((sbb)->block) & ~1)) + +#define BUF_IS_VAR(buf) (BUF_LOCATOR(buf) & 1) +#define VARBUF_SBB(buf) ((SubBlockBase *) ((long) (buf) - sizeof(SubBlockBase))) +#define VARBUF_SB(buf) ((SubBlock *) ((long) (buf) - sizeof(SubBlockBase))) +#define VARBUF_BLOCKSIZE(buf) (VARBUF_SBB(buf)->x0 & ~FLAGMASK) +#define VARBUF_SIZE(buf) (((VARBUF_SBB(buf)->x0 & ~FLAGMASK) - sizeof(SubBlockBase))) +#define VARBUF_BLOCK(buf) SBB_BLOCK(VARBUF_SBB(buf)) +#define FIXBUF_SIZE(buf) (((FixBlock *) BUF_LOCATOR(buf))->entrysize) + +#define BUF_SIZE(buf) BUF_IS_VAR(buf) ? VARBUF_SIZE(buf) : FIXBUF_SIZE(buf) + +static void Block_construct(Block *block, size_t size) { + SubBlock *subblock; + + block->x14 = size | 3; + ((BlockTail *) ((long) block + size - sizeof(BlockTail)))->x14copy = block->x14; + + subblock = (SubBlock *) (block + 1); + SubBlock_construct(subblock, size - sizeof(Block) - sizeof(BlockTail), block, 0, 0); + + block->remain = size - sizeof(Block) - sizeof(BlockTail); + BLOCK_TAIL(block)->unk = NULL; + + Block_link(block, subblock); +} + +static SubBlock *Block_subBlock(Block *block, size_t size) { + SubBlock *subblock; + size_t check; + size_t best; + + if (!BLOCK_TAIL(block)->unk) + return NULL; + + subblock = BLOCK_TAIL(block)->unk; + best = subblock->x0 & ~FLAGMASK; + check = subblock->x0 & ~FLAGMASK; + while (check < size) { + subblock = subblock->xC; + check = subblock->x0 & ~FLAGMASK; + if (best < check) + best = check; + if (subblock == BLOCK_TAIL(block)->unk) { + block->remain = best; + return NULL; + } + } + + if ((check - size) >= 0x60) + SubBlock_split(subblock, size); + + BLOCK_TAIL(block)->unk = subblock->xC; + Block_unlink(block, subblock); + return subblock; +} + +static void Block_link(Block *block, SubBlock *subblock) { + size_t size; + SubBlock **sbptr; + + size = subblock->x0 & ~FLAGMASK; + subblock->x0 &= ~2; + ((SubBlock *) ((long) subblock + size))->x0 &= ~4; + ((SubBlockTail *) ((long) subblock + size - sizeof(SubBlockTail)))->x0copy = size; + + sbptr = &BLOCK_TAIL(block)->unk; + if (*sbptr) { + subblock->x8 = (*sbptr)->x8; + subblock->x8->xC = subblock; + subblock->xC = *sbptr; + (*sbptr)->x8 = subblock; + *sbptr = subblock; + *sbptr = SubBlock_merge_prev(*sbptr, sbptr); + SubBlock_merge_next(*sbptr, sbptr); + } else { + *sbptr = subblock; + subblock->x8 = subblock; + subblock->xC = subblock; + } + + if (block->remain < ((*sbptr)->x0 & ~FLAGMASK)) + block->remain = (*sbptr)->x0 & ~FLAGMASK; +} + +static void Block_unlink(Block *block, SubBlock *subblock) { + size_t size; + SubBlock **sbptr; + + size = subblock->x0 & ~FLAGMASK; + subblock->x0 |= 2; + ((SubBlock *) ((long) subblock + size))->x0 |= 4; + + sbptr = &BLOCK_TAIL(block)->unk; + if (*sbptr == subblock) + *sbptr = subblock->xC; + + if (*sbptr == subblock) { + *sbptr = NULL; + block->remain = 0; + } else { + subblock->xC->x8 = subblock->x8; + subblock->x8->xC = subblock->xC; + } +} + +static void SubBlock_construct(SubBlock *subblock, size_t size, Block *block, int flag1, int flag2) { + subblock->block = (Block *) ((long) block | 1); + subblock->x0 = size; + if (flag1) + subblock->x0 |= 4; + if (flag2) { + subblock->x0 |= 2; + ((SubBlock *) (((long) subblock) + size))->x0 |= 4; + } else { + ((SubBlockTail *) (((long) subblock) + size - sizeof(SubBlockTail)))->x0copy = size; + } +} + +static SubBlock *SubBlock_split(SubBlock *subblock, size_t pos) { + size_t oldsize; + int flag; + SubBlock *splitright; + Block *block; + + oldsize = subblock->x0 & ~FLAGMASK; + flag = !(subblock->x0 & 2); + splitright = (SubBlock *) ((long) subblock + pos); + block = (Block *) ((long) subblock->block & ~1); + SubBlock_construct(subblock, pos, block, subblock->x0 & 4, !flag); + SubBlock_construct(splitright, oldsize - pos, block, !flag, !flag); + if (flag) { + splitright->xC = subblock->xC; + splitright->xC->x8 = splitright; + splitright->x8 = subblock; + subblock->xC = splitright; + } + + return splitright; +} + +static SubBlock *SubBlock_merge_prev(SubBlock *subblock, SubBlock **sbptr) { + size_t prevsize; + SubBlock *prevblock; + + if (!(subblock->x0 & 4)) { + prevsize = ((SubBlockTail *) ((long) subblock - sizeof(SubBlockTail)))->x0copy; + if (prevsize & 2) + return subblock; + + prevblock = (SubBlock *) ((long) subblock - prevsize); + prevblock->x0 = prevblock->x0 & FLAGMASK; + prevblock->x0 |= (prevsize + (subblock->x0 & ~FLAGMASK)) & ~FLAGMASK; + if (!(prevblock->x0 & 2)) + ((SubBlockTail *) ((long) prevblock + prevsize + (subblock->x0 & ~FLAGMASK) - sizeof(SubBlockTail)))->x0copy = prevsize + (subblock->x0 & ~FLAGMASK); + + if (*sbptr == subblock) + *sbptr = (*sbptr)->xC; + + subblock->xC->x8 = subblock->x8; + subblock->xC->x8->xC = subblock->xC; + return prevblock; + } + + return subblock; +} + +static void SubBlock_merge_next(SubBlock *subblock, SubBlock **sbptr) { + SubBlock *nextblock; + size_t nextsize; + + nextblock = (SubBlock *) ((long) subblock + (subblock->x0 & ~FLAGMASK)); + if (!(nextblock->x0 & 2)) { + nextsize = (subblock->x0 & ~FLAGMASK) + (nextblock->x0 & ~FLAGMASK); + subblock->x0 = subblock->x0 & FLAGMASK; + subblock->x0 |= nextsize & ~FLAGMASK; + + if (!(subblock->x0 & 2)) + ((SubBlockTail *) ((long) subblock + nextsize - sizeof(SubBlockTail)))->x0copy = nextsize; + + if (!(subblock->x0 & 2)) + ((SubBlock *) ((long) subblock + nextsize))->x0 &= ~4; + else + ((SubBlock *) ((long) subblock + nextsize))->x0 |= 4; + + if (*sbptr == nextblock) + *sbptr = (*sbptr)->xC; + if (*sbptr == nextblock) + *sbptr = NULL; + + nextblock->xC->x8 = nextblock->x8; + nextblock->x8->xC = nextblock->xC; + } +} + +static void link_block(Block *block) { + if (start_) { + block->prev = start_->prev; + block->prev->next = block; + block->next = start_; + + start_->prev = block; + start_ = block; + } else { + start_ = block; + block->prev = block; + block->next = block; + } +} + +static Block *unlink_block(Block *block) { + Block *newblock; + + newblock = block->next; + if (newblock == block) + newblock = NULL; + + if (start_ == block) + start_ = newblock; + + if (newblock) { + newblock->prev = block->prev; + newblock->prev->next = newblock; + } + + block->prev = block->next = NULL; + return newblock; +} + +static Block *link_new_block(size_t size) { + Block *block; + + size = (size + 0x1000 + sizeof(Block) + sizeof(BlockTail) - 1) & ~0xFFF; + if (size < 0x10000) + size = 0x10000; + + if (!(block = galloc(size))) + return NULL; + + Block_construct(block, size); + link_block(block); + return block; +} + +static void *allocate_from_var_pools(size_t size) { + Block *block; + SubBlock *subblock; + + size = (size + sizeof(Block) - 1) & ~0xF; + if (size < 0x60) + size = 0x60; + + block = start_ ? start_ : link_new_block(size); + if (!block) + return NULL; + + do { + if (size <= block->remain) { + if ((subblock = Block_subBlock(block, size))) { + start_ = block; + goto allocated; + } + } + } while ((block = block->next) != start_); + + block = link_new_block(size); + if (!block) + return NULL; + subblock = Block_subBlock(block, size); +allocated: + return (SubBlockBase *) subblock + 1; +} + +static void deallocate_from_var_pools(void *buf) { + Block *block; + SubBlock *subblock; + int flag; + + subblock = (SubBlock *) ((long) buf - sizeof(SubBlockBase)); + block = (Block *) ((long) subblock->block & ~1); + Block_link(block, subblock); + + flag = 0; + subblock = (SubBlock *) (block + 1); + if (!(subblock->x0 & 2)) { + if ((subblock->x0 & ~FLAGMASK) == ((block->x14 & ~FLAGMASK) - sizeof(Block) - sizeof(BlockTail))) + flag = 1; + } + + if (flag) + unlink_block(block); +} + +static void FixBlock_construct(FixBlock *fixblock, FixBlock *prev, FixBlock *next, int poolIndex, void *buffer, size_t buffersize) { + size_t entrysize; + size_t entrycount; + size_t i; + FixSubBlock *fsb; + FixSubBlock *fsbnext; + + fixblock->prev = prev; + fixblock->next = next; + fixblock->entrysize = fix_pool_sizes[poolIndex]; + + entrysize = fix_pool_sizes[poolIndex] + sizeof(void *); + entrycount = (buffersize / entrysize); + fsb = buffer; + for (i = 0; i < (entrycount - 1); i++) { + fsbnext = (FixSubBlock *) ((long) fsb + entrysize); + fsb->fixblock = fixblock; + fsb->next = fsbnext; + fsb = fsbnext; + } + + fsb->fixblock = fixblock; + fsb->next = fix_start[poolIndex].b; + fix_start[poolIndex].b = buffer; +} + +static void *allocate_from_fixed_pools(size_t size) { + int poolIndex; + FixSubBlock *fsb; + + poolIndex = 0; + while (size > fix_pool_sizes[poolIndex]) + poolIndex++; + + if (!fix_start[poolIndex].b) { + void *buf; + size_t bufsize; + + buf = allocate_from_var_pools(4000); + if (!buf) + return NULL; + + bufsize = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf); + FixBlock_construct( + buf, NULL, fix_start[poolIndex].a, poolIndex, + ((FixBlock *) buf) + 1, + bufsize - sizeof(FixBlock) + ); + fix_start[poolIndex].a = buf; + } + + fsb = fix_start[poolIndex].b; + fix_start[poolIndex].b = fsb->next; + fix_start[poolIndex].count++; + return ((FixSubBlockBase *) fsb) + 1; +} + +static void deallocate_from_fixed_pools(void *buf, size_t size) { + int poolIndex; + FixBlock *fixblock; + FixBlock *nextfb; + FixSubBlock *fsb; + + poolIndex = 0; + while (size > fix_pool_sizes[poolIndex]) + poolIndex++; + + fsb = (FixSubBlock *) ((long) buf - sizeof(FixSubBlockBase)); + fsb->next = fix_start[poolIndex].b; + fix_start[poolIndex].b = fsb; + if (--fix_start[poolIndex].count == 0) { + fixblock = fix_start[poolIndex].a; + while (fixblock) { + nextfb = fixblock->next; + deallocate_from_var_pools(fixblock); + fixblock = nextfb; + } + fix_start[poolIndex].a = NULL; + fix_start[poolIndex].b = NULL; + } +} + +size_t IRO_msize(void *buf) { + return BUF_SIZE(buf); +} + +void *IRO_malloc(size_t size) { + if (!size) + return NULL; + + if (size <= 0x4C) + return allocate_from_fixed_pools(size); + else + return allocate_from_var_pools(size); +} + +void IRO_free(void *buf) { + if (buf) { + size_t size = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf); + + if (size <= 0x4C) + deallocate_from_fixed_pools(buf, size); + else + deallocate_from_var_pools(buf); + } +} + +void *IRO_realloc(void *buf, size_t newsize) { + size_t oldsize; + size_t newblocksize; + void *newbuf; + + if (!buf) + return IRO_malloc(newsize); + + if (!newsize) { + IRO_free(buf); + return NULL; + } + + oldsize = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf); + if (newsize > oldsize) { + if (BUF_IS_VAR(buf)) { + newblocksize = (newsize + sizeof(Block) - 1) & ~FLAGMASK; + if (newblocksize < 0x60) + newblocksize = 0x60; + SubBlock_merge_next(VARBUF_SB(buf), &BLOCK_TAIL(VARBUF_BLOCK(buf))->unk); + if (VARBUF_BLOCKSIZE(buf) >= newblocksize) { + if ((VARBUF_BLOCKSIZE(buf) - newblocksize) >= 0x60) { + Block_link(VARBUF_BLOCK(buf), SubBlock_split(VARBUF_SB(buf), newblocksize)); + } + return buf; + } + } + + newbuf = IRO_malloc(newsize); + if (!newbuf) + return NULL; + + memcpy(newbuf, buf, oldsize); + IRO_free(buf); + return newbuf; + } + + if (BUF_IS_VAR(buf)) { + newsize = (newsize + sizeof(Block) - 1) & ~FLAGMASK; + if (newsize < 0x60) + newsize = 0x60; + if ((VARBUF_BLOCKSIZE(buf) - newsize) >= 0x60) { + Block_link(VARBUF_BLOCK(buf), SubBlock_split(VARBUF_SB(buf), newsize)); + } + } + + return buf; +} + +void *IRO_calloc(size_t a, size_t b) { + void *buf; + size_t len = b * a; + buf = IRO_malloc(len); + if (buf) + memset(buf, 0, len); + return buf; +} + +void IRO_pool_free_all(void) { + int i; + Block *block; + if ((block = start_)) { + do { + block = block->next; + } while (block != start_); + start_ = NULL; + + for (i = 0; i < 4; i++) { + fix_start[i].a = NULL; + fix_start[i].b = NULL; + fix_start[i].count = 0; + } + } +} + +void IRO_InitializeAllocator(void) { + if (!initialized) { + int i; + for (i = 0; i < 4; i++) { + fix_start[i].a = NULL; + fix_start[i].b = NULL; + fix_start[i].count = 0; + } + start_ = NULL; + initialized = 1; + } +} + +void IRO_TerminateAllocator(void) { + initialized = 0; +} + diff --git a/compiler_and_linker/unsorted/IroPointerAnalysis.c b/compiler_and_linker/unsorted/IroPointerAnalysis.c index e69de29..a47d544 100644 --- a/compiler_and_linker/unsorted/IroPointerAnalysis.c +++ b/compiler_and_linker/unsorted/IroPointerAnalysis.c @@ -0,0 +1,5912 @@ +#include "compiler/IroPointerAnalysis.h" +#include "compiler/IroEval.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroMalloc.h" +#include "compiler/IroUtil.h" +#include "compiler/IroVars.h" +#include "compiler/CDecl.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler_and_linker/unsorted/IroPointerAnalysisADTs.c" + +// forward decls +static Object *GetLocalObject(PALocalVar *local, Object *proc, Boolean flag); +static Boolean GetActualLocsOfExtendedParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, ParamMappingFunction *map, Boolean flag); +static int ExpandLocationSetSetToActuals(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *thingsPointedTo); +static Boolean Lookup(LocationSetSet *set, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, LocationSet *dst, PointsToFunction *pointsToFunc, Boolean unk, Type *indRtype); +static ExtendedParam *CreateExtendedParam(Stack **stackPtr, ParamMappingFunction *map, Object *var, Boolean *result); +static Boolean Assign(PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *srcs, Object *proc, IROLinear *nd, IRONode *fnode); +static ObjectList *FunctionArguments(Object *proc); +static IRONode **FunctionNodeTable(Object *proc); +static Boolean ApplySummary(PartialTransferFunction *tgtPTF, ParamMappingFunction *tgtMap, Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map, Boolean flag); +static PartialTransferFunction *GetPTF(ParamMappingFunction *map, Object *proc, IROLinear *nd, PartialTransferFunction *ptf, Boolean *needVisit); +static Boolean ObjectIsAFunctionArgument(Object *proc, Object *obj); +static Boolean ObjectIsARealFunctionArgument(Object *proc, Object *obj); +static void EvalProc(Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf); +static void FindGlobalObjectAction(Object *object, void *refcon); + +static Boolean ObjectIsRestrictQualified(Object *obj) { + return (CParser_GetTypeQualifiers(obj->type, obj->qual) & Q_RESTRICT) != 0; +} + +static Boolean LocationIsVolatile(LocationSet *loc, Object *proc) { + Boolean result; + Type *rtype; + +#line 932 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(proc != NULL); + + result = 0; + + if ((rtype = LocationSet_rtype(loc))) { + UInt32 qual; + switch (rtype->type) { + case TYPEARRAY: + qual = TYPE_POINTER(rtype)->qual; + break; + case TYPEPOINTER: + qual = TYPE_POINTER(rtype)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(rtype)->qual; + break; + default: + qual = 0; + } + if (qual & Q_VOLATILE) + result = 1; + } + + if (!result && !LocationSet_IsUnknown(loc)) { + Object *obj = NULL; + PAMemoryBlock *block = LocationSet_block(loc); + + switch (PAMemoryBlock_kind(block)) { + case PAMEMORYBLOCKKIND_LOCALVAR: { + PALocalVar *local = PAMemoryBlock_thing(block); + if (local) + obj = GetLocalObject(local, proc, 0); + break; + } + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: { + ExtendedParam *ep = PAMemoryBlock_thing(block); + if (ep) { + ObjectSet *objSet = ExtendedParam_objectSet(ep); + if (objSet) { + if (ObjectSet_Count(objSet) == 1) + obj = ObjectSet_FindFirst(objSet); + else + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + } + } + break; + } + } + + if (obj && is_volatile_object(obj)) + result = 1; + } + + return result; +} + +static Object *GetLocalObject(PALocalVar *local, Object *proc, Boolean flag) { + ObjectList *list; + Object *arg; + Object *obj; + char *name; + +#line 999 + IRO_ASSERT(local != NULL); + IRO_ASSERT(proc != NULL); + + obj = PALocalVar_Get0_sub_4847E0(local); + name = PALocalVar_Get4_sub_4847D0(local); + + if (proc != &stUnknown && !obj && name && name[0] && flag) { + for (list = FunctionArguments(proc); list && !obj; list = list->next) { + arg = list->object; + if (arg && arg != &stUnknown && arg->name && arg->name->name) { + if (!strcmp(arg->name->name, name)) + obj = arg; + } + } + } + + if (obj) + PALocalVar_SetSth_sub_4847C0(local, obj); + + return obj; +} + +static Boolean ObjectIsAnExtendedParamCandidate(Object *obj) { +#line 1042 + IRO_ASSERT(obj != NULL); + + return Inline_IsObjectData(obj) || + obj->datatype == DABSOLUTE || + obj->datatype == DFUNC || + obj->datatype == DVFUNC || + obj->datatype == DINLINEFUNC; +} + +static Boolean ObjectIsAFunction(Object *obj) { +#line 1054 + IRO_ASSERT(obj != NULL); + + return obj->datatype == DFUNC || + obj->datatype == DVFUNC || + obj->datatype == DINLINEFUNC; +} + +static Boolean LocationSetRepresentsSingleLocation(LocationSet *ls, Object *proc, PointsToFunction *pointsToFunc) { + Boolean result; + PAMemoryBlock *mb; + PAMemoryBlockKind kind; + ExtendedParam *ep; + ObjectSet *objSet; + +#line 1073 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(proc == NULL || proc != NULL); + IRO_ASSERT(pointsToFunc == NULL || pointsToFunc != NULL); + + result = 1; + if (LocationSet_IsUnknown(ls) || LocationSet_stride(ls)) { + result = 0; + } else { + mb = LocationSet_block(ls); +#line 1084 + IRO_ASSERT(mb != NULL); + + kind = PAMemoryBlock_kind(mb); + if (kind == PAMEMORYBLOCKKIND_HEAPBLOCK) { + result = 0; + } else if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + ep = PAMemoryBlock_thing(mb); + if (!ep) { + result = 0; + } else { + if ((objSet = ExtendedParam_objectSet(ep)) && ObjectSet_Count(objSet) > 1) { + Object *obj = NULL; + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + + if (!obj) { + LocationSetSet *lss; + LocationSet *tmp; + ExtendedParam *ep; + ObjectSet *objSet; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + GetActualLocsOfExtendedParam(lss, ls, NULL, &stCallingContextStack, NULL, 0); + if ( + LocationSetSet_Count(lss) != 1 || + !(tmp = LocationSetSet_FindFirst(lss)) || + LocationSet_IsUnknown(tmp) || + (!((mb = LocationSet_block(tmp)) && (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) && (ep = PAMemoryBlock_thing(mb)) && (objSet = ExtendedParam_objectSet(ep)) && (ObjectSet_Count(objSet) == 1) && + ObjectIsAnExtendedParamCandidate(ObjectSet_FindFirst(objSet))) && + !LocationSetRepresentsSingleLocation(tmp, proc, pointsToFunc)) + ) + result = 0; + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } + } + } + } + } + + return result; +} + +static void EvalExprAction(LocationSet *ls, void *refcon) { + CInt64 value; + UInt32 stride; + PAMemoryBlock *mb; + +#line 1151 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(ls)); + IRO_ASSERT(refcon != NULL); + + value = *((CInt64 *) refcon); + stride = LocationSet_stride(ls); + mb = LocationSet_block(ls); + + if (mb && PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) { + Type *rtype = LocationSet_rtype(ls); + LocationSet_Term(ls); + value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb))); + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); + LocationSet_InitKnown(ls, mb, cint64_zero, stride, rtype); + } else { + value = CInt64_Add(value, LocationSet_field(ls)); + if (stride) { + CInt64 strideval; + CInt64_SetLong(&strideval, stride); + value = CInt64_Mod(value, strideval); + } + SetsLocationSetField_sub_4851B0(ls, value); + } +} + +static void EvalExprAction2(LocationSet *ls, void *refcon) { + UInt32 value; + +#line 1188 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(ls)); + IRO_ASSERT(refcon != NULL); + + value = CInt64_GetULong((CInt64 *) refcon); + if (value) { + SetsLocationSetField_sub_4851B0(ls, CInt64_Mod(LocationSet_field(ls), *((CInt64 *) refcon))); + } + SetsLocationSetStride_sub_4852D0(ls, value); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalExprAction3Params { + LocationSetSet *set; + Stack **stackPtr; + Object *proc; + ParamMappingFunction *map; + PartialTransferFunction *ptf; + PointsToFunction *pointsToFunc; + Type *indRtype; + Boolean x1C; +} EvalExprAction3Params; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalExprAction3(LocationSet *ls, void *refcon) { + EvalExprAction3Params *params; + +#line 1219 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + + params->x1C |= Lookup( + params->set, + params->stackPtr, + params->proc, + params->map, + params->ptf, + ls, + params->pointsToFunc, + 1, + params->indRtype + ); +} + +static void EvalExprAction4(LocationSet *ls, void *refcon) { + Type *type; + PAMemoryBlock *mb; + +#line 1235 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(refcon != NULL); + + type = refcon; + + if (LocationSet_IsUnknown(ls)) { + LocationSet_SetRtype(ls, type); + } else if ((mb = LocationSet_block(ls))) { + if (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) { + CInt64 value; + CInt64 field; + UInt32 stride; + + value = *((CInt64 *) PAMemoryBlock_thing(mb)); + IRO_TruncateValueToType(&value, type); + field = LocationSet_field(ls); + IRO_TruncateValueToType(&field, type); + stride = LocationSet_stride(ls); + LocationSet_Term(ls); + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); + + LocationSet_InitKnown(ls, mb, field, stride, type); + } + LocationSet_SetRtype(ls, type); + } +} + +static Boolean EvalExpr(LocationSetSet *set, Object *proc, IROLinear *Int, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) { + Boolean result; + LocationSetSet *lss; + LocationSetSet *lss2; + IROLinear *indirect; + EvalExprAction3Params params; + IROLinear *originalInt; + +#line 1284 + IRO_ASSERT(set == NULL || set != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(Int != NULL); + IRO_ASSERT(map == NULL || map != NULL); + IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + + result = 0; + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + + originalInt = Int; + while (Int && Int->type == IROLinearOp1Arg && Int->nodetype == ETYPCON) + Int = Int->u.monadic; + +#line 1302 + IRO_ASSERT(Int != NULL); + + if (IRO_IsAssignment(Int)) { + if (Int->type == IROLinearOp1Arg) + indirect = Int->u.monadic; + else + indirect = Int->u.diadic.left; +#line 1310 + IRO_ASSERT(indirect->type == IROLinearOp1Arg && indirect->nodetype == EINDIRECT); + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalExpr(lss2, proc, indirect->u.monadic, stackPtr, map, ptf); + + memset(¶ms, 0, sizeof(params)); + params.set = lss; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + if (Int->nodetype == EPOSTINC || Int->nodetype == EPOSTDEC) + params.pointsToFunc = indirect->pointsToFunction; + else + params.pointsToFunc = Int->pointsToFunction; + params.indRtype = indirect->rtype; + params.x1C = 0; + LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); + result |= params.x1C; + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else if (Int->type == IROLinearFunccall) { +#line 1338 + IRO_ASSERT(Int->u.funccall.returnedLocs != NULL); + LocationSetSet_AddSet(lss, Int->u.funccall.returnedLocs); + } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EINDIRECT) { + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalExpr(lss2, proc, Int->u.monadic, stackPtr, map, ptf); + + memset(¶ms, 0, sizeof(params)); + params.set = lss; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + params.pointsToFunc = Int->pointsToFunction; + params.indRtype = Int->rtype; + params.x1C = 0; + LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); + result |= params.x1C; + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else if (Int->type == IROLinearOp2Arg && Int->nodetype == EADD) { + IROAddrRecord *addr = IRO_InitAddrRecordPointer(Int); + IRO_DecomposeAddressExpression(Int, addr); + if (addr->numObjRefs > 1) { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } else { + CInt64 value; + CInt64 max; + CInt64 work; + Boolean flag1; + Boolean flag2; + + CInt64_SetLong(&value, 0); + flag1 = 0; + flag2 = 0; + if (addr->numObjRefs == 1) { + Object *obj; +#line 1383 + IRO_ASSERT(addr->objRefs->element->type == IROLinearOperand); + IRO_ASSERT(addr->objRefs->element->u.node->type == EOBJREF); + obj = ((IROLinear *) addr->objRefs->element)->u.node->data.objref; +#line 1387 + IRO_ASSERT(obj != NULL); + result |= EvalExpr(lss, proc, addr->objRefs->element, stackPtr, map, ptf); + flag2 = 1; + } + + if (addr->numMisc != 0) { + IROElmList *list; + IROLinear *nd; + max = cint64_max; + + for (list = addr->misc; list; list = list->next) { + nd = list->element; + while (nd && nd->type == IROLinearOp1Arg && nd->nodetype == ETYPCON) + nd = nd->u.monadic; + + if (nd) { + if (nd->type == IROLinearOp2Arg && nd->nodetype == EMUL) { + if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) { + if (IRO_IsUnsignedType(nd->rtype)) + work = CInt64_MulU(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval); + else + work = CInt64_Mul(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval); + IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype); + value = CInt64_Add(value, work); + } else if (IRO_IsIntConstant(nd->u.diadic.left)) { + work = nd->u.diadic.left->u.node->data.intval; + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else if (IRO_IsIntConstant(nd->u.diadic.right)) { + work = nd->u.diadic.right->u.node->data.intval; + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else { + max = cint64_one; + } + } else if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHL) { + if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) { + work = CInt64_Shl(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval); + IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype); + value = CInt64_Add(value, work); + } else if (IRO_IsIntConstant(nd->u.diadic.right)) { + work = CInt64_Shl(cint64_one, nd->u.diadic.right->u.node->data.intval); + IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype); + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else { + max = cint64_one; + } + } else { + LocationSet *tmp; + PAMemoryBlock *mb; + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalExpr(lss2, proc, nd, stackPtr, map, ptf); + + if (LocationSetSet_FindUnknown(lss2)) { + max = cint64_one; + } else if ( + LocationSetSet_Count(lss2) == 1 && + (tmp = LocationSetSet_FindFirst(lss2)) && + (LocationSet_stride(tmp) == 0) && + (mb = LocationSet_block(tmp)) && + (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) + ) { + value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb))); + } else if (!flag2 && (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype))) { + if (flag1) { + LocationSetSet_RemoveAll(lss); + max = cint64_one; + } + LocationSetSet_AddSet(lss, lss2); + flag2 = 1; + } else if (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype)) { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } else if (!flag1) { + LocationSetSet_AddSet(lss, lss2); + flag1 = 1; + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } + } + } + + if (IS_TYPE_POINTER(Int->rtype)) + CInt64_SetLong(&work, TYPE_POINTER(Int->rtype)->target->size); + else if (IS_TYPE_MEMBERPOINTER(Int->rtype)) + CInt64_SetLong(&work, TYPE_MEMBER_POINTER(Int->rtype)->ty1->size); + else + work = cint64_zero; + + if (CInt64_GreaterU(work, max)) + max = work; + } + + if (addr->numInts != 0) { + IROElmList *list; + IROLinear *addend; + + for (list = addr->ints; list; list = list->next) { + addend = list->element; + + if (addend) { +#line 1536 + IRO_ASSERT(IRO_IsIntConstant(addend)); + + value = CInt64_Add(value, addend->u.node->data.intval); + } + } + } + + IRO_TruncateValueToType(&value, Int->rtype); + + if (LocationSetSet_Count(lss) == 0) { + if (CInt64_Equal(max, cint64_max)) { + PAMemoryBlock *mb; + LocationSet *ls; + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); + + ls = LocationSet_New(); + LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); + LocationSetSet_Add(lss, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + } else { + if (!LocationSetSet_FindUnknown(lss) && !CInt64_IsZero(&value)) + LocationSetSet_ForEach(lss, EvalExprAction, &value); + } + + if (!LocationSetSet_FindUnknown(lss) && addr->numMisc && !CInt64_Equal(max, cint64_max)) + LocationSetSet_ForEach(lss, EvalExprAction2, &max); + } + } else if (Int->type == IROLinearOperand) { + Object *obj; + void *thing; + PAMemoryBlockKind kind; + + thing = NULL; + if (IRO_IsIntConstant(Int)) { + kind = PAMEMORYBLOCKKIND_INT; + thing = &Int->u.node->data.intval; + } else if (Int->u.node->type == ESTRINGCONST) { + kind = PAMEMORYBLOCKKIND_6; + thing = Int->u.node; + } else if (Int->u.node->type == EOBJREF) { + obj = Int->u.node->data.objref; +#line 1597 + IRO_ASSERT(obj != NULL); + if (ObjectIsAnExtendedParamCandidate(obj)) { + kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; + thing = CreateExtendedParam(stackPtr, map, obj, &result); + } else { + kind = PAMEMORYBLOCKKIND_LOCALVAR; + thing = PALocalVar_New(); + if (obj->name && obj->name->name && ObjectIsARealFunctionArgument(proc, obj)) + PALocalVar_InitByName(thing, obj->name->name); + else + PALocalVar_InitByObject(thing, obj); + } + } + + if (thing) { + PAMemoryBlock *mb; + LocationSet *ls; + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, kind, thing); + + ls = LocationSet_New(); + LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); + LocationSetSet_Add(lss, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); + } + } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EBITFIELD) { + LocationSet *ls; + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalExpr(lss2, proc, Int->u.monadic, stackPtr, map, ptf); + + if (LocationSetSet_Count(lss2) == 1 && (ls = LocationSetSet_FindFirst(lss2))) { + LocationSetSet_AddUnknown(lss, NULL, NULL, ls); + } else { +#line 1643 + CError_FATAL(); + } + + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + + LocationSetSet_ForEach(lss, EvalExprAction4, originalInt->rtype); + + if (set && lss) + LocationSetSet_AddSet(set, lss); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + + return result; +} + +static IROAddrRecord *IRO_InitENodeAddrRecordPointer(ENode *enode) { + IROAddrRecord *addr = IRO_malloc(sizeof(IROAddrRecord)); + + addr->numObjRefs = 0; + addr->objRefs = NULL; + addr->numMisc = 0; + addr->misc = NULL; + addr->numInts = 0; + addr->ints = NULL; + addr->x16 = 0; + addr->linear = (IROLinear *) enode; + + return addr; +} + +static void IRO_AddENodeElmToList(ENode *linear, IROElmList **list) { + IROElmList *elmlist = IRO_malloc(sizeof(IROElmList)); + elmlist->element = linear; + elmlist->next = NULL; + if (!*list) { + *list = elmlist; + } else { + elmlist->next = *list; + *list = elmlist; + } +} + +static void IRO_DecomposeENodeAddressExpression(ENode *node, IROAddrRecord *addr) { + if (node->data.diadic.left->type == EADD) { + IRO_DecomposeENodeAddressExpression(node->data.diadic.left, addr); + } else if (node->data.diadic.left->type == EINTCONST) { + addr->numInts++; + IRO_AddENodeElmToList(node->data.diadic.left, &addr->ints); + } else if (node->data.diadic.left->type == EOBJREF) { + addr->numObjRefs++; + IRO_AddENodeElmToList(node->data.diadic.left, &addr->objRefs); + } else { + addr->numMisc++; + IRO_AddENodeElmToList(node->data.diadic.left, &addr->misc); + } + + if (node->data.diadic.right->type == EADD) { + IRO_DecomposeENodeAddressExpression(node->data.diadic.right, addr); + } else if (node->data.diadic.right->type == EINTCONST) { + addr->numInts++; + IRO_AddENodeElmToList(node->data.diadic.right, &addr->ints); + } else if (node->data.diadic.right->type == EOBJREF) { + addr->numObjRefs++; + IRO_AddENodeElmToList(node->data.diadic.right, &addr->objRefs); + } else { + addr->numMisc++; + IRO_AddENodeElmToList(node->data.diadic.right, &addr->misc); + } +} + +static Boolean EvalENodeExpr(LocationSetSet *set, Object *proc, ENode *Int, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) { + Boolean result; + LocationSetSet *lss; + LocationSetSet *lss2; + ENode *indirect; + EvalExprAction3Params params; + ENode *originalInt; + + IRO_ASSERT(set == NULL || set != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(Int != NULL); + IRO_ASSERT(map == NULL || map != NULL); + IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + + result = 0; + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + + originalInt = Int; + while (Int && Int->type == ETYPCON) + Int = Int->data.monadic; + + IRO_ASSERT(Int != NULL); + + if (IRO_IsAssignOp[Int->type]) { + if (Int->type == EPOSTINC || Int->type == EPOSTDEC || Int->type == EPREINC || Int->type == EPREDEC) + indirect = Int->data.monadic; + else + indirect = Int->data.diadic.left; + IRO_ASSERT(indirect->type == EINDIRECT); + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalENodeExpr(lss2, proc, indirect->data.monadic, stackPtr, map, ptf); + + memset(¶ms, 0, sizeof(params)); + params.set = lss; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + if (Int->type == EPOSTINC || Int->type == EPOSTDEC) + params.pointsToFunc = indirect->pointsTo; + else + params.pointsToFunc = Int->pointsTo; + params.indRtype = indirect->rtype; + params.x1C = 0; + LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); + result |= params.x1C; + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else if (Int->type == EINDIRECT) { + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalENodeExpr(lss2, proc, Int->data.monadic, stackPtr, map, ptf); + + memset(¶ms, 0, sizeof(params)); + params.set = lss; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + params.pointsToFunc = Int->pointsTo; + params.indRtype = Int->rtype; + params.x1C = 0; + LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); + result |= params.x1C; + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else if (Int->type == EADD) { + IROAddrRecord *addr = IRO_InitENodeAddrRecordPointer(Int); + IRO_DecomposeENodeAddressExpression(Int, addr); + if (addr->numObjRefs > 1) { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } else { + CInt64 value; + CInt64 max; + CInt64 work; + Boolean flag1; + Boolean flag2; + + CInt64_SetLong(&value, 0); + flag1 = 0; + flag2 = 0; + if (addr->numObjRefs == 1) { + Object *obj; + // IRO_ASSERT(addr->objRefs->element->type == IROLinearOperand); + // IRO_ASSERT(addr->objRefs->element->u.node->type == EOBJREF); + obj = ((ENode *) addr->objRefs->element)->data.objref; + IRO_ASSERT(obj != NULL); + result |= EvalENodeExpr(lss, proc, addr->objRefs->element, stackPtr, map, ptf); + flag2 = 1; + } + + if (addr->numMisc != 0) { + IROElmList *list; + ENode *nd; + max = cint64_max; + + for (list = addr->misc; list; list = list->next) { + nd = list->element; + while (nd && nd->type == ETYPCON) + nd = nd->data.monadic; + + if (nd) { + if (nd->type == EMUL) { + if (nd->data.diadic.left->type == EINTCONST && nd->data.diadic.right->type == EINTCONST) { + if (IRO_IsUnsignedType(nd->rtype)) + work = CInt64_MulU(nd->data.diadic.left->data.intval, + nd->data.diadic.right->data.intval); + else + work = CInt64_Mul(nd->data.diadic.left->data.intval, + nd->data.diadic.right->data.intval); + IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype); + value = CInt64_Add(value, work); + } else if (nd->data.diadic.left->type == EINTCONST) { + work = nd->data.diadic.left->data.intval; + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else if (nd->data.diadic.right->type == EINTCONST) { + work = nd->data.diadic.right->data.intval; + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else { + max = cint64_one; + } + } else if (nd->type == ESHL) { + if (nd->data.diadic.left->type == EINTCONST && nd->data.diadic.right->type == EINTCONST) { + work = CInt64_Shl(nd->data.diadic.left->data.intval, + nd->data.diadic.right->data.intval); + IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype); + value = CInt64_Add(value, work); + } else if (nd->data.diadic.right->type == EINTCONST) { + work = CInt64_Shl(cint64_one, nd->data.diadic.right->data.intval); + IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype); + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else { + max = cint64_one; + } + } else { + LocationSet *tmp; + PAMemoryBlock *mb; + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalENodeExpr(lss2, proc, nd, stackPtr, map, ptf); + + if (LocationSetSet_FindUnknown(lss2)) { + max = cint64_one; + } else if ( + LocationSetSet_Count(lss2) == 1 && + (tmp = LocationSetSet_FindFirst(lss2)) && + (LocationSet_stride(tmp) == 0) && + (mb = LocationSet_block(tmp)) && + (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) + ) { + value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb))); + } else if (!flag2 && (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype))) { + if (flag1) { + LocationSetSet_RemoveAll(lss); + max = cint64_one; + } + LocationSetSet_AddSet(lss, lss2); + flag2 = 1; + } else if (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype)) { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } else if (!flag1) { + LocationSetSet_AddSet(lss, lss2); + flag1 = 1; + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } + } + } + + if (IS_TYPE_POINTER(Int->rtype)) + CInt64_SetLong(&work, TYPE_POINTER(Int->rtype)->target->size); + else if (IS_TYPE_MEMBERPOINTER(Int->rtype)) + CInt64_SetLong(&work, TYPE_MEMBER_POINTER(Int->rtype)->ty1->size); + else + work = cint64_zero; + + if (CInt64_GreaterU(work, max)) + max = work; + } + + if (addr->numInts != 0) { + IROElmList *list; + ENode *addend; + + for (list = addr->ints; list; list = list->next) { + addend = list->element; + + if (addend) { + IRO_ASSERT(addend->type == EINTCONST); + + value = CInt64_Add(value, addend->data.intval); + } + } + } + + IRO_TruncateValueToType(&value, Int->rtype); + + if (LocationSetSet_Count(lss) == 0) { + if (CInt64_Equal(max, cint64_max)) { + PAMemoryBlock *mb; + LocationSet *ls; + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); + + ls = LocationSet_New(); + LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); + LocationSetSet_Add(lss, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + } else { + if (!LocationSetSet_FindUnknown(lss) && !CInt64_IsZero(&value)) + LocationSetSet_ForEach(lss, EvalExprAction, &value); + } + + if (!LocationSetSet_FindUnknown(lss) && addr->numMisc && !CInt64_Equal(max, cint64_max)) + LocationSetSet_ForEach(lss, EvalExprAction2, &max); + } + } else if (Int->type == EOBJREF || Int->type == EINTCONST || Int->type == ESTRINGCONST) { + Object *obj; + void *thing; + PAMemoryBlockKind kind; + + thing = NULL; + if (Int->type == EINTCONST) { + kind = PAMEMORYBLOCKKIND_INT; + thing = &Int->data.intval; + } else if (Int->type == ESTRINGCONST) { + kind = PAMEMORYBLOCKKIND_6; + thing = Int; + } else if (Int->type == EOBJREF) { + obj = Int->data.objref; + IRO_ASSERT(obj != NULL); + if (ObjectIsAnExtendedParamCandidate(obj)) { + kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; + thing = CreateExtendedParam(stackPtr, map, obj, &result); + } else { + kind = PAMEMORYBLOCKKIND_LOCALVAR; + thing = PALocalVar_New(); + if (obj->name && obj->name->name && ObjectIsARealFunctionArgument(proc, obj)) + PALocalVar_InitByName(thing, obj->name->name); + else + PALocalVar_InitByObject(thing, obj); + } + } + + if (thing) { + PAMemoryBlock *mb; + LocationSet *ls; + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, kind, thing); + + ls = LocationSet_New(); + LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); + LocationSetSet_Add(lss, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); + } + } else if (Int->type == EBITFIELD) { + LocationSet *ls; + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalENodeExpr(lss2, proc, Int->data.monadic, stackPtr, map, ptf); + + if (LocationSetSet_Count(lss2) == 1 && (ls = LocationSetSet_FindFirst(lss2))) { + LocationSetSet_AddUnknown(lss, NULL, NULL, ls); + } else { +#line 2146 + CError_FATAL(); + } + + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + + LocationSetSet_ForEach(lss, EvalExprAction4, originalInt->rtype); + + if (set && lss) + LocationSetSet_AddSet(set, lss); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + + return result; +} + +static Boolean EvalVarAddr(LocationSetSet *set, Object *proc, VarRecord *var, Stack **stackPtr, ParamMappingFunction *map) { + Boolean result; + PAMemoryBlockKind kind; + void *thing; + Object *obj; + PAMemoryBlock *block; + LocationSet *loc; + + result = 0; + obj = var->object; + + if (ObjectIsAnExtendedParamCandidate(obj)) { + kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; + thing = CreateExtendedParam(stackPtr, map, obj, &result); + } else { + kind = PAMEMORYBLOCKKIND_LOCALVAR; + thing = PALocalVar_New(); + if (obj->name && obj->name->name && ObjectIsAFunctionArgument(proc, obj)) + PALocalVar_InitByName(thing, obj->name->name); + else + PALocalVar_InitByObject(thing, obj); + } + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, kind, thing); + + loc = LocationSet_New(); + LocationSet_InitKnown(loc, block, cint64_zero, 0, CDecl_NewPointerType(obj->type)); + LocationSetSet_Add(set, loc); + LocationSet_Term(loc); + LocationSet_Delete(loc); + + return result; +} + +static Boolean EvalVariable(LocationSetSet *set, Object *proc, VarRecord *var, PointsToFunction *pointsToFunc, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) { + LocationSetSet *locs; + Boolean result; + EvalExprAction3Params params; + + locs = LocationSetSet_New(); + LocationSetSet_Init(locs); + result = EvalVarAddr(locs, proc, var, stackPtr, map); + + memset(¶ms, 0, sizeof(params)); + params.set = set; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + params.pointsToFunc = pointsToFunc; + params.indRtype = var->object->type; + params.x1C = 0; + LocationSetSet_ForEach(locs, EvalExprAction3, ¶ms); + + result |= params.x1C; + LocationSetSet_Term(locs); + LocationSetSet_Delete(locs); + + return result; +} + +static void StoreReturnedLocationsAction(LocationSet *loc, void *refcon) { +#line 2275 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(refcon != NULL); + + if (!LocationSet_IsUnknown(loc)) { + if (PAMemoryBlock_kind(LocationSet_block(loc)) == PAMEMORYBLOCKKIND_HEAPBLOCK) { + PAHeapBlock *hb; + PAMemoryBlock *mb; + CInt64 field; + UInt32 stride; + Type *rtype; + + hb = CreateUniqueHeapAlloc_sub_486420(); + InitUniqueHeapAlloc_sub_486410(hb, refcon); + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_HEAPBLOCK, hb); + + field = LocationSet_field(loc); + stride = LocationSet_stride(loc); + rtype = LocationSet_rtype(loc); + LocationSet_Term(loc); + LocationSet_InitKnown(loc, mb, field, stride, rtype); + } + } +} + +static void StoreReturnedLocations(IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map) { + LocationSet *retLoc; + LocationSetSet *retLocs; + +#line 2307 + IRO_ASSERT(nd != NULL); + IRO_ASSERT(nd->type == IROLinearFunccall); + IRO_ASSERT(ptf != NULL); + IRO_ASSERT(map != NULL); + + retLoc = PartialTransferFunction_returnLocation(ptf); + retLocs = nd->u.funccall.returnedLocs; + if (!retLocs) { + LocationSetSet_Init(retLocs = nd->u.funccall.returnedLocs = LocationSetSet_New()); + } else { + LocationSetSet_RemoveAll(retLocs); + } + + Lookup(retLocs, NULL, NULL, NULL, NULL, retLoc, PartialTransferFunction_finalPointsToFn(ptf), 0, NULL); + ExpandLocationSetSetToActuals(&stCallingContextStack, map, retLocs); + LocationSetSet_ForEach(retLocs, StoreReturnedLocationsAction, nd); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EPParams { + ParamMappingFunction *map; + ExtendedParam *ep; + Object *proc; + Object *var; + unsigned char x10; + unsigned char x11; +} EPParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void FillInAppropriateMappingsWithExtParamAction(Object *obj, void *refcon) { + EPParams *params; + ParamMapping *mapping; + +#line 2352 + IRO_ASSERT(obj != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 2357 + IRO_ASSERT(params->map != NULL); + IRO_ASSERT(params->ep != NULL); + IRO_ASSERT(params->proc == NULL || params->proc != NULL); + IRO_ASSERT(params->proc != &stUnknown); + IRO_ASSERT(params->var == NULL || params->var != NULL); + IRO_ASSERT(params->var != &stUnknown); + + mapping = ParamMappingFunction_FindMappingByFormal(params->map, obj); + if (!mapping) { + if (ObjectIsAnExtendedParamCandidate(obj) || !params->proc || ObjectIsAFunctionArgument(params->proc, obj)) { + mapping = ParamMapping_New(); + ParamMapping_Init_PROBABLY(mapping, NULL, obj, params->ep); + Pmf_Add_sub_486610(params->map, mapping); + ParamMapping_Term(mapping); + ParamMapping_Delete(mapping); + params->x11 = 1; + } + } else { + if (ParamMapping_extended(mapping) != params->ep) { + ParamMapping_SetExtended(mapping, params->ep); + params->x11 = 1; + } + } + + if (obj == params->var) + params->x10 = 1; +} + +static Boolean FillInAppropriateMappingsWithExtParam(ParamMappingFunction *map, Object *var, ExtendedParam *ep, Object *proc) { + EPParams params; + ObjectSet *objSet; + +#line 2398 + IRO_ASSERT(map != NULL); + IRO_ASSERT(var == NULL || var != NULL); + IRO_ASSERT(var != &stUnknown); + IRO_ASSERT(ep != NULL); + IRO_ASSERT(proc == NULL || proc != NULL); + IRO_ASSERT(proc != &stUnknown); + + memset(¶ms, 0, sizeof(params)); + params.map = map; + params.ep = ep; + params.proc = proc; + params.var = var; + params.x10 = 0; + params.x11 = 0; + + if ((objSet = ExtendedParam_objectSet(ep))) + ObjectSet_ForEach(objSet, FillInAppropriateMappingsWithExtParamAction, ¶ms); + + if (var && !params.x10) { + ExtendedParam_sub_4867B0(ep, var); + FillInAppropriateMappingsWithExtParamAction(var, ¶ms); + } + + return params.x11; +} + +static void MatchPTFHelper(LocationSet *loc, LocationSetSet *locs, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf) { + PointsToFunction *initial; + PAMemoryBlock *block; + PAMemoryBlockKind kind; + Object *obj; + +#line 2448 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(loc)); + IRO_ASSERT(locs != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(map != NULL); + IRO_ASSERT(ptf != NULL); + + initial = PartialTransferFunction_initialPointsToFn(ptf); +#line 2456 + IRO_ASSERT(initial != NULL); + +#line 2458 + IRO_ASSERT(!LocationSet_IsUnknown(loc)); + + block = LocationSet_block(loc); +#line 2460 + IRO_ASSERT(block != NULL); + + kind = PAMemoryBlock_kind(block); + + if (kind == PAMEMORYBLOCKKIND_LOCALVAR) { + PALocalVar *local; + + local = PAMemoryBlock_thing(block); +#line 2466 + IRO_ASSERT(local != NULL); + + obj = GetLocalObject(local, proc, 1); + if (obj && ObjectIsAFunctionArgument(proc, obj)) { + if (LocationSetSet_Count(locs) == 1) { + LocationSet *ls; + ls = LocationSetSet_FindFirst(locs); + if (ls && !LocationSet_IsUnknown(ls)) { + if ((block = LocationSet_block(ls))) { + if (PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + ExtendedParam *ep; + if ((ep = PAMemoryBlock_thing(block))) { + ExtendedParam_sub_4867B0(ep, obj); + if (stExtParamSet) + ExtParamSet_sub_487630(stExtParamSet, ep); + FillInAppropriateMappingsWithExtParam(map, obj, ep, proc); + } + } + } + } + } + } + } else if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + void *ep = PAMemoryBlock_thing(block); +#line 2489 + IRO_ASSERT(ep != NULL); + + obj = NULL; + ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &obj); + if (obj && obj != &stUnknown) + FillInAppropriateMappingsWithExtParam(map, obj, ep, proc); + } else { +#line 2500 + CError_FATAL(); + } + + if (!PointsToFunction_FindByLookupCompatibleLocationSet(initial, loc)) { + PointsToEntry *pte = PointsToEntry_New(); + PointsToEntry_Init(pte, loc, locs); + PointsToFunction_AddWithoutChecking(initial, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct MatchPTFActionParams { + Object *proc; + PartialTransferFunction *ptfCopy; + ParamMappingFunction *mapCopy; + Stack **stackPtr; +} MatchPTFActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void MatchPTFAction1(PointsToEntry *tgtPTE, void *refcon) { + MatchPTFActionParams *params; + LocationSet *loc; + LocationSetSet *locs; + PAMemoryBlock *block; + PAMemoryBlockKind kind; + +#line 2525 + IRO_ASSERT(tgtPTE != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 2530 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->ptfCopy != NULL); + IRO_ASSERT(params->mapCopy != NULL); + + if ((loc = PointsToEntry_loc(tgtPTE)) && (locs = PointsToEntry_locs(tgtPTE))) { + if ((block = LocationSet_block(loc))) { + kind = PAMemoryBlock_kind(block); + if (kind == PAMEMORYBLOCKKIND_LOCALVAR) { + MatchPTFHelper(loc, locs, params->proc, params->mapCopy, params->ptfCopy); + } else if (kind != PAMEMORYBLOCKKIND_EXTENDEDPARAM) { +#line 2547 + CError_FATAL(); + } + } + } +} + +static void MatchPTFAction2(PointsToEntry *tgtPTE, void *refcon) { + MatchPTFActionParams *params; + LocationSet *loc; + LocationSetSet *locs; + PAMemoryBlock *block; + PAMemoryBlockKind kind; + +#line 2561 + IRO_ASSERT(tgtPTE != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 2566 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->ptfCopy != NULL); + IRO_ASSERT(params->mapCopy != NULL); + + if ((loc = PointsToEntry_loc(tgtPTE)) && (locs = PointsToEntry_locs(tgtPTE))) { + if ((block = LocationSet_block(loc))) { + kind = PAMemoryBlock_kind(block); + if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + MatchPTFHelper(loc, locs, params->proc, params->mapCopy, params->ptfCopy); + } + } + } +} + +static Boolean MatchPTF(PartialTransferFunction *tgtPTF, Object *proc, ParamMappingFunction *map, IROLinear *nd, PartialTransferFunction *ptf) { + Boolean result; + PartialTransferFunction *ptfCopy; + ParamMappingFunction *mapCopy; + PointsToFunction *initial; + MatchPTFActionParams params; + +#line 2593 + IRO_ASSERT(tgtPTF != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(map != NULL); + IRO_ASSERT(nd != NULL); + IRO_ASSERT(ptf != NULL); + + ptfCopy = PartialTransferFunction_New(); + PartialTransferFunction_Copy(ptfCopy, ptf); + + mapCopy = ParamMappingFunction_New(); + ParamMappingFunction_Copy(mapCopy, map); + + initial = PartialTransferFunction_initialPointsToFn(tgtPTF); + PointsToFunction_SortByExtendedParamNum(initial); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptfCopy = ptfCopy; + params.mapCopy = mapCopy; + params.stackPtr = &stCallingContextStack; + + PointsToFunction_ForEach(initial, MatchPTFAction1, ¶ms); + PointsToFunction_ForEach(initial, MatchPTFAction2, ¶ms); + + result = PointsToFunctions_Match(initial, PartialTransferFunction_initialPointsToFn(ptfCopy)); + if (result) { + PartialTransferFunction_Term(ptf); + PartialTransferFunction_Copy(ptf, ptfCopy); + + ParamMappingFunction_Term(map); + ParamMappingFunction_Copy(map, mapCopy); + } + + PartialTransferFunction_Term(ptfCopy); + PartialTransferFunction_Delete(ptfCopy); + + ParamMappingFunction_Term(mapCopy); + ParamMappingFunction_Delete(mapCopy); + + return result; +} + +static void FindCallTargetsAction2(Object *obj, void *refcon) { + ObjectSet *procList; + +#line 2650 + IRO_ASSERT(obj != NULL); + IRO_ASSERT(refcon != NULL); + + procList = refcon; + + if (obj == &stUnknown || ObjectIsAFunction(obj)) + ObjectSet_sub_4867D0(procList, obj); +} + +static void FindCallTargetsAction(LocationSet *ls, void *refcon) { + ObjectSet *procList; + +#line 2669 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(refcon != NULL); + + procList = refcon; + + if (!LocationSet_IsUnknown(ls)) { + PAMemoryBlock *mb = LocationSet_block(ls); + if (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + ExtendedParam *ep = PAMemoryBlock_thing(mb); + ObjectSet *objSet = ExtendedParam_objectSet(ep); + ObjectSet_ForEach(objSet, FindCallTargetsAction2, procList); + } + } else { + FindCallTargetsAction2(&stUnknown, procList); + } +} + +static int FindCallTargets(ObjectSet *procList, Object *proc, IROLinear *nd, ParamMappingFunction *map, PartialTransferFunction *ptf) { + LocationSetSet *set; + int evalResult; + int result; + +#line 2696 + IRO_ASSERT(procList != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(nd != NULL); + IRO_ASSERT(nd->type == IROLinearFunccall); + IRO_ASSERT(map != NULL); + IRO_ASSERT(ptf != NULL); + + set = LocationSetSet_New(); + LocationSetSet_Init(set); + evalResult = EvalExpr(set, proc, nd->u.funccall.linear8, &stCallingContextStack, map, ptf); + result = evalResult | ExpandLocationSetSetToActuals(&stCallingContextStack, map, set); + LocationSetSet_ForEach(set, FindCallTargetsAction, procList); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + + return result; +} + +static int LookupParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, Boolean unkflag) { + Boolean result; + ExtendedParam *ep; + +#line 2728 + IRO_ASSERT(set == NULL || set != NULL); + IRO_ASSERT(ls != NULL); + IRO_ASSERT(var != NULL); + IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(map == NULL || map != NULL); + IRO_ASSERT(ptf == NULL || ptf != NULL); + + result = 0; + + ep = ExtendedParam_FindByObject(var); + if (!ep) + ep = CreateExtendedParam(stackPtr, map, var, &result); + +#line 2741 + IRO_ASSERT(ep != NULL); + + if (ep) { + PAMemoryBlock *block; + LocationSet *newLS; + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep); + + newLS = LocationSet_New(); + LocationSet_InitKnown(newLS, block, LocationSet_field(ls), LocationSet_stride(ls), LocationSet_rtype(ls)); + if (set) + LocationSetSet_Add(set, newLS); + + if (unkflag) { + if (map) + result |= FillInAppropriateMappingsWithExtParam(map, var, ep, proc); + + if (ptf) { + PointsToFunction *initial; + + initial = PartialTransferFunction_initialPointsToFn(ptf); + if (initial && !PointsToFunction_FindByLookupCompatibleLocationSet(initial, ls)) { + LocationSet_Term(newLS); + LocationSet_InitKnown(newLS, LocationSet_block(ls), cint64_zero, 0, LocationSet_rtype(ls)); + if (!PointsToFunction_FindByLookupCompatibleLocationSet(initial, newLS)) { + LocationSet *newLS2; + LocationSetSet *newSet; + PointsToEntry *newPTE; + + newLS2 = LocationSet_New(); + LocationSet_InitKnown(newLS2, block, cint64_zero, 0, LocationSet_rtype(ls)); + + newSet = LocationSetSet_New(); + LocationSetSet_Init(newSet); + LocationSetSet_Add(newSet, newLS2); + + newPTE = PointsToEntry_New(); + PointsToEntry_Init(newPTE, newLS, newSet); + result |= PointsToFunction_Add(initial, newPTE); + PointsToEntry_Term(newPTE); + PointsToEntry_Delete(newPTE); + + LocationSetSet_Term(newSet); + LocationSetSet_Delete(newSet); + + LocationSet_Term(newLS2); + LocationSet_Delete(newLS2); + } + } + } + } + + LocationSet_Term(newLS); + LocationSet_Delete(newLS); + } + + return result; +} + +static Boolean GetActualLocsOfExtendedParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, ParamMappingFunction *map, Boolean flag) { + Boolean result; + PAMemoryBlock *block; + IROLinear *nd; + ExtendedParam *ep; + ParamMapping *mapping; + Type *savedRtype; + CInt64 savedField; + UInt32 savedStride; + LocationSetSet *newSet; + +#line 2821 + IRO_ASSERT(set == NULL || set != NULL); + IRO_ASSERT((ls != NULL && var == NULL) || (ls == NULL && var != NULL)); + IRO_ASSERT(ls == NULL || !LocationSet_IsUnknown(ls)); + IRO_ASSERT(var != &stUnknown); + IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(map == NULL || map != NULL); + + result = 0; + block = NULL; + nd = 0; + ep = NULL; + mapping = NULL; + + if (ls) { + block = LocationSet_block(ls); +#line 2838 + IRO_ASSERT(block != NULL); + IRO_ASSERT(PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM); + + ep = PAMemoryBlock_thing(block); +#line 2842 + IRO_ASSERT(ep != NULL); + + savedField = LocationSet_field(ls); + savedStride = LocationSet_stride(ls); + savedRtype = LocationSet_rtype(ls); + } + +#line 2848 + IRO_ASSERT(ep == NULL || ep != NULL); + + if (stackPtr && *stackPtr) { + StackElement *element = Stack_Top(stackPtr); + if (element && !map) + map = StackElement_map(element); + } + +#line 2859 + IRO_ASSERT(map == NULL || map != NULL); + + if (ep) { +#line 2863 + IRO_ASSERT(var == NULL); + ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &var); + if (!var) + var = ObjectSet_FindFirst(ExtendedParam_objectSet(ep)); + if (!var) + var = &stUnknown; + } + +#line 2870 + IRO_ASSERT(var != NULL); + + if (map && var != &stUnknown) { + if (flag) + result |= FillInAppropriateMappingsWithExtParam(map, var, ep, NULL); + mapping = ParamMappingFunction_FindMappingByFormal(map, var); + } + + newSet = LocationSetSet_New(); + LocationSetSet_Init(newSet); + +#line 2884 + IRO_ASSERT(mapping == NULL || mapping != NULL); + + if (mapping) + nd = ParamMapping_actual(mapping); + + if (!nd) { + if (!ls) { +#line 2893 + IRO_ASSERT(var != NULL); + IRO_ASSERT(ep == NULL); + + if (var != &stUnknown) { + ep = CreateExtendedParam(stackPtr, NULL, var, &result); + if (flag && mapping && ParamMapping_extended(mapping) != ep) { + ParamMapping_SetExtended(mapping, ep); + result = 1; + } + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep); + savedField = cint64_zero; + savedStride = 0; + savedRtype = CDecl_NewPointerType(var->type); + } else { + block = LocationSet_block(stUnknownLs); + savedRtype = NULL; + } + } else if (var == &stUnknown || !ObjectIsAnExtendedParamCandidate(var)) { + block = LocationSet_block(stUnknownLs); + savedRtype = NULL; + } + +#line 2925 + IRO_ASSERT(block != NULL); + + if (block == LocationSet_block(stUnknownLs)) { + LocationSetSet_AddUnknown(newSet, savedRtype, NULL, NULL); + } else { + LocationSet *tmp = LocationSet_New(); + LocationSet_InitKnown(tmp, block, savedField, savedStride, savedRtype); + LocationSetSet_Add(newSet, tmp); + LocationSet_Term(tmp); + LocationSet_Delete(tmp); + } + } else { + Stack *next; + StackElement *element; + if (stackPtr && *stackPtr && (next = Stack_Next(stackPtr)) && (element = Stack_Top(&next))) { + if (ls) { + if (!savedStride && !CInt64_IsZero(&savedField)) { + IROLinear *ic; + IROLinear *d; + ic = IRO_NewIntConst(savedField, TYPE(&stunsignedlong)); + d = IRO_NewLinear(IROLinearOp2Arg); + d->index = ++IRO_NumLinear; + d->rtype = nd->rtype; + d->u.diadic.left = nd; + d->u.diadic.right = ic; + nd = d; + } + if (savedStride) { + IROLinear *call; + IROLinear *d; + call = IRO_NewLinear(IROLinearFunccall); + call->u.funccall.returnedLocs = LocationSetSet_New(); + LocationSetSet_Init(call->u.funccall.returnedLocs); + LocationSetSet_AddUnknown(call->u.funccall.returnedLocs, NULL, NULL, NULL); + d = IRO_NewLinear(IROLinearOp2Arg); + d->index = ++IRO_NumLinear; + d->rtype = nd->rtype; + d->u.diadic.left = nd; + d->u.diadic.right = call; + nd = d; + } + } + EvalExpr(newSet, StackElement_proc(element), nd, &next, StackElement_map(element), StackElement_ptf(element)); + } else { + LocationSetSet_AddUnknown(newSet, NULL, NULL, NULL); + } + } + + if (set) + LocationSetSet_AddSet(set, newSet); + + LocationSetSet_Term(newSet); + LocationSetSet_Delete(newSet); + + return result; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct ExpandLocationSetSetActionParams { + LocationSetSet *toBeRemoved; + LocationSetSet *toBeAdded; + Stack **stackPtr; + ParamMappingFunction *map; + Boolean x10; +} ExpandLocationSetSetActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void ExpandLocationSetSetToActualsAction(LocationSet *ls, void *refcon) { + ExpandLocationSetSetActionParams *params; + +#line 3021 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 3026 + IRO_ASSERT(params->toBeRemoved != NULL); + IRO_ASSERT(params->toBeAdded != NULL); + IRO_ASSERT(params->stackPtr == NULL || *params->stackPtr == NULL || *params->stackPtr != NULL); + IRO_ASSERT(params->map == NULL || params->map != NULL); + + if (!LocationSet_IsUnknown(ls)) { + PAMemoryBlock *block = LocationSet_block(ls); + if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + ExtendedParam *ep = PAMemoryBlock_thing(block); + if (ep) { + ObjectSet *objSet = ExtendedParam_objectSet(ep); + Object *obj = NULL; + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + if (!obj) { + LocationSetSet_Add(params->toBeRemoved, ls); + params->x10 |= GetActualLocsOfExtendedParam(params->toBeAdded, ls, NULL, params->stackPtr, params->map, 0); + } + } + } + } +} + +static int ExpandLocationSetSetToActuals(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *thingsPointedTo) { + LocationSetSet *toBeRemoved; + LocationSetSet *toBeAdded; + ExpandLocationSetSetActionParams params; + Boolean result; + +#line 3063 + IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(map == NULL || map != NULL); + IRO_ASSERT(thingsPointedTo != NULL); + + toBeRemoved = LocationSetSet_New(); + LocationSetSet_Init(toBeRemoved); + + toBeAdded = LocationSetSet_New(); + LocationSetSet_Init(toBeAdded); + + memset(¶ms, 0, sizeof(params)); + params.toBeRemoved = toBeRemoved; + params.toBeAdded = toBeAdded; + params.stackPtr = stackPtr; + params.map = map; + params.x10 = 0; + + LocationSetSet_ForEach(thingsPointedTo, ExpandLocationSetSetToActualsAction, ¶ms); + + result = params.x10; + LocationSetSet_sub_488700(thingsPointedTo, toBeRemoved); + LocationSetSet_AddSet(thingsPointedTo, toBeAdded); + + LocationSetSet_Term(toBeRemoved); + LocationSetSet_Delete(toBeRemoved); + + LocationSetSet_Term(toBeAdded); + LocationSetSet_Delete(toBeAdded); + + return result; +} + +static void EvaluatePartialAbsolute(LocationSetSet *set, LocationSetSet *thingsPointedTo, LocationSet *dst, Type *indRtype) { + LocationSet *absLoc; + Type *absLocRtype; + PAMemoryBlock *block; + +#line 3108 + IRO_ASSERT(set != NULL); + IRO_ASSERT(thingsPointedTo != NULL); + IRO_ASSERT(dst != NULL); + IRO_ASSERT(indRtype != NULL); + + absLoc = LocationSetSet_FindFirst(thingsPointedTo); +#line 3114 + IRO_ASSERT(absLoc != NULL); + + if (!LocationSet_IsUnknown(absLoc)) + absLocRtype = LocationSet_rtype(absLoc); + + if (!LocationSet_IsUnknown(absLoc) && indRtype->size == absLocRtype->size) { + LocationSetSet_AddSet(set, thingsPointedTo); + } else if ( + !LocationSet_IsUnknown(absLoc) && + !LocationSet_stride(absLoc) && + LocationSetSet_Count(thingsPointedTo) == 1 && + (block = LocationSet_block(absLoc)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT && + absLocRtype->size <= stsignedlonglong.size && + indRtype->size < absLocRtype->size + ) { + CInt64 val2; + CInt64 val8; + CInt64 val4; + CInt64 val5; + CInt64 val1; + CInt64 val3; + CInt64 val7; + CInt64 val6; + LocationSet *ls; + + val1 = LocationSet_field(absLoc); + val2 = *((CInt64 *) PAMemoryBlock_thing(block)); + CInt64_SetLong(&val3, 8); + val4 = cint64_zero; + CInt64_SetLong(&val5, stsignedlonglong.size - absLocRtype->size); + val6 = CInt64_Sub(LocationSet_field(dst), val1); + CInt64_SetLong(&val7, absLocRtype->size - indRtype->size); + val5 = CInt64_Add(val5, val6); + val4 = CInt64_Add(val4, val7); + val4 = CInt64_Sub(val4, val6); + val5 = CInt64_MulU(val5, val3); + val4 = CInt64_MulU(val4, val3); + val8 = cint64_negone; + val8 = CInt64_Shl(val8, val5); + val8 = CInt64_ShrU(val8, val5); + val2 = CInt64_And(val2, val8); + val2 = CInt64_ShrU(val2, val4); + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &val2); + + ls = LocationSet_New(); + LocationSet_InitKnown(ls, block, cint64_zero, 0, indRtype); + LocationSetSet_Add(set, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); + } else { + LocationSetSet_AddUnknown(set, indRtype, NULL, NULL); + } +} + +static Boolean AddToInitialPointsToFunc(Boolean flag, PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *set) { + Boolean result; + LocationSet *ls; + PointsToFunction *initial; + PointsToEntry *pte; + +#line 3192 + IRO_ASSERT(ptf == NULL || ptf != NULL); + IRO_ASSERT(dst != NULL); + IRO_ASSERT(set != NULL); + + result = 0; + + if (flag && ptf) { + ls = LocationSetSet_FindUnknown(set); + if (!ls || LocationSet_rtype(ls)) { + initial = PartialTransferFunction_initialPointsToFn(ptf); + if (initial && !PointsToFunction_FindByLookupCompatibleLocationSet(initial, dst)) { +#line 3208 + IRO_ASSERT(dst != NULL); + + pte = PointsToEntry_New(); + PointsToEntry_Init(pte, dst, set); + result = PointsToFunction_AddWithoutChecking(initial, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } + } + } + + return result; +} + +static Boolean Lookup(LocationSetSet *set, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, LocationSet *dst, PointsToFunction *pointsToFunc, Boolean unk, Type *indRtype) { + Boolean result; + LocationSetSet *mySet; + LocationSetSet *set2; + PAMemoryBlock *block; + ExtendedParam *ep; + PALocalVar *local; + ObjectSet *objSet; + Object *obj; + +#line 3245 + IRO_ASSERT(set == NULL || set != NULL); + IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(proc == NULL || proc != NULL); + IRO_ASSERT(map == NULL || map != NULL); + IRO_ASSERT(ptf == NULL || ptf != NULL); + IRO_ASSERT(dst != NULL); + IRO_ASSERT(pointsToFunc == NULL || pointsToFunc != NULL); + IRO_ASSERT(indRtype == NULL || indRtype != NULL); + + result = 0; + + set2 = NULL; + + mySet = LocationSetSet_New(); + LocationSetSet_Init(mySet); + + if (proc) { + if (LocationIsVolatile(dst, proc)) + LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); + } + + if (pointsToFunc && !LocationSet_IsUnknown(dst)) { + PointsToEntry *pte = PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, dst); + if (pte) { + set2 = PointsToEntry_locs(pte); + } else if (indRtype) { + pte = PointsToFunction_FindContainingLocationSet(pointsToFunc, dst, indRtype); + if (pte) + set2 = PointsToEntry_locs(pte); + } + } + + if (set2) { + if (indRtype) + EvaluatePartialAbsolute(mySet, set2, dst, indRtype); + else + LocationSetSet_AddSet(mySet, set2); + } else if (!set2) { + block = NULL; + if (!LocationSet_IsUnknown(dst)) + block = LocationSet_block(dst); + + if (!LocationSet_IsUnknown(dst) && LocationSet_stride(dst)) { + LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); + } else if ( + block && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && + (ep = PAMemoryBlock_thing(block)) && + (objSet = ExtendedParam_objectSet(ep)) + ) { + obj = NULL; + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + if (!obj) { + LocationSetSet *lss3; + LocationSet *tmp; + // Boolean result1; + EvalExprAction3Params params; + + lss3 = LocationSetSet_New(); + LocationSetSet_Init(lss3); + result = GetActualLocsOfExtendedParam(lss3, dst, NULL, stackPtr, map, unk); + + memset(¶ms, 0, sizeof(params)); + params.set = mySet; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + params.pointsToFunc = pointsToFunc; + params.indRtype = indRtype; + params.x1C = 0; + LocationSetSet_ForEach(lss3, EvalExprAction3, ¶ms); + result |= params.x1C; + + LocationSetSet_Term(lss3); + LocationSetSet_Delete(lss3); + + if ((tmp = LocationSetSet_FindUnknown(mySet))) { + if (!LocationSet_restriction(tmp) && ObjectSet_Count(objSet) == 1) { + if ((obj = ObjectSet_FindFirst(objSet))) { + if (ObjectIsRestrictQualified(obj)) { + LocationSet_Term(tmp); + LocationSet_InitUnknown(tmp, indRtype, block, NULL); + } + } + } + } + + result |= AddToInitialPointsToFunc(unk, ptf, dst, mySet); + } else { + // Boolean result1; + Stack *next; + StackElement *element; + + result = GetActualLocsOfExtendedParam(NULL, dst, NULL, stackPtr, map, unk); + if (stackPtr && *stackPtr && (next = Stack_Next(stackPtr)) && (element = Stack_Top(&next))) { + result |= Lookup(mySet, &next, StackElement_proc(element), StackElement_map(element), + StackElement_ptf(element), dst, StackElement_funcCall(element)->pointsToFunction, unk, indRtype); + } else { + LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); + } + + result |= AddToInitialPointsToFunc(unk, ptf, dst, mySet); + } + } else if ( + block && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && + (local = PAMemoryBlock_thing(block)) && + proc && + (obj = GetLocalObject(local, proc, 1)) && + ObjectIsAFunctionArgument(proc, obj) + ) { + result = LookupParam(mySet, dst, obj, stackPtr, proc, map, ptf, unk); + } else { + LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); + } + } + + if (set) + LocationSetSet_AddSet(set, mySet); + + LocationSetSet_Term(mySet); + LocationSetSet_Delete(mySet); + + return result; +} + +static Boolean InputsHaveNewPointerValues(PartialTransferFunction *tgtPTF, PartialTransferFunction *ptf) { +#line 3393 + IRO_ASSERT(tgtPTF != NULL); + IRO_ASSERT(ptf != NULL); + + return 0; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct CreateEPActionParams { + ParamMapping *last; + ParamMapping *lowest; +} CreateEPActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void CreateExtendedParamAction(ParamMapping *mapping, void *refcon) { + CreateEPActionParams *params; + ExtendedParam *ep; + uint32 value; + ExtendedParam *lowestEP; + uint32 lowestValue; + ExtendedParam *lastEP; + uint32 lastValue; + +#line 3417 + IRO_ASSERT(mapping != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + + IRO_ASSERT(params->last == NULL || params->last != NULL); + IRO_ASSERT(params->lowest == NULL || params->lowest != NULL); + + if ((ep = ParamMapping_extended(mapping))) { + value = ExtendedParam_sub_489110(ep); + + if (params->lowest) { + lowestEP = ParamMapping_extended(params->lowest); + lowestValue = ExtendedParam_sub_489110(lowestEP); + if (params->last) { + lastEP = ParamMapping_extended(params->last); + lastValue = ExtendedParam_sub_489110(lastEP); + if (value > lastValue && value < lowestValue) + params->lowest = mapping; + } else if (value < lowestValue) { + params->lowest = mapping; + } + } else if (params->last) { + lastEP = ParamMapping_extended(params->last); + lastValue = ExtendedParam_sub_489110(lastEP); + if (value > lastValue) + params->lowest = mapping; + } else { + params->lowest = mapping; + } + } +} + +static ExtendedParam *FindMatchingExtendedParam(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *lss, ParamMapping *lowest, Boolean *result) { + ExtendedParam *ep; + ExtendedParam *lowestEP; + +#line 3473 + IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(map == NULL || map != NULL); + IRO_ASSERT(lss != NULL); + IRO_ASSERT(lowest != NULL); + + ep = NULL; + if ((lowestEP = ParamMapping_extended(lowest))) { + PAMemoryBlock *block; + LocationSet *lowestLS; + LocationSetSet *lowestLSS; + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, lowestEP); + + lowestLS = LocationSet_New(); + LocationSet_InitKnown(lowestLS, block, cint64_zero, 0, TYPE(&void_ptr)); + + lowestLSS = LocationSetSet_New(); + LocationSetSet_Init(lowestLSS); + + *result |= GetActualLocsOfExtendedParam(lowestLSS, lowestLS, NULL, stackPtr, map, 0); + if (LocationSetSets_Equal(lowestLSS, lss)) + ep = lowestEP; + + LocationSetSet_Term(lowestLSS); + LocationSetSet_Delete(lowestLSS); + + LocationSet_Term(lowestLS); + LocationSet_Delete(lowestLS); + } + + return ep; +} + +static ExtendedParam *CreateExtendedParam(Stack **stackPtr, ParamMappingFunction *map, Object *var, Boolean *result) { + ExtendedParam *ep; + ParamMapping *mapping; + LocationSetSet *lss; + CreateEPActionParams params; + +#line 3518 + IRO_ASSERT(map == NULL || map != NULL); + IRO_ASSERT(stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(var != NULL); + + mapping = NULL; + if (map) + mapping = ParamMappingFunction_FindMappingByFormal(map, var); + + ep = ExtendedParam_FindByObject(var); + if (ep) { + if (mapping) { +#line 3535 + IRO_ASSERT(ep == ParamMapping_extended(mapping) || ParamMapping_extended(mapping) == NULL); + } + } else if (map && !ObjectIsRestrictQualified(var)) { + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + *result |= GetActualLocsOfExtendedParam(lss, NULL, var, stackPtr, map, 0); + + memset(¶ms, 0, sizeof(params)); + params.last = NULL; + do { + params.lowest = NULL; + pmf_sub_487C70(map, CreateExtendedParamAction, ¶ms); + if (params.lowest && params.lowest != mapping) + ep = FindMatchingExtendedParam(stackPtr, map, lss, params.lowest, result); + params.last = params.lowest; + } while (params.lowest && !ep); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } + + if (!ep) + ep = ExtendedParam_FindByObject(var); + + if (!ep) { + ep = ExtendedParam_New(); + ExtendedParam_Init(ep, var); + } else { + ExtendedParam_sub_4867B0(ep, var); + } + + if (stExtParamSet) + ExtParamSet_sub_487630(stExtParamSet, ep); + +#line 3583 + IRO_ASSERT(ep != NULL); + + return ep; +} + +#ifdef IRO_DEBUG +void __assertion_failed(char *expr, char *filename, int line) { +#line 3605 + CError_ASSERT(filename); + CError_Internal(filename, line); +} +#endif + +static void RecordActuals(IROLinear *nd, Object *proc, ParamMappingFunction *map) { +#line 3628 + IRO_ASSERT(nd != NULL); + IRO_ASSERT(nd->type == IROLinearFunccall); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(map != NULL); + + if (proc != &stUnknown) { + int i; + ObjectList *args; + Object *arg; + + args = FunctionArguments(proc); + if (args) + arg = args->object; + else + arg = &stUnknown; + + for (i = 0; i < nd->u.funccall.argCount; i++) { +#line 3643 + IRO_ASSERT(arg != NULL); + + if (arg != &stUnknown) { + ParamMapping *mapping = ParamMapping_New(); + ParamMapping_Init_PROBABLY(mapping, nd->u.funccall.args[i], arg, NULL); + Pmf_Add_sub_486610(map, mapping); + ParamMapping_Term(mapping); + ParamMapping_Delete(mapping); + } + + if (args) { + args = args->next; + if (args) + arg = args->object; + else + arg = &stUnknown; + } + } + } +} + +static Boolean IsAddressableLocation(LocationSet *loc, Object *proc, IRONode *fnode, IROLinear *nd) { +#line 3676 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(fnode != NULL); + IRO_ASSERT(nd != NULL); + + if (!LocationSet_IsUnknown(loc)) { + PAMemoryBlock *block; + PALocalVar *local; + Object *obj; + ExtendedParam *ep; + ObjectSet *objSet; + + block = LocationSet_block(loc); + if ( + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && + (local = PAMemoryBlock_thing(block)) && + (obj = GetLocalObject(local, proc, 0)) && + fnode->addressed && + !ObjectSet_sub_485020(fnode->addressed, obj) + ) { + return 0; + } + + if ( + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && + (ep = PAMemoryBlock_thing(block)) && + (objSet = ExtendedParam_objectSet(ep)) && + ObjectSet_Count(objSet) == 1 && + (obj = ObjectSet_FindFirst(objSet)) && + ObjectIsAFunctionArgument(proc, obj) && + ObjectIsRestrictQualified(obj) + ) { + return 0; + } + } + + return 1; +} + +static Boolean LocationSetsAlias(LocationSet *ls1, LocationSet *ls2) { +#line 3719 + IRO_ASSERT(ls1 != NULL); + IRO_ASSERT(ls2 != NULL); + + return + (ls1 == ls2) || + LocationSet_IsUnknown(ls1) || + LocationSet_IsUnknown(ls2) || + ( + (LocationSet_stride(ls1) || + LocationSet_stride(ls2) || + CInt64_Equal(LocationSet_field(ls1), LocationSet_field(ls2))) && + MemoryBlocks_Equal(LocationSet_block(ls1), LocationSet_block(ls2)) + ); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct FindAliasingParams { + LocationSetSet *x0; + LocationSet *x4; + Boolean x8; +} FindAliasingParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void FindAliasingAction2(LocationSet *ls, void *refcon) { + FindAliasingParams *params; + + params = refcon; + + if (!params->x8) { + if (LocationSetsAlias(params->x4, ls)) + params->x8 = 1; + } +} + +static void FindAliasingAction(LocationSet *ls, void *refcon) { + FindAliasingParams *params; + +#line 3751 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + + if (!params->x8) { + params->x4 = ls; + LocationSetSet_ForEach(params->x0, FindAliasingAction2, params); + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct KillLocationParams { + Object *proc; + IRONode *fnode; + IROLinear *nd; + PartialTransferFunction *ptf; + PointsToFunction *toBeKilled; + LocationSet *dst; + Boolean x18; +} KillLocationParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void KillAllAddressableLocationsAction(PointsToEntry *pte, void *refcon) { + KillLocationParams *params; + LocationSet *loc; + +#line 3779 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 3784 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->fnode != NULL); + IRO_ASSERT(params->nd != NULL); + IRO_ASSERT(params->ptf != NULL); + IRO_ASSERT(params->toBeKilled != NULL); + IRO_ASSERT(params->dst == NULL); + + loc = PointsToEntry_loc(pte); +#line 3793 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(loc)); + + if (IsAddressableLocation(loc, params->proc, params->fnode, params->nd)) + PointsToFunction_Add(params->toBeKilled, pte); +} + +static void KillAllAliasingExtParamLocsAction(PointsToEntry *pte, void *refcon) { + KillLocationParams *params; + LocationSet *loc; + +#line 3813 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 3818 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->fnode != NULL); + IRO_ASSERT(params->nd != NULL); + IRO_ASSERT(params->ptf != NULL); + IRO_ASSERT(params->toBeKilled != NULL); + IRO_ASSERT(params->dst != NULL); + IRO_ASSERT(LocationSet_block(params->dst) != NULL); + IRO_ASSERT(PAMemoryBlock_kind(LocationSet_block(params->dst)) == PAMEMORYBLOCKKIND_EXTENDEDPARAM); + + loc = PointsToEntry_loc(pte); +#line 3829 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(loc)); + + if (loc != params->dst) { + if (LocationSetsAlias(loc, params->dst)) { + PointsToFunction_Add(params->toBeKilled, pte); + } else { + ExtendedParam *ep; + ObjectSet *objSet; + Object *obj; + PAMemoryBlock *block; + + if ( + (ep = PAMemoryBlock_thing(LocationSet_block(params->dst))) && + (objSet = ExtendedParam_objectSet(ep)) && + (ObjectSet_Count(objSet) != 1 || !(obj = ObjectSet_FindFirst(objSet)) || !ObjectIsRestrictQualified(obj)) && + (block = LocationSet_block(loc)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && + (ep = PAMemoryBlock_thing(block)) && + (objSet = ExtendedParam_objectSet(ep)) && + (ObjectSet_Count(objSet) != 1 || !(obj = ObjectSet_FindFirst(objSet)) || !ObjectIsRestrictQualified(obj)) + ) { + LocationSetSet *lss1; + LocationSetSet *lss2; + Boolean changed; + FindAliasingParams aparams; + + lss1 = LocationSetSet_New(); + LocationSetSet_Init(lss1); + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + + changed = GetActualLocsOfExtendedParam(lss1, loc, NULL, &stCallingContextStack, NULL, 0); + changed |= GetActualLocsOfExtendedParam(lss2, params->dst, NULL, &stCallingContextStack, NULL, 0); + + memset(&aparams, 0, sizeof(aparams)); + aparams.x8 = 0; + aparams.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, &aparams); + if (aparams.x8) + PointsToFunction_Add(params->toBeKilled, pte); + + LocationSetSet_Term(lss1); + LocationSetSet_Delete(lss1); + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } + } + } +} + +static void KillLocationsAction(PointsToEntry *pte, void *refcon) { + KillLocationParams *params; + LocationSet *loc; + LocationSetSet *lss; + +#line 3886 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 3891 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->fnode != NULL); + IRO_ASSERT(params->nd != NULL); + IRO_ASSERT(params->ptf != NULL); + IRO_ASSERT(params->toBeKilled != NULL); + IRO_ASSERT(params->dst == NULL); + + loc = PointsToEntry_loc(pte); +#line 3900 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(loc)); + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + + params->x18 |= Assign(params->ptf, loc, lss, params->proc, params->nd, params->fnode); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); +} + +static Boolean KillAllAddressableLocations(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf) { + Boolean result; + PointsToFunction *pointsToFunc; + PointsToFunction *pointsToFuncCopy; + PointsToFunction *toBeKilled; + KillLocationParams params; + +#line 3921 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(fnode == NULL || fnode != NULL); + IRO_ASSERT(nd == NULL || nd != NULL); + IRO_ASSERT(ptf != NULL); + + if (nd && nd->pointsToFunction) + pointsToFunc = nd->pointsToFunction; + else + pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); + + pointsToFuncCopy = PointsToFunction_New(); + PointsToFunction_Copy(pointsToFuncCopy, pointsToFunc); + + toBeKilled = PointsToFunction_New(); + PointsToFunction_Init(toBeKilled); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.fnode = fnode; + params.nd = nd; + params.ptf = ptf; + params.toBeKilled = toBeKilled; + params.dst = NULL; + params.x18 = 0; + + if (pointsToFunc) { + PointsToFunction_ForEach(pointsToFunc, KillAllAddressableLocationsAction, ¶ms); + PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, ¶ms); + } + + PointsToFunction_Term(toBeKilled); + PointsToFunction_Delete(toBeKilled); + + if (params.x18) + result = !PointsToFunctions_Equal(pointsToFuncCopy, pointsToFunc); + else + result = 0; + + PointsToFunction_Term(pointsToFuncCopy); + PointsToFunction_Delete(pointsToFuncCopy); + + return result; +} + +static void KillAllAliasingExtParamLocs(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, LocationSet *dst) { + PointsToFunction *pointsToFunc; + PointsToFunction *toBeKilled; + KillLocationParams params; + +#line 3974 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(fnode == NULL || fnode != NULL); + IRO_ASSERT(nd == NULL || nd != NULL); + IRO_ASSERT(ptf != NULL); + IRO_ASSERT(dst != NULL); + + if (!LocationSet_IsUnknown(dst) && LocationSet_block(dst)) { + if (PAMemoryBlock_kind(LocationSet_block(dst)) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + + if (nd && nd->pointsToFunction) + pointsToFunc = nd->pointsToFunction; + else + pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); + + toBeKilled = PointsToFunction_New(); + PointsToFunction_Init(toBeKilled); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.fnode = fnode; + params.nd = nd; + params.ptf = ptf; + params.toBeKilled = toBeKilled; + params.dst = dst; + params.x18 = 0; + + if (pointsToFunc) { + PointsToFunction_ForEach(pointsToFunc, KillAllAliasingExtParamLocsAction, ¶ms); + PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, ¶ms); + } + + PointsToFunction_Term(toBeKilled); + PointsToFunction_Delete(toBeKilled); + } + } +} + +static Boolean Assign(PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *srcs, Object *proc, IROLinear *nd, IRONode *fnode) { + PointsToFunction *pointsToFunc; + Boolean result; + PointsToEntry *pte; + LocationSet *loc; + LocationSetSet *locs; + LocationSet *bitfieldOf; + LocationSetSet *lss; + +#line 4027 + IRO_ASSERT(ptf != NULL); + IRO_ASSERT(dst != NULL); + IRO_ASSERT(srcs != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(nd == NULL || nd != NULL); + IRO_ASSERT(fnode == NULL || fnode != NULL); + + if (nd) { + if (!nd->pointsToFunction) { + nd->pointsToFunction = PointsToFunction_New(); + PointsToFunction_Init(nd->pointsToFunction); + } + pointsToFunc = nd->pointsToFunction; + } else { + pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); + } + + pte = PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, dst); + if (pte) { + loc = PointsToEntry_loc(pte); + locs = PointsToEntry_locs(pte); +#line 4056 + IRO_ASSERT(!LocationSet_IsUnknown(dst)); + IRO_ASSERT(LocationSet_stride(dst) == 0 || LocationSet_stride(loc) != 0); + + result = !LocationSetSets_Equal(srcs, locs) || LocationSet_stride(dst) != LocationSet_stride(loc); + + if (result) { + pte = PointsToEntry_New(); + PointsToEntry_Init(pte, dst, srcs); + PointsToFunction_RemoveByLocationSet(pointsToFunc, loc); + PointsToFunction_AddWithoutChecking(pointsToFunc, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } + } else if (!LocationSet_IsUnknown(dst)) { + KillAllAliasingExtParamLocs(proc, fnode, nd, ptf, dst); + + pte = PointsToEntry_New(); + PointsToEntry_Init(pte, dst, srcs); + result = PointsToFunction_AddWithoutChecking(pointsToFunc, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } else if ((bitfieldOf = LocationSet_bitfieldOf(dst))) { + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + result = Assign(ptf, bitfieldOf, lss, proc, nd, fnode); + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } else if (!LocationSet_restriction(dst)) { + result = KillAllAddressableLocations(proc, fnode, nd, ptf); + } + + return result; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalMeetActionParams { + Object *proc; + IRONode *fnode; + IRONode *pred; + IROLinear *nd; + PartialTransferFunction *ptf; + Boolean x14; + Boolean x15; +} EvalMeetActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalMeetAction(PointsToEntry *pte, void *refcon) { + EvalMeetActionParams *params; + LocationSet *loc; + LocationSetSet *set; + UInt16 i; + +#line 4123 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 4128 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->fnode != NULL); + IRO_ASSERT(params->pred != NULL); + IRO_ASSERT(params->nd != NULL); + IRO_ASSERT(params->ptf != NULL); + + loc = PointsToEntry_loc(pte); + + set = LocationSetSet_New(); + LocationSetSet_Init(set); + LocationSetSet_AddSet(set, PointsToEntry_locs(pte)); + + for (i = 0; i < params->fnode->numpred; i++) { + IRONode *pred = FunctionNodeTable(params->proc)[params->fnode->pred[i]]; + if (pred->x3C && pred != params->pred) { + params->x14 |= Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, loc, pred->last->pointsToFunction, 0, NULL); + } + } + + params->x15 |= Assign(params->ptf, loc, set, params->proc, params->nd, params->fnode); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); +} + +static Boolean EvalMeet(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf) { + PointsToFunction *pointsToFunc; + EvalMeetActionParams params; + int i; + +#line 4163 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(fnode != NULL); + IRO_ASSERT(nd != NULL); + IRO_ASSERT(ptf != NULL); + + pointsToFunc = PointsToFunction_New(); + if (nd->pointsToFunction) + PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction); + else + PointsToFunction_Init(pointsToFunc); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.fnode = fnode; + params.nd = nd; + params.ptf = ptf; + params.x14 = 0; + params.x15 = 0; + + for (i = 0; i < fnode->numpred; i++) { + IRONode *pred = FunctionNodeTable(proc)[fnode->pred[i]]; + params.pred = pred; + if (pred->x3C && pred->last->pointsToFunction) { + PointsToFunction_ForEach(pred->last->pointsToFunction, EvalMeetAction, ¶ms); + } + } + + if (!params.x14 && params.x15) { + if (nd->pointsToFunction) + params.x14 = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction); + else + params.x14 = PointsToFunction_FindFirst(pointsToFunc) != NULL; + } + + PointsToFunction_Term(pointsToFunc); + PointsToFunction_Delete(pointsToFunc); + + return params.x14; +} + +static PartialTransferFunction *AllocatePTF(Object *proc, IROLinear *nd, PartialTransferFunction *ptf) { + PartialTransferFunction *newPTF; + +#line 4210 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(proc->u.func.ptfList != NULL); + IRO_ASSERT(nd == NULL || nd != NULL); + IRO_ASSERT(ptf == NULL || ptf != NULL); + + newPTF = PartialTransferFunction_New(); + PartialTransferFunction_Init(newPTF, nd, ptf); + PTFList_sub_48A050(proc->u.func.ptfList, newPTF); + return newPTF; +} + +static Object *FindMainEntryPoint(Object *function) { +#line 4229 + IRO_ASSERT(function != NULL); + + return function; +} + +static ObjectList *FunctionArguments(Object *proc) { + Object *search; + ObjectList *scan; + ObjectList *list; + ObjectList *prev; + ExtendedParam *ep; + char *name; + VarInfo *vi; + Object *obj; + FuncArg *args; + Boolean notFound; + +#line 4252 + IRO_ASSERT(proc != NULL); + + if (proc == stCurrentProc) { + for (list = arguments; list; list = list->next) { + if ((obj = list->object) && obj->name && (name = obj->name->name) && name[0]) { + prev = NULL; + for (scan = proc->u.func.argList; scan; scan = scan->next) { + prev = scan; + if ((search = scan->object) && search->name && search->name->name) { + if (!strcmp(name, search->name->name)) + break; + } + } + + if (!scan) + search = NULL; + + notFound = !search; + + if (!search) { + search = IRO_malloc(sizeof(Object)); + ep = NULL; + search->u.var.info = IRO_malloc(sizeof(VarInfo)); + memset(search->u.var.info, 0, sizeof(VarInfo)); + search->u.var.info->func = proc; + } else { + ep = search->extParam; + } + + vi = search->u.var.info; + memcpy(search, obj, sizeof(Object)); + search->extParam = ep; + search->u.var.info = vi; + search->u.var.realObj = obj; + + if (notFound) { + scan = IRO_malloc(sizeof(ObjectList)); + scan->next = NULL; + scan->object = search; + if (!prev) + proc->u.func.argList = scan; + else + prev->next = scan; + } + } + } + } else if (proc->type) { + for (args = TYPE_FUNC(proc->type)->args; args; args = args->next) { + if (args->name && (name = args->name->name) && name[0]) { + prev = NULL; + for (scan = proc->u.func.argList; scan; scan = scan->next) { + prev = scan; + if ((search = scan->object) && search->name && search->name->name) { + if (!strcmp(name, search->name->name)) + break; + } + } + + if (!scan) + search = NULL; + + if (!search) { + search = IRO_malloc(sizeof(Object)); + memset(search, 0, sizeof(Object)); + search->datatype = DLOCAL; + search->extParam = NULL; + search->name = GetHashNameNodeExport(name); + search->type = args->type; + search->qual = args->qual; + search->u.var.info = IRO_malloc(sizeof(VarInfo)); + memset(search->u.var.info, 0, sizeof(VarInfo)); + search->u.var.info->func = proc; + + scan = IRO_malloc(sizeof(ObjectList)); + scan->next = NULL; + scan->object = search; + if (!prev) + proc->u.func.argList = scan; + else + prev->next = scan; + } + } + } + } + + return proc->u.func.argList; +} + +static IRONode **FunctionNodeTable(Object *proc) { +#line 4383 + IRO_ASSERT(proc != NULL); + +#line 4391 + IRO_ASSERT(proc == stCurrentProc); + + return IRO_NodeTable; +} + +static IRONode *FunctionFirstNode(Object *proc) { +#line 4401 + IRO_ASSERT(proc != NULL); + +#line 4409 + IRO_ASSERT(proc == stCurrentProc); + + return IRO_FirstNode; +} + +static void UpdatePTFDomain() { + // no idea what this would've done +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalCallActionParams { + Object *proc; + IRONode *fnode; + IROLinear *nd; + PartialTransferFunction *ptf; + ParamMappingFunction *map; + int x14; + Boolean x18; + Boolean x19; + Boolean x1A; +} EvalCallActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalCallAction(Object *proc, void *refcon) { + EvalCallActionParams *params; + ParamMappingFunction *pmf; + PartialTransferFunction *tgtPTF; + Boolean flag; + Boolean flag2; + +#line 4458 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 4463 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->fnode != NULL); + IRO_ASSERT(params->nd != NULL); + IRO_ASSERT(params->ptf != NULL); + IRO_ASSERT(params->map == NULL || params->map != NULL); + + if (!params->x18) { + pmf = ParamMappingFunction_New(); + ParamMappingFunction_Init(pmf); + RecordActuals(params->nd, proc, pmf); + + flag = 0; + if (!Stack_sub_48A710(&stCallingContextStack, proc)) { + StackElement *element; + + flag2 = 0; + tgtPTF = GetPTF(pmf, proc, params->nd, params->ptf, &flag2); + + element = StackElement_New(); + StackElement_Init(element, proc, tgtPTF, pmf, params->nd); + Stack_sub_48A660(&stCallingContextStack, element); + StackElement_Term(element); + StackElement_Delete(element); + +#line 4490 + IRO_ASSERT(tgtPTF != NULL); + + flag = 1; + + if (stPTFList) + PTFList_sub_48A050(stPTFList, tgtPTF); + PartialTransferFunction_sub_48A610(tgtPTF, 0); + + if (flag2 || params->x1A) { + if (params->x1A) { + params->x1A = 0; + EvalProc(proc, pmf, tgtPTF); + } else { + tgtPTF = stUnknownPTF; + } + } + } else { + tgtPTF = stUnknownPTF; + } + + if (params->map) + params->x19 |= ApplySummary(tgtPTF, pmf, params->proc, params->fnode, params->nd, params->ptf, params->map, params->x14 == 1); + + if (flag) { + StackElement *element = Stack_sub_48A5B0(&stCallingContextStack); + StackElement_Term(element); + StackElement_Delete(element); + } + + ParamMappingFunction_Term(pmf); + ParamMappingFunction_Delete(pmf); + } +} + +static Boolean EvalCall(Object *proc, IRONode *fnode, IROLinear *nd, ParamMappingFunction *map, PartialTransferFunction *ptf) { + EvalCallActionParams params; + ObjectSet *objSet; + +#line 4548 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(fnode != NULL); + IRO_ASSERT(nd != NULL); + IRO_ASSERT(map != NULL); + IRO_ASSERT(ptf != NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.fnode = fnode; + params.nd = nd; + params.ptf = ptf; + params.map = map; + params.x18 = 0; + params.x19 = 0; + params.x1A = 0; + + objSet = ObjectSet_New(); + ObjectSet_Init(objSet); + + params.x19 |= FindCallTargets(objSet, proc, nd, map, ptf); + params.x14 = ObjectSet_Count(objSet); + ObjectSet_ForEach(objSet, EvalCallAction, ¶ms); + + ObjectSet_Term(objSet); + ObjectSet_Delete(objSet); + + return params.x19; +} + +static void AdjustTypesForVolatilityAction(LocationSet *ls, void *refcon) { + Type *type; + Type *newtype; + UInt32 qual; + + type = LocationSet_rtype(ls); + switch (type->type) { + case TYPEARRAY: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEPOINTER: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(type)->qual; + break; + default: +#line 4604 + CError_FATAL(); + } + + if (!(qual & Q_VOLATILE)) { + switch (type->type) { + case TYPEARRAY: + newtype = CDecl_NewArrayType(TYPE_POINTER(type)->target, type->size); + TYPE_POINTER(newtype)->qual |= Q_VOLATILE; + break; + case TYPEPOINTER: + newtype = CDecl_NewPointerType(TYPE_POINTER(type)->target); + TYPE_POINTER(newtype)->qual |= Q_VOLATILE; + break; + case TYPEMEMBERPOINTER: + newtype = galloc(sizeof(TypeMemberPointer)); + memcpy(newtype, type, sizeof(TypeMemberPointer)); + TYPE_MEMBER_POINTER(newtype)->qual |= Q_VOLATILE; + break; + } + + LocationSet_SetRtype(ls, newtype); + } +} + +static void AdjustTypesForVolatility(LocationSetSet *set, Object *proc, IROLinear *nd) { + if (nd->rtype && CParser_IsVolatile(nd->rtype, nd->nodeflags & ENODE_FLAG_QUALS)) + LocationSetSet_ForEach(set, AdjustTypesForVolatilityAction, NULL); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalAssignAction2Params { + CInt64 x0; + IROLinear *nd; + Boolean xC; +} EvalAssignAction2Params; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalAssignAction2(LocationSet *ls, void *refcon) { + EvalAssignAction2Params *params; + CInt64 value; + IROLinear *nd; + ENodeType oper; + UInt32 stride; + Type *rtype; + PAMemoryBlock *block; + +#line 4657 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + + if (!params->xC && !LocationSet_IsUnknown(ls)) { + value = params->x0; + nd = params->nd; +#line 4665 + IRO_ASSERT(nd != NULL); + oper = nd->nodetype; + + stride = LocationSet_stride(ls); + rtype = LocationSet_rtype(ls); + block = LocationSet_block(ls); + + if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT) { + LocationSet_Term(ls); + + switch (oper) { + case EPOSTINC: + case EPREINC: + case EADDASS: + value = CInt64_Add(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EPOSTDEC: + case EPREDEC: + case ESUBASS: + value = CInt64_Sub(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EMULASS: + if (IRO_IsUnsignedType(nd->rtype)) + value = CInt64_MulU(*((CInt64 *) PAMemoryBlock_thing(block)), value); + else + value = CInt64_Mul(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EDIVASS: + if (CInt64_IsZero(&value)) { + if (nd->stmt->sourceoffset) { + TStreamElement *e = CPrep_CurStreamElement(); + e->tokenoffset = nd->stmt->sourceoffset; + CError_SetErrorToken(e); + } + CError_Warning(CErrorStr139); + params->xC = 1; + } else { + if (IRO_IsUnsignedType(nd->rtype)) + value = CInt64_DivU(*((CInt64 *) PAMemoryBlock_thing(block)), value); + else + value = CInt64_Div(*((CInt64 *) PAMemoryBlock_thing(block)), value); + } + break; + case EMODASS: + if (CInt64_IsZero(&value)) { + if (nd->stmt->sourceoffset) { + TStreamElement *e = CPrep_CurStreamElement(); + e->tokenoffset = nd->stmt->sourceoffset; + CError_SetErrorToken(e); + } + CError_Warning(CErrorStr139); + params->xC = 1; + } else { + if (IRO_IsUnsignedType(nd->rtype)) + value = CInt64_ModU(*((CInt64 *) PAMemoryBlock_thing(block)), value); + else + value = CInt64_Mod(*((CInt64 *) PAMemoryBlock_thing(block)), value); + } + break; + case ESHLASS: + value = CInt64_Shl(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case ESHRASS: + if (IRO_IsUnsignedType(nd->rtype)) + value = CInt64_ShrU(*((CInt64 *) PAMemoryBlock_thing(block)), value); + else + value = CInt64_Shr(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EANDASS: + value = CInt64_And(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EXORASS: + value = CInt64_Xor(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EORASS: + value = CInt64_Or(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + default: +#line 4746 + CError_FATAL(); + } + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &value); + LocationSet_InitKnown(ls, block, cint64_zero, stride, rtype); + } else { + if (oper == EPOSTDEC || oper == EPREDEC || oper == ESUBASS) + value = CInt64_Neg(value); + + switch (oper) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EADDASS: + case ESUBASS: + value = CInt64_Add(LocationSet_field(ls), value); + if (stride) { + CInt64 tmp; + CInt64_SetLong(&tmp, stride); + value = CInt64_Mod(value, tmp); + } + SetsLocationSetField_sub_4851B0(ls, value); + break; + default: + params->xC = 1; + break; + } + } + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalAssignActionParams { + Object *proc; + PartialTransferFunction *ptf; + IROLinear *nd; + IRONode *fnode; + LocationSetSet *srcs; + Boolean x14; + Boolean x15; + Boolean x16; +} EvalAssignActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalAssignAction(LocationSet *dst, void *refcon) { + EvalAssignActionParams *params; + LocationSetSet *srcs; + +#line 4797 + IRO_ASSERT(dst != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 4802 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->ptf != NULL); + IRO_ASSERT(params->nd != NULL); + IRO_ASSERT(params->fnode != NULL); + IRO_ASSERT(params->srcs != NULL); + + srcs = params->srcs; + if ( + !params->x14 || + !LocationSetRepresentsSingleLocation(dst, params->proc, params->nd->pointsToFunction) || + LocationIsVolatile(dst, params->proc) || + LocationSet_sub_48AF30(dst) + ) { + LocationSetSet *set = LocationSetSet_New(); + LocationSetSet_Init(set); + params->x15 |= Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, dst, params->nd->pointsToFunction, 0, params->nd->rtype); + LocationSetSet_AddSet(srcs, set); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } + + params->x16 |= Assign(params->ptf, dst, srcs, params->proc, params->nd, params->fnode); +} + +static Boolean EvalAssign(Object *proc, IROLinear *nd, IRONode *fnode, ParamMappingFunction *map, PartialTransferFunction *ptf) { + EvalAssignActionParams params; + EvalAssignAction2Params params2; + LocationSetSet *set; + LocationSet *tmp; + PAMemoryBlock *block; + Type *type; + +#line 4840 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(nd != NULL); + IRO_ASSERT(fnode != NULL); + IRO_ASSERT(map != NULL); + IRO_ASSERT(ptf != NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + params.nd = nd; + params.fnode = fnode; + params.x15 = 0; + params.x16 = 0; + + set = LocationSetSet_New(); + params.srcs = LocationSetSet_New(); + LocationSetSet_Init(set); + LocationSetSet_Init(params.srcs); + + if (nd->type == IROLinearOp2Arg) { +#line 4861 + IRO_ASSERT(nd->u.diadic.left->type == IROLinearOp1Arg && nd->u.diadic.left->nodetype == EINDIRECT); + + params.x15 |= EvalExpr(set, proc, nd->u.diadic.left->u.monadic, &stCallingContextStack, map, ptf); + AdjustTypesForVolatility(set, proc, nd->u.diadic.left); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.right, &stCallingContextStack, map, ptf); + + if (nd->nodetype != EASS) { + switch (nd->nodetype) { + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + if ( + LocationSetSet_Count(params.srcs) == 1 && + (tmp = LocationSetSet_FindFirst(params.srcs)) && + !LocationSet_IsUnknown(tmp) && + !LocationSet_stride(tmp) && + (block = LocationSet_block(tmp)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT + ) { + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf); + + memset(¶ms2, 0, sizeof(params2)); + params2.x0 = *((CInt64 *) PAMemoryBlock_thing(block)); + IRO_TruncateValueToType(¶ms2.x0, nd->u.diadic.right->rtype); + params2.nd = nd; + params2.xC = 0; + + if (!CInt64_IsZero(¶ms2.x0)) { + LocationSetSet_ForEach(params.srcs, EvalAssignAction2, ¶ms2); + if (params2.xC) { + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf); + if (!LocationSetSet_FindUnknown(params.srcs)) + LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one); + } + } + } else { + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf); + if (!LocationSetSet_FindUnknown(params.srcs)) + LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one); + } + break; + default: + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + LocationSetSet_AddUnknown(params.srcs, nd->rtype, NULL, NULL); + break; + } + } + } else if (nd->type == IROLinearOp1Arg) { +#line 4958 + IRO_ASSERT(nd->u.monadic.left->type == IROLinearOp1Arg && nd->u.monadic->nodetype == EINDIRECT); + + params.x15 |= EvalExpr(set, proc, nd->u.monadic->u.monadic, &stCallingContextStack, map, ptf); + AdjustTypesForVolatility(set, proc, nd->u.monadic); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf); + + switch (nd->nodetype) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + memset(¶ms2, 0, sizeof(params2)); + params2.x0 = cint64_one; + params2.nd = nd; + params2.xC = 0; + + type = NULL; + if (IS_TYPE_POINTER(nd->rtype)) + type = TPTR_TARGET(nd->rtype); + else if (IS_TYPE_MEMBERPOINTER(nd->rtype)) + type = TYPE_MEMBER_POINTER(nd->rtype)->ty1; + + if (type) + CInt64_SetLong(¶ms2.x0, type->size); + + if (!CInt64_IsZero(¶ms2.x0)) { + LocationSetSet_ForEach(params.srcs, EvalAssignAction2, ¶ms2); + if (params2.xC) { + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf); + if (!LocationSetSet_FindUnknown(params.srcs)) + LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one); + } + } + break; + + default: + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + LocationSetSet_AddUnknown(params.srcs, nd->rtype, NULL, NULL); + break; + } + } else { +#line 5006 + CError_FATAL(); + } + + if (LocationSetSet_Count(params.srcs) != 0) { + PointsToFunction *pointsToFunc; + + pointsToFunc = PointsToFunction_New(); + if (nd->pointsToFunction) + PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction); + else + PointsToFunction_Init(pointsToFunc); + + params.x14 = LocationSetSet_Count(set) == 1; + LocationSetSet_ForEach(set, EvalAssignAction, ¶ms); + + if (!params.x15 && params.x16) { + if (nd->pointsToFunction) + params.x15 = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction); + else + params.x15 = PointsToFunction_FindFirst(pointsToFunc) != NULL; + } + + PointsToFunction_Term(pointsToFunc); + PointsToFunction_Delete(pointsToFunc); + } + + LocationSetSet_Term(set); + LocationSetSet_Term(params.srcs); + LocationSetSet_Delete(set); + LocationSetSet_Delete(params.srcs); + + return params.x15; +} + +static Boolean EvalReturn(Object *proc, IROLinear *nd, IRONode *fnode, ParamMappingFunction *map, PartialTransferFunction *ptf) { + EvalAssignActionParams params; + LocationSet *loc; + +#line 5046 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(nd != NULL); + IRO_ASSERT(nd->type == IROLinearReturn); + IRO_ASSERT(fnode != NULL); + IRO_ASSERT(map != NULL); + IRO_ASSERT(ptf != NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + params.nd = nd; + params.fnode = fnode; + params.x15 = 0; + params.x16 = 0; + + if (nd->u.monadic) { + params.srcs = LocationSetSet_New(); + LocationSetSet_Init(params.srcs); + + loc = PartialTransferFunction_returnLocation(ptf); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf); + + if (LocationSetSet_Count(params.srcs) != 0) { + params.x14 = 1; + EvalAssignAction(loc, ¶ms); + params.x15 |= params.x16; + } + + LocationSetSet_Term(params.srcs); + LocationSetSet_Delete(params.srcs); + } + + return params.x15; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct ApplySummaryActionParams { + ParamMappingFunction *tgtMap; + Object *proc; + IRONode *fnode; + IROLinear *nd; + PartialTransferFunction *ptf; + ParamMappingFunction *map; + LocationSet *loc; + LocationSetSet *locs; + Boolean x20; + Boolean x21; + Boolean x22; +} ApplySummaryActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void ApplySummaryAction2(ParamMapping *mapping, void *refcon) { + ApplySummaryActionParams *params; + PAMemoryBlock *block; + ExtendedParam *ep; + IROLinear *nd; + LocationSetSet *set; + EvalAssignActionParams assignParams; + +#line 5108 + IRO_ASSERT(mapping != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 5113 + IRO_ASSERT(params->tgtMap != NULL); + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->fnode != NULL); + IRO_ASSERT(params->nd != NULL); + IRO_ASSERT(params->nd->type == IROLinearFunccall); + IRO_ASSERT(params->ptf != NULL); + IRO_ASSERT(params->map != NULL); + IRO_ASSERT(params->loc != NULL); + IRO_ASSERT(params->locs != NULL); + + block = LocationSet_block(params->loc); + +#line 5124 + IRO_ASSERT(block != NULL); + IRO_ASSERT(PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM); + + ep = PAMemoryBlock_thing(block); + +#line 5127 + IRO_ASSERT(ep != NULL); + + if (ParamMapping_extended(mapping) == ep && (nd = ParamMapping_actual(mapping))) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + params->x21 |= EvalExpr(set, params->proc, nd, &stCallingContextStack, params->map, params->ptf); + + if (!LocationSetSet_FindUnknown(set)) { + CInt64 stride64; + CInt64 value; + + value = LocationSet_field(params->loc); + LocationSetSet_ForEach(set, EvalExprAction, &value); + + CInt64_SetULong(&stride64, LocationSet_stride(params->loc)); + LocationSetSet_ForEach(set, EvalExprAction2, &stride64); + } + + memset(&assignParams, 0, sizeof(assignParams)); + assignParams.proc = params->proc; + assignParams.ptf = params->ptf; + assignParams.nd = params->nd; + assignParams.fnode = params->fnode; + assignParams.srcs = params->locs; + assignParams.x14 = params->x20 && (LocationSetSet_Count(set) == 1); + assignParams.x15 = 0; + assignParams.x16 = 0; + LocationSetSet_ForEach(set, EvalAssignAction, &assignParams); + + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + + params->x21 |= assignParams.x15; + params->x22 |= assignParams.x16; + } +} + +static void ApplySummaryAction(PointsToEntry *pte, void *refcon) { + ApplySummaryActionParams *params; + LocationSet *loc; + PAMemoryBlock *block; + +#line 5175 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 5180 + IRO_ASSERT(params->tgtMap != NULL); + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->fnode != NULL); + IRO_ASSERT(params->nd != NULL); + IRO_ASSERT(params->nd->type == IROLinearFunccall); + IRO_ASSERT(params->ptf != NULL); + IRO_ASSERT(params->map != NULL); + + loc = PointsToEntry_loc(pte); + +#line 5189 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(loc)); + + block = LocationSet_block(loc); + if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + params->loc = loc; + params->locs = PointsToEntry_locs(pte); + pmf_sub_487C70(params->tgtMap, ApplySummaryAction2, params); + } +} + +static Boolean ApplySummary(PartialTransferFunction *tgtPTF, ParamMappingFunction *tgtMap, Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map, Boolean flag) { + Boolean result; + ApplySummaryActionParams params; + PointsToFunction *pointsToFunc; + +#line 5208 + IRO_ASSERT(tgtPTF != NULL); + IRO_ASSERT(tgtMap != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(fnode != NULL); + IRO_ASSERT(nd != NULL); + IRO_ASSERT(nd->type == IROLinearFunccall); + IRO_ASSERT(ptf != NULL); + IRO_ASSERT(map != NULL); + + StoreReturnedLocations(nd, tgtPTF, tgtMap); + if (tgtPTF == stUnknownPTF) { + result = KillAllAddressableLocations(proc, fnode, nd, ptf); + } else { + pointsToFunc = PointsToFunction_New(); + if (nd->pointsToFunction) + PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction); + else + PointsToFunction_Init(pointsToFunc); + + memset(¶ms, 0, sizeof(params)); + params.tgtMap = tgtMap; + params.proc = proc; + params.fnode = fnode; + params.nd = nd; + params.ptf = ptf; + params.map = map; + params.loc = NULL; + params.locs = NULL; + params.x20 = flag; + params.x21 = 0; + params.x22 = 0; + + PointsToFunction_ForEach(PartialTransferFunction_finalPointsToFn(tgtPTF), ApplySummaryAction, ¶ms); + + result = params.x21; + if (!params.x21 && params.x22) { + if (nd->pointsToFunction) + result = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction); + else + result = PointsToFunction_FindFirst(pointsToFunc) != NULL; + } + } + + return result; +} + +static void GetPTFAction2(ParamMapping *mapping, void *refcon) { +#line 5331 + IRO_ASSERT(mapping != NULL); + + if (ParamMapping_extended(mapping)) + ParamMapping_SetExtended(mapping, NULL); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct GetPTFActionParams { + ParamMappingFunction *map; + Object *proc; + IROLinear *nd; + PartialTransferFunction *ptf; + Boolean *needVisit; + PartialTransferFunction *x14; + PartialTransferFunction *x18; +} GetPTFActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void GetPTFAction(PartialTransferFunction *tgtPTF, void *refcon) { + GetPTFActionParams *params; + +#line 5359 + IRO_ASSERT(tgtPTF != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 5364 + IRO_ASSERT(params->map != NULL); + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->proc != &stUnknown); + IRO_ASSERT(params->nd != NULL); + IRO_ASSERT(params->ptf != NULL); + IRO_ASSERT(params->needVisit != NULL); + + if (!params->x18) { + if (MatchPTF(tgtPTF, params->proc, params->map, params->nd, params->ptf)) { + if (InputsHaveNewPointerValues(tgtPTF, params->ptf)) + *params->needVisit = 1; + params->x18 = tgtPTF; + } else { + pmf_sub_487C70(params->map, GetPTFAction2, NULL); + if (PTF_sub_48B980(tgtPTF) == params->nd && PTF_sub_48B970(tgtPTF) == params->ptf) + params->x14 = tgtPTF; + } + } +} + +static PartialTransferFunction *GetPTF(ParamMappingFunction *map, Object *proc, IROLinear *nd, PartialTransferFunction *ptf, Boolean *needVisit) { + PartialTransferFunction *found; + PartialTransferFunction *result; + GetPTFActionParams params; + +#line 5396 + IRO_ASSERT(map != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(nd != NULL); + IRO_ASSERT(ptf != NULL); + IRO_ASSERT(needVisit != NULL); + + if (proc == &stUnknown) { + result = stUnknownPTF; + } else { + memset(¶ms, 0, sizeof(params)); + params.map = map; + params.proc = proc; + params.nd = nd; + params.ptf = PartialTransferFunction_New(); + PartialTransferFunction_Init(params.ptf, nd, ptf); + params.needVisit = needVisit; + params.x14 = NULL; + params.x18 = NULL; + + if (!proc->u.func.ptfList) { + proc->u.func.ptfList = PTFList_New(); + PTFList_Init(proc->u.func.ptfList); + } + + PTFList_ForEach(proc->u.func.ptfList, GetPTFAction, ¶ms); + + found = params.x18; + if (found && !*needVisit) { + PartialTransferFunction_Copy(result = PartialTransferFunction_New(), found); + } else { + result = stUnknownPTF; + } + + PartialTransferFunction_Term(params.ptf); + PartialTransferFunction_Delete(params.ptf); + } + + return result; +} + +static Boolean IsMeetNode(IRONode *fnode, IROLinear *nd) { + return (fnode->numpred > 1) && (fnode->first == nd); +} + +static Boolean IsExitNode(Object *proc, IRONode *fnode) { +#line 5467 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(fnode != NULL); + + return (fnode->numsucc == 0) && Bv_IsBitSet(FunctionFirstNode(proc)->index, fnode->dom); +} + +static Boolean SomePredecessorHasBeenVisited(Object *proc, IRONode *fnode) { + UInt16 i; + +#line 5479 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(fnode != NULL); + + for (i = 0; i < fnode->numpred; i++) { + if (FunctionNodeTable(proc)[fnode->pred[i]]->x3C) + return 1; + } + + return 0; +} + +static Boolean AllPredecessorsHaveBeenVisited(Object *proc, IRONode *fnode) { + UInt16 i; + + IRO_ASSERT(proc != NULL); + IRO_ASSERT(fnode != NULL); + + for (i = 0; i < fnode->numpred; i++) { + if (!FunctionNodeTable(proc)[fnode->pred[i]]->x3C) + return 0; + } + + return 1; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalProcActionParams { + Object *proc; + IRONode *fnode; + PartialTransferFunction *ptf; +} EvalProcActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalProcAction2(PointsToEntry *pte, void *refcon) { + EvalProcActionParams *params; + LocationSet *dst; + PAMemoryBlock *block; + LocationSetSet *set; + IRONode *node; + +#line 5525 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 5530 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->fnode != NULL); + IRO_ASSERT(params->ptf != NULL); + + dst = PointsToEntry_loc(pte); + +#line 5535 + IRO_ASSERT(dst != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(dst)); + + block = LocationSet_block(dst); + + if (block && (LocationSet_sub_48AF30(dst) || PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM)) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + LocationSetSet_AddSet(set, PointsToEntry_locs(pte)); + + for (node = FunctionFirstNode(params->proc); node; node = node->nextnode) { + if (node->x3C && node != params->fnode && IsExitNode(params->proc, node)) { + if (node->last->pointsToFunction) + Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, dst, node->last->pointsToFunction, 0, NULL); + } + } + + Assign(params->ptf, dst, set, params->proc, NULL, NULL); + + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct AssignEachInPointsToFunctionActionParams { + Object *proc; + IROLinear *nd; + IRONode *fnode; + PartialTransferFunction *ptf; + Boolean x10; +} AssignEachInPointsToFunctionActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void AssignEachInPointsToFunctionAction(PointsToEntry *pte, void *refcon) { + AssignEachInPointsToFunctionActionParams *params; + LocationSet *dst; + LocationSetSet *srcs; + +#line 5577 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 5582 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->nd != NULL); + IRO_ASSERT(params->fnode != NULL); + IRO_ASSERT(params->ptf != NULL); + + dst = PointsToEntry_loc(pte); + + srcs = LocationSetSet_New(); + LocationSetSet_Init(srcs); + LocationSetSet_AddSet(srcs, PointsToEntry_locs(pte)); + params->x10 |= Assign(params->ptf, dst, srcs, params->proc, params->nd, params->fnode); + LocationSetSet_Term(srcs); + LocationSetSet_Delete(srcs); +} + +static void AssignEachInPointsToFunction(PointsToFunction *pointsTo, void *refcon) { + AssignEachInPointsToFunctionActionParams *params; + PointsToFunction *pointsToFunc; + +#line 5602 + IRO_ASSERT(pointsTo != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 5607 + IRO_ASSERT(params->nd != NULL); + + pointsToFunc = PointsToFunction_New(); + if (params->nd->pointsToFunction) + PointsToFunction_Copy(pointsToFunc, params->nd->pointsToFunction); + else + PointsToFunction_Init(pointsToFunc); + + if (PointsToFunction_FindFirst(pointsToFunc)) { + PointsToFunction_ForEach(pointsTo, AssignEachInPointsToFunctionAction, params); + } else { + if (!params->nd->pointsToFunction) + params->nd->pointsToFunction = PointsToFunction_New(); + else + PointsToFunction_Term(params->nd->pointsToFunction); + + PointsToFunction_Copy(params->nd->pointsToFunction, pointsTo); + params->x10 = 1; + } + + if (params->x10) { + if (params->nd->pointsToFunction) + params->x10 = !PointsToFunctions_Equal(pointsToFunc, params->nd->pointsToFunction); + else + params->x10 = PointsToFunction_FindFirst(pointsToFunc) != NULL; + } + + PointsToFunction_Term(pointsToFunc); + PointsToFunction_Delete(pointsToFunc); +} + +static Boolean ObjectIsAFunctionArgument(Object *proc, Object *obj) { + ObjectList *list; + +#line 5643 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(proc != &stUnknown); + IRO_ASSERT(obj != NULL); + + if (obj->datatype == DLOCAL) { + for (list = FunctionArguments(proc); list; list = list->next) { + if (obj == list->object) + return 1; + } + } + + return 0; +} + +static Boolean ObjectIsARealFunctionArgument(Object *proc, Object *obj) { + ObjectList *list; + +#line 5661 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(proc != &stUnknown); + IRO_ASSERT(obj != NULL); + + if (obj->datatype == DLOCAL && proc == cscope_currentfunc) { + for (list = arguments; list; list = list->next) { + if (obj == list->object) + return 1; + } + } + + return 0; +} + +static void AddLocalVarsAddressedByExceptionUses(Object *var) { +#line 5699 + IRO_ASSERT(var != NULL); + IRO_ASSERT(stExceptionFNode != NULL); + IRO_ASSERT(stExceptionFNode->addressed != NULL); + + if (var->datatype == DLOCAL) + ObjectSet_sub_4867D0(stExceptionFNode->addressed, var); +} + +static Boolean LinearNodeIsInFlowgraphNode(IROLinear *nd, IRONode *fnode) { + IROLinear *first; + IROLinear *last; + IROLinear *scan; + + if (fnode && (first = fnode->first) && (last = fnode->last)) { + for (scan = first; scan && scan != last->next; scan = scan->next) { + if (scan == nd) + return 1; + } + } + + return 0; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +static struct { + Object *proc; + IRONode *fnode; + ParamMappingFunction *map; + PartialTransferFunction *ptf; + PointsToFunction *pointsToFunc; + Boolean *changed; + Boolean x18; + Boolean x19; +} stEvalProcActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalProcAction(IROLinear *Int, Boolean flag) { + Boolean *changed; + Boolean result; + Object *proc; + PartialTransferFunction *ptf; + Boolean x18; + Boolean x19; + IRONode *fnode; + PointsToFunction *pointsToFunc; + ParamMappingFunction *map; + Object *obj; + AssignEachInPointsToFunctionActionParams params; + + static int userBreakCounter; + + if (!flag && !Int->x1E) { +#line 5748 + IRO_ASSERT(Int != NULL); + IRO_ASSERT(stEvalProcActionParams.changed != NULL); + + proc = stEvalProcActionParams.proc; + fnode = stEvalProcActionParams.fnode; + map = stEvalProcActionParams.map; + ptf = stEvalProcActionParams.ptf; + pointsToFunc = stEvalProcActionParams.pointsToFunc; + changed = stEvalProcActionParams.changed; + x18 = stEvalProcActionParams.x18; + x19 = stEvalProcActionParams.x19; + +#line 5760 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(fnode != NULL); + IRO_ASSERT(map != NULL); + IRO_ASSERT(ptf != NULL); + + if (++userBreakCounter > 40) { + IRO_CheckForUserBreak(); + userBreakCounter = 0; + } + + result = 0; + + if (x19 && Int->pointsToFunction) { + PointsToFunction_Term(Int->pointsToFunction); + PointsToFunction_Delete(Int->pointsToFunction); + Int->pointsToFunction = NULL; + } + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.nd = Int; + params.fnode = fnode; + params.ptf = ptf; + params.x10 = 0; + + if (x18) { + PointsToFunction *initial = PartialTransferFunction_initialPointsToFn(ptf); + if (fnode == FunctionFirstNode(proc) && initial) { + AssignEachInPointsToFunction(initial, ¶ms); + result |= params.x10; + } + result |= EvalMeet(proc, fnode, Int, ptf); + pointsToFunc = Int->pointsToFunction; + x18 = 0; + } else if (!Int->pointsToFunction) { + if (pointsToFunc) + AssignEachInPointsToFunction(pointsToFunc, ¶ms); + result |= params.x10; + pointsToFunc = Int->pointsToFunction; + } + + if (IRO_IsAssignment(Int)) { + if (Int->flags & IROLF_4000) + longjmp(stAbortPointerAnalysis, 1); + result |= EvalAssign(proc, Int, fnode, map, ptf); + pointsToFunc = Int->pointsToFunction; + } else if (Int->type == IROLinearReturn) { + result |= EvalReturn(proc, Int, fnode, map, ptf); + pointsToFunc = Int->pointsToFunction; + } else if (Int->type == IROLinearFunccall) { + if (Int->flags & IROLF_4000) + longjmp(stAbortPointerAnalysis, 1); + if (Int->stmt && IRO_FunctionCallMightThrowException(Int)) { + stExceptionFNode = fnode; + IRO_WalkExcActions(Int->stmt->dobjstack, AddLocalVarsAddressedByExceptionUses); + } + result |= EvalCall(proc, fnode, Int, map, ptf); + pointsToFunc = Int->pointsToFunction; + } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EINDIRECT && (!(Int->flags & IROLF_Assigned) || (Int->flags & IROLF_Used))) { + result |= EvalExpr(NULL, proc, Int, &stCallingContextStack, map, ptf); + } else if (Int->type == IROLinearOperand && !(Int->flags & IROLF_Ind) && Int->u.node->type == EOBJREF && (obj = Int->u.node->data.objref) && obj->datatype == DLOCAL) { + ObjectSet_sub_4867D0(fnode->addressed, obj); + } else if (Int->type == IROLinearAsm) { + IAEffects effects; + int i; + CodeGen_GetAsmEffects(Int->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) { + obj = effects.operands[i].object; + if (obj && obj->datatype == DLOCAL && effects.operands[i].type == IAEffect_3) { + ObjectSet_sub_4867D0(fnode->addressed, obj); + } + } + } + + if (result && Int != fnode->last && fnode->last->pointsToFunction) { + PointsToFunction_Term(fnode->last->pointsToFunction); + PointsToFunction_Delete(fnode->last->pointsToFunction); + fnode->last->pointsToFunction = NULL; + } + + *changed |= result; + x19 |= result; + + stEvalProcActionParams.pointsToFunc = pointsToFunc; + stEvalProcActionParams.x18 = x18; + stEvalProcActionParams.x19 = x19; + + Int->x1E = 1; + + if (Int->type != IROLinearReturn) { + IROLinear *father = IRO_LocateFather(Int); + if (father && father->type == IROLinearReturn) { + if (LinearNodeIsInFlowgraphNode(father, fnode)) + EvalProcAction(father, 0); + else + longjmp(stAbortPointerAnalysis, 1); + } + } + } +} + +static void EvalProc(Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf) { + IRONode *fnode; + IRONode *pred; + IROLinear *nd; + UInt32 passCount; + Boolean changed; + UInt16 i; + AssignEachInPointsToFunctionActionParams assignParams; + EvalProcActionParams params; + +#line 5964 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(map != NULL); + IRO_ASSERT(ptf != NULL); + + for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) + fnode->x3C = 0; + + passCount = 0; + do { + clock(); + changed = 0; + for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) { + if (fnode->last && ((fnode->numpred == 0) || SomePredecessorHasBeenVisited(proc, fnode))) { + clock(); + if (!fnode->addressed) { + fnode->addressed = ObjectSet_New(); + ObjectSet_Init(fnode->addressed); + } + + for (i = 0; i < fnode->numpred; i++) { + pred = FunctionNodeTable(proc)[fnode->pred[i]]; + if (pred->addressed) + ObjectSet_sub_48C590(fnode->addressed, pred->addressed); + } + + memset(&stEvalProcActionParams, 0, sizeof(stEvalProcActionParams)); + stEvalProcActionParams.proc = proc; + stEvalProcActionParams.fnode = fnode; + stEvalProcActionParams.map = map; + stEvalProcActionParams.ptf = ptf; + stEvalProcActionParams.pointsToFunc = NULL; + stEvalProcActionParams.changed = &changed; + stEvalProcActionParams.x18 = 1; + stEvalProcActionParams.x19 = 0; + + for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) + nd->x1E = 0; + IRO_WalkInts(fnode->first, fnode->last, EvalProcAction); + + if (stEvalProcActionParams.x18 || !fnode->last->pointsToFunction) { + memset(&assignParams, 0, sizeof(assignParams)); + assignParams.proc = proc; + assignParams.nd = fnode->last; + assignParams.fnode = fnode; + assignParams.ptf = ptf; + assignParams.x10 = 0; + if (stEvalProcActionParams.x18) { + PointsToFunction *initial = PartialTransferFunction_initialPointsToFn(ptf); + if (fnode == FunctionFirstNode(proc) && initial) { + AssignEachInPointsToFunction(initial, &assignParams); + changed |= assignParams.x10; + } + changed |= EvalMeet(proc, fnode, fnode->last, ptf); + stEvalProcActionParams.x18 = 0; + } else { + if (stEvalProcActionParams.pointsToFunc) + AssignEachInPointsToFunction(stEvalProcActionParams.pointsToFunc, &assignParams); + changed |= assignParams.x10; + } + } + + fnode->x3C = 1; + clock(); + } + } + + clock(); + if (++passCount > 32) { +#line 6072 + CError_FATAL(); + } + } while (changed); + + if (passCount > stMaxPassCount) + stMaxPassCount = passCount; + + PartialTransferFunction_sub_48A610(ptf, 1); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) { + if (fnode->x3C && IsExitNode(proc, fnode) && fnode->last->pointsToFunction) { + params.fnode = fnode; + PointsToFunction_ForEach(fnode->last->pointsToFunction, EvalProcAction2, ¶ms); + } + } +} + +static void PointerAnalysis_Init(void) { + stCallingContextStack = Stack_New(); + Stack_Init(stCallingContextStack); + + stUnknownPTF = PartialTransferFunction_New(); + PartialTransferFunction_Init(stUnknownPTF, NULL, NULL); + + stExtParamSet = AllocsExtParamSet_sub_4876C0(); + InitsExtParamSet_sub_4876A0(stExtParamSet); + + stPTFList = PTFList_New(); + PTFList_Init(stPTFList); +} + +static void CleanseLocationSet(LocationSet *loc, void *refcon) { + PAMemoryBlock *block; + PALocalVar *local; + +#line 6161 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(refcon == NULL); + + if ( + !LocationSet_IsUnknown(loc) && + (block = LocationSet_block(loc)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && + (local = PAMemoryBlock_thing(block)) + ) { + PALocalVar_SetSth_sub_4847C0(local, NULL); + } +} + +static void CleansePointsToEntry(PointsToEntry *pte, void *refcon) { +#line 6177 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(refcon == NULL); + + CleanseLocationSet(PointsToEntry_loc(pte), NULL); + LocationSetSet_ForEach(PointsToEntry_locs(pte), CleanseLocationSet, NULL); +} + +static void PointerAnalysis_TermAction4(PartialTransferFunction *ptf, void *refcon) { +#line 6187 + IRO_ASSERT(ptf != NULL); + IRO_ASSERT(refcon == NULL); + + if (ptf != stUnknownPTF) { + PointsToFunction_ForEach(PartialTransferFunction_initialPointsToFn(ptf), CleansePointsToEntry, NULL); + PointsToFunction_ForEach(PartialTransferFunction_finalPointsToFn(ptf), CleansePointsToEntry, NULL); + } +} + +static void PointerAnalysis_TermAction3(ExtendedParam *ep) { + ExtendedParam_Term(ep); + ExtendedParam_Delete(ep); +} + +static void PointerAnalysis_TermAction2(Object *obj, void *refcon) { + ObjectSet *objSet; + Object *proc; + ObjectList *list; + + objSet = refcon; + + if (!ObjectIsAnExtendedParamCandidate(obj)) { + if ( + obj->datatype == DLOCAL && + obj->u.var.info && + (proc = obj->u.var.info->func) && + ObjectIsAFunction(proc) && + proc->u.func.argList + ) { + for (list = proc->u.func.argList; list; list = list->next) { + if (obj == list->object) + break; + } + + if (!list) + ObjectSet_sub_4867D0(objSet, obj); + } else { + ObjectSet_sub_4867D0(objSet, obj); + } + } +} + +static void PointerAnalysis_TermAction1(ExtendedParam *ep, void *refcon) { + ObjectSet *objSet; + ObjectSet *epObjSet; + Object *obj; + + objSet = ObjectSet_New(); + ObjectSet_Init(objSet); + + epObjSet = ExtendedParam_objectSet(ep); + obj = NULL; + ObjectSet_ForEach(epObjSet, FindGlobalObjectAction, &obj); + if (obj) { + ObjectSet_ForEach(epObjSet, PointerAnalysis_TermAction2, objSet); + if (ObjectSet_FindFirst(objSet)) + EP_sub_48C850(ep, objSet); + } + + ObjectSet_Term(objSet); + ObjectSet_Delete(objSet); +} + +static void PointerAnalysis_Term(void) { + if (stExtParamSet) { + MaybeWalkExtParamSet_sub_48CBE0(stExtParamSet, PointerAnalysis_TermAction1, NULL); + TermsExtParamSet_sub_48CB00(stExtParamSet); + FreesExtParamSet_sub_48CAE0(stExtParamSet); + stExtParamSet = NULL; + } + + if (stPTFList) { + PTFList_ForEach(stPTFList, PointerAnalysis_TermAction4, NULL); + PTFList_Term(stPTFList); + PTFList_Delete(stPTFList); + stPTFList = NULL; + } + + PartialTransferFunction_Term(stUnknownPTF); + PartialTransferFunction_Delete(stUnknownPTF); + stUnknownPTF = NULL; + + Stack_Term(&stCallingContextStack); + Stack_Delete(stCallingContextStack); + stCallingContextStack = NULL; +} + +static void InvalidatePointsToFunctions(Object *proc) { + IRONode *fnode; + IROLinear *nd; + +#line 6302 + IRO_ASSERT(proc != NULL); + + for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) { + if (fnode->last) { + if (fnode->addressed) { + ObjectSet_Term(fnode->addressed); + ObjectSet_Delete(fnode->addressed); + fnode->addressed = NULL; + } + + for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) { + if (nd->pointsToFunction) { + PointsToFunction_Term(nd->pointsToFunction); + PointsToFunction_Delete(nd->pointsToFunction); + nd->pointsToFunction = NULL; + } + } + } + } +} + +static void InitialSetup(void) { +} + +static void PointerAnalysis_HeapErrorProc(void) { + longjmp(stAbortPointerAnalysis, 2); +} + +void PointerAnalysis_Setup(void) { + IRO_InitializeAllocator(); + stExtendedParamNum = 0; + stParamObjs = NULL; + stMaxPassCount = 0; +} + +void PointerAnalysis_Cleanup(void) { + ObjectList *list; + ObjectList *next; + + for (list = stParamObjs; list; list = next) { + IRO_free(list->object); + next = list->next; + IRO_free(list); + } + stParamObjs = NULL; + IRO_TerminateAllocator(); +} + +void IRO_AnalyzePointers(Object *function) { + EvalCallActionParams params; + IROLinear nd; + IRONode fnode; + int code; + volatile heaperror_t saveheaperror; + +#line 6393 + IRO_ASSERT(function != NULL); + + PointerAnalysis_Init(); + + memset(¶ms, 0, sizeof(params)); + memset(&nd, 0, sizeof(nd)); + nd.type = IROLinearFunccall; + memset(&fnode, 0, sizeof(fnode)); + params.proc = &stUnknown; + params.fnode = &fnode; + params.nd = &nd; + params.ptf = stUnknownPTF; + params.map = NULL; + params.x18 = 0; + params.x19 = 0; + params.x1A = 1; + + stCurrentProc = FindMainEntryPoint(function); + + if ((code = setjmp(stAbortPointerAnalysis)) == 0) { + saveheaperror = getheaperror(); + setheaperror(PointerAnalysis_HeapErrorProc); + InitialSetup(); + EvalCallAction(stCurrentProc, ¶ms); + PointerAnalysis_Term(); + stCurrentProc = NULL; + setheaperror(saveheaperror); + } else { + setheaperror(saveheaperror); + InvalidatePointsToFunctions(stCurrentProc); + PointerAnalysis_Term(); + stCurrentProc = NULL; + if (code == 2 && saveheaperror) + saveheaperror(); + } +} + +static void RemoveRestrictedExtendedParamsAction(LocationSet *ls, void *refcon) { + LocationSetSet *locs; + PAMemoryBlock *block; + ExtendedParam *ep; + ObjectSet *objSet; + Object *obj; + + locs = refcon; + + if ( + !LocationSet_IsUnknown(ls) && + (block = LocationSet_block(ls)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && + (ep = PAMemoryBlock_thing(block)) + ) { + objSet = ExtendedParam_objectSet(ep); + if ( + ObjectSet_Count(objSet) == 1 && + (obj = ObjectSet_FindFirst(objSet)) && + ObjectIsRestrictQualified(obj) + ) { + LocationSetSet_Add(locs, ls); + } + } +} + +static void RemoveRestrictedExtendedParams(LocationSetSet *locs) { + LocationSetSet *set; + + set = LocationSetSet_New(); + LocationSetSet_Init(set); + LocationSetSet_ForEach(locs, RemoveRestrictedExtendedParamsAction, set); + LocationSetSet_sub_488700(locs, set); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); +} + +Boolean PointerAnalysis_TwoLinearNodePointerExprsMightAlias(Object *proc, IROLinear *nd1, IROLinear *nd2) { + LocationSetSet *lss1; + LocationSetSet *lss2; + PointsToFunction *pointsTo1; + PointsToFunction *pointsTo2; + PointsToFunction *savePointsTo1; + PointsToFunction *savePointsTo2; + FindAliasingParams params; + + pointsTo1 = nd1->pointsToFunction; + pointsTo2 = nd2->pointsToFunction; + if (!pointsTo1) + pointsTo1 = pointsTo2; + if (!pointsTo2) + pointsTo2 = pointsTo1; + + if (copts.opt_pointer_analysis_mode == 2 && !is_typeequal(nd1->rtype, nd2->rtype)) + return 0; + if (!pointsTo1 || !pointsTo2) + return 1; + + lss1 = LocationSetSet_New(); + LocationSetSet_Init(lss1); + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + + savePointsTo1 = nd1->pointsToFunction; + nd1->pointsToFunction = pointsTo1; + EvalExpr(lss1, proc, nd1, NULL, NULL, NULL); + nd1->pointsToFunction = savePointsTo1; + + savePointsTo2 = nd2->pointsToFunction; + nd2->pointsToFunction = pointsTo2; + EvalExpr(lss2, proc, nd2, NULL, NULL, NULL); + nd2->pointsToFunction = savePointsTo2; + + memset(¶ms, 0, sizeof(params)); + params.x8 = 0; + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + + if (!params.x8) { + RemoveRestrictedExtendedParams(lss1); + RemoveRestrictedExtendedParams(lss2); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2); + + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + } + } + } + + LocationSetSet_Term(lss1); + LocationSetSet_Delete(lss1); + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + + return params.x8; +} + +Boolean PointerAnalysis_TwoENodePointerExprsMightAlias(Object *proc, ENode *nd1, ENode *nd2) { + LocationSetSet *lss1; + LocationSetSet *lss2; + PointsToFunction *pointsTo1; + PointsToFunction *pointsTo2; + PointsToFunction *savePointsTo1; + PointsToFunction *savePointsTo2; + FindAliasingParams params; + + pointsTo1 = nd1->pointsTo; + pointsTo2 = nd2->pointsTo; + if (!pointsTo1) + pointsTo1 = pointsTo2; + if (!pointsTo2) + pointsTo2 = pointsTo1; + + if (copts.opt_pointer_analysis_mode == 2 && !is_typeequal(nd1->rtype, nd2->rtype)) + return 0; + if (!pointsTo1 || !pointsTo2) + return 1; + + lss1 = LocationSetSet_New(); + LocationSetSet_Init(lss1); + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + + savePointsTo1 = nd1->pointsTo; + nd1->pointsTo = pointsTo1; + EvalENodeExpr(lss1, proc, nd1, NULL, NULL, NULL); + nd1->pointsTo = savePointsTo1; + + savePointsTo2 = nd2->pointsTo; + nd2->pointsTo = pointsTo2; + EvalENodeExpr(lss2, proc, nd2, NULL, NULL, NULL); + nd2->pointsTo = savePointsTo2; + + memset(¶ms, 0, sizeof(params)); + params.x8 = 0; + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + + if (!params.x8) { + RemoveRestrictedExtendedParams(lss1); + RemoveRestrictedExtendedParams(lss2); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2); + + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + } + } + } + + LocationSetSet_Term(lss1); + LocationSetSet_Delete(lss1); + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + + return params.x8; +} + +Boolean PointerAnalysis_IsLinearNodePointerExprDefinite(Object *proc, IROLinear *nd) { + LocationSetSet *lss; + LocationSet *loc; + Boolean result; + + if (!nd->pointsToFunction) + return 0; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + EvalExpr(lss, proc, nd, NULL, NULL, NULL); + + result = + (LocationSetSet_Count(lss) == 1) && + (loc = LocationSetSet_FindFirst(lss)) && + LocationSetRepresentsSingleLocation(loc, NULL, NULL); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + + return result; +} + +Boolean PointerAnalysis_IsENodePointerExprDefinite(Object *proc, ENode *nd) { + LocationSetSet *lss; + LocationSet *loc; + Boolean result; + + if (!nd->pointsTo) + return 0; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + EvalENodeExpr(lss, proc, nd, NULL, NULL, NULL); + + result = + (LocationSetSet_Count(lss) == 1) && + (loc = LocationSetSet_FindFirst(lss)) && + LocationSetRepresentsSingleLocation(loc, NULL, NULL); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + + return result; +} + +Boolean PointerAnalysis_IsVariableValueDefinite(Object *proc, VarRecord *var, PointsToFunction *pointsTo) { + LocationSetSet *lss; + LocationSet *loc; + Boolean result; + + if (!pointsTo) + return 0; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + EvalVariable(lss, proc, var, pointsTo, NULL, NULL, NULL); + + result = + (LocationSetSet_Count(lss) == 1) && + (loc = LocationSetSet_FindFirst(lss)) && + LocationSetRepresentsSingleLocation(loc, NULL, NULL); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + + return result; +} + +static void FindGlobalObjectAction(Object *object, void *refcon) { + if (ObjectIsAnExtendedParamCandidate(object)) { + Object **ptr = refcon; + *ptr = object; + } +} + +static void GetDefiniteObjectOfExtendedParamLoc(LocationSet *loc, Object **resultObj, CInt64 *resultField) { + Object *obj; + CInt64 field; + PAMemoryBlock *block; + ExtendedParam *ep; + ObjectSet *objSet; + LocationSetSet *locs; + LocationSet *tmp; + PALocalVar *local; + +#line 6763 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(resultObj != NULL); + IRO_ASSERT(resultField != NULL); + + obj = NULL; + field = LocationSet_field(loc); + block = LocationSet_block(loc); + + if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + if ((ep = PAMemoryBlock_thing(block)) && (objSet = ExtendedParam_objectSet(ep))) { +#line 6777 + IRO_ASSERT(obj == NULL); + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + } + } + + if (!obj) { + locs = LocationSetSet_New(); + LocationSetSet_Init(locs); + GetActualLocsOfExtendedParam(locs, loc, NULL, &stCallingContextStack, NULL, 0); + + if ( + LocationSetSet_Count(locs) == 1 && + (tmp = LocationSetSet_FindFirst(locs)) && + !LocationSet_IsUnknown(tmp)) + { + field = CInt64_Add(field, LocationSet_field(tmp)); + if ( + (block = LocationSet_block(tmp)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && + (ep = PAMemoryBlock_thing(block)) && + (objSet = ExtendedParam_objectSet(ep)) + ) + { +#line 6801 + IRO_ASSERT(obj == NULL); + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + } else if ( + (block = LocationSet_block(tmp)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && + (local = PAMemoryBlock_thing(block)) + ) + { + obj = GetLocalObject(local, &stUnknown, 0); + } + } + + LocationSetSet_Term(locs); + LocationSetSet_Delete(locs); + } + + *resultObj = obj; + *resultField = field; +} + +static void CreateExpressionForLocationSet(LocationSet *loc, IROList *list, Type *rtype, Object *proc) { + CInt64 field; + PAMemoryBlock *block; + PAMemoryBlockKind kind; + void *thing; + IROLinear *nd; + Object *obj; + +#line 6833 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(loc)); + IRO_ASSERT(LocationSet_stride(loc) == 0); + IRO_ASSERT(list != NULL); + IRO_ASSERT(rtype != NULL); + IRO_ASSERT(proc != NULL); + + field = LocationSet_field(loc); + block = LocationSet_block(loc); + kind = PAMemoryBlock_kind(block); + thing = PAMemoryBlock_thing(block); + nd = NULL; + + switch (kind) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + GetDefiniteObjectOfExtendedParamLoc(loc, &obj, &field); + if (obj) { + nd = IRO_NewLinear(IROLinearOperand); + nd->u.node = create_objectrefnode(obj); + nd->rtype = rtype; + nd->index = ++IRO_NumLinear; + IRO_AddToList(nd, list); + } + break; + case PAMEMORYBLOCKKIND_LOCALVAR: + obj = GetLocalObject(thing, proc, 0); + if (obj) { + if (ObjectIsAFunctionArgument(proc, obj) && obj->u.var.realObj) + obj = obj->u.var.realObj; + nd = IRO_NewLinear(IROLinearOperand); + nd->u.node = create_objectrefnode(obj); + nd->rtype = rtype; + nd->index = ++IRO_NumLinear; + IRO_AddToList(nd, list); + } + break; + case PAMEMORYBLOCKKIND_INT: + if (IS_TYPE_INT(rtype)) { + nd = IRO_NewIntConst(*((CInt64 *) thing), rtype); + IRO_AddToList(nd, list); + } + break; + case PAMEMORYBLOCKKIND_6: + break; + default: +#line 6894 + CError_FATAL(); + } + + if (nd && !CInt64_IsZero(&field)) { + IROLinear *nd2; + IROLinear *nd3; + + nd2 = IRO_NewIntConst(field, TYPE(&stunsignedlong)); + IRO_AddToList(nd2, list); + + nd3 = IRO_NewLinear(IROLinearOp2Arg); + nd3->nodetype = EADD; + nd3->index = ++IRO_NumLinear; + nd3->rtype = rtype; + nd3->u.diadic.left = nd; + nd3->u.diadic.right = nd2; + IRO_AddToList(nd3, list); + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct LookupLinearExprActionParams { + Object *proc; + Type *indirectType; + IROListNode **list; +} LookupLinearExprActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void LookupLinearExprAction(LocationSet *loc, void *refcon) { + LookupLinearExprActionParams *params; + IROListNode *list; + +#line 6926 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 6931 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->indirectType != NULL); + IRO_ASSERT(params->list != NULL); + + list = *params->list = IRO_malloc(sizeof(IROListNode)); + IRO_InitList(&list->list); + list->nextList = NULL; + + if (!LocationSet_IsUnknown(loc) && LocationSetRepresentsSingleLocation(loc, NULL, NULL)) + CreateExpressionForLocationSet(loc, &list->list, params->indirectType, params->proc); + + params->list = &list->nextList; +} + +void PointerAnalysis_LookupLinearNodePointerExpr(Object *proc, IROLinear *indirect, IROListNode **list) { + LocationSetSet *set; + LookupLinearExprActionParams params; + +#line 6957 + IRO_ASSERT(indirect != NULL); + + if (indirect->pointsToFunction) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + EvalExpr(set, proc, indirect, NULL, NULL, NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = indirect->rtype; + params.list = list; + + LocationSetSet_ForEach(set, LookupLinearExprAction, ¶ms); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +static void CreateENodeForLocationSet(LocationSet *loc, ENode **resultNode, Type *rtype, Object *proc) { + CInt64 field; + PAMemoryBlock *block; + PAMemoryBlockKind kind; + void *thing; + ENode *nd; + Object *obj; + + IRO_ASSERT(loc != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(loc)); + IRO_ASSERT(LocationSet_stride(loc) == 0); + IRO_ASSERT(resultNode != NULL); + IRO_ASSERT(rtype != NULL); + IRO_ASSERT(proc != NULL); + + field = LocationSet_field(loc); + block = LocationSet_block(loc); + kind = PAMemoryBlock_kind(block); + thing = PAMemoryBlock_thing(block); + nd = NULL; + + switch (kind) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + GetDefiniteObjectOfExtendedParamLoc(loc, &obj, &field); + if (obj) { + nd = create_objectrefnode(obj); + nd->rtype = rtype; + } + break; + case PAMEMORYBLOCKKIND_LOCALVAR: + obj = GetLocalObject(thing, proc, 0); + if (obj) { + if (ObjectIsAFunctionArgument(proc, obj) && obj->u.var.realObj) + obj = obj->u.var.realObj; + nd = create_objectrefnode(obj); + nd->rtype = rtype; + } + break; + case PAMEMORYBLOCKKIND_INT: + if (IS_TYPE_INT(rtype)) { + nd = IRO_NewENode(EINTCONST); + nd->data.intval = *((CInt64 *) thing); + nd->rtype = rtype; + } + break; + case PAMEMORYBLOCKKIND_6: + break; + default: +#line 7040 + CError_FATAL(); + } + + if (nd && !CInt64_IsZero(&field)) { + ENode *nd2; + ENode *nd3; + + nd2 = IRO_NewENode(EINTCONST); + nd2->data.intval = field; + nd2->rtype = TYPE(&stunsignedlong); + + nd3 = IRO_NewENode(EADD); + nd3->data.diadic.left = nd; + nd3->data.diadic.right = nd2; + nd3->rtype = rtype; + + *resultNode = nd3; + } else { + *resultNode = nd; + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct LookupENodeExprActionParams { + Object *proc; + Type *indirectType; + ENodeList **list; +} LookupENodeExprActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void LookupENodeExprAction(LocationSet *loc, void *refcon) { + LookupENodeExprActionParams *params; + ENodeList *list; + + IRO_ASSERT(loc != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->indirectType != NULL); + IRO_ASSERT(params->list != NULL); + + list = *params->list = IRO_malloc(sizeof(ENodeList)); + list->node = NULL; + list->next = NULL; + + if (!LocationSet_IsUnknown(loc) && LocationSetRepresentsSingleLocation(loc, NULL, NULL)) + CreateENodeForLocationSet(loc, &list->node, params->indirectType, params->proc); + + params->list = &list->next; +} + +void PointerAnalysis_LookupENodePointerExpr(Object *proc, ENode *indirect, ENodeList **list) { + LocationSetSet *set; + LookupENodeExprActionParams params; + + IRO_ASSERT(indirect != NULL); + + if (indirect->pointsTo) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + EvalENodeExpr(set, proc, indirect, NULL, NULL, NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = indirect->rtype; + params.list = list; + + LocationSetSet_ForEach(set, LookupENodeExprAction, ¶ms); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +void PointerAnalysis_LookupVariableIntoLinearNodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, IROList **list) { + LocationSetSet *set; + LookupLinearExprActionParams params; + + if (pointsTo) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + EvalVariable(set, proc, var, pointsTo, NULL, NULL, NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = var->object->type; + params.list = list; + + LocationSetSet_ForEach(set, LookupLinearExprAction, ¶ms); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +void PointerAnalysis_LookupVariableIntoENodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, ENodeList **list) { + LocationSetSet *set; + LookupENodeExprActionParams params; + + if (pointsTo) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + EvalVariable(set, proc, var, pointsTo, NULL, NULL, NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = var->object->type; + params.list = list; + + LocationSetSet_ForEach(set, LookupENodeExprAction, ¶ms); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct GetFunctionDepsOrKillsActionParams { + Object *proc; + PartialTransferFunction *ptf; + IROLinear *funccall; + ParamMappingFunction *map; + ObjectList **list; +} GetFunctionDepsOrKillsActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void GetFunctionDepsOrKillsAction(LocationSet *ls, void *refcon) { + GetFunctionDepsOrKillsActionParams *params; + ObjectList *list; + PAMemoryBlock *block; + ExtendedParam *ep; + ObjectSet *objSet; + PALocalVar *local; + Object *obj; + +#line 7204 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 7209 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->ptf != NULL); + IRO_ASSERT(params->funccall != NULL); + IRO_ASSERT(params->map == NULL || params->map != NULL); + IRO_ASSERT(params->list != NULL); + + list = *params->list = IRO_malloc(sizeof(ObjectList)); + list->object = NULL; + list->next = NULL; + + if (!LocationSet_IsUnknown(ls) && (block = LocationSet_block(ls))) { + obj = NULL; + switch (PAMemoryBlock_kind(block)) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + if ((ep = PAMemoryBlock_thing(block)) && (objSet = ExtendedParam_objectSet(ep))) { +#line 7232 + IRO_ASSERT(obj == NULL); + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + } + break; + case PAMEMORYBLOCKKIND_LOCALVAR: + if ((local = PAMemoryBlock_thing(block))) { + obj = GetLocalObject(local, &stUnknown, 0); + if (ObjectIsAFunctionArgument(FunctionName, obj) && obj->u.var.realObj) + obj = obj->u.var.realObj; + } + break; + } + + list->object = obj; + } + + params->list = &list->next; +} + +static void GetFunctionDepsOrKillsAction2(PointsToEntry *pte, void *refcon) { + GetFunctionDepsOrKillsActionParams *params; + LocationSet *loc; + PAMemoryBlock *block; + LocationSetSet *set; + +#line 7264 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(refcon != NULL); + + params = refcon; + +#line 7269 + IRO_ASSERT(params->proc != NULL); + IRO_ASSERT(params->ptf != NULL); + IRO_ASSERT(params->funccall != NULL); + IRO_ASSERT(params->map != NULL); + IRO_ASSERT(params->list != NULL); + + loc = PointsToEntry_loc(pte); + +#line 7277 + IRO_ASSERT(!LocationSet_IsUnknown(loc)); + + if ((block = LocationSet_block(loc)) && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + GetActualLocsOfExtendedParam(set, loc, NULL, &stCallingContextStack, params->map, 0); + LocationSetSet_ForEach(set, GetFunctionDepsOrKillsAction, params); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +static void CreateFalseContext(Object *proc, IROLinear *funccall, PartialTransferFunction **resultPTF, ParamMappingFunction **resultMap) { + IROLinear myFunccall; + Boolean needVisit; + ParamMappingFunction *map; + PartialTransferFunction *ptf; + StackElement *stackElement; + ParamMappingFunction *map2; + PartialTransferFunction *ptf2; + StackElement *stackElement2; + + PointerAnalysis_Init(); + memset(&myFunccall, 0, sizeof(myFunccall)); + myFunccall.type = IROLinearFunccall; + + map = ParamMappingFunction_New(); + ParamMappingFunction_Init(map); + RecordActuals(&myFunccall, FunctionName, map); + + needVisit = 0; + ptf = GetPTF(map, FunctionName, &myFunccall, stUnknownPTF, &needVisit); + + stackElement = StackElement_New(); + StackElement_Init(stackElement, FunctionName, ptf, map, &myFunccall); + Stack_sub_48A660(&stCallingContextStack, stackElement); + StackElement_Term(stackElement); + StackElement_Delete(stackElement); + + map2 = ParamMappingFunction_New(); + ParamMappingFunction_Init(map2); + RecordActuals(funccall, proc, map2); + + if (FunctionName != proc) { + needVisit = 0; + ptf2 = GetPTF(map2, proc, funccall, ptf, &needVisit); + + stackElement2 = StackElement_New(); + StackElement_Init(stackElement2, proc, ptf2, map2, funccall); + Stack_sub_48A660(&stCallingContextStack, stackElement2); + StackElement_Term(stackElement2); + StackElement_Delete(stackElement2); + } else { + ptf2 = stUnknownPTF; + } + + *resultPTF = ptf2; + *resultMap = map2; +} + +static void DestroyFalseContext(Object *proc, PartialTransferFunction *ptf, ParamMappingFunction *map) { + StackElement *element; + + if (FunctionName != proc) { + element = Stack_sub_48A5B0(&stCallingContextStack); + StackElement_Term(element); + StackElement_Delete(element); + } + + ParamMappingFunction_Term(map); + ParamMappingFunction_Delete(map); + + element = Stack_sub_48A5B0(&stCallingContextStack); + map = StackElement_map(element); + ParamMappingFunction_Term(map); + ParamMappingFunction_Delete(map); + StackElement_Term(element); + StackElement_Delete(element); + + PointerAnalysis_Term(); +} + +void PointerAnalysis_GetFunctionKills(Object *proc, IROLinear *funccall, ObjectList **list) { + Boolean fail; + PartialTransferFunction *ptf; + LocationSetSet *set; + GetFunctionDepsOrKillsActionParams params; + +#line 7398 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(funccall != NULL); + IRO_ASSERT(funccall->type == IROLinearFunccall); + + if (!ObjectIsAFunction(proc)) + return; + + fail = !proc->u.func.ptfList || !(ptf = PTFList_FindFirst(proc->u.func.ptfList)); + if (!fail) { + fail = !(set = PTF_sub_48D750(ptf)); + if (!fail) { + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + params.funccall = funccall; + params.map = NULL; + params.list = list; + LocationSetSet_ForEach(set, GetFunctionDepsOrKillsAction, ¶ms); + } + } + + if (fail) { + *list = IRO_malloc(sizeof(ObjectList)); + (*list)->object = NULL; + (*list)->next = NULL; + } +} + +void PointerAnalysis_GetFunctionDependencies(Object *proc, IROLinear *funccall, ObjectList **list) { + Boolean fail; + PartialTransferFunction *ptf; + ParamMappingFunction *map; + PointsToFunction *finalPointsTo; + GetFunctionDepsOrKillsActionParams params; + +#line 7446 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(funccall != NULL); + IRO_ASSERT(funccall->type == IROLinearFunccall); + + if (!ObjectIsAFunction(proc)) + return; + + fail = !proc->u.func.ptfList || !PTFList_FindFirst(proc->u.func.ptfList); + if (!fail) { + CreateFalseContext(proc, funccall, &ptf, &map); + fail = !ptf || !map || !(finalPointsTo = PartialTransferFunction_finalPointsToFn(ptf)); + if (!fail) { + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + params.funccall = funccall; + params.map = map; + params.list = list; + PointsToFunction_ForEach(finalPointsTo, GetFunctionDepsOrKillsAction2, ¶ms); + } + DestroyFalseContext(proc, ptf, map); + } + + if (fail) { + *list = IRO_malloc(sizeof(ObjectList)); + (*list)->object = NULL; + (*list)->next = NULL; + } +} + +void PointerAnalysis_PragmaMode(void) { + if (cparamblkptr->isPreprocessing) { + skipendofline(); + return; + } + + if (notendofline()) { + if (plex() == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "addr")) { + copts.opt_pointer_analysis_mode = 0; + return; + } + if (!strcmp(tkidentifier->name, "ansi")) { + copts.opt_pointer_analysis_mode = 1; + return; + } + if (!strcmp(tkidentifier->name, "type")) { + copts.opt_pointer_analysis_mode = 2; + return; + } + } + + CPrep_Warning(CErrorStr105); + skipendofline(); + return; + } + + if (copts.warn_illpragma) + CPrep_Warning(CErrorStr186); + skipendofline(); +} + +typedef enum CreateNewParamObjects { + CREATE_NEW_PARAM_OBJECTS_FALSE, + CREATE_NEW_PARAM_OBJECTS_TRUE +} CreateNewParamObjects; + +static void ParseLocationSet(LocationSet *loc, Type *rtype, Object *proc, CreateNewParamObjects createNewParamObjects, Boolean arg5, int arg6, Boolean *arg7, Boolean *resultFailed) { + CInt64 field; + UInt32 stride; + PAMemoryBlock *block; + PAMemoryBlock *restriction; + Boolean failed; + Boolean flag37; + Boolean epFlag; + Boolean anotherFlag; + Boolean isUnknown; + +#line 7552 + IRO_ASSERT(loc != NULL); + IRO_ASSERT(rtype == NULL || rtype != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_FALSE || createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_TRUE); + IRO_ASSERT(resultFailed != NULL); + IRO_ASSERT(*resultFailed == false); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(proc == NULL || ObjectIsAFunction(proc)); + + failed = 0; + isUnknown = 0; + anotherFlag = 0; + field = cint64_zero; + stride = 0; + + tk = lex(); + if (tk == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "__unknown")) { + flag37 = 0; + isUnknown = 1; + tk = lookahead(); + if (tk == '(') { + lex(); + tk = lex(); + if (tk != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + failed = 1; + } + if (!failed) { + PALocalVar *local; + local = PALocalVar_New(); + PALocalVar_InitByName(local, tkidentifier->name); + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_LOCALVAR, local); + + tk = lex(); + if (tk != ')') { + CError_Error(CErrorStr115); + failed = 1; + } + if (!failed) { + rtype = NULL; + restriction = block; + } + } + } else { + rtype = NULL; + restriction = NULL; + } + } else if (arg5 && !strcmp(tkidentifier->name, "__return_value")) { + flag37 = 0; + anotherFlag = 1; + } else if (!strcmp(tkidentifier->name, "__unique_heap_allocation")) { + PAHeapBlock *hb; + + flag37 = 0; + hb = CreateUniqueHeapAlloc_sub_486420(); + InitUniqueHeapAlloc_sub_486410(hb, NULL); + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_HEAPBLOCK, hb); + } else if (!strcmp(tkidentifier->name, "__parameter_representative")) { + flag37 = 1; + tk = lex(); + + if (tk == '(') { + tk = lex(); + if (tk != TK_INTCONST) { + CError_Error(CErrorStr121); + failed = 1; + } + if (!failed) { + Object *obj; + ObjectList *list; + ExtendedParam *ep; + obj = NULL; + for (list = stParamObjs; list; list = list->next) { + if ((obj = list->object) && (obj->u.var.uid == CInt64_GetULong(&tkintconst))) + break; + } + if (!list) + obj = NULL; + + if (!obj) { + if (createNewParamObjects) { + obj = IRO_malloc(sizeof(Object)); + memset(obj, 0, sizeof(Object)); + obj->datatype = DLOCAL; + obj->extParam = NULL; + obj->name = CParser_GetUniqueName(); + obj->type = TYPE(&stunsignedlong); + obj->qual = 0; + obj->u.var.info = NULL; + obj->u.var.uid = CInt64_GetULong(&tkintconst); + + list = IRO_malloc(sizeof(ObjectList)); + list->next = stParamObjs; + list->object = obj; + stParamObjs = list; + + ep = CreateExtendedParam(NULL, NULL, obj, &epFlag); + } else { + char buf[64]; + sprintf(buf, "__parameter_representative(%ld)", obj->u.var.uid); + CError_Error(CErrorStr140, buf); + failed = 1; + } + } else { + ep = obj->extParam; +#line 7687 + IRO_ASSERT(ep != NULL); + } + + if (!failed) { + tk = lex(); + if (tk != ')') { + CError_Error(CErrorStr115); + failed = 1; + } + } + if (!failed) { + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep); + } + } + } + } else { + Object *obj; + NameSpace *nspace; + + obj = NULL; + for (nspace = cscope_current; nspace; nspace = nspace->parent) { + NameSpaceObjectList *chk; + if ((chk = CScope_GetLocalObject(nspace, tkidentifier)) && chk->object->otype == OT_OBJECT) { + if (notendofline()) { + obj = OBJECT(chk->object); + break; + } + } + } + + if (!obj) { + ObjectList *chk; + for (chk = FunctionArguments(proc); chk; chk = chk->next) { + if (chk->object && chk->object->name && chk->object->name->name && !strcmp(tkidentifier->name, chk->object->name->name)) { + obj = chk->object; + } + } + } + + if (obj) { + PAMemoryBlockKind kind; + void *thing; + + if (ObjectIsAnExtendedParamCandidate(obj)) { + kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; + thing = CreateExtendedParam(NULL, NULL, obj, &epFlag); + } else { + kind = PAMEMORYBLOCKKIND_LOCALVAR; + thing = PALocalVar_New(); + if (obj->name && obj->name->name && ObjectIsAFunctionArgument(proc, obj)) + PALocalVar_InitByName(thing, obj->name->name); + else + PALocalVar_InitByObject(thing, obj); + } + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, kind, thing); + rtype = CDecl_NewPointerType(obj->type); + } else { + CError_Error(CErrorStr140, tkidentifier->name); + failed = 1; + } + } + } else if (tk == TK_INTCONST) { + flag37 = 0; + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &tkintconst); + } else if (tk == '(') { + ParseLocationSet(loc, rtype, proc, createNewParamObjects, arg5, 1, &anotherFlag, &failed); + if (!failed) { + tk = plex(); + if (tk != ')') + CError_Error(CErrorStr115); + failed = 1; + } + } else { + CError_Error(CErrorStr121); + failed = 1; + } + + if (!failed && flag37) { + tk = lookahead(); + if (tk == '[') { + lex(); + if (rtype && IS_TYPE_POINTER(rtype) && IS_TYPE_POINTER(TPTR_TARGET(rtype))) { + tk = lex(); + if (tk == ']') { + if ((stride = rtype->size)) { + CInt64 tmp; + CInt64_SetLong(&tmp, stride); + field = CInt64_Mod(field, tmp); + } + rtype = TPTR_TARGET(rtype); + } else { + CError_Error(CErrorStr125); + } + } else { + CError_Error(CErrorStr148); + } + } else if (tk == '.') { + lex(); + if (rtype && IS_TYPE_POINTER(rtype) && IS_TYPE_STRUCT(TPTR_TARGET(rtype))) { + if (TPTR_TARGET(rtype)->size) { + tk = lex(); + if (tk == TK_IDENTIFIER) { + StructMember *member; + if ((member = ismember(TYPE_STRUCT(TPTR_TARGET(rtype)), tkidentifier))) { + CInt64_SetLong(&field, member->offset); + rtype = CDecl_NewPointerType(member->type); + } else { + CError_Error(CErrorStr150, tkidentifier); + } + } else { + CError_Error(CErrorStr107); + } + } else { + CError_Error(CErrorStr136, TPTR_TARGET(rtype), 0); + } + } else { + CError_Error(CErrorStr149); + } + } + } + + if (!failed && !anotherFlag) { + LocationSet_Term(loc); + if (!isUnknown) + LocationSet_InitKnown(loc, block, field, stride, rtype); + else + LocationSet_InitUnknown(loc, rtype, restriction, NULL); + } + + *arg7 = anotherFlag; + *resultFailed = failed; +} + +static void ParseLocationSetSet(LocationSetSet *locs, Type *rtype, Object *proc, CreateNewParamObjects createNewParamObjects, Boolean *resultFailed) { + Boolean failed; + +#line 7892 + IRO_ASSERT(locs != NULL); + IRO_ASSERT(rtype == NULL || rtype != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_FALSE || createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_TRUE); + IRO_ASSERT(resultFailed != NULL); + IRO_ASSERT(*resultFailed == false); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(proc == NULL || ObjectIsAFunction(proc)); + + failed = 0; + + tk = lex(); + if (tk != '(') { + CError_Error(CErrorStr114); + failed = 1; + } + + if (!failed) { + Boolean anotherFlag; + + LocationSet *ls; + ls = LocationSet_New(); + LocationSet_InitUnknown(ls, NULL, NULL, NULL); + + tk = lookahead(); + while (!failed && tk != ')') { + ParseLocationSet(ls, rtype, proc, createNewParamObjects, 0, 0, &anotherFlag, &failed); + if (!failed) + LocationSetSet_Add(locs, ls); + + if (!failed) { + tk = lookahead(); + if (tk == ',') { + lex(); + tk = lookahead(); + } else if (tk != ')') { + lex(); + CError_Error(CErrorStr121); + failed = 1; + } + } + } + + if (!failed) + lex(); + + LocationSet_Term(ls); + LocationSet_Delete(ls); + } + + *resultFailed = failed; +} + +static Object *GetFunctionObjectFromDeclInfo(DeclInfo *di) { + Object *proc; + +#line 7953 + IRO_ASSERT(di != NULL); + + if (di->storageclass != TK_TYPEDEF && IS_TYPE_FUNC(di->thetype)) { + Boolean flag; + proc = CDecl_GetFunctionObject(di, NULL, &flag, 1); + if (flag) + di->fileoffsetinfo.is_inline = 1; + } else { + proc = NULL; + } + + return proc; +} + +void PointerAnalysis_ParseEntryPointsToSpecifier(DeclInfo *di) { + Object *proc; + Boolean failed; + Boolean anotherFlag; + +#line 7982 + IRO_ASSERT(di != NULL); + + proc = GetFunctionObjectFromDeclInfo(di); + if (proc) { +#line 7987 + IRO_ASSERT(proc == NULL || ObjectIsAFunction(proc)); + + tk = lex(); +#line 7996 + IRO_ASSERT(tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"entry_points_to") == 0); + + failed = 0; + + tk = lex(); + if (tk != '(') { + CError_Error(CErrorStr114); + failed = 1; + } + + if (!failed) { + LocationSet *ls; + ls = LocationSet_New(); + LocationSet_InitUnknown(ls, NULL, NULL, NULL); + ParseLocationSet(ls, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, 0, 0, &anotherFlag, &failed); + if (!failed) { + if ((tk = lex()) != ',') { + CError_Error(CErrorStr116); + failed = 1; + } + } + if (!failed) { + Type *type; + Type *innerType; + LocationSetSet *lss; + + type = LocationSet_rtype(ls); + if (type && IS_TYPE_POINTER(type)) + innerType = TPTR_TARGET(type); + else + innerType = NULL; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + ParseLocationSetSet(lss, innerType, proc, CREATE_NEW_PARAM_OBJECTS_TRUE, &failed); + if (!failed) { + if ((tk = lex()) != ')') { + CError_Error(CErrorStr115); + failed = 1; + } + } + if (!failed) { + PartialTransferFunction *ptf; + PointsToFunction *pointsToFunc; + PointsToEntry *pte; + + if (!proc->u.func.ptfList) { + proc->u.func.ptfList = PTFList_New(); + PTFList_Init(proc->u.func.ptfList); + } + ptf = PTFList_FindFirst(proc->u.func.ptfList); + if (!ptf) + ptf = AllocatePTF(proc, NULL, NULL); + + pointsToFunc = PartialTransferFunction_initialPointsToFn(ptf); + pte = PointsToEntry_New(); + PointsToEntry_Init(pte, ls, lss); + PointsToFunction_Add(pointsToFunc, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } + LocationSet_Term(ls); + LocationSet_Delete(ls); + } + } +} + +void PointerAnalysis_ParseExitPointsToSpecifier(DeclInfo *di) { + Object *proc; + Boolean failed; + Boolean anotherFlag; + +#line 8097 + IRO_ASSERT(di != NULL); + + proc = GetFunctionObjectFromDeclInfo(di); + if (proc) { +#line 8102 + IRO_ASSERT(proc == NULL || ObjectIsAFunction(proc)); + + tk = lex(); +#line 8111 + IRO_ASSERT(tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"exit_points_to") == 0); + + failed = 0; + + tk = lex(); + if (tk != '(') { + CError_Error(CErrorStr114); + failed = 1; + } + + if (!failed) { + LocationSet *ls; + ls = LocationSet_New(); + LocationSet_InitUnknown(ls, NULL, NULL, NULL); + ParseLocationSet(ls, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, 1, 0, &anotherFlag, &failed); + if (!failed) { + if ((tk = lex()) != ',') { + CError_Error(CErrorStr116); + failed = 1; + } + } + if (!failed) { + Type *type; + Type *innerType; + LocationSetSet *lss; + + type = LocationSet_rtype(ls); + if (type && IS_TYPE_POINTER(type)) + innerType = TPTR_TARGET(type); + else + innerType = NULL; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + ParseLocationSetSet(lss, innerType, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, &failed); + if (!failed) { + if ((tk = lex()) != ')') { + CError_Error(CErrorStr115); + failed = 1; + } + } + if (!failed) { + PartialTransferFunction *ptf; + PointsToFunction *pointsToFunc; + PointsToEntry *pte; + + if (!proc->u.func.ptfList) { + proc->u.func.ptfList = PTFList_New(); + PTFList_Init(proc->u.func.ptfList); + } + ptf = PTFList_FindFirst(proc->u.func.ptfList); + if (!ptf) + ptf = AllocatePTF(proc, NULL, NULL); + + pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); + pte = PointsToEntry_New(); + if (anotherFlag) + PointsToEntry_Init(pte, PartialTransferFunction_returnLocation(ptf), lss); + else + PointsToEntry_Init(pte, ls, lss); + PointsToFunction_Add(pointsToFunc, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } + LocationSet_Term(ls); + LocationSet_Delete(ls); + } + } +} + +void PointerAnalysis_ParseFunctionModifiesSpecifier(DeclInfo *di) { + Object *proc; + Boolean failed; + LocationSetSet *lss; + PartialTransferFunction *ptf; + LocationSetSet *ptfLSS; + +#line 8211 + IRO_ASSERT(di != NULL); + + proc = GetFunctionObjectFromDeclInfo(di); + if (proc) { +#line 8216 + IRO_ASSERT(proc == NULL || ObjectIsAFunction(proc)); + + tk = lex(); +#line 8225 + IRO_ASSERT(tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"function_modifies") == 0); + + failed = 0; + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + ParseLocationSetSet(lss, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, &failed); + if (!failed) { + if (!proc->u.func.ptfList) { + proc->u.func.ptfList = PTFList_New(); + PTFList_Init(proc->u.func.ptfList); + } + ptf = PTFList_FindFirst(proc->u.func.ptfList); + if (!ptf) + ptf = AllocatePTF(proc, NULL, NULL); + ptfLSS = PTF_sub_48D750(ptf); + LocationSetSet_RemoveAll(ptfLSS); + LocationSetSet_AddSet(ptfLSS, lss); + } + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } +} + diff --git a/compiler_and_linker/unsorted/IroPointerAnalysisADTs.c b/compiler_and_linker/unsorted/IroPointerAnalysisADTs.c new file mode 100644 index 0000000..baec435 --- /dev/null +++ b/compiler_and_linker/unsorted/IroPointerAnalysisADTs.c @@ -0,0 +1,2925 @@ +#include "compiler/IroPointerAnalysis.h" +#include "compiler/IroMalloc.h" +#include "compiler/CError.h" +#include "compiler/CInt64.h" + +// TODO: this should really be elsewhere (but where?) +inline UInt32 gcd(UInt32 a, UInt32 b) { + UInt32 chk; + + if (!a) + return b; + if (!b) + return a; + + while (1) { + chk = a % b; + if (!chk) + return b; + a = b; + b = chk; + } +} + +// #define IRO_DEBUG + +typedef struct ExtendedParamSet ExtendedParamSet; +typedef struct LocationSet LocationSet; +typedef struct LocationSetSet LocationSetSet; +typedef struct ObjectSet ObjectSet; +typedef struct PAHeapBlock PAHeapBlock; +typedef struct PALocalVar PALocalVar; +typedef struct PAMemoryBlock PAMemoryBlock; +typedef struct ParamMapping ParamMapping; +typedef struct ParamMappingFunction ParamMappingFunction; +typedef struct PartialTransferFunction PartialTransferFunction; +typedef struct PointsToEntry PointsToEntry; +// typedef struct PointsToFunction PointsToFunction; +typedef struct Stack Stack; +typedef struct StackElement StackElement; + +typedef UInt32 uint32; + +void __assertion_failed(char *expr, char *filename, int line); + +#ifdef IRO_DEBUG +#define IRO_ASSERT(expr) \ + do { \ + if (!(expr)) { \ + __assertion_failed(#expr, __FILE__, __LINE__); \ + } \ + } while (0); + +#define IRO_DEBUG_CLEAR(obj, type) \ + memset((obj), 0xFF, sizeof(type)) +#else +#define IRO_ASSERT(expr) ((void) 0) +#define IRO_DEBUG_CLEAR(obj, type) ((void) 0) +#endif + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +struct StackElement { + Object *proc; + PartialTransferFunction *ptf; + ParamMappingFunction *map; + IROLinear *funcCall; +}; + +struct Stack { + StackElement *top; + Stack *next; +}; + +struct ObjectSet { + Object *proc; + ObjectSet *otherProcs; +}; + +struct ExtendedParam { + ObjectSet *objectSet; + uint32 x4; +}; + +struct ExtendedParamSet { + ExtendedParam *ep; + ExtendedParamSet *otherEps; +}; + +struct PAHeapBlock { + IROLinear *x0; +}; + +struct PALocalVar { + Object *x0; + char *x4; +}; + +typedef enum { + PAMEMORYBLOCKKIND_INVALID, + PAMEMORYBLOCKKIND_1, + PAMEMORYBLOCKKIND_EXTENDEDPARAM, + PAMEMORYBLOCKKIND_LOCALVAR, + PAMEMORYBLOCKKIND_HEAPBLOCK, + PAMEMORYBLOCKKIND_INT, + PAMEMORYBLOCKKIND_6 +} PAMemoryBlockKind; + +struct PAMemoryBlock { + PAMemoryBlockKind kind; + union { + ExtendedParam *ep; + PALocalVar *localvar; + PAHeapBlock *heapblock; + CInt64 intval; + void *x6; + } u; +}; + +struct LocationSet { + PAMemoryBlock *block; + Type *rtype; + union { + struct { + CInt64 field; + UInt32 stride; + } known; + struct { + PAMemoryBlock *restriction; + LocationSet *bitfieldOf; + } unknown; + } u; +}; + +struct LocationSetSet { + LocationSet *loc; + LocationSetSet *otherLocs; + UInt8 count; +}; + +struct ParamMapping { + IROLinear *actual; + Object *formal; + ExtendedParam *extended; +}; + +struct ParamMappingFunction { + ParamMapping *mapping; + ParamMappingFunction *otherMappings; +}; + +struct PointsToEntry { + LocationSet *loc; + LocationSetSet *locs; +}; + +struct PointsToFunction { + PointsToEntry *pte; + PointsToFunction *otherPtes; +}; + +struct PartialTransferFunction { + PointsToFunction *initialPointsToFn; + PointsToFunction *finalPointsToFn; + LocationSetSet *funcModifies; + LocationSet *returnLocation; + Boolean x10; + struct { + IROLinear *nd; + PartialTransferFunction *ptf; + } context; +}; + +struct PTFList { + PartialTransferFunction *ptf; + PTFList *otherPTFs; +}; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +// TODO: how many of these are actually in IroPointerAnalysis.c? +static uint32 stExtendedParamNum; +static PartialTransferFunction *stUnknownPTF; +static uint32 stIndentationLevel; +static UInt8 stTabs[0x2C]; // unused mystery object +static Stack *stCallingContextStack; +static ObjectList *stParamObjs; +static jmp_buf stAbortPointerAnalysis; +static Object stUnknown; +static Object *stCurrentProc; +static ExtendedParamSet *stExtParamSet; +static PTFList *stPTFList; +static uint32 stMaxPassCount; +// TODO: stEvalProcActionParams +static IRONode *stExceptionFNode; + +static PAMemoryBlock stDummyMemoryBlock = { + PAMEMORYBLOCKKIND_1 +}; +static PAMemoryBlock *stUnknownMb = &stDummyMemoryBlock; + +static LocationSet stDummyLocationSet = { + &stDummyMemoryBlock +}; + +static LocationSet *stUnknownLs = &stDummyLocationSet; + +// forward decls +inline StackElement *Stack_sub_48A5B0(Stack **stackPtr); +inline void ObjectSet_RemoveAll(ObjectSet *procList); +inline void ExtendedParamSet_RemoveAll(ExtendedParamSet *epList); +inline void LocationSet_Copy(LocationSet *dest, LocationSet *src); +inline Boolean LocationSet_IsUnknown(LocationSet *ls); +inline void LocationSetSet_RemoveAll(LocationSetSet *lss); +inline void LocationSetSet_AddSet(LocationSetSet *dest, LocationSetSet *src); +inline void ParamMappingFunction_RemoveAll(ParamMappingFunction *pmf); +inline void ParamMappingFunction_AddAllMaybe_sub_487C50(ParamMappingFunction *dest, ParamMappingFunction *src); +inline void PointsToFunction_RemoveAll(PointsToFunction *pointsToFunc); +inline void PointsToFunction_AddAllIGuess_sub_487D80(PointsToFunction *dest, PointsToFunction *src); +inline void PTFList_RemoveAll(PTFList *ptfList); + +inline StackElement *StackElement_New(void) { + StackElement *stackElement = IRO_malloc(sizeof(StackElement)); +#line 103 + IRO_ASSERT(stackElement != NULL); +#ifdef IRO_DEBUG + stackElement->proc = NULL; + stackElement->ptf = NULL; + stackElement->map = NULL; + stackElement->funcCall = NULL; +#endif + return stackElement; +} + +inline void StackElement_Delete(StackElement *stackElement) { +#line 117 + IRO_ASSERT(stackElement != NULL); + IRO_ASSERT(stackElement->proc == NULL); + IRO_ASSERT(stackElement->ptf == NULL); + IRO_ASSERT(stackElement->map == NULL); + IRO_ASSERT(stackElement->funcCall == NULL); + IRO_DEBUG_CLEAR(stackElement, sizeof(StackElement)); + IRO_free(stackElement); +} + +inline void StackElement_Init(StackElement *stackElement, Object *proc, PartialTransferFunction *ptf, ParamMappingFunction *map, IROLinear *funcCall) { +#line 131 + IRO_ASSERT(stackElement != NULL); + IRO_ASSERT(proc != NULL); + IRO_ASSERT(ptf != NULL); + IRO_ASSERT(map != NULL); + IRO_ASSERT(funcCall != NULL); + stackElement->proc = proc; + stackElement->ptf = ptf; + stackElement->map = map; + stackElement->funcCall = funcCall; +} + +inline void StackElement_Copy(StackElement *dest, StackElement *src) { +#line 145 + IRO_ASSERT(dest != NULL); + IRO_ASSERT(src != NULL); + StackElement_Init(dest, src->proc, src->ptf, src->map, src->funcCall); +} + +inline void StackElement_Term(StackElement *stackElement) { +#line 156 + IRO_ASSERT(stackElement != NULL); +#ifdef IRO_DEBUG + stackElement->proc = NULL; + stackElement->ptf = NULL; + stackElement->map = NULL; + stackElement->funcCall = NULL; +#endif +} + +inline void *StackElement_sub_48A780(StackElement *stackElement) { +#line 213 + IRO_ASSERT(stackElement != NULL); + return stackElement->proc; +} + +inline Boolean StackRelated_sub_48A760(void *key1, void *key2) { +#line 220 + IRO_ASSERT(key1 != NULL); + IRO_ASSERT(key2 != NULL); + return key1 == key2; +} + +inline Object *StackElement_proc(StackElement *stackElement) { +#line 228 + IRO_ASSERT(stackElement != NULL); + return stackElement->proc; +} + +inline PartialTransferFunction *StackElement_ptf(StackElement *stackElement) { +#line 235 + IRO_ASSERT(stackElement != NULL); + return stackElement->ptf; +} + +inline ParamMappingFunction *StackElement_map(StackElement *stackElement) { +#line 242 + IRO_ASSERT(stackElement != NULL); + return stackElement->map; +} + +inline IROLinear *StackElement_funcCall(StackElement *stackElement) { +#line 249 + IRO_ASSERT(stackElement != NULL); + return stackElement->funcCall; +} + +inline Stack *Stack_New(void) { + Stack *stack = IRO_malloc(sizeof(Stack)); +#line 265 + IRO_ASSERT(stack != NULL); +#ifdef IRO_DEBUG + stack->top = NULL; + stack->next = NULL; +#endif + return stack; +} + +inline void Stack_Delete(Stack *stack) { +#line 277 + IRO_ASSERT(stack != NULL); + IRO_ASSERT(stack->top == NULL); + IRO_ASSERT(stack->next == NULL); + IRO_DEBUG_CLEAR(stack, sizeof(Stack)); + IRO_free(stack); +} + +inline void Stack_Init(Stack *stack) { +#line 289 + IRO_ASSERT(stack != NULL); + stack->top = NULL; + stack->next = NULL; +} + +inline void Stack_Term(Stack **stackPtr) { + StackElement *stackElement; + +#line 299 + IRO_ASSERT(stackPtr != NULL); + IRO_ASSERT(*stackPtr != NULL); + + while ((*stackPtr)->top) { + stackElement = Stack_sub_48A5B0(stackPtr); + StackElement_Term(stackElement); + StackElement_Delete(stackElement); + } +} + +inline void Stack_sub_48A660(Stack **stackPtr, StackElement *stackElement) { + StackElement *newElement; + Stack *newStack; + +#line 315 + IRO_ASSERT(stackPtr != NULL); + IRO_ASSERT(*stackPtr != NULL); + + newElement = StackElement_New(); + StackElement_Copy(newElement, stackElement); + + newStack = Stack_New(); + newStack->top = newElement; + newStack->next = *stackPtr; + *stackPtr = newStack; +} + +inline StackElement *Stack_Top(Stack **stackPtr) { +#line 331 + IRO_ASSERT(stackPtr != NULL); + IRO_ASSERT(*stackPtr != NULL); + + return (*stackPtr)->top; +} + +inline Stack *Stack_Next(Stack **stackPtr) { +#line 343 + IRO_ASSERT(stackPtr != NULL); + IRO_ASSERT(*stackPtr != NULL); + + return (*stackPtr)->next; +} + +inline StackElement *Stack_sub_48A5B0(Stack **stackPtr) { + StackElement *stackElement; + +#line 357 + IRO_ASSERT(stackPtr != NULL); + IRO_ASSERT(*stackPtr != NULL); + + stackElement = (*stackPtr)->top; + if (stackElement) { + Stack *next = (*stackPtr)->next; + (*stackPtr)->top = NULL; + (*stackPtr)->next = NULL; + Stack_Delete(*stackPtr); + *stackPtr = next; + } + + return stackElement; +} + +inline StackElement *Stack_sub_48A710(Stack **stackPtr, void *key) { + Stack *stack; + +#line 379 + IRO_ASSERT(stackPtr != NULL); + IRO_ASSERT(key != NULL); + + for (stack = *stackPtr; stack; stack = stack->next) { + if (stack->top) { + if (StackRelated_sub_48A760(StackElement_sub_48A780(stack->top), key)) + return stack->top; + } + } + + return NULL; +} + +inline ObjectSet *ObjectSet_New(void) { + ObjectSet *procList; + + procList = IRO_malloc(sizeof(ObjectSet)); +#line 439 + IRO_ASSERT(procList != NULL); +#ifdef IRO_DEBUG + procList->proc = NULL; + procList->otherProcs = NULL; +#endif + return procList; +} + +inline void ObjectSet_Delete(ObjectSet *procList) { +#line 451 + IRO_ASSERT(procList != NULL); + IRO_ASSERT(procList->proc == NULL); + IRO_ASSERT(procList->otherProcs == NULL); + IRO_DEBUG_CLEAR(procList, sizeof(ObjectSet)); + IRO_free(procList); +} + +inline void ObjectSet_Init(ObjectSet *procList) { +#line 463 + IRO_ASSERT(procList != NULL); + procList->proc = NULL; + procList->otherProcs = NULL; +} + +inline void ObjectSet_Term(ObjectSet *procList) { +#line 481 + IRO_ASSERT(procList != NULL); + ObjectSet_RemoveAll(procList); +#ifdef IRO_DEBUG + procList->proc = NULL; + procList->otherProcs = NULL; +#endif +} + +inline void ObjectSet_ForEach(ObjectSet *procList, void (*action)(Object *, void *), void *refcon) { +#line 528 + IRO_ASSERT(procList != NULL); + IRO_ASSERT(action != NULL); + IRO_ASSERT(refcon == NULL || refcon != NULL); + + while (procList && procList->proc) { + action(procList->proc, refcon); + procList = procList->otherProcs; + } +} + +inline Object *ObjectSet_sub_485020(ObjectSet *procList, Object *proc) { +#line 540 + IRO_ASSERT(procList != NULL); + IRO_ASSERT(proc != NULL); + while (procList && procList->proc) { + if (procList->proc == proc) + return procList->proc; + procList = procList->otherProcs; + } + return NULL; +} + +inline Object *ObjectSet_FindFirst(ObjectSet *procList) { +#line 552 + IRO_ASSERT(procList != NULL); + return procList->proc; +} + +inline int ObjectSet_Count(ObjectSet *procList) { + int count; + +#line 552 + IRO_ASSERT(procList != NULL); + + count = 0; + while (procList && procList->proc) { + count++; + procList = procList->otherProcs; + } + + return count; +} + +inline void ObjectSet_sub_486800(ObjectSet *procList, Object *proc) { + ObjectSet *newProcList; + +#line 574 + IRO_ASSERT(procList != NULL); + IRO_ASSERT(proc != NULL); + + if (procList->proc) { + newProcList = ObjectSet_New(); + ObjectSet_Init(newProcList); + newProcList->proc = procList->proc; + newProcList->otherProcs = procList->otherProcs; + procList->otherProcs = newProcList; + } + + procList->proc = proc; +} + +inline void ObjectSet_sub_4867D0(ObjectSet *procList, Object *proc) { +#line 592 + IRO_ASSERT(procList != NULL); + IRO_ASSERT(proc != NULL); + + if (!ObjectSet_sub_485020(procList, proc)) + ObjectSet_sub_486800(procList, proc); +} + +inline void ObjectSet_Remove(ObjectSet *procList, Object *proc) { + ObjectSet *prev; + ObjectSet *tmp; + +#line 605 + IRO_ASSERT(procList != NULL); + IRO_ASSERT(proc != NULL); + + prev = NULL; + while (procList && procList->proc) { + if (procList->proc == proc) { + if (!prev) { + if (procList->otherProcs == NULL) { + procList->proc = NULL; + } else { + tmp = procList->otherProcs; + procList->proc = procList->otherProcs->proc; + procList->otherProcs = procList->otherProcs->otherProcs; + tmp->proc = NULL; + tmp->otherProcs = NULL; + ObjectSet_Term(tmp); + ObjectSet_Delete(tmp); + } + } else { + prev->otherProcs = procList->otherProcs; + procList->proc = NULL; + procList->otherProcs = NULL; + ObjectSet_Term(procList); + ObjectSet_Delete(procList); + } + return; + } + prev = procList; + procList = procList->otherProcs; + } +} + +inline void ObjectSet_RemoveAll(ObjectSet *procList) { +#line 645 + IRO_ASSERT(procList != NULL); + + while (procList && procList->proc) + ObjectSet_Remove(procList, procList->proc); +} + +inline void ObjectSet_AddSetAction(Object *proc, void *refcon) { +#line 655 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(refcon != NULL); + + ObjectSet_sub_4867D0(refcon, proc); +} + +inline void ObjectSet_SimpleAddSetAction(Object *proc, void *refcon) { +#line 663 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(refcon != NULL); + + ObjectSet_sub_486800(refcon, proc); +} + +inline void ObjectSet_sub_48C590(ObjectSet *dest, ObjectSet *src) { +#line 671 + IRO_ASSERT(dest != NULL); + IRO_ASSERT(src != NULL); + + if (dest->proc) + ObjectSet_ForEach(src, ObjectSet_AddSetAction, dest); + else + ObjectSet_ForEach(src, ObjectSet_SimpleAddSetAction, dest); +} + +inline void ObjectSet_RemoveSetAction(Object *proc, void *refcon) { +#line 682 + IRO_ASSERT(proc != NULL); + IRO_ASSERT(refcon != NULL); + + ObjectSet_Remove(refcon, proc); +} + +inline void ObjectSet_removeiter_sub_48C890(ObjectSet *dest, ObjectSet *src) { +#line 690 + IRO_ASSERT(dest != NULL); + IRO_ASSERT(src != NULL); + + ObjectSet_ForEach(src, ObjectSet_RemoveSetAction, dest); +} + +inline Boolean ObjectSet_sub_484FA0(ObjectSet *os1, ObjectSet *os2) { + ObjectSet *scan; + +#line 700 + IRO_ASSERT(os1 != NULL); + IRO_ASSERT(os2 != NULL); + + if (os1 == os2) + return 1; + + for (scan = os1; scan && scan->proc; scan = scan->otherProcs) { + if (!ObjectSet_sub_485020(os2, scan->proc)) + return 0; + } + + for (scan = os2; scan && scan->proc; scan = scan->otherProcs) { + if (!ObjectSet_sub_485020(os1, scan->proc)) + return 0; + } + + return 1; +} + +inline ExtendedParam *ExtendedParam_New(void) { + ExtendedParam *ep = IRO_malloc(sizeof(ExtendedParam)); + +#line 755 + IRO_ASSERT(ep != NULL); +#ifdef IRO_DEBUG + ep->objectSet = NULL; +#endif + return ep; +} + +inline void ExtendedParam_Delete(ExtendedParam *ep) { + IRO_ASSERT(ep != NULL); + IRO_ASSERT(ep->objectSet == NULL); + IRO_DEBUG_CLEAR(ep, sizeof(ExtendedParam)); + IRO_free(ep); +} + +inline void ExtendedParam_Init(ExtendedParam *ep, Object *obj) { +#line 777 + IRO_ASSERT(ep != NULL); + IRO_ASSERT(obj != NULL); + IRO_ASSERT(obj->extParam == NULL); + IRO_ASSERT(stExtendedParamNum < ((uint32) -1) / 2 - 1); + + ep->objectSet = ObjectSet_New(); + ObjectSet_Init(ep->objectSet); + ObjectSet_sub_4867D0(ep->objectSet, obj); + obj->extParam = ep; + + ep->x4 = stExtendedParamNum++; +} + +inline void ExtendedParam_TermAction(Object *obj, void *refcon) { + obj->extParam = NULL; +} + +inline void ExtendedParam_Term(ExtendedParam *ep) { + IRO_ASSERT(ep != NULL); + + ObjectSet_ForEach(ep->objectSet, ExtendedParam_TermAction, NULL); + ObjectSet_Term(ep->objectSet); + ObjectSet_Delete(ep->objectSet); +#ifdef IRO_DEBUG + ep->objectSet = NULL; +#endif +} + +inline Boolean ExtendedParams_Equal(ExtendedParam *ep1, ExtendedParam *ep2) { +#line 841 + IRO_ASSERT(ep1 != NULL); + IRO_ASSERT(ep2 != NULL); + IRO_ASSERT(ep1->objectSet != NULL); + IRO_ASSERT(ep2->objectSet != NULL); + + if (ep1 == ep2) + return 1; + + return ep1->x4 == ep2->x4 && ObjectSet_sub_484FA0(ep1->objectSet, ep2->objectSet); +} + +inline ExtendedParam *ExtendedParam_FindByObject(Object *obj) { +#line 856 + IRO_ASSERT(obj != NULL); + + return obj->extParam; +} + +inline void ExtendedParam_sub_4867B0(ExtendedParam *ep, Object *obj) { +#line 863 + IRO_ASSERT(ep != NULL); + IRO_ASSERT(ep->objectSet != NULL); + IRO_ASSERT(obj != NULL); + + ObjectSet_sub_4867D0(ep->objectSet, obj); + obj->extParam = ep; +} + +inline void ExtendedParam_RemoveObjectSetAction(Object *object, void *refcon) { + object->extParam = NULL; +} + +inline void EP_sub_48C850(ExtendedParam *ep, ObjectSet *objSet) { +#line 888 + IRO_ASSERT(ep != NULL); + IRO_ASSERT(ep->objectSet != NULL); + IRO_ASSERT(objSet != NULL); + + ObjectSet_removeiter_sub_48C890(ep->objectSet, objSet); + ObjectSet_ForEach(objSet, ExtendedParam_RemoveObjectSetAction, NULL); +} + +inline ObjectSet *ExtendedParam_objectSet(ExtendedParam *ep) { +#line 898 + IRO_ASSERT(ep != NULL); + + return ep->objectSet; +} + +inline uint32 ExtendedParam_sub_489110(ExtendedParam *ep) { +#line 905 + IRO_ASSERT(ep != NULL); + + return ep->x4; +} + +inline ExtendedParamSet *AllocsExtParamSet_sub_4876C0(void) { + ExtendedParamSet *epList = IRO_malloc(sizeof(ExtendedParamSet)); + +#line 924 + IRO_ASSERT(epList != NULL); +#ifdef IRO_DEBUG + epList->ep = NULL; + epList->otherEps = NULL; +#endif + return epList; +} + +inline void FreesExtParamSet_sub_48CAE0(ExtendedParamSet *epList) { +#line 936 + IRO_ASSERT(epList != NULL); + IRO_ASSERT(epList->ep == NULL); + IRO_ASSERT(epList->otherEps == NULL); + IRO_DEBUG_CLEAR(epList, sizeof(ExtendedParamSet)); + IRO_free(epList); +} + +inline void InitsExtParamSet_sub_4876A0(ExtendedParamSet *epList) { +#line 948 + IRO_ASSERT(epList != NULL); + epList->ep = NULL; + epList->otherEps = NULL; +} + +inline void TermsExtParamSet_sub_48CB00(ExtendedParamSet *epList) { +#line 966 + IRO_ASSERT(epList != NULL); + ExtendedParamSet_RemoveAll(epList); +#ifdef IRO_DEBUG + epList->ep = NULL; + epList->otherEps = NULL; +#endif +} + +inline void MaybeWalkExtParamSet_sub_48CBE0(ExtendedParamSet *epList, void (*action)(ExtendedParam *, void *), void *refcon) { +#line 1010 + IRO_ASSERT(epList != NULL); + IRO_ASSERT(action != NULL); + + while (epList && epList->ep) { + action(epList->ep, refcon); + epList = epList->otherEps; + } +} + +inline ExtendedParam *ExtParamSet_sub_4876D0(ExtendedParamSet *epList, ExtendedParam *ep) { +#line 1022 + IRO_ASSERT(epList != NULL); + IRO_ASSERT(ep != NULL); + + while (epList && epList->ep) { + if (epList->ep == ep) + return epList->ep; + epList = epList->otherEps; + } + + return NULL; +} + +inline void ExtParamSet_sub_487660(ExtendedParamSet *epList, ExtendedParam *ep) { +#line 1056 + IRO_ASSERT(epList != NULL); + IRO_ASSERT(ep != NULL); + + if (epList->ep) { + ExtendedParamSet *newSet = AllocsExtParamSet_sub_4876C0(); + InitsExtParamSet_sub_4876A0(newSet); + newSet->ep = epList->ep; + newSet->otherEps = epList->otherEps; + epList->otherEps = newSet; + } + + epList->ep = ep; +} + +inline void ExtParamSet_sub_487630(ExtendedParamSet *epList, ExtendedParam *ep) { +#line 1076 + IRO_ASSERT(epList != NULL); + IRO_ASSERT(ep != NULL); + + if (!ExtParamSet_sub_4876D0(epList, ep)) + ExtParamSet_sub_487660(epList, ep); +} + +inline void ExtendedParamSet_Remove(ExtendedParamSet *epList, ExtendedParam *ep) { + ExtendedParamSet *prev; + ExtendedParamSet *tmp; + +#line 1089 + IRO_ASSERT(epList != NULL); + IRO_ASSERT(ep != NULL); + + prev = NULL; + while (epList && epList->ep) { + if (epList->ep == ep) { + if (!prev) { + if (epList->otherEps == NULL) { + epList->ep = NULL; + } else { + tmp = epList->otherEps; + epList->ep = epList->otherEps->ep; + epList->otherEps = epList->otherEps->otherEps; + tmp->ep = NULL; + tmp->otherEps = NULL; + TermsExtParamSet_sub_48CB00(tmp); + FreesExtParamSet_sub_48CAE0(tmp); + } + } else { + prev->otherEps = epList->otherEps; + epList->ep = NULL; + epList->otherEps = NULL; + TermsExtParamSet_sub_48CB00(epList); + FreesExtParamSet_sub_48CAE0(epList); + } + return; + } + prev = epList; + epList = epList->otherEps; + } +} + +inline void ExtendedParamSet_RemoveAll(ExtendedParamSet *epList) { +#line 1129 + IRO_ASSERT(epList != NULL); + + while (epList && epList->ep) + ExtendedParamSet_Remove(epList, epList->ep); +} + +inline PAHeapBlock *CreateUniqueHeapAlloc_sub_486420(void) { + PAHeapBlock *hb = IRO_malloc(sizeof(PAHeapBlock)); + +#line 1225 + IRO_ASSERT(hb != NULL); +#ifdef IRO_DEBUG + hb->parent = NULL; +#endif + return hb; +} + +inline void InitUniqueHeapAlloc_sub_486410(PAHeapBlock *hb, IROLinear *nd) { +#line 1247 + IRO_ASSERT(hb != NULL); + + hb->x0 = nd; +} + +inline Boolean PAHeapBlocks_Equal(PAHeapBlock *hb1, PAHeapBlock *hb2) { +#line 1296 + IRO_ASSERT(hb1 != NULL); + IRO_ASSERT(hb2 != NULL); + + return (hb1 == hb2) || (hb1->x0 == hb2->x0); +} + +inline PALocalVar *PALocalVar_New(void) { + PALocalVar *local = IRO_malloc(sizeof(PALocalVar)); + +#line 1333 + IRO_ASSERT(local != NULL); +#ifdef IRO_DEBUG + local->parent = NULL; + local->nextSibling = NULL; +#endif + return local; +} + +inline void PALocalVar_InitByObject(PALocalVar *local, Object *obj) { +#line 1357 + IRO_ASSERT(local != NULL); + IRO_ASSERT(obj != NULL); + + local->x0 = obj; + if (obj->name && obj->name->name) { + local->x4 = IRO_malloc(strlen(obj->name->name) + 1); + strcpy(local->x4, obj->name->name); + } else { + local->x4 = NULL; + } +} + +inline void PALocalVar_InitByName(PALocalVar *local, char *name) { +#line 1372 + IRO_ASSERT(local != NULL); + IRO_ASSERT(name != NULL); + + local->x0 = NULL; + local->x4 = IRO_malloc(strlen(name) + 1); + strcpy(local->x4, name); +} + +inline Boolean PALocalVars_Equal(PALocalVar *local1, PALocalVar *local2) { +#line 1419 + IRO_ASSERT(local1 == NULL || local1 != NULL); + IRO_ASSERT(local2 == NULL || local2 != NULL); + + if (local1 == local2) + return 1; + if (!local1 || !local2) + return 0; + + if (!local1->x0 || !local2->x0) { + if (local1->x4) + return local2->x4 && !strcmp(local1->x4, local2->x4); + } + + return local1->x0 == local2->x0; +} + +inline void PALocalVar_SetSth_sub_4847C0(PALocalVar *local, Object *obj) { +#line 1436 + IRO_ASSERT(local != NULL); + IRO_ASSERT(obj == NULL || obj != NULL); + + local->x0 = obj; +} + +inline Object *PALocalVar_Get0_sub_4847E0(PALocalVar *local) { +#line 1444 + IRO_ASSERT(local != NULL); + return local->x0; +} + +inline char *PALocalVar_Get4_sub_4847D0(PALocalVar *local) { +#line 1451 + IRO_ASSERT(local != NULL); + return local->x4; +} + +inline PAMemoryBlock *PAMemoryBlock_New(void) { + PAMemoryBlock *mb = IRO_malloc(sizeof(PAMemoryBlock)); + +#line 1491 + IRO_ASSERT(mb != NULL); +#ifdef IRO_DEBUG + mb->kind = PAMEMORYBLOCKKIND_INVALID; +#endif + return mb; +} + +inline void PAMemoryBlock_Delete(PAMemoryBlock *mb) { +#line 1502 + IRO_ASSERT(mb != NULL); + IRO_ASSERT(mb->kind == PAMEMORYBLOCKKIND_INVALID); + IRO_free(mb); +} + +inline void PAMemoryBlock_Init(PAMemoryBlock *mb, PAMemoryBlockKind kind, void *thing) { +#line 1513 + IRO_ASSERT(mb != NULL); + IRO_ASSERT(thing == NULL || thing != NULL); + + mb->kind = kind; + switch (mb->kind) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + mb->u.ep = (ExtendedParam *) thing; + break; + case PAMEMORYBLOCKKIND_LOCALVAR: + mb->u.localvar = (PALocalVar *) thing; + break; + case PAMEMORYBLOCKKIND_HEAPBLOCK: + mb->u.heapblock = (PAHeapBlock *) thing; + break; + case PAMEMORYBLOCKKIND_INT: + mb->u.intval = *((CInt64 *) thing); + break; + case PAMEMORYBLOCKKIND_6: + mb->u.x6 = (void *) thing; + break; + default: +#line 1535 + CError_FATAL(); + } +} + +inline void PAMemoryBlock_Term(PAMemoryBlock *mb) { +#line 1552 + IRO_ASSERT(mb != NULL); + +#ifdef IRO_DEBUG + mb->kind = PAMEMORYBLOCKKIND_INVALID; +#endif +} + +inline Boolean MemoryBlocks_Equal(PAMemoryBlock *mb1, PAMemoryBlock *mb2) { +#line 1657 + IRO_ASSERT(mb1 == NULL || mb1 != NULL); + IRO_ASSERT(mb2 == NULL || mb2 != NULL); + + if (mb1 == mb2) + return 1; + + if (!mb1 || !mb2 || mb1->kind != mb2->kind) + return 0; + + switch (mb1->kind) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + return ExtendedParams_Equal(mb1->u.ep, mb2->u.ep); + case PAMEMORYBLOCKKIND_LOCALVAR: + return PALocalVars_Equal(mb1->u.localvar, mb2->u.localvar); + case PAMEMORYBLOCKKIND_HEAPBLOCK: + return PAHeapBlocks_Equal(mb1->u.heapblock, mb2->u.heapblock); + case PAMEMORYBLOCKKIND_INT: + return CInt64_Equal(mb1->u.intval, mb2->u.intval); + case PAMEMORYBLOCKKIND_6: + return mb1->u.x6 == mb2->u.x6; + default: +#line 1684 + CError_FATAL(); + return 0; + } +} + +inline PAMemoryBlockKind PAMemoryBlock_kind(PAMemoryBlock *mb) { +#line 1692 + IRO_ASSERT(mb != NULL); + + return mb->kind; +} + +inline void *PAMemoryBlock_thing(PAMemoryBlock *mb) { +#line 1699 + IRO_ASSERT(mb != NULL); + + switch (mb->kind) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + return mb->u.ep; + case PAMEMORYBLOCKKIND_LOCALVAR: + return mb->u.localvar; + case PAMEMORYBLOCKKIND_HEAPBLOCK: + return mb->u.heapblock; + case PAMEMORYBLOCKKIND_INT: + return &mb->u.intval; + case PAMEMORYBLOCKKIND_6: + return mb->u.x6; + default: +#line 1719 + CError_FATAL(); + return NULL; + } +} + +inline LocationSet *LocationSet_New(void) { + LocationSet *ls = IRO_malloc(sizeof(LocationSet)); + +#line 1767 + IRO_ASSERT(ls != NULL); +#ifdef IRO_DEBUG + ls->block = NULL; + ls->rtype = NULL; + ls->u.known.field = cint64_zero; + ls->u.known.stride = 0; +#endif + return ls; +} + +inline void LocationSet_Delete(LocationSet *ls) { +#line 1781 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(ls != stUnknownLs); + IRO_ASSERT(ls->block == NULL); + IRO_ASSERT(CInt64_IsZero(&ls->u.known.field)); + IRO_ASSERT(ls->u.known.stride == 0); + IRO_ASSERT(ls->rtype == NULL); + IRO_DEBUG_CLEAR(ls, sizeof(LocationSet)); + IRO_free(ls); +} + +inline void LocationSet_InitKnown(LocationSet *ls, PAMemoryBlock *block, CInt64 field, UInt32 stride, Type *rtype) { +#line 1796 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(ls != stUnknownLs); + IRO_ASSERT(block != NULL); + IRO_ASSERT(rtype == NULL || rtype != NULL); + ls->block = block; + ls->rtype = rtype; + ls->u.known.field = field; + ls->u.known.stride = stride; +} + +inline void LocationSet_InitUnknown(LocationSet *ls, Type *rtype, PAMemoryBlock *restriction, LocationSet *bitfieldOf) { +#line 1809 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(ls != stUnknownLs); + IRO_ASSERT(rtype == NULL || rtype != NULL); + IRO_ASSERT(restriction == NULL || restriction != NULL); + IRO_ASSERT(bitfieldOf == NULL || bitfieldOf != NULL); + + LocationSet_Copy(ls, stUnknownLs); + ls->rtype = rtype; + ls->u.unknown.restriction = restriction; + if (bitfieldOf) { + ls->u.unknown.bitfieldOf = LocationSet_New(); + LocationSet_Copy(ls->u.unknown.bitfieldOf, bitfieldOf); + } else { + ls->u.unknown.bitfieldOf = NULL; + } +} + +inline void LocationSet_Copy(LocationSet *dest, LocationSet *src) { +#line 1829 + IRO_ASSERT(src != NULL); + IRO_ASSERT(dest != NULL); + + dest->block = src->block; + dest->rtype = src->rtype; + + if (!LocationSet_IsUnknown(src)) { + dest->u.known.field = src->u.known.field; + dest->u.known.stride = src->u.known.stride; + } else { + dest->u.unknown.restriction = src->u.unknown.restriction; + if (src->u.unknown.bitfieldOf != NULL) { + dest->u.unknown.bitfieldOf = LocationSet_New(); + LocationSet_Copy(dest->u.unknown.bitfieldOf, src->u.unknown.bitfieldOf); + } else { + dest->u.unknown.bitfieldOf = NULL; + } + } +} + +inline void LocationSet_Term(LocationSet *ls) { +#line 1857 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(ls != stUnknownLs); + +#ifdef IRO_DEBUG + if (LocationSet_IsUnknown(ls) && ls->u.unknown.bitfieldOf) { + LocationSet_Term(ls->u.unknown.bitfieldOf); + LocationSet_Delete(ls->u.unknown.bitfieldOf); + } + ls->block = NULL; + ls->rtype = NULL; + ls->u.known.field = cint64_zero; + ls->u.known.stride = 0; +#endif +} + +inline Boolean LocationSets_Overlap(LocationSet *ls1, Type *rtype1, LocationSet *ls2, Type *rtype2) { + Boolean isUnknown1, isUnknown2; + PAMemoryBlock *restriction1, *restriction2; + +#line 1974 + IRO_ASSERT(ls1 != NULL); + IRO_ASSERT(rtype1 == NULL || rtype1 != NULL); + IRO_ASSERT(ls2 != NULL); + IRO_ASSERT(rtype2 == NULL || rtype2 != NULL); + + if (ls1 == ls2) + return 1; + + isUnknown1 = LocationSet_IsUnknown(ls1); + if (isUnknown1) + restriction1 = ls1->u.unknown.restriction; + else + restriction1 = NULL; + + isUnknown2 = LocationSet_IsUnknown(ls2); + if (isUnknown2) + restriction2 = ls2->u.unknown.restriction; + else + restriction2 = NULL; + + if ( + (isUnknown1 && !restriction1) || + (isUnknown2 && !restriction2) || + (isUnknown1 && isUnknown2 && MemoryBlocks_Equal(restriction1, restriction2)) + ) + return 1; + + if (isUnknown1 || isUnknown2) + return 0; + + if (MemoryBlocks_Equal(ls1->block, ls2->block)) { + UInt32 size1; + UInt32 size2; + UInt32 i; + CInt64 work; + CInt64 longgcd; + + if (rtype1) + size1 = rtype1->size; + else + size1 = -1; + + if (rtype2) + size2 = rtype2->size; + else + size2 = -1; + + if (ls1->u.known.stride == ls2->u.known.stride) { + CInt64 longsize1; + CInt64 longsize2; + CInt64_SetULong(&longsize1, size1); + CInt64_SetULong(&longsize2, size2); + + return CInt64_Equal(ls1->u.known.field, ls2->u.known.field) || + (CInt64_Less(ls1->u.known.field, ls2->u.known.field) && CInt64_Greater(CInt64_Add(ls1->u.known.field, longsize1), ls2->u.known.field)) || + (CInt64_Less(ls2->u.known.field, ls1->u.known.field) && CInt64_Greater(CInt64_Add(ls2->u.known.field, longsize2), ls1->u.known.field)); + } else { + work = CInt64_Sub(ls1->u.known.field, ls2->u.known.field); + if (CInt64_IsNegative(&work)) + work = CInt64_Neg(work); + + CInt64_SetULong(&longgcd, gcd(ls1->u.known.stride, ls2->u.known.stride)); + if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero)) + return 1; + + if (size1 == -1) + return 1; + + for (i = 1; i < size1; i++) { + CInt64_SetLong(&work, i); + work = CInt64_Add(work, ls1->u.known.field); + work = CInt64_Sub(work, ls2->u.known.field); + if (CInt64_IsNegative(&work)) + work = CInt64_Neg(work); + if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero)) + return 1; + } + + if (size2 == -1) + return 1; + + for (i = 1; i < size2; i++) { + CInt64_SetLong(&work, i); + work = CInt64_Add(work, ls2->u.known.field); + work = CInt64_Sub(work, ls1->u.known.field); + if (CInt64_IsNegative(&work)) + work = CInt64_Neg(work); + if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero)) + return 1; + } + + return 0; + } + } + + return 0; +} + +inline Boolean LocationSets_Equal(LocationSet *ls1, LocationSet *ls2) { +#line 2080 + IRO_ASSERT(ls1 != NULL); + IRO_ASSERT(ls2 != NULL); + + return + (ls1 == ls2) || + ( + (LocationSet_IsUnknown(ls1) && LocationSet_IsUnknown(ls2)) && + (MemoryBlocks_Equal(ls1->u.unknown.restriction, ls2->u.unknown.restriction)) && + ((ls1->u.unknown.bitfieldOf == ls2->u.unknown.bitfieldOf) || + (ls1->u.unknown.bitfieldOf && ls2->u.unknown.bitfieldOf && LocationSets_Equal(ls1->u.unknown.bitfieldOf, ls2->u.unknown.bitfieldOf))) && + ((ls1->rtype == ls2->rtype) || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) + ) || + ( + (!LocationSet_IsUnknown(ls1) && !LocationSet_IsUnknown(ls2)) && + (ls1->u.known.stride == ls2->u.known.stride) && + ((ls1->rtype == ls2->rtype) || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) && + CInt64_Equal(ls1->u.known.field, ls2->u.known.field) && + MemoryBlocks_Equal(ls1->block, ls2->block) + ); +} + +inline Boolean LocationSets_LookupCompatible(LocationSet *ls1, LocationSet *ls2) { +#line 2119 + IRO_ASSERT(ls1 != NULL); + IRO_ASSERT(ls2 != NULL); + + if ( + (ls1 == ls2) || + ( + LocationSet_IsUnknown(ls1) && + LocationSet_IsUnknown(ls2) && + MemoryBlocks_Equal(ls1->u.unknown.restriction, ls2->u.unknown.restriction) && + (ls1->rtype == ls2->rtype || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) + )) + return 1; + + if ( + (!LocationSet_IsUnknown(ls1) && !LocationSet_IsUnknown(ls2)) && + (ls1->rtype == ls2->rtype || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) && + MemoryBlocks_Equal(ls1->block, ls2->block) + ) { + CInt64 work; + CInt64 longgcd; + + if (ls1->u.known.stride == ls2->u.known.stride) + return CInt64_Equal(ls1->u.known.field, ls2->u.known.field); + + work = CInt64_Sub(ls1->u.known.field, ls2->u.known.field); + if (CInt64_IsNegative(&work)) + work = CInt64_Neg(work); + + CInt64_SetULong(&longgcd, gcd(ls1->u.known.stride, ls2->u.known.stride)); + return CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero); + } + + return 0; +} + +inline Boolean LocationSet_Contains(LocationSet *ls1, Type *rtype1, LocationSet *ls2, Type *rtype2) { + Boolean unknown1; + Boolean unknown2; + PAMemoryBlock *restriction2; + PAMemoryBlock *restriction1; + CInt64 longsize1; + CInt64 longsize2; + +#line 2168 + IRO_ASSERT(ls1 != NULL); + IRO_ASSERT(ls2 != NULL); + IRO_ASSERT(rtype1 != NULL); + IRO_ASSERT(rtype2 != NULL); + + if (ls1 == ls2) + return 1; + + unknown1 = LocationSet_IsUnknown(ls1); + if (unknown1) + restriction1 = ls1->u.unknown.restriction; + else + restriction1 = NULL; + + unknown2 = LocationSet_IsUnknown(ls2); + if (unknown2) + restriction2 = ls2->u.unknown.restriction; + else + restriction2 = NULL; + + if (unknown1) + return !restriction1 || (unknown2 && MemoryBlocks_Equal(restriction2, restriction1)); + + CInt64_SetULong(&longsize1, rtype1->size); + CInt64_SetULong(&longsize2, rtype2->size); + + return + !LocationSet_IsUnknown(ls2) && + (ls1->u.known.stride == 0) && + (ls2->u.known.stride == 0) && + rtype1->size >= rtype2->size && + CInt64_LessEqual(ls1->u.known.field, ls2->u.known.field) && + CInt64_GreaterEqual(CInt64_Add(ls1->u.known.field, longsize1), CInt64_Add(ls2->u.known.field, longsize2)) && + MemoryBlocks_Equal(ls1->block, ls2->block); +} + +inline Boolean LocationSet_IsUnknown(LocationSet *ls) { +#line 2233 + IRO_ASSERT(ls != NULL); + + return (ls == stUnknownLs) || (ls->block == stUnknownMb); +} + +inline Boolean LocationSet_sub_48AF30(LocationSet *ls) { + return + !LocationSet_IsUnknown(ls) && + (ls->u.known.stride == 0) && + CInt64_IsZero(&ls->u.known.field) && + PAMemoryBlock_kind(ls->block) == PAMEMORYBLOCKKIND_LOCALVAR && + !PAMemoryBlock_thing(ls->block); +} + +inline void LocationSet_SetRtype(LocationSet *ls, Type *rtype) { +#line 2263 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(ls != stUnknownLs); + IRO_ASSERT(rtype != NULL); + + ls->rtype = rtype; +} + +inline void SetsLocationSetField_sub_4851B0(LocationSet *ls, CInt64 field) { +#line 2272 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(ls)); + + ls->u.known.field = field; +} + +inline void SetsLocationSetStride_sub_4852D0(LocationSet *ls, SInt32 stride) { +#line 2280 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(ls)); + + ls->u.known.stride = stride; +} + +inline PAMemoryBlock *LocationSet_block(LocationSet *ls) { +#line 2298 + IRO_ASSERT(ls != NULL); + + return ls->block; +} + +inline Type *LocationSet_rtype(LocationSet *ls) { +#line 2306 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(ls != stUnknownLs); + + return ls->rtype; +} + +inline CInt64 LocationSet_field(LocationSet *ls) { +#line 2314 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(ls)); + + return ls->u.known.field; +} + +inline UInt32 LocationSet_stride(LocationSet *ls) { +#line 2322 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(ls)); + + return ls->u.known.stride; +} + +inline PAMemoryBlock *LocationSet_restriction(LocationSet *ls) { +#line 2330 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(LocationSet_IsUnknown(ls)); + + return ls->u.unknown.restriction; +} + +inline LocationSet *LocationSet_bitfieldOf(LocationSet *ls) { +#line 2338 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(LocationSet_IsUnknown(ls)); + + return ls->u.unknown.bitfieldOf; +} + +inline LocationSetSet *LocationSetSet_New() { + LocationSetSet *lss = IRO_malloc(sizeof(LocationSetSet)); + +#line 2356 + IRO_ASSERT(lss != NULL); +#ifdef IRO_DEBUG + lss->loc = NULL; + lss->otherLocs = NULL; + lss->count = 0; +#endif + return lss; +} + +inline void LocationSetSet_Delete(LocationSetSet *lss) { +#line 2369 + IRO_ASSERT(lss != NULL); + IRO_ASSERT(lss->loc == NULL); + IRO_ASSERT(lss->otherLocs == NULL); + IRO_ASSERT(lss->count == 0); + IRO_DEBUG_CLEAR(lss, sizeof(LocationSetSet)); + IRO_free(lss); +} + +inline void LocationSetSet_Init(LocationSetSet *lss) { +#line 2382 + IRO_ASSERT(lss != NULL); + + lss->loc = NULL; + lss->otherLocs = NULL; + lss->count = 0; +} + +inline void LocationSetSet_Copy(LocationSetSet *dest, LocationSetSet *src) { +#line 2391 + IRO_ASSERT(dest != NULL); + IRO_ASSERT(src != NULL); + + dest->loc = NULL; + dest->otherLocs = NULL; + dest->count = 0; + LocationSetSet_AddSet(dest, src); +} + +inline void LocationSetSet_Term(LocationSetSet *lss) { +#line 2402 + IRO_ASSERT(lss != NULL); + + LocationSetSet_RemoveAll(lss); + +#ifdef IRO_DEBUG + lss->loc = NULL; + lss->otherLocs = NULL; + lss->count = 0; +#endif +} + +inline void LocationSetSet_ForEach(LocationSetSet *lss, void (*action)(LocationSet *, void *), void *refcon) { +#line 2446 + IRO_ASSERT(lss != NULL); + IRO_ASSERT(action != NULL); + IRO_ASSERT(refcon == NULL || refcon != NULL); + + while (lss && lss->loc) { + action(lss->loc, refcon); + lss = lss->otherLocs; + } +} + +inline LocationSet *LocationSetSet_Find(LocationSetSet *lss, LocationSet *ls) { +#line 2458 + IRO_ASSERT(lss != NULL); + IRO_ASSERT(ls != NULL); + + while (lss && lss->loc) { + if (LocationSets_Equal(lss->loc, ls)) + return lss->loc; + lss = lss->otherLocs; + } + + return NULL; +} + +inline LocationSet *LocationSetSet_FindUnknown(LocationSetSet *lss) { +#line 2470 + IRO_ASSERT(lss != NULL); + + if (!lss->loc) + return stUnknownLs; + + while (lss && lss->loc) { + if (LocationSet_IsUnknown(lss->loc)) + return lss->loc; + lss = lss->otherLocs; + } + + return NULL; +} + +inline LocationSet *LocationSetSet_FindFirst(LocationSetSet *lss) { +#line 2498 + IRO_ASSERT(lss != NULL); + + return lss->loc; +} + +inline int LocationSetSet_Count(LocationSetSet *lss) { +#line 2505 + IRO_ASSERT(lss != NULL); + + return lss->count; +} + +inline void LocationSetSet_RemoveAllWithMemoryBlock(LocationSetSet *lss, PAMemoryBlock *block) { + LocationSetSet *first; + LocationSetSet *prev; + LocationSetSet *next; + LocationSetSet *tmp; + +#line 2514 + IRO_ASSERT(lss != NULL); + IRO_ASSERT(block != NULL); + + first = lss; + prev = NULL; + while (lss && lss->loc) { + next = lss->otherLocs; + if (MemoryBlocks_Equal(block, lss->loc->block)) { + if (lss->loc != stUnknownLs) { + LocationSet_Term(lss->loc); + LocationSet_Delete(lss->loc); + } + if (!prev) { + if (lss->otherLocs == NULL) { + lss->loc = NULL; + prev = lss; + } else { + tmp = lss->otherLocs; + lss->loc = lss->otherLocs->loc; + lss->otherLocs = lss->otherLocs->otherLocs; + tmp->loc = NULL; + tmp->otherLocs = NULL; + LocationSetSet_Term(tmp); + LocationSetSet_Delete(tmp); + prev = NULL; + next = lss; + } + } else { + prev->otherLocs = lss->otherLocs; + lss->loc = NULL; + lss->otherLocs = NULL; + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + prev = lss; + } + first->count--; + } + lss = next; + } +} + +inline void LocationSetSet_SimpleAdd(LocationSetSet *lss, LocationSet *ls) { +#line 2572 + IRO_ASSERT(lss != NULL); + IRO_ASSERT(ls != NULL); + + if (!LocationSet_IsUnknown(ls) && lss->count < 4) { + LocationSet *ls2; + + if (ls == stUnknownLs) { + ls2 = stUnknownLs; + } else { + ls2 = LocationSet_New(); + LocationSet_Copy(ls2, ls); + } + + if (lss->loc) { + LocationSetSet *lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + lss2->loc = lss->loc; + lss2->otherLocs = lss->otherLocs; + lss->otherLocs = lss2; + } + + lss->loc = ls2; + lss->count++; + } else { + LocationSet *ls2; + + LocationSetSet_RemoveAll(lss); + ls2 = LocationSet_New(); + if (LocationSet_IsUnknown(ls)) { + LocationSet_Copy(ls2, ls); + } else { + LocationSet_Copy(ls2, stUnknownLs); + if (ls->rtype) + LocationSet_SetRtype(ls2, ls->rtype); + } + + lss->loc = ls2; + lss->count = 1; + } +} + +inline void LocationSetSet_Add(LocationSetSet *lss, LocationSet *ls) { +#line 2622 + IRO_ASSERT(lss != NULL); + IRO_ASSERT(ls != NULL); + + if (!lss->loc || (!LocationSet_IsUnknown(lss->loc) && !LocationSetSet_Find(lss, ls))) { + if (!LocationSet_IsUnknown(ls) && ls->u.known.stride) + LocationSetSet_RemoveAllWithMemoryBlock(lss, ls->block); + LocationSetSet_SimpleAdd(lss, ls); + } +} + +inline void LocationSetSet_AddUnknown(LocationSetSet *lss, Type *rtype, PAMemoryBlock *restriction, LocationSet *bitfieldOf) { + LocationSet *ls; + +#line 2643 + IRO_ASSERT(lss != NULL); + IRO_ASSERT(rtype == NULL || rtype != NULL); + IRO_ASSERT(restriction == NULL || restriction != NULL); + IRO_ASSERT(bitfieldOf == NULL || bitfieldOf != NULL); + + ls = LocationSet_New(); + LocationSet_InitUnknown(ls, rtype, restriction, bitfieldOf); + LocationSetSet_Add(lss, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); +} + +inline void LocationSetSet_Remove(LocationSetSet *lss, LocationSet *ls) { + LocationSetSet *prev; + LocationSetSet *first; + LocationSetSet *tmp; + +#line 2659 + IRO_ASSERT(lss != NULL); + IRO_ASSERT(ls != NULL); + + first = lss; + prev = NULL; + while (lss && lss->loc) { + if (LocationSets_Equal(lss->loc, ls)) { + if (lss->loc != stUnknownLs) { + LocationSet_Term(lss->loc); + LocationSet_Delete(lss->loc); + } + if (!prev) { + if (lss->otherLocs == NULL) { + lss->loc = NULL; + } else { + tmp = lss->otherLocs; + lss->loc = lss->otherLocs->loc; + lss->otherLocs = lss->otherLocs->otherLocs; + tmp->loc = NULL; + tmp->otherLocs = NULL; + LocationSetSet_Term(tmp); + LocationSetSet_Delete(tmp); + } + } else { + prev->otherLocs = lss->otherLocs; + lss->loc = NULL; + lss->otherLocs = NULL; + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } + first->count--; + return; + } + + prev = lss; + lss = lss->otherLocs; + } +} + +inline void LocationSetSet_RemoveAll(LocationSetSet *lss) { +#line 2707 + IRO_ASSERT(lss != NULL); + + while (lss && lss->loc) + LocationSetSet_Remove(lss, lss->loc); +} + +inline void LocationSetSet_AddSetAction(LocationSet *ls, void *refcon) { +#line 2717 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(refcon != NULL); + + LocationSetSet_Add((LocationSetSet *) refcon, ls); +} + +inline void LocationSetSet_SimpleAddSetAction(LocationSet *ls, void *refcon) { +#line 2725 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(refcon != NULL); + + LocationSetSet_SimpleAdd((LocationSetSet *) refcon, ls); +} + +inline void LocationSetSet_AddSet(LocationSetSet *dest, LocationSetSet *src) { +#line 2733 + IRO_ASSERT(dest != NULL); + IRO_ASSERT(src != NULL); + + if (dest->count) + LocationSetSet_ForEach(src, LocationSetSet_AddSetAction, dest); + else + LocationSetSet_ForEach(src, LocationSetSet_SimpleAddSetAction, dest); +} + +inline void LocationSetSet_RemoveSetAction(LocationSet *ls, void *refcon) { +#line 2744 + IRO_ASSERT(ls != NULL); + IRO_ASSERT(refcon != NULL); + + LocationSetSet_Remove((LocationSetSet *) refcon, ls); +} + +inline void LocationSetSet_sub_488700(LocationSetSet *dest, LocationSetSet *src) { +#line 2752 + IRO_ASSERT(dest != NULL); + IRO_ASSERT(src != NULL); + + LocationSetSet_ForEach(src, LocationSetSet_RemoveSetAction, dest); +} + +inline Boolean LocationSetSets_Equal(LocationSetSet *lss1, LocationSetSet *lss2) { +#line 2826 + IRO_ASSERT(lss1 != NULL); + IRO_ASSERT(lss2 != NULL); + + if (lss1 == lss2) + return 1; + if (LocationSetSet_Count(lss1) != LocationSetSet_Count(lss2)) + return 0; + + while (lss1 && lss1->loc) { + if (!LocationSetSet_Find(lss2, lss1->loc)) + return 0; + lss1 = lss1->otherLocs; + } + + return 1; +} + +inline ParamMapping *ParamMapping_New(void) { + ParamMapping *pm = IRO_malloc(sizeof(ParamMapping)); + +#line 2885 + IRO_ASSERT(pm != NULL); +#ifdef IRO_DEBUG + pm->actual = NULL; + pm->formal = NULL; + pm->extended = NULL; +#endif + return pm; +} + +inline void ParamMapping_Delete(ParamMapping *pm) { +#line 2898 + IRO_ASSERT(pm != NULL); + IRO_ASSERT(pm->actual == NULL); + IRO_ASSERT(pm->formal == NULL); + IRO_ASSERT(pm->extended == NULL); + IRO_DEBUG_CLEAR(pm, sizeof(ParamMapping)); + IRO_free(pm); +} + +inline void ParamMapping_Init_PROBABLY(ParamMapping *pm, IROLinear *actual, Object *formal, ExtendedParam *extended) { +#line 2911 + IRO_ASSERT(pm != NULL); + + pm->actual = actual; + pm->formal = formal; + pm->extended = extended; +} + +inline void ParamMapping_Copy(ParamMapping *dest, ParamMapping *src) { +#line 2920 + IRO_ASSERT(src != NULL); + IRO_ASSERT(dest != NULL); + + dest->actual = src->actual; + dest->formal = src->formal; + dest->extended = src->extended; +} + +inline void ParamMapping_Term(ParamMapping *pm) { +#line 2933 + IRO_ASSERT(pm != NULL); + +#ifdef IRO_DEBUG + pm->actual = NULL; + pm->formal = NULL; + pm->extended = NULL; +#endif +} + +inline void ParamMapping_SetExtended(ParamMapping *pm, ExtendedParam *ep) { +#line 2992 + IRO_ASSERT(pm != NULL); + + pm->extended = ep; +} + +inline IROLinear *ParamMapping_actual(ParamMapping *pm) { +#line 2999 + IRO_ASSERT(pm != NULL); + + return pm->actual; +} + +inline ExtendedParam *ParamMapping_extended(ParamMapping *pm) { +#line 3011 + IRO_ASSERT(pm != NULL); + + return pm->extended; +} + +inline ParamMappingFunction *ParamMappingFunction_New(void) { + ParamMappingFunction *pmf = IRO_malloc(sizeof(ParamMappingFunction)); + +#line 3026 + IRO_ASSERT(pmf != NULL); +#ifdef IRO_DEBUG + pmf->mapping = NULL; + pmf->otherMappings = NULL; +#endif + return pmf; +} + +inline void ParamMappingFunction_Delete(ParamMappingFunction *pmf) { +#line 3039 + IRO_ASSERT(pmf != NULL); + IRO_ASSERT(pmf->mapping == NULL); + IRO_ASSERT(pmf->otherMappings == NULL); + IRO_DEBUG_CLEAR(pmf, sizeof(ParamMappingFunction)); + IRO_free(pmf); +} + +inline void ParamMappingFunction_Init(ParamMappingFunction *pmf) { +#line 3050 + IRO_ASSERT(pmf != NULL); + + pmf->mapping = NULL; + pmf->otherMappings = NULL; +} + +inline void ParamMappingFunction_Copy(ParamMappingFunction *dest, ParamMappingFunction *src) { +#line 3058 + IRO_ASSERT(src != NULL); + IRO_ASSERT(dest != NULL); + + dest->mapping = NULL; + dest->otherMappings = NULL; + ParamMappingFunction_AddAllMaybe_sub_487C50(dest, src); +} + +inline void ParamMappingFunction_Term(ParamMappingFunction *pmf) { +#line 3068 + IRO_ASSERT(pmf != NULL); + + ParamMappingFunction_RemoveAll(pmf); + +#ifdef IRO_DEBUG + pmf->mapping = NULL; + pmf->otherMappings = NULL; +#endif +} + +inline void pmf_sub_487C70(ParamMappingFunction *pmf, void (*action)(ParamMapping *, void *), void *refcon) { +#line 3111 + IRO_ASSERT(pmf != NULL); + IRO_ASSERT(action != NULL); + IRO_ASSERT(refcon == NULL || refcon != NULL); + + while (pmf && pmf->mapping) { + action(pmf->mapping, refcon); + pmf = pmf->otherMappings; + } +} + +inline ParamMapping *ParamMappingFunction_FindMappingByFormal(ParamMappingFunction *pmf, Object *formal) { +#line 3123 + IRO_ASSERT(pmf != NULL); + IRO_ASSERT(formal != NULL); + + while (pmf && pmf->mapping) { + if (pmf->mapping->formal == formal) + return pmf->mapping; + pmf = pmf->otherMappings; + } + + return NULL; +} + +inline void Pmf_Add_sub_486610(ParamMappingFunction *pmf, ParamMapping *mapping) { + ParamMapping *existing; + +#line 3138 + IRO_ASSERT(pmf != NULL); + IRO_ASSERT(mapping != NULL); + + existing = ParamMappingFunction_FindMappingByFormal(pmf, mapping->formal); + if (!existing) { + existing = ParamMapping_New(); + ParamMapping_Copy(existing, mapping); + if (pmf->mapping) { + ParamMappingFunction *newPMF = ParamMappingFunction_New(); + ParamMappingFunction_Init(newPMF); + newPMF->mapping = pmf->mapping; + newPMF->otherMappings = pmf->otherMappings; + pmf->otherMappings = newPMF; + } + pmf->mapping = existing; + } else { + existing->actual = mapping->actual; + existing->extended = mapping->extended; + } +} + +inline void ParamMappingFunction_Remove(ParamMappingFunction *pmf, ParamMapping *mapping) { + ParamMappingFunction *prev; + ParamMappingFunction *tmp; + +#line 3170 + IRO_ASSERT(pmf != NULL); + IRO_ASSERT(mapping != NULL); + + prev = NULL; + while (pmf && pmf->mapping) { + if (pmf->mapping->formal == mapping->formal) { + ParamMapping_Term(pmf->mapping); + ParamMapping_Delete(pmf->mapping); + if (!prev) { + if (pmf->otherMappings == NULL) { + pmf->mapping = NULL; + } else { + tmp = pmf->otherMappings; + pmf->mapping = pmf->otherMappings->mapping; + pmf->otherMappings = pmf->otherMappings->otherMappings; + tmp->mapping = NULL; + tmp->otherMappings = NULL; + ParamMappingFunction_Term(tmp); + ParamMappingFunction_Delete(tmp); + } + } else { + prev->otherMappings = pmf->otherMappings; + pmf->mapping = NULL; + pmf->otherMappings = NULL; + ParamMappingFunction_Term(pmf); + ParamMappingFunction_Delete(pmf); + } + return; + } + + prev = pmf; + pmf = pmf->otherMappings; + } +} + +inline void ParamMappingFunction_RemoveAll(ParamMappingFunction *pmf) { +#line 3213 + IRO_ASSERT(pmf != NULL); + + while (pmf && pmf->mapping) + ParamMappingFunction_Remove(pmf, pmf->mapping); +} + +inline void ParamMappingFunction_AddFunctionAction(ParamMapping *mapping, void *refcon) { +#line 3223 + IRO_ASSERT(mapping != NULL); + IRO_ASSERT(refcon != NULL); + + Pmf_Add_sub_486610((ParamMappingFunction *) refcon, mapping); +} + +inline void ParamMappingFunction_AddAllMaybe_sub_487C50(ParamMappingFunction *dest, ParamMappingFunction *src) { +#line 3231 + IRO_ASSERT(dest != NULL); + IRO_ASSERT(src != NULL); + + pmf_sub_487C70(src, ParamMappingFunction_AddFunctionAction, dest); +} + +inline PointsToEntry *PointsToEntry_New(void) { + PointsToEntry *pte = IRO_malloc(sizeof(PointsToEntry)); + +#line 3288 + IRO_ASSERT(pte != NULL); +#ifdef IRO_DEBUG + pte->loc = NULL; + pte->locs = NULL; +#endif + return pte; +} + +inline void PointsToEntry_Delete(PointsToEntry *pte) { +#line 3300 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(pte->loc == NULL); + IRO_ASSERT(pte->locs == NULL); + IRO_DEBUG_CLEAR(pte, sizeof(PointsToEntry)); + IRO_free(pte); +} + +inline void PointsToEntry_Init(PointsToEntry *pte, LocationSet *loc, LocationSetSet *locs) { +#line 3312 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(loc != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(loc)); + IRO_ASSERT(locs != NULL); + + pte->loc = LocationSet_New(); + LocationSet_Copy(pte->loc, loc); + + pte->locs = LocationSetSet_New(); + LocationSetSet_Copy(pte->locs, locs); +} + +inline void PointsToEntry_Copy(PointsToEntry *dest, PointsToEntry *src) { +#line 3325 + IRO_ASSERT(src != NULL); + IRO_ASSERT(dest != NULL); + + PointsToEntry_Init(dest, src->loc, src->locs); +} + +inline void PointsToEntry_Term(PointsToEntry *pte) { +#line 3333 + IRO_ASSERT(pte != NULL); + + LocationSet_Term(pte->loc); + LocationSet_Delete(pte->loc); + LocationSetSet_Term(pte->locs); + LocationSetSet_Delete(pte->locs); + +#ifdef IRO_DEBUG + pte->loc = NULL; + pte->locs = NULL; +#endif +} + +inline Boolean PointsToEntries_Equal(PointsToEntry *pte1, PointsToEntry *pte2) { +#line 3381 + IRO_ASSERT(pte1 != NULL); + IRO_ASSERT(pte2 != NULL); + + if (pte1 == pte2) + return 1; + + return LocationSets_Equal(pte1->loc, pte2->loc) && LocationSetSets_Equal(pte1->locs, pte2->locs); +} + +inline LocationSet *PointsToEntry_loc(PointsToEntry *pte) { +#line 3407 + IRO_ASSERT(pte != NULL); + + return pte->loc; +} + +inline LocationSetSet *PointsToEntry_locs(PointsToEntry *pte) { +#line 3414 + IRO_ASSERT(pte != NULL); + + return pte->locs; +} + +inline PointsToFunction *PointsToFunction_New(void) { + PointsToFunction *pointsToFunc = IRO_malloc(sizeof(PointsToFunction)); + +#line 3430 + IRO_ASSERT(pointsToFunc != NULL); +#ifdef IRO_DEBUG + pointsToFunc->pte = NULL; + pointsToFunc->otherPtes = NULL; +#endif + return pointsToFunc; +} + +inline void PointsToFunction_Delete(PointsToFunction *pointsToFunc) { +#line 3442 + IRO_ASSERT(pointsToFunc != NULL); + IRO_ASSERT(pointsToFunc->pte == NULL); + IRO_ASSERT(pointsToFunc->otherPtes == NULL); + IRO_DEBUG_CLEAR(pointsToFunc, sizeof(PointsToFunction)); + IRO_free(pointsToFunc); +} + +inline void PointsToFunction_Init(PointsToFunction *pointsToFunc) { +#line 3454 + IRO_ASSERT(pointsToFunc != NULL); + + pointsToFunc->pte = NULL; + pointsToFunc->otherPtes = NULL; +} + +inline void PointsToFunction_Copy(PointsToFunction *dest, PointsToFunction *src) { +#line 3462 + IRO_ASSERT(src != NULL); + IRO_ASSERT(dest != NULL); + + dest->pte = NULL; + dest->otherPtes = NULL; + PointsToFunction_AddAllIGuess_sub_487D80(dest, src); +} + +inline void PointsToFunction_Term(PointsToFunction *pointsToFunc) { +#line 3472 + IRO_ASSERT(pointsToFunc != NULL); + + PointsToFunction_RemoveAll(pointsToFunc); + +#ifdef IRO_DEBUG + pointsToFunc->pte = NULL; + pointsToFunc->otherPtes = NULL; +#endif +} + +inline void PointsToFunction_ForEach(PointsToFunction *pointsToFunc, void (*action)(PointsToEntry *, void *), void *refcon) { +#line 3515 + IRO_ASSERT(pointsToFunc != NULL); + IRO_ASSERT(action != NULL); + IRO_ASSERT(refcon == NULL || refcon != NULL); + + while (pointsToFunc && pointsToFunc->pte) { + action(pointsToFunc->pte, refcon); + pointsToFunc = pointsToFunc->otherPtes; + } +} + +inline PointsToEntry *PointsToFunction_FindByLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) { +#line 3527 + IRO_ASSERT(pointsToFunc != NULL); + IRO_ASSERT(ls != NULL); + + while (pointsToFunc && pointsToFunc->pte) { + if (LocationSets_Equal(pointsToFunc->pte->loc, ls)) + return pointsToFunc->pte; + pointsToFunc = pointsToFunc->otherPtes; + } + + return NULL; +} + +inline PointsToEntry *PointsToFunction_FindFirst(PointsToFunction *pointsToFunc) { +#line 3539 + IRO_ASSERT(pointsToFunc != NULL); + + return pointsToFunc->pte; +} + +inline PointsToEntry *PointsToFunction_FindByLookupCompatibleLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) { +#line 3546 + IRO_ASSERT(pointsToFunc != NULL); + IRO_ASSERT(ls != NULL); + + while (pointsToFunc && pointsToFunc->pte) { + if (ls->u.known.stride) { + if (LocationSets_Equal(pointsToFunc->pte->loc, ls)) + return pointsToFunc->pte; + } else if (LocationSets_LookupCompatible(pointsToFunc->pte->loc, ls)) { + return pointsToFunc->pte; + } + pointsToFunc = pointsToFunc->otherPtes; + } + + return NULL; +} + +inline PointsToEntry *PointsToFunction_FindContainingLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls, Type *rtype) { +#line 3565 + IRO_ASSERT(pointsToFunc != NULL); + IRO_ASSERT(ls != NULL); + IRO_ASSERT(rtype != NULL); + + while (pointsToFunc && pointsToFunc->pte) { + if (pointsToFunc->pte->locs->loc && !LocationSet_IsUnknown(pointsToFunc->pte->locs->loc)) { + if (!pointsToFunc->pte->locs->otherLocs && LocationSet_Contains(pointsToFunc->pte->loc, pointsToFunc->pte->locs->loc->rtype, ls, rtype)) + return pointsToFunc->pte; + } + pointsToFunc = pointsToFunc->otherPtes; + } + + return NULL; +} + +inline void PointsToFunction_RemoveOverlappingLocations(PointsToFunction *pointsToFunc, PointsToEntry *pte) { + Type *rtype1; + Type *rtype2; + LocationSet *ls; + PointsToFunction *prev; + PointsToFunction *next; + PointsToFunction *tmp; + +#line 3601 + IRO_ASSERT(pointsToFunc != NULL); + IRO_ASSERT(pte != NULL); + IRO_ASSERT(pte->locs != NULL); + + if (pte->locs->loc && pte->locs->loc != stUnknownLs) + rtype1 = pte->locs->loc->rtype; + else + rtype1 = NULL; + ls = pte->loc; +#line 3614 + IRO_ASSERT(ls != NULL); + + prev = NULL; + while (pointsToFunc && pointsToFunc->pte) { + next = pointsToFunc->otherPtes; + if (pointsToFunc->pte->locs->loc && pointsToFunc->pte->locs->loc != stUnknownLs) + rtype2 = pointsToFunc->pte->locs->loc->rtype; + else + rtype2 = NULL; + + if (LocationSets_Overlap(ls, rtype1, pointsToFunc->pte->loc, rtype2)) { + PointsToEntry_Term(pointsToFunc->pte); + PointsToEntry_Delete(pointsToFunc->pte); + if (!prev) { + if (pointsToFunc->otherPtes == NULL) { + pointsToFunc->pte = NULL; + prev = pointsToFunc; + } else { + tmp = pointsToFunc->otherPtes; + pointsToFunc->pte = pointsToFunc->otherPtes->pte; + pointsToFunc->otherPtes = pointsToFunc->otherPtes->otherPtes; + tmp->pte = NULL; + tmp->otherPtes = NULL; + PointsToFunction_Term(tmp); + PointsToFunction_Delete(tmp); + prev = NULL; + next = pointsToFunc; + } + } else { + prev->otherPtes = pointsToFunc->otherPtes; + pointsToFunc->pte = NULL; + pointsToFunc->otherPtes = NULL; + PointsToFunction_Term(pointsToFunc); + PointsToFunction_Delete(pointsToFunc); + prev = pointsToFunc; + } + } + + pointsToFunc = next; + } +} + +inline Boolean ShouldAddNewPointsToEntryToFunction(PointsToFunction *pointsToFunc, PointsToEntry *pte) { + Boolean flag; + Boolean isKnown; + SInt32 stride; + PointsToFunction *next; + LocationSet *loc; + LocationSet *loc2; + Type *rtype1; + Type *rtype2; + LocationSetSet *locs2; + LocationSet *tmp; + LocationSet *unknown; + Boolean flag2; + Boolean flag3; + +#line 3675 + IRO_ASSERT(pointsToFunc != NULL); + IRO_ASSERT(pte != NULL); + IRO_ASSERT(pte->locs != NULL); + IRO_ASSERT(PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, pte->loc) == NULL); + IRO_ASSERT((unknown = LocationSetSet_FindFirst(pte->locs)) != NULL); + IRO_ASSERT(LocationSet_IsUnknown(unknown)); + IRO_ASSERT(LocationSet_bitfieldOf(unknown) == NULL); + IRO_ASSERT(LocationSet_restriction(unknown) == NULL); + + if (pte->locs->loc && pte->locs->loc != stUnknownLs) + rtype1 = pte->locs->loc->rtype; + else + rtype1 = NULL; + + loc = pte->loc; +#line 3693 + IRO_ASSERT(loc != NULL); + + isKnown = !LocationSet_IsUnknown(loc); + if (isKnown) + stride = LocationSet_stride(loc); + + flag = 0; + while (pointsToFunc && pointsToFunc->pte) { + next = pointsToFunc->otherPtes; + + locs2 = pointsToFunc->pte->locs; + + if (locs2->loc && locs2->loc != stUnknownLs) + rtype2 = locs2->loc->rtype; + else + rtype2 = NULL; + + loc2 = pointsToFunc->pte->loc; + + flag2 = !(tmp = LocationSetSet_FindFirst(locs2)) || + !LocationSet_IsUnknown(tmp) || + LocationSet_bitfieldOf(tmp) || + LocationSet_restriction(tmp); + + flag3 = LocationSets_Overlap(loc, rtype1, loc2, rtype2); + + if (!flag && flag3) + flag = 1; + + if (flag3 && (flag2 || (isKnown && stride && LocationSet_stride(loc2) == 0))) + return 1; + + pointsToFunc = next; + } + + return !flag; +} + +inline Boolean PointsToFunction_SimpleAdd(PointsToFunction *pointsToFunc, PointsToEntry *pte) { + PointsToEntry *newPTE; + +#line 3741 + IRO_ASSERT(pointsToFunc != NULL); + IRO_ASSERT(pte != NULL); + + newPTE = PointsToEntry_New(); + PointsToEntry_Copy(newPTE, pte); + if (pointsToFunc->pte) { + PointsToFunction *newPointsToFunc = PointsToFunction_New(); + PointsToFunction_Init(newPointsToFunc); + newPointsToFunc->pte = pointsToFunc->pte; + newPointsToFunc->otherPtes = pointsToFunc->otherPtes; + pointsToFunc->otherPtes = newPointsToFunc; + } + pointsToFunc->pte = newPTE; + return 1; +} + +inline Boolean PointsToFunction_Add(PointsToFunction *pointsToFunc, PointsToEntry *pte) { +#line 3766 + IRO_ASSERT(pointsToFunc != NULL); + IRO_ASSERT(pte != NULL); + + if (!PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, pte->loc)) { + LocationSet *ls; + if (!(ls = LocationSetSet_FindFirst(pte->locs)) || !LocationSet_IsUnknown(ls) || LocationSet_bitfieldOf(ls) || + LocationSet_restriction(ls) || ShouldAddNewPointsToEntryToFunction(pointsToFunc, pte)) { + PointsToFunction_RemoveOverlappingLocations(pointsToFunc, pte); + if (!LocationSet_IsUnknown(pte->loc) || pte->loc->rtype) + PointsToFunction_SimpleAdd(pointsToFunc, pte); + return 1; + } + } + + return 0; +} + +inline Boolean PointsToFunction_AddWithoutChecking(PointsToFunction *pointsToFunc, PointsToEntry *pte) { + LocationSet *ls; + +#line 3793 + IRO_ASSERT(pointsToFunc != NULL); + IRO_ASSERT(pte != NULL); + + if (!(ls = LocationSetSet_FindFirst(pte->locs)) || !LocationSet_IsUnknown(ls) || LocationSet_bitfieldOf(ls) || + LocationSet_restriction(ls) || ShouldAddNewPointsToEntryToFunction(pointsToFunc, pte)) { + PointsToFunction_RemoveOverlappingLocations(pointsToFunc, pte); + if (!LocationSet_IsUnknown(pte->loc) || pte->loc->rtype) + PointsToFunction_SimpleAdd(pointsToFunc, pte); + return 1; + } + + return 0; +} + +inline void PointsToFunction_RemoveByLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) { + PointsToFunction *prev; + PointsToFunction *tmp; + +#line 3170 + IRO_ASSERT(pointsToFunc != NULL); + IRO_ASSERT(ls != NULL); + IRO_ASSERT(!LocationSet_IsUnknown(ls)); + + prev = NULL; + while (pointsToFunc && pointsToFunc->pte) { + if (LocationSets_Equal(pointsToFunc->pte->loc, ls)) { + PointsToEntry_Term(pointsToFunc->pte); + PointsToEntry_Delete(pointsToFunc->pte); + if (!prev) { + if (pointsToFunc->otherPtes == NULL) { + pointsToFunc->pte = NULL; + } else { + tmp = pointsToFunc->otherPtes; + pointsToFunc->pte = pointsToFunc->otherPtes->pte; + pointsToFunc->otherPtes = pointsToFunc->otherPtes->otherPtes; + tmp->pte = NULL; + tmp->otherPtes = NULL; + PointsToFunction_Term(tmp); + PointsToFunction_Delete(tmp); + } + } else { + prev->otherPtes = pointsToFunc->otherPtes; + pointsToFunc->pte = NULL; + pointsToFunc->otherPtes = NULL; + PointsToFunction_Term(pointsToFunc); + PointsToFunction_Delete(pointsToFunc); + } + return; + } + + prev = pointsToFunc; + pointsToFunc = pointsToFunc->otherPtes; + } +} + +inline void PointsToFunction_RemoveAll(PointsToFunction *pointsToFunc) { +#line 3862 + IRO_ASSERT(pointsToFunc != NULL); + + while (pointsToFunc && pointsToFunc->pte) + PointsToFunction_RemoveByLocationSet(pointsToFunc, pointsToFunc->pte->loc); +} + +inline void PointsToFunction_AddFunctionAction(PointsToEntry *pte, void *refcon) { +#line 3872 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(refcon != NULL); + + PointsToFunction_Add((PointsToFunction *) refcon, pte); +} + +inline void PointsToFunction_SimpleAddFunctionAction(PointsToEntry *pte, void *refcon) { +#line 3880 + IRO_ASSERT(pte != NULL); + IRO_ASSERT(refcon != NULL); + + PointsToFunction_SimpleAdd((PointsToFunction *) refcon, pte); +} + +inline void PointsToFunction_AddAllIGuess_sub_487D80(PointsToFunction *dest, PointsToFunction *src) { +#line 3888 + IRO_ASSERT(dest != NULL); + IRO_ASSERT(src != NULL); + + if (dest->pte) + PointsToFunction_ForEach(src, PointsToFunction_AddFunctionAction, dest); + else + PointsToFunction_ForEach(src, PointsToFunction_SimpleAddFunctionAction, dest); +} + +inline void PointsToFunction_SortByExtendedParamNum(PointsToFunction *pointsToFunc) { + UInt32 value1; + UInt32 value2; + PointsToFunction *scan; + + while (pointsToFunc && pointsToFunc->pte) { + value1 = 0; + if (pointsToFunc->pte->loc && pointsToFunc->pte->loc->block) { + PAMemoryBlock *block = pointsToFunc->pte->loc->block; + if (block->kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM && block->u.ep) { + value1 = 2 * (block->u.ep->x4) + 1; + } else if (block->kind == PAMEMORYBLOCKKIND_LOCALVAR && block->u.localvar) { + if (block->u.localvar->x0 && block->u.localvar->x0->extParam) + value1 = 2 * block->u.localvar->x0->extParam->x4; + } + } + + for (scan = pointsToFunc->otherPtes; scan && scan->pte; scan = scan->otherPtes) { + value2 = 0; + if (scan->pte->loc && scan->pte->loc->block) { + PAMemoryBlock *block = scan->pte->loc->block; + if (block->kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM && block->u.ep) { + value2 = 2 * (block->u.ep->x4) + 1; + } else if (block->kind == PAMEMORYBLOCKKIND_LOCALVAR && block->u.localvar) { + if (block->u.localvar->x0 && block->u.localvar->x0->extParam) + value2 = 2 * block->u.localvar->x0->extParam->x4; + } + } + + if (value2 < value1) { + LocationSet *saveloc; + LocationSetSet *savelocs; + saveloc = pointsToFunc->pte->loc; + savelocs = pointsToFunc->pte->locs; + pointsToFunc->pte->loc = scan->pte->loc; + pointsToFunc->pte->locs = scan->pte->locs; + scan->pte->loc = saveloc; + scan->pte->locs = savelocs; + } + } + + pointsToFunc = pointsToFunc->otherPtes; + } +} + +inline Boolean PointsToFunctions_Equal(PointsToFunction *pointsToFunc1, PointsToFunction *pointsToFunc2) { + PointsToFunction *scan; + PointsToEntry *pte; + +#line 3968 + IRO_ASSERT(pointsToFunc1 != NULL); + IRO_ASSERT(pointsToFunc2 != NULL); + + if (pointsToFunc1 == pointsToFunc2) + return 1; + + for (scan = pointsToFunc1; scan && scan->pte; scan = scan->otherPtes) { + pte = PointsToFunction_FindByLocationSet(pointsToFunc2, scan->pte->loc); + if (!pte || !PointsToEntries_Equal(pte, scan->pte)) + return 0; + } + + for (scan = pointsToFunc2; scan && scan->pte; scan = scan->otherPtes) { + pte = PointsToFunction_FindByLocationSet(pointsToFunc1, scan->pte->loc); + if (!pte || !PointsToEntries_Equal(pte, scan->pte)) + return 0; + } + + return 1; +} + +inline Boolean PointsToFunctions_Match(PointsToFunction *pointsToFunc1, PointsToFunction *pointsToFunc2) { + return 1; +} + +inline PartialTransferFunction *PartialTransferFunction_New() { + PartialTransferFunction *ptf = IRO_malloc(sizeof(PartialTransferFunction)); + +#line 4110 + IRO_ASSERT(ptf != NULL); +#ifdef IRO_DEBUG + ptf->initialPointsToFn = NULL; + ptf->finalPointsToFn = NULL; + ptf->funcModifies = NULL; + ptf->context.nd = NULL; + ptf->context.ptf = NULL; + ptf->returnLocation = NULL; +#endif + return ptf; +} + +inline void PartialTransferFunction_Delete(PartialTransferFunction *ptf) { +#line 4126 + IRO_ASSERT(ptf != NULL); + IRO_ASSERT(ptf->initialPointsToFn == NULL); + IRO_ASSERT(ptf->finalPointsToFn == NULL); + IRO_ASSERT(ptf->funcModifies == NULL); + IRO_ASSERT(ptf->context.nd == NULL); + IRO_ASSERT(ptf->context.ptf == NULL); + IRO_ASSERT(ptf->returnLocation == NULL); + IRO_DEBUG_CLEAR(ptf, sizeof(PartialTransferFunction)); + IRO_free(ptf); +} + +inline void PartialTransferFunction_Init(PartialTransferFunction *ptf, IROLinear *contextNd, PartialTransferFunction *contextPTF) { +#line 4142 + IRO_ASSERT(ptf != NULL); + IRO_ASSERT(contextNd != NULL); + IRO_ASSERT(contextPTF != NULL); + + ptf->initialPointsToFn = PointsToFunction_New(); + PointsToFunction_Init(ptf->initialPointsToFn); + ptf->finalPointsToFn = PointsToFunction_New(); + PointsToFunction_Init(ptf->finalPointsToFn); + + ptf->funcModifies = LocationSetSet_New(); + LocationSetSet_Init(ptf->funcModifies); + LocationSetSet_AddUnknown(ptf->funcModifies, NULL, NULL, NULL); + + ptf->returnLocation = NULL; + ptf->x10 = 0; + + ptf->context.nd = contextNd; + ptf->context.ptf = contextPTF; +} + +inline void PartialTransferFunction_Copy(PartialTransferFunction *dest, PartialTransferFunction *src) { +#line 4164 + IRO_ASSERT(src != NULL); + IRO_ASSERT(dest != NULL); + + dest->initialPointsToFn = PointsToFunction_New(); + PointsToFunction_Copy(dest->initialPointsToFn, src->initialPointsToFn); + dest->finalPointsToFn = PointsToFunction_New(); + PointsToFunction_Copy(dest->finalPointsToFn, src->finalPointsToFn); + + dest->funcModifies = LocationSetSet_New(); + LocationSetSet_Copy(dest->funcModifies, src->funcModifies); + + if (src->returnLocation) { + dest->returnLocation = LocationSet_New(); + LocationSet_Copy(dest->returnLocation, src->returnLocation); + } else { + dest->returnLocation = NULL; + } + + dest->x10 = src->x10; + dest->context = src->context; +} + +inline void PartialTransferFunction_Term(PartialTransferFunction *ptf) { +#line 4190 + IRO_ASSERT(ptf != NULL); + + PointsToFunction_Term(ptf->initialPointsToFn); + PointsToFunction_Delete(ptf->initialPointsToFn); + PointsToFunction_Term(ptf->finalPointsToFn); + PointsToFunction_Delete(ptf->finalPointsToFn); + LocationSetSet_Term(ptf->funcModifies); + LocationSetSet_Delete(ptf->funcModifies); + + if (ptf->returnLocation) { + PAMemoryBlock_Term(ptf->returnLocation->block); + PAMemoryBlock_Delete(ptf->returnLocation->block); + LocationSet_Term(ptf->returnLocation); + LocationSet_Delete(ptf->returnLocation); + ptf->returnLocation = NULL; + } + +#ifdef IRO_DEBUG + ptf->initialPointsToFn = NULL; + ptf->finalPointsToFn = NULL; + ptf->funcModifies = NULL; + ptf->context.nd = NULL; + ptf->context.ptf = NULL; +#endif +} + +inline PointsToFunction *PartialTransferFunction_initialPointsToFn(PartialTransferFunction *ptf) { +#line 4221 + IRO_ASSERT(ptf != NULL); + + return ptf->initialPointsToFn; +} + +inline PointsToFunction *PartialTransferFunction_finalPointsToFn(PartialTransferFunction *ptf) { +#line 4227 + IRO_ASSERT(ptf != NULL); + + return ptf->finalPointsToFn; +} + +inline LocationSetSet *PTF_sub_48D750(PartialTransferFunction *ptf) { +#line 4233 + IRO_ASSERT(ptf != NULL); + + return ptf->funcModifies; +} + +inline LocationSet *PartialTransferFunction_returnLocation(PartialTransferFunction *ptf) { +#line 4249 + IRO_ASSERT(ptf != NULL); + + if (!ptf->returnLocation) { + PAMemoryBlock *block; + LocationSet *ls; + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_LOCALVAR, NULL); + ls = LocationSet_New(); + LocationSet_InitKnown(ls, block, cint64_zero, 0, TYPE(&void_ptr)); + ptf->returnLocation = ls; + } + + return ptf->returnLocation; +} + +inline IROLinear *PTF_sub_48B980(PartialTransferFunction *ptf) { +#line 4265 + IRO_ASSERT(ptf != NULL); + + return ptf->context.nd; +} + +inline PartialTransferFunction *PTF_sub_48B970(PartialTransferFunction *ptf) { +#line 4271 + IRO_ASSERT(ptf != NULL); + + return ptf->context.ptf; +} + +inline void PartialTransferFunction_sub_48A610(PartialTransferFunction *ptf, Boolean value) { +#line 4298 + IRO_ASSERT(ptf != NULL); + + ptf->x10 = (value != 0) ? 1 : 0; +} + +inline PTFList *PTFList_New(void) { + PTFList *ptfList = IRO_malloc(sizeof(PTFList)); + +#line 4393 + IRO_ASSERT(ptfList != NULL); +#ifdef IRO_DEBUG + ptfList->ptf = NULL; + ptfList->otherPTFs = NULL; +#endif + return ptfList; +} + +inline void PTFList_Delete(PTFList *ptfList) { +#line 4405 + IRO_ASSERT(ptfList != NULL); + IRO_ASSERT(ptfList->ptf == NULL); + IRO_ASSERT(ptfList->otherPTFs == NULL); + IRO_DEBUG_CLEAR(ptfList, sizeof(PTFList)); + IRO_free(ptfList); +} + +inline void PTFList_Init(PTFList *ptfList) { +#line 4417 + IRO_ASSERT(ptfList != NULL); + + ptfList->ptf = NULL; + ptfList->otherPTFs = NULL; +} + +inline void PTFList_Term(PTFList *ptfList) { +#line 4435 + IRO_ASSERT(ptfList != NULL); + + PTFList_RemoveAll(ptfList); + +#ifdef IRO_DEBUG + ptfList->ptf = NULL; + ptfList->otherPTFs = NULL; +#endif +} + +inline void PTFList_ForEach(PTFList *ptfList, void (*action)(PartialTransferFunction *, void *), void *refcon) { +#line 4478 + IRO_ASSERT(ptfList != NULL); + IRO_ASSERT(action != NULL); + IRO_ASSERT(refcon == NULL || refcon != NULL); + + while (ptfList && ptfList->ptf) { + action(ptfList->ptf, refcon); + ptfList = ptfList->otherPTFs; + } +} + +inline PartialTransferFunction *PTFList_sub_48A0F0(PTFList *ptfList, PartialTransferFunction *ptf) { +#line 4490 + IRO_ASSERT(ptfList != NULL); + IRO_ASSERT(ptf != NULL); + + while (ptfList && ptfList->ptf) { + if (ptfList->ptf == ptf) + return ptfList->ptf; + + ptfList = ptfList->otherPTFs; + } + + return NULL; +} + +inline PartialTransferFunction *PTFList_FindFirst(PTFList *ptfList) { +#line 4502 + IRO_ASSERT(ptfList != NULL); + + return ptfList->ptf; +} + +inline void PTFList_sub_48A080(PTFList *ptfList, PartialTransferFunction *ptf) { +#line 4511 + IRO_ASSERT(ptfList != NULL); + IRO_ASSERT(ptf != NULL); + + if (ptfList->ptf) { + PTFList *newList = PTFList_New(); + PTFList_Init(newList); + newList->ptf = ptfList->ptf; + newList->otherPTFs = ptfList->otherPTFs; + ptfList->otherPTFs = newList; + } + + ptfList->ptf = ptf; +} + +inline void PTFList_sub_48A050(PTFList *ptfList, PartialTransferFunction *ptf) { +#line 4529 + IRO_ASSERT(ptfList != NULL); + IRO_ASSERT(ptf != NULL); + + if (!PTFList_sub_48A0F0(ptfList, ptf)) + PTFList_sub_48A080(ptfList, ptf); +} + +inline void PTFList_Remove(PTFList *ptfList, PartialTransferFunction *ptf) { + PTFList *prev; + PTFList *tmp; + +#line 4542 + IRO_ASSERT(ptfList != NULL); + IRO_ASSERT(ptf != NULL); + + prev = NULL; + while (ptfList && ptfList->ptf) { + if (ptfList->ptf == ptf) { + if (!prev) { + if (ptfList->otherPTFs == NULL) { + ptfList->ptf = NULL; + } else { + tmp = ptfList->otherPTFs; + ptfList->ptf = ptfList->otherPTFs->ptf; + ptfList->otherPTFs = ptfList->otherPTFs->otherPTFs; + tmp->ptf = NULL; + tmp->otherPTFs = NULL; + PTFList_Term(tmp); + PTFList_Delete(tmp); + } + } else { + prev->otherPTFs = ptfList->otherPTFs; + ptfList->ptf = NULL; + ptfList->otherPTFs = NULL; + PTFList_Term(ptfList); + PTFList_Delete(ptfList); + } + return; + } + + prev = ptfList; + ptfList = ptfList->otherPTFs; + } +} + +inline void PTFList_RemoveAll(PTFList *ptfList) { +#line 4582 + IRO_ASSERT(ptfList != NULL); + + while (ptfList && ptfList->ptf) + PTFList_Remove(ptfList, ptfList->ptf); +} diff --git a/compiler_and_linker/unsorted/IroPropagate.c b/compiler_and_linker/unsorted/IroPropagate.c index e69de29..ebcbb56 100644 --- a/compiler_and_linker/unsorted/IroPropagate.c +++ b/compiler_and_linker/unsorted/IroPropagate.c @@ -0,0 +1,595 @@ +#include "compiler/IroPropagate.h" +#include "compiler/IroCSE.h" +#include "compiler/IroDump.h" +#include "compiler/IroEval.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IROUseDef.h" +#include "compiler/IroUtil.h" +#include "compiler/IroVars.h" +#include "compiler/objects.h" +#include "compiler/CExpr.h" +#include "compiler/CompilerTools.h" +#include "compiler/CParser.h" +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmPPC.h" + +IROAssign *IRO_FirstAssign; +IROAssign *IRO_LastAssign; +SInt32 IRO_NumAssign; + +static Boolean VarIsUsedInOtherFNodes(VarRecord *var, IRONode *node) { + if (var->defs && var->uses) { + IROUse *use; + IRODef *def = NULL; + for (use = var->uses; use; use = use->varnext) { + if (!def && use->node == node && use->linear && !(use->linear->flags & IROLF_Assigned)) { + for (def = var->defs; def; def = def->varnext) { + if (Bv_IsBitSet(def->index, use->x18)) + break; + } + } + } + + if (def) { + for (use = var->uses; use; use = use->varnext) { + if (use->node != node && use->linear && !(use->linear->flags & IROLF_Assigned)) { + if (Bv_IsBitSet(def->index, use->x18)) + return 1; + } + } + } + } else { + IROLinear *linear; + IRONode *scan; + for (scan = IRO_FirstNode; scan; scan = scan->nextnode) { + if (scan != node) { + linear = scan->first; + while (1) { + if (!linear) + break; + + if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { + if (IRO_FindVar(linear->u.diadic.left->u.node->data.objref, 0, 1) == var) + return 1; + } + + if (linear == scan->last) + break; + linear = linear->next; + } + } + } + IRO_CheckForUserBreak(); + } + + return 0; +} + +static void GetExprUses(IROLinear *linear, Boolean isFirst) { + if (isFirst && IS_LINEAR_ENODE(linear, EOBJREF)) { + Object *obj = linear->u.node->data.objref; + if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) { + VarRecord *var = IRO_FindVar(obj, 0, 1); + if (var) + Bv_SetBit(var->index, IRO_VarKills); + } + } +} + +static void GetExprKills(IROLinear *linear, Boolean isFirst) { + if (isFirst) + IRO_GetKills(linear); +} + +static void CheckUnorderedRegionForDefs(IROLinear *linear, BitVector *a, BitVector *b, Boolean *flag) { + Bv_Clear(a); + Bv_Clear(IRO_VarKills); + IRO_WalkTree(linear, GetExprKills); + Bv_Or(IRO_VarKills, a); + if (Bv_BitsInCommon(a, b)) + *flag = 1; +} + +static void CheckUnorderedRegionsForDefs(IROLinear *linear1, IROLinear *linear2, BitVector *a, BitVector *b, Boolean *flag) { + int i; + + switch (linear1->type) { + case IROLinearOp2Arg: + if (linear1->nodetype == ELAND) break; + if (linear1->nodetype == ELOR) break; + if (linear1->nodetype == ECOMMA) break; + if (linear1->u.diadic.left != linear2) + CheckUnorderedRegionForDefs(linear1->u.diadic.left, a, b, flag); + if (linear1->u.diadic.right != linear2) + CheckUnorderedRegionForDefs(linear1->u.diadic.right, a, b, flag); + break; + case IROLinearFunccall: + if (linear1->u.funccall.linear8 != linear2) + CheckUnorderedRegionForDefs(linear1->u.funccall.linear8, a, b, flag); + for (i = 0; !*flag && i < linear1->u.funccall.argCount; i++) { + if (linear1->u.funccall.args[i] != linear2) + CheckUnorderedRegionForDefs(linear1->u.funccall.args[i], a, b, flag); + } + break; + } +} + +static Boolean PropagationHasDefsInUnorderedRegions(IROLinear *a, IROLinear *b) { + Boolean flag; + IROLinear *father; + BitVector *bv1; + BitVector *bv2; + VarRecord *var; + + flag = 0; + if ((father = IRO_LocateFather(a))) { + Bv_AllocVector(&bv1, IRO_NumVars + 1); + Bv_AllocVector(&bv2, IRO_NumVars + 1); + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + IRO_WalkTree(b, GetExprUses); + Bv_Or(IRO_VarKills, bv2); + var = IRO_FindVar(a->u.diadic.left->u.node->data.objref, 0, 1); + Bv_SetBit(var->index, bv2); + while (father && !flag) { + CheckUnorderedRegionsForDefs(father, a, bv1, bv2, &flag); + a = father; + father = IRO_LocateFather(father); + } + } + + return flag; +} + +int IRO_IsRegable(Object *obj) { + if (obj->datatype == DLOCAL && obj->u.var.info) + return obj->u.var.info->noregister == 0; + return 0; +} + +static Boolean IsPropagatable(IROLinear *linear) { + Object *obj; + Object *obj2; + + if (IS_LINEAR_DIADIC(linear, EASS) && (obj = IRO_IsVariable(linear->u.diadic.left)) && obj->type == linear->rtype && !is_volatile_object(obj)) { + if (linear->u.diadic.left->flags & IROLF_BitfieldIndirect) { + if (!IRO_IsConstant(linear->u.diadic.right)) + return 0; + else + return 1; + } + + if (IRO_IsConstant(linear->u.diadic.right)) + return 1; + + if ((obj2 = IRO_IsVariable(linear->u.diadic.right)) && !is_volatile_object(obj2) && IRO_TypesEqual(obj->type, linear->rtype)) { + if (!Inline_IsObjectData(linear->u.diadic.right->u.monadic->u.node->data.objref)) { + if (IRO_IsRegable(obj) && !IRO_IsRegable(obj2)) + return 0; + return 1; + } + } + } + + return 0; +} + +static Boolean IsIntGenKillCandidate(IROLinear *linear) { + if (linear->type == IROLinearFunccall) + return 1; + + if (IRO_IsAssignOp[linear->nodetype] && (linear->type == IROLinearOp1Arg || linear->type == IROLinearOp2Arg)) + return 1; + + if (linear->type == IROLinearAsm) + return 1; + + return 0; +} + +static Boolean IsPropagatableExpr(IROLinear *linear, IROList *list) { + Object *obj; + if (IS_LINEAR_DIADIC(linear, EASS) && !(linear->flags & IROLF_Reffed)) { + if ((obj = IRO_IsVariable(linear->u.diadic.left)) && !is_volatile_object(obj) && !(linear->u.diadic.left->flags & IROLF_BitfieldIndirect)) { + if (!IRO_IsRegable(obj)) + return 0; + if (IS_LINEAR_ENODE(linear->u.diadic.right, ESTRINGCONST)) + return 0; + + IRO_FindDepends(linear->u.diadic.right); + if (!IRO_NotSubable) + return 1; + } + } + + return 0; +} + +static void ClearAvailibilityOnNode(IRONode *node, UInt32 bit) { + IRONode *scan; + + for (scan = node->nextnode; scan; scan = scan->nextnode) + Bv_ClearBit(bit, scan->x16); +} + +Boolean IRO_CopyAndConstantPropagation(void) { + IROAssign *ass2; + IROAssign *ass; + IROLinear *linear; + IRONode *node; + VarRecord *var; + BitVector *bv; + Boolean flag; + Boolean result; + + IRO_FirstAssign = NULL; + IRO_NumAssign = 0; + result = 0; + + for (node = IRO_FirstNode; node; node = node->nextnode) { + linear = node->first; + while (1) { + if (!linear) + break; + + if (IsPropagatable(linear) && (var = IRO_FindAssigned(linear))) { + IROAssign *newass; + IRO_Dump("Found propagatable assignment at: %d\n", linear->index); + newass = oalloc(sizeof(IROAssign)); + newass->linear = linear; + newass->next = NULL; + newass->index = ++IRO_NumAssign; + newass->varIndex = var->index; + newass->linear2 = linear->u.diadic.right; + newass->var = NULL; + newass->varObj = IRO_IsVariable(linear->u.diadic.right); + newass->node = node; + if (newass->varObj) + newass->var = IRO_FindVar(newass->varObj, 0, 1); + if (!IRO_FirstAssign) + IRO_FirstAssign = newass; + else + IRO_LastAssign->next = newass; + IRO_LastAssign = newass; + } + + if (linear == node->last) + break; + linear = linear->next; + } + } + + IRO_CheckForUserBreak(); + + node = IRO_FirstNode; + ass = IRO_FirstAssign; + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + while (node) { + Bv_AllocVector(&node->x16, IRO_NumAssign); + if (node != IRO_FirstNode) + Bv_Set(node->x16); + Bv_AllocVector(&node->x22, IRO_NumAssign); + Bv_AllocVector(&node->x1E, IRO_NumAssign); + Bv_AllocVector(&node->x2A, IRO_NumAssign); + node->x1A = NULL; + + linear = node->first; + while (1) { + if (!linear) + break; + + if (IsIntGenKillCandidate(linear)) { + //IROAssign *ass2; + Bv_Clear(IRO_VarKills); + IRO_GetKills(linear); + + for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { + if (Bv_IsBitSet(ass2->varIndex, IRO_VarKills)) { + Bv_SetBit(ass2->index, node->x22); + Bv_ClearBit(ass2->index, node->x1E); + } + if (ass2->var && Bv_IsBitSet(ass2->var->index, IRO_VarKills)) { + Bv_SetBit(ass2->index, node->x22); + Bv_ClearBit(ass2->index, node->x1E); + } + } + } + + while (ass && ass->linear == linear) { + Bv_SetBit(ass->index, node->x1E); + ass = ass->next; + } + + if (linear == node->last) + break; + linear = linear->next; + } + + Bv_Copy(node->x16, node->x2A); + Bv_Minus(node->x22, node->x2A); + Bv_Or(node->x1E, node->x2A); + node = node->nextnode; + } + + IRO_CheckForUserBreak(); + + Bv_AllocVector(&bv, IRO_NumAssign); + do { + flag = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node == IRO_FirstNode) { + Bv_Clear(bv); + } else { + UInt16 i; + Bv_Set(bv); + for (i = 0; i < node->numpred; i++) + Bv_And(IRO_NodeTable[node->pred[i]]->x2A, bv); + } + + if (!Bv_Compare(bv, node->x16)) { + flag = 1; + Bv_Copy(bv, node->x16); + } + + Bv_Copy(node->x16, node->x2A); + Bv_Minus(node->x22, node->x2A); + Bv_Or(node->x1E, node->x2A); + } + } while (flag); + + IRO_CheckForUserBreak(); + + node = IRO_FirstNode; + ass = IRO_FirstAssign; + while (node) { + IRO_Avail = node->x16; + linear = node->first; + while (1) { + if (!linear) + break; + + if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { + if ((var = IRO_FindVar(linear->u.diadic.left->u.node->data.objref, 0, 1))) { + //IROAssign *ass2; + for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { + if ( + ass2->varIndex == var->index && + Bv_IsBitSet(ass2->index, IRO_Avail) && + (IRO_IsConstant(ass2->linear2) || node->loopdepth <= ass2->node->loopdepth) && + !PropagationHasDefsInUnorderedRegions(linear, ass2->linear2) + ) { + if (ass2->linear2->type == IROLinearOperand && IRO_is_CPtypeequal(linear->rtype, ass2->linear->u.diadic.left->rtype)) { + ENode *enode = IRO_NewENode(ass2->linear2->u.node->type); + *enode = *ass2->linear2->u.node; + if (enode->type == EINTCONST) { + if (linear->flags & IROLF_BitfieldIndirect) { + IRO_TruncateBitfieldValueToType(&enode->data.intval, linear->rtype, var->x1A); + enode->rtype = linear->rtype; + result = 1; + } else { + IRO_TruncateValueToType(&enode->data.intval, linear->rtype); + enode->rtype = linear->rtype; + } + } + linear->u.monadic->type = IROLinearNop; + linear->type = IROLinearOperand; + linear->u.node = enode; + } else if (ass2->varObj && IRO_is_CPtypeequal(linear->rtype, ass2->linear->rtype)) { + linear->u.diadic.left->u.node = create_objectrefnode(ass2->varObj); + if (ass2->linear2->flags & IROLF_BitfieldIndirect) + linear->flags |= IROLF_BitfieldIndirect; + } + IRO_Dump("Found propagation at %d from %d\n", linear->index, ass2->linear->index); + break; + } + } + } + } else if (linear->type == IROLinearAsm) { + IAEffects effects; + int i; + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + + for (i = 0; i < effects.numoperands; i++) { + if (effects.operands[i].type == IAEffect_0 && effects.operands[i].offset == 0 && effects.operands[i].object->type->size == effects.operands[i].size) { + if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) { + //IROAssign *ass2; + for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { + if (ass2->varIndex == var->index && Bv_IsBitSet(ass2->index, IRO_Avail) && ass2->linear->rtype->size == effects.operands[i].size) { + ENode *enode; + if (ass2->varObj) { + enode = create_objectrefnode(ass2->varObj); + } else if (ass2->linear2->type == IROLinearOperand) { + enode = ass2->linear2->u.node; + } else { +#line 768 + CError_FATAL(); + } + CodeGen_PropagateIntoAsm(linear->u.asm_stmt, effects.operands[i].object, enode); + break; + } + } + } + } + } + } + + if (IsIntGenKillCandidate(linear)) { + //IROAssign *ass2; + Bv_Clear(IRO_VarKills); + IRO_GetKills(linear); + + for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { + if (Bv_IsBitSet(ass2->varIndex, IRO_VarKills)) { + Bv_ClearBit(ass2->index, IRO_Avail); + } + if (ass2->var && Bv_IsBitSet(ass2->var->index, IRO_VarKills)) { + Bv_ClearBit(ass2->index, IRO_Avail); + } + } + + while (ass && ass->linear == linear) { + Bv_SetBit(ass->index, IRO_Avail); + ass = ass->next; + } + } + + if (linear == node->last) + break; + linear = linear->next; + } + node = node->nextnode; + } + + IRO_CheckForUserBreak(); + + return result; +} + +void IRO_ExpressionPropagation(void) { + IRONode *node; + IROLinear *linear; + Object *obj; + VarRecord *var; + IROAssign *ass; + + for (node = IRO_FirstNode; node; node = node->nextnode) { + IRO_FirstAssign = NULL; + IRO_LastAssign = NULL; + IRO_NumAssign = 0; + + linear = node->first; + while (1) { + IROList list; + if (!linear) + break; + + IRO_InitList(&list); + if (IsPropagatableExpr(linear, &list)) { + if ((var = IRO_FindAssigned(linear))) { + IRO_Dump("Found propagatable expression assignment at: %d\n", linear->index); + ass = oalloc(sizeof(IROAssign)); + ass->linear = linear; + ass->next = NULL; + ass->index = ++IRO_NumAssign; + ass->varIndex = var->index; + ass->linear2 = linear->u.diadic.right; + ass->x20 = 0; + ass->node = node; + IRO_FindDepends(linear->u.diadic.right); + ass->depends = IRO_Depends; + if (!IRO_FirstAssign) { + IRO_FirstAssign = ass; + ass->prev = NULL; + } else { + IRO_LastAssign->next = ass; + ass->prev = IRO_LastAssign; + } + IRO_LastAssign = ass; + } + } + + if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { + if ((var = IRO_FindVar(linear->u.monadic->u.node->data.objref, 0, 1))) { + for (ass = IRO_LastAssign; ass; ass = ass->prev) { + if (ass->varIndex == var->index) + ass->x20++; + } + } + } + + if (linear == node->last) + break; + linear = linear->next; + } + + Bv_AllocVector(&IRO_Avail, IRO_NumAssign); + + linear = node->first; + while (1) { + if (!linear) + break; + + if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { + if ((var = IRO_FindVar(linear->u.monadic->u.node->data.objref, 0, 1))) { + for (ass = IRO_LastAssign; ass; ass = ass->next) { + if (ass->varIndex == var->index && Bv_IsBitSet(ass->index, IRO_Avail) && !PropagationHasDefsInUnorderedRegions(linear, ass->linear2)) { + if (ass->linear2->type == IROLinearOperand && IRO_is_CPtypeequal(linear->rtype, ass->linear->u.diadic.left->rtype)) { + ENode *enode = IRO_NewENode(ass->linear2->u.node->type); + *enode = *ass->linear2->u.node; + if (enode->type == EINTCONST) { + IRO_TruncateValueToType(&enode->data.intval, linear->rtype); + enode->rtype = linear->rtype; + } else if (enode->type == EOBJREF) { + IROLinear *tmp = IRO_LocateFather(linear); + if (tmp && (tmp->flags & IROLF_Assigned)) + linear->flags |= IROLF_Assigned; + } + linear->u.monadic->type = IROLinearNop; + linear->type = IROLinearOperand; + linear->u.node = enode; + } else if (IRO_IsVariable(ass->linear2) && IRO_is_CPtypeequal(linear->rtype, ass->linear->rtype)) { + linear->u.monadic->u.node = create_objectrefnode(ass->linear2->u.monadic->u.node->data.objref); + if (ass->linear2->flags & IROLF_BitfieldIndirect) + linear->flags |= IROLF_BitfieldIndirect; + } else if (IRO_is_CPtypeequal(linear->rtype, ass->linear->rtype) && ass->x20 == 1 && !VarIsUsedInOtherFNodes(var, node)) { + IROList list; + IRO_InitList(&list); + IRO_DuplicateExpr(ass->linear->u.diadic.right, &list); + if (IS_TYPE_FLOAT(ass->linear->rtype)) { + IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg); + tmp->index = ++IRO_NumLinear; + tmp->rtype = ass->linear->rtype; + tmp->nodetype = ETYPCON; + tmp->nodeflags = ENODE_FLAG_80; + tmp->u.monadic = list.tail; + IRO_AddToList(tmp, &list); + } + IRO_PasteAfter(list.head, list.tail, linear); + IRO_LocateFather_Cut_And_Paste(linear, list.tail); + linear = list.tail; + } + IRO_Dump("Found expression propagation at %d from %d\n", linear->index, ass->linear->index); + break; + } + } + } + } + + if (linear->type != IROLinearNop && IsIntGenKillCandidate(linear)) { + Bv_Clear(IRO_VarKills); + IRO_GetKills(linear); + for (ass = IRO_FirstAssign; ass; ass = ass->next) { + if (Bv_IsBitSet(ass->varIndex, IRO_VarKills)) + Bv_ClearBit(ass->index, IRO_Avail); + if ((obj = IRO_IsVariable(ass->linear->u.diadic.right))) { + if ((var = IRO_FindVar(obj, 0, 1))) { + if (Bv_IsBitSet(var->index, IRO_VarKills)) + Bv_ClearBit(ass->index, IRO_Avail); + } + } else { + IROList list; + IRO_InitList(&list); + IRO_Depends = ass->depends; + IRO_FindDepends_NoAlloc(ass->linear->u.diadic.right); + if (Bv_BitsInCommon(IRO_VarKills, ass->depends)) + Bv_ClearBit(ass->index, IRO_Avail); + } + } + + for (ass = IRO_FirstAssign; ass; ass = ass->next) { + IRO_Depends = ass->depends; + IRO_FindDepends_NoAlloc(ass->linear->u.diadic.right); + if (ass->linear == linear && !Bv_IsBitSet(ass->varIndex, ass->depends)) + Bv_SetBit(ass->index, IRO_Avail); + } + } + + if (linear == node->last) + break; + linear = linear->next; + } + } + + IRO_CheckForUserBreak(); +} + diff --git a/compiler_and_linker/unsorted/IroRangePropagation.c b/compiler_and_linker/unsorted/IroRangePropagation.c index e69de29..c471277 100644 --- a/compiler_and_linker/unsorted/IroRangePropagation.c +++ b/compiler_and_linker/unsorted/IroRangePropagation.c @@ -0,0 +1,776 @@ +#include "compiler/IroRangePropagation.h" +#include "compiler/IroDump.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroMalloc.h" +#include "compiler/IroPointerAnalysis.h" +#include "compiler/IroUtil.h" +#include "compiler/IroVars.h" +#include "compiler/CInt64.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef enum ERangeType { + ERangeType0, + ERangeType1, + ERangeType2, + ERangeType3 +} ERangeType; + +typedef struct ERange { + ERangeType type; + CInt64 upper; + CInt64 lower; +} ERange; + +typedef struct ERecord { + Object *object; + ERange *range; + struct ERecord *next; +} ERecord; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static ERecord *ERangeFirst; +static ERecord *ERangeLast; + +static ERange *ERnewERange(ERangeType type) { + ERange *range; + + range = oalloc(sizeof(ERange)); + range->type = type; + return range; +} + +static ERecord *ERnewRecord(Object *object, ERange *range) { + ERecord *record; + + record = oalloc(sizeof(ERecord)); + record->object = object; + record->range = range; + record->next = ERangeFirst; + ERangeFirst = record; + if (!ERangeLast) + ERangeLast = record; + return record; +} + +static ERecord *ERecordFound(Object *obj) { + ERecord *scan; + + scan = ERangeFirst; + while (scan && obj != scan->object) + scan = scan->next; + + return scan; +} + +static Boolean EREandHasNoUse(ERange *range, CInt64 val) { + UInt16 i; + CInt64 v11; + CInt64 work; + + i = 0; + work = range->upper; + while (CInt64_NotEqual(work = CInt64_ShrU(work, cint64_one), cint64_zero)) + i++; + + if (CInt64_NotEqual(range->upper, cint64_zero)) + i++; + + CInt64_SetULong(&work, i); + v11 = CInt64_Sub(CInt64_Shl(cint64_one, work), cint64_one); + if (CInt64_NotEqual(cint64_zero, CInt64_And(CInt64_Inv(val), v11))) + return 0; + else + return 1; +} + +static void ERcheckOverflow(ERange *range, Type *type) { + CInt64 typeSize; + CInt64 work; + CInt64 work2; + CInt64 value3; + + if (!range) + return; + + if (!IS_TYPE_INT(type)) { + range->type = ERangeType3; + return; + } + + CInt64_SetLong(&typeSize, type->size); + CInt64_SetLong(&value3, 3); + + if (IRO_IsUnsignedType(type)) { + if (type->size < 8) { + work = CInt64_Sub(CInt64_Shl(cint64_one, CInt64_Shl(typeSize, value3)), cint64_one); + if (CInt64_GreaterU(range->upper, work)) + range->type = ERangeType3; + } else { + range->type = ERangeType3; + } + } else { + if (type->size < 8) { + work = CInt64_Sub(CInt64_Shl(cint64_one, CInt64_Sub(CInt64_Shl(typeSize, value3), cint64_one)), cint64_one); + work2 = CInt64_Shl(cint64_negone, CInt64_Sub(CInt64_Shl(typeSize, value3), cint64_one)); + if (CInt64_Greater(range->upper, work) || CInt64_Less(range->lower, work2)) + range->type = ERangeType3; + } else { + range->type = ERangeType3; + } + } +} + +static void ERinvalidAll(void) { + ERecord *record; + + for (record = ERangeFirst; record; record = record->next) + record->range->type = ERangeType3; +} + +static void SetRangesForKillsByIndirectAssignment(IROLinear *nd) { + IROListNode *list; + IROListNode *scan; + IROLinear *inner; + Boolean failed; + IROListNode *resultList; + IROLinear *scannd; + Boolean foundObjRef; + ERecord *record; + ERange *range; + IROListNode *next; + Object *obj; + IROLinear *analysend; + Object *proc; + + failed = 0; + if (nd->type == IROLinearOp2Arg) + inner = nd->u.diadic.left; + else + inner = nd->u.monadic; + + if ( + inner && + inner->type == IROLinearOp1Arg && + inner->nodetype == EINDIRECT && + (analysend = inner->u.monadic) && + copts.opt_pointer_analysis && + analysend->pointsToFunction && + (proc = FunctionName) + ) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(proc, analysend, &resultList); + + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + failed = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + break; + } + } + + if (!foundObjRef) { + failed = 1; + break; + } + } + + if (!failed) { + for (; list; list = list->nextList) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; +#line 302 + CError_ASSERT(obj != NULL); + + range = nd->x16; + if (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) + range = inner->x16; + + record = ERecordFound(obj); + if (!record) + ERnewRecord(obj, range); + else + record->range = range; + } + } + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + failed = 1; + } + } else { + failed = 1; + } + + if (failed) { + ERinvalidAll(); + nd->x16 = ERnewERange(ERangeType3); + } +} + +static void InvalidateRangesForKillsByFunctionCall(IROLinear *nd) { + IROListNode *scan; + IROLinear *scannd; + Boolean failed; + Boolean foundObjRef; + IROListNode *list; + IROListNode *resultList; + ERecord *record; + IROListNode *next; + Object *obj; + IROLinear *analysend; + Object *proc; + ObjectList *olist; + ObjectList *killList; + + failed = 0; + + if ( + (analysend = nd->u.funccall.linear8) && + copts.opt_pointer_analysis && + analysend->pointsToFunction && + (proc = FunctionName) + ) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(proc, analysend, &resultList); + + if (resultList) { + for (scan = resultList; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + failed = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = scannd->u.node->data.objref; +#line 385 + CError_ASSERT(obj != NULL); + + killList = NULL; + PointerAnalysis_GetFunctionKills(obj, nd, &killList); + + for (olist = killList; olist; olist = olist->next) { + if (!olist->object) { + failed = 1; + break; + } + } + + while (killList) { + olist = killList->next; + IRO_free(killList); + killList = olist; + } + + if (failed) + break; + } + } + + if (!foundObjRef) + failed = 1; + if (failed) + break; + } + + if (!failed) { + for (list = resultList; list; list = list->nextList) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; + killList = NULL; + PointerAnalysis_GetFunctionKills(obj, nd, &killList); + + for (olist = killList; olist; olist = olist->next) { + if ((record = ERecordFound(olist->object))) + record->range->type = ERangeType3; + } + + while (killList) { + olist = killList->next; + IRO_free(killList); + killList = olist; + } + } + } + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + failed = 1; + } + } else { + failed = 1; + } + + if (failed) + ERinvalidAll(); +} + +static void ERfoldOperand(IROLinear *nd) { + switch (nd->u.node->type) { + case EOBJREF: + nd->x16 = NULL; + break; + case EINTCONST: + nd->x16 = ERnewERange(ERangeType0); + nd->x16->upper = nd->x16->lower = nd->u.node->data.intval; + break; + case EFLOATCONST: + case ESTRINGCONST: + nd->x16 = ERnewERange(ERangeType0); + break; + } +} + +static Boolean ERfoldExpr(IROLinear *nd) { + ERecord *record; + ERange *range; + IROLinear *tmp; + IROLinear *inner; + Object *obj; + + switch (nd->nodetype) { + case EINDIRECT: + inner = nd->u.monadic; + if (IS_TYPE_INT(nd->rtype)) { + if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF) { + if (!inner->x16 && (obj = inner->u.node->data.objref)) { + if ((record = ERecordFound(obj))) { + inner->x16 = ERnewERange(ERangeType3); + *inner->x16 = *record->range; + } else { + inner->x16 = ERnewERange(ERangeType3); + inner->x16->upper = cint64_max; + inner->x16->lower = cint64_min; + ERnewRecord(obj, inner->x16); + } + } + nd->x16 = inner->x16; + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } else { + if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF && !inner->x16) + inner->x16 = ERnewERange(ERangeType3); + nd->x16 = ERnewERange(ERangeType3); + } + break; + case EAND: + case EANDASS: + if (IRO_IsIntConstant(nd->u.diadic.right)) { + CInt64 val = nd->u.diadic.right->u.node->data.intval; + nd->x16 = ERnewERange(ERangeType1); + nd->x16->upper = val; + nd->x16->lower = cint64_zero; + if ( + (range = nd->u.diadic.left->x16) && + range->type != ERangeType3 && + CInt64_LessEqualU(range->upper, val) && + CInt64_LessEqualU(range->lower, val) && + EREandHasNoUse(range, val) && + !IRO_HasSideEffect(nd->u.diadic.left) + ) { + IRO_Dump("eliminating redundant EAND %ld; upperBound==0x%x, lowerBound==0x%x, Constant==0x%x\n", + nd->index, + CInt64_GetULong(&range->upper), + CInt64_GetULong(&range->upper), + CInt64_GetULong(&val) + ); + IRO_NopOut(nd->u.diadic.right); + nd->type = IROLinearNop; + nd->expr = NULL; + tmp = nd->u.diadic.left; + nd->u.diadic.left = nd->u.diadic.right; + if (!IRO_LocateFather_Cut_And_Paste(nd, tmp)) { + tmp->flags &= ~IROLF_Reffed; + if (IRO_IsVariable(tmp)) + IRO_NopOut(tmp); + } + } + } else { + if (nd->u.diadic.right->x16) { + nd->x16 = ERnewERange(ERangeType3); + *nd->x16 = *nd->u.diadic.right->x16; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case ELOGNOT: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case ELAND: + case ELOR: + nd->x16 = ERnewERange(ERangeType1); + nd->x16->upper = cint64_one; + nd->x16->lower = cint64_zero; + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EBINNOT: + case EFORCELOAD: + case EXOR: + case EOR: + case EXORASS: + case EORASS: + case ECOMMA: + case ETYPCON: + case EBITFIELD: + case ECOND: + case ENULLCHECK: + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + break; + case EASS: + if (IS_TYPE_INT(nd->rtype)) + nd->x16 = nd->u.diadic.right->x16; + break; + case EMUL: + case EMULV: + case EMULASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + if (IRO_IsUnsignedType(nd->rtype)) { + nd->x16->upper = CInt64_MulU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); + nd->x16->lower = CInt64_MulU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); + } else { + nd->x16->upper = CInt64_Mul(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); + nd->x16->lower = CInt64_Mul(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EDIV: + case EDIVASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + if (!CInt64_IsZero(&nd->u.diadic.right->x16->lower) && !CInt64_IsZero(&nd->u.diadic.right->x16->upper)) { + if (IRO_IsUnsignedType(nd->rtype)) { + nd->x16->upper = CInt64_DivU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_DivU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } else { + nd->x16->upper = CInt64_Div(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_Div(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EMODULO: + case EMODASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + if (!CInt64_IsZero(&nd->u.diadic.right->x16->lower) && !CInt64_IsZero(&nd->u.diadic.right->x16->upper)) { + if (IRO_IsUnsignedType(nd->rtype)) { + nd->x16->upper = CInt64_ModU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_ModU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } else { + nd->x16->upper = CInt64_Mod(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_Mod(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EADDV: + case EADD: + case EADDASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + nd->x16->upper = CInt64_Add(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); + nd->x16->lower = CInt64_Add(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case ESUBV: + case ESUB: + case ESUBASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + nd->x16->upper = CInt64_Sub(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_Sub(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case ESHL: + case ESHLASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + nd->x16->upper = CInt64_Shl(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); + nd->x16->lower = CInt64_Shl(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case ESHR: + case ESHRASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + if (IRO_IsUnsignedType(nd->rtype)) { + nd->x16->upper = CInt64_ShrU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_ShrU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } else { + nd->x16->upper = CInt64_Shr(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_Shr(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EPOSTINC: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + range = nd->u.monadic->x16; + *nd->x16 = *range; + range->upper = CInt64_Add(range->upper, cint64_one); + range->lower = CInt64_Add(range->lower, cint64_one); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EPOSTDEC: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + range = nd->u.monadic->x16; + *nd->x16 = *range; + range->upper = CInt64_Sub(range->upper, cint64_one); + range->lower = CInt64_Sub(range->lower, cint64_one); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EPREINC: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + range = nd->u.monadic->x16; + nd->x16->upper = CInt64_Add(range->upper, cint64_one); + nd->x16->lower = CInt64_Add(range->lower, cint64_one); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EPREDEC: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + range = nd->u.monadic->x16; + nd->x16->upper = CInt64_Sub(range->upper, cint64_one); + nd->x16->lower = CInt64_Sub(range->lower, cint64_one); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EMONMIN: + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + break; + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + break; + default: + ERcheckOverflow(nd->x16, nd->rtype); + break; + } + + if ( + (nd->type == IROLinearOp1Arg || nd->type == IROLinearOp2Arg) && + IRO_IsAssignOp[nd->nodetype] && + nd->x16 && + IS_TYPE_INT(nd->rtype) + ) { + IROLinear *x = NULL; + if (nd->type == IROLinearOp2Arg) + x = nd->u.diadic.left; + else if (nd->type == IROLinearOp1Arg) + x = nd->u.monadic; + + if (x->type == IROLinearOp1Arg && + x->nodetype == EINDIRECT && + (x->u.monadic->nodetype == EINDIRECT || x->u.monadic->nodetype == EADD)) { + SetRangesForKillsByIndirectAssignment(nd); + } else { + obj = NULL; + if (x) + obj = IRO_IsVariable(x); + if (!obj) + return 0; + + range = nd->x16; + if (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) + range = x->x16; + + record = ERecordFound(obj); + if (!record) + ERnewRecord(obj, range); + else + record->range = range; + } + } + + return nd->x16 != NULL; +} + +static Boolean ERfoldLinear(IROLinear *nd) { + nd->x16 = 0; + + switch (nd->type) { + case IROLinearNop: + case IROLinearEnd: + break; + case IROLinearOperand: + ERfoldOperand(nd); + break; + case IROLinearOp1Arg: + case IROLinearOp2Arg: + ERfoldExpr(nd); + break; + case IROLinearFunccall: + InvalidateRangesForKillsByFunctionCall(nd); + break; + case IROLinearAsm: + ERinvalidAll(); + break; + } + + return 0; +} + +Boolean IRO_RangePropagateInFNode(void) { + IRONode *fnode; + IROLinear *nd; + Boolean result; + + result = 0; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + ERangeFirst = ERangeLast = NULL; + for (nd = fnode->first; nd != fnode->last; nd = nd->next) + ERfoldLinear(nd); + if (ERfoldLinear(nd)) + result = 1; + } + + if (result) { + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } + + IRO_CheckForUserBreak(); + return result; +} diff --git a/compiler_and_linker/unsorted/IroSubable.c b/compiler_and_linker/unsorted/IroSubable.c index e69de29..6b8daf0 100644 --- a/compiler_and_linker/unsorted/IroSubable.c +++ b/compiler_and_linker/unsorted/IroSubable.c @@ -0,0 +1,160 @@ +#include "compiler/IroSubable.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroPropagate.h" +#include "compiler/IroUtil.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +static Boolean IsSubableOp[MAXEXPR]; + +void IRO_InitializeIsSubableOpArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + IsSubableOp[i] = 0; + + IsSubableOp[EPOSTINC] = 0; + IsSubableOp[EPOSTDEC] = 0; + IsSubableOp[EPREINC] = 0; + IsSubableOp[EPREDEC] = 0; + IsSubableOp[EINDIRECT] = 0; + IsSubableOp[EMONMIN] = 1; + IsSubableOp[EBINNOT] = 1; + IsSubableOp[ELOGNOT] = 1; + IsSubableOp[EFORCELOAD] = 0; + IsSubableOp[EMUL] = 1; + IsSubableOp[EMULV] = 1; + IsSubableOp[EDIV] = 1; + IsSubableOp[EMODULO] = 1; + IsSubableOp[EADDV] = 1; + IsSubableOp[ESUBV] = 1; + IsSubableOp[EADD] = 1; + IsSubableOp[ESUB] = 1; + IsSubableOp[ESHL] = 1; + IsSubableOp[ESHR] = 1; + IsSubableOp[ELESS] = 0; + IsSubableOp[EGREATER] = 0; + IsSubableOp[ELESSEQU] = 0; + IsSubableOp[EGREATEREQU] = 0; + IsSubableOp[EEQU] = 0; + IsSubableOp[ENOTEQU] = 0; + IsSubableOp[EAND] = 1; + IsSubableOp[EXOR] = 1; + IsSubableOp[EOR] = 1; + IsSubableOp[ELAND] = 0; + IsSubableOp[ELOR] = 0; + IsSubableOp[EASS] = 0; + IsSubableOp[EMULASS] = 0; + IsSubableOp[EDIVASS] = 0; + IsSubableOp[EMODASS] = 0; + IsSubableOp[EADDASS] = 0; + IsSubableOp[ESUBASS] = 0; + IsSubableOp[ESHLASS] = 0; + IsSubableOp[ESHRASS] = 0; + IsSubableOp[EANDASS] = 0; + IsSubableOp[EXORASS] = 0; + IsSubableOp[EORASS] = 0; + IsSubableOp[ECOMMA] = 0; + IsSubableOp[EPMODULO] = 0; + IsSubableOp[EROTL] = 0; + IsSubableOp[EROTR] = 0; + IsSubableOp[EBCLR] = 0; + IsSubableOp[EBTST] = 0; + IsSubableOp[EBSET] = 0; + IsSubableOp[ETYPCON] = 0; + IsSubableOp[EBITFIELD] = 0; + IsSubableOp[EINTCONST] = 0; + IsSubableOp[EFLOATCONST] = 0; + IsSubableOp[ESTRINGCONST] = 0; + IsSubableOp[ECOND] = 0; + IsSubableOp[EFUNCCALL] = 0; + IsSubableOp[EFUNCCALLP] = 0; + IsSubableOp[EOBJREF] = 0; + IsSubableOp[EMFPOINTER] = 0; + IsSubableOp[ENULLCHECK] = 0; + IsSubableOp[EPRECOMP] = 0; + IsSubableOp[ETEMP] = 0; + IsSubableOp[EARGOBJ] = 0; + IsSubableOp[ELOCOBJ] = 0; + IsSubableOp[ELABEL] = 0; + IsSubableOp[ESETCONST] = 0; + IsSubableOp[ENEWEXCEPTION] = 0; + IsSubableOp[ENEWEXCEPTIONARRAY] = 0; + IsSubableOp[EOBJLIST] = 0; + IsSubableOp[EMEMBER] = 0; + IsSubableOp[ETEMPLDEP] = 0; + IsSubableOp[EINSTRUCTION] = 0; + IsSubableOp[EDEFINE] = 0; + IsSubableOp[EREUSE] = 0; + IsSubableOp[EASSBLK] = 0; + IsSubableOp[EVECTOR128CONST] = 0; + IsSubableOp[ECONDASS] = 0; +} + +static int IsSubscript(IROLinear *nd) { + return 0; +} + +Boolean IRO_IsSubableExpression(IROLinear *nd) { + Object *varobj; + Boolean result; + + switch (nd->type) { + case IROLinearOp2Arg: + if (nd->nodetype == EADD || nd->nodetype == ESUB) { + if ( + IRO_IsConstant(nd->u.diadic.right) && + (varobj = IRO_IsVariable(nd->u.diadic.left)) && + varobj->datatype == DLOCAL && + varobj->u.var.info && + !varobj->u.var.info->noregister) + return 0; + + } + result = IsSubableOp[nd->nodetype] && !IsSubscript(nd); + return result; + case IROLinearOp1Arg: + if (IsSubableOp[nd->nodetype] && !IsSubscript(nd)) + return 1; + + if (nd->nodetype == EINDIRECT && !(nd->flags & IROLF_Assigned)) { + if (nd->flags & IROLF_Ind) { + nd = nd->u.monadic; + if (nd->type == IROLinearOperand && + nd->u.node->type == EOBJREF && + nd->u.node->data.objref->datatype == DLOCAL && + nd->u.node->data.objref->u.var.info && + !nd->u.node->data.objref->u.var.info->noregister + ) + return 0; + return 1; + } + + if (IRO_IsVariable(nd) && IRO_IsRegable(nd->u.monadic->u.node->data.objref)) + return 0; + return 1; + } else if (nd->nodetype == ETYPCON && IS_TYPE_INT(nd->rtype) && nd->rtype->size >= nd->u.monadic->rtype->size) { + return 1; + } else { + return 0; + } + case IROLinearOperand: + default: + return 0; + } +} + +Boolean IRO_IsVectorTempCandidate(IROLinear *nd) { + return + ( + nd->type == IROLinearOp1Arg || + nd->type == IROLinearOp2Arg || + nd->type == IROLinearOp3Arg || + nd->type == IROLinearOperand || + nd->type == IROLinearFunccall + ) && ( + (nd->flags & IROLF_LoopInvariant) && + !(nd->flags & IROLF_Ind) + ); +} diff --git a/compiler_and_linker/unsorted/IroTransform.c b/compiler_and_linker/unsorted/IroTransform.c index e69de29..710f2d8 100644 --- a/compiler_and_linker/unsorted/IroTransform.c +++ b/compiler_and_linker/unsorted/IroTransform.c @@ -0,0 +1,3 @@ +#include "compiler/IroTransform.h" + +// TODO diff --git a/compiler_and_linker/unsorted/IroUnrollLoop.c b/compiler_and_linker/unsorted/IroUnrollLoop.c index e69de29..f5c4fb0 100644 --- a/compiler_and_linker/unsorted/IroUnrollLoop.c +++ b/compiler_and_linker/unsorted/IroUnrollLoop.c @@ -0,0 +1,95 @@ +#include "compiler/IroUnrollLoop.h" +#include "compiler/IroUtil.h" + +// forward decls +static void IRO_FindLoops_Unroll(void); + +void IRO_LoopUnroller(void) { + VectorPhaseCalledFromUnroll = 1; + IRO_FindLoops_Unroll(); + IRO_CheckForUserBreak(); +} + +static void IRO_FindLoops_Unroll(void) { +} + +static void CheckConstant() { +} + +static void UnrollWhileLoopBody() { +} + +static void PatternMatchLoop() { +} + +static void UnrollWhileLoop() { +} + +void IRO_IterateForLoopBody() { +} + +void IRO_LinearizeForLoopPostLoop() { +} + +static void UnrollForLoop() { +} + +static void UnrollStandardLoop() { +} + +static void LoopUnroll() { +} + +static void IsLoopUnrollable() { +} + +void BuildEarlyLoopExitTest() { +} + +void BuildLoopExitTest() { +} + +void IsIterationCountConstant() { +} + +static void IsDifferenceOfTermsConstant() { +} + +void NoOpBlock() { +} + +void IRO_TestConstantIterationCount() { +} + +void BuildOrigIterationCount() { +} + +static void BuildOrigIterationCount_DoWhile() { +} + +void BuildNewFinalvalue() { +} + +static void BuildPreAlignTemp() { +} + +static void BuildNewFinalvalue_DoWhile() { +} + +static void BuildUnrolledFinalvalue_DoWhile() { +} + +void BuildUnrolledBodyEntryTest() { +} + +void ChangeInductionReference() { +} + +void UpdateInductionIncrement() { +} + +void GenInitialAssignment() { +} + +void GenNewInduction() { +} diff --git a/compiler_and_linker/unsorted/IroUtil.c b/compiler_and_linker/unsorted/IroUtil.c index e69de29..37a6be9 100644 --- a/compiler_and_linker/unsorted/IroUtil.c +++ b/compiler_and_linker/unsorted/IroUtil.c @@ -0,0 +1,1250 @@ +#include "compiler/IroUtil.h" +#include "compiler/IroCSE.h" +#include "compiler/IroDump.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroLoop.h" +#include "compiler/IroVars.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/CompilerTools.h" +#include "compiler/CCompiler.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/Exceptions.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "cos.h" + +static UInt32 IRO_LastUserBreakTick; +static IROLinear *ExprStart; +static IROLinear *ExprEnd; +static IRONode *IRO_Node; +static SInt32 FuncLevel; +Object *FunctionName; +Boolean IRO_IsLeafFunction; +Boolean IRO_FunctionHasReturn; +Boolean DisableDueToAsm; +Boolean LoopOptimizerRun; + +Object *IRO_IsVariable(IROLinear *linear) { + if (linear->type == IROLinearOp1Arg && + linear->nodetype == EINDIRECT && + linear->u.monadic->type == IROLinearOperand && + linear->u.monadic->u.node->type == EOBJREF) + return linear->u.monadic->u.node->data.objref; + + return NULL; +} + +Boolean IRO_IsConstant(IROLinear *linear) { + if (linear->type == IROLinearOperand && ENODE_IS3(linear->u.node, EINTCONST, EVECTOR128CONST, EFLOATCONST)) + return 1; + return 0; +} + +Boolean IRO_IsPow2(IROLinear *linear, SInt32 *powvalue) { + UInt32 desired; + UInt32 value; + SInt32 i; + + *powvalue = -1; + if (linear->type == IROLinearOperand && linear->u.node->type == EINTCONST) { + if (CTool_EndianReadWord32(&linear->u.node->data.intval.hi)) + return 0; + + desired = CInt64_GetULong(&linear->u.node->data.intval); + value = 1; + for (i = 0; i < 31; i++) { + if (value == desired) { + *powvalue = i; + return 1; + } + value += value; + } + } + + return 0; +} + +Boolean IRO_IsIntConstant(IROLinear *linear) { + if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EINTCONST)) + return 1; + return 0; +} + +Boolean IRO_IsFloatConstant(IROLinear *linear) { + if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EFLOATCONST)) + return 1; + return 0; +} + +Boolean IRO_IsVector128Constant(IROLinear *linear) { + if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EVECTOR128CONST)) + return 1; + return 0; +} + +Boolean IRO_IsAssignment(IROLinear *linear) { + if (linear->type == IROLinearOp1Arg || linear->type == IROLinearOp2Arg) { + if (IRO_IsAssignOp[linear->nodetype]) + return 1; + } + return 0; +} + +static Boolean IRO_OperandsSame(ENode *a, ENode *b) { + if (a->type == b->type) { + switch (a->type) { + case EINTCONST: + return CInt64_Equal(a->data.intval, b->data.intval); + case ESTRINGCONST: + return 0; + case EFLOATCONST: + return a->data.floatval.value == b->data.floatval.value; + case EVECTOR128CONST: + return (a->data.vector128val.ul[0] == b->data.vector128val.ul[0]) && + (a->data.vector128val.ul[1] == b->data.vector128val.ul[1]) && + (a->data.vector128val.ul[2] == b->data.vector128val.ul[2]) && + (a->data.vector128val.ul[3] == b->data.vector128val.ul[3]); + case EOBJREF: + return a->data.objref == b->data.objref; + } + } + + return 0; +} + +Boolean IRO_TypesEqual(Type *a, Type *b) { + if (IS_TYPE_BITFIELD(a)) { + if (IS_TYPE_BITFIELD(b)) { + if ( + (TYPE_BITFIELD(a)->bitfieldtype == TYPE_BITFIELD(b)->bitfieldtype) && + (TYPE_BITFIELD(a)->unkA == TYPE_BITFIELD(b)->unkA) && + (TYPE_BITFIELD(a)->unkB == TYPE_BITFIELD(b)->unkB)) + return 1; + } + return 0; + } + + if (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b)) + return 1; + + return is_typeequal(a, b) != 0; +} + +Type *IRO_UnsignedType(Type *type) { + if (IS_TYPE_ENUM(type) || IS_TYPE_POINTER_ONLY(type)) { + if (type->size == stunsignedchar.size) + return TYPE(&stunsignedchar); + if (type->size == stunsignedint.size) + return TYPE(&stunsignedint); + if (type->size == stunsignedshort.size) + return TYPE(&stunsignedshort); + if (type->size == stunsignedlong.size) + return TYPE(&stunsignedlong); + if (type->size == stunsignedlonglong.size) + return TYPE(&stunsignedlonglong); +#line 281 + CError_FATAL(); + return NULL; + } + + if (!IS_TYPE_INT(type)) { +#line 287 + CError_FATAL(); + return NULL; + } + + if (type == TYPE(&stbool) || type == TYPE(&stwchar)) + return type; + + if (type == TYPE(&stchar) || type == TYPE(&stsignedchar) || type == TYPE(&stunsignedchar)) + return TYPE(&stunsignedchar); + if (type == TYPE(&stsignedshort) || type == TYPE(&stunsignedshort)) + return TYPE(&stunsignedshort); + if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint)) + return TYPE(&stunsignedint); + if (type == TYPE(&stsignedlong) || type == TYPE(&stunsignedlong)) + return TYPE(&stunsignedlong); + if (type == TYPE(&stsignedlonglong) || type == TYPE(&stunsignedlonglong)) + return TYPE(&stunsignedlonglong); + +#line 319 + CError_FATAL(); + return NULL; +} + +Type *IRO_SignedType(Type *type) { + if (IS_TYPE_ENUM(type) || IS_TYPE_POINTER_ONLY(type)) { + if (type->size == stsignedchar.size) + return TYPE(&stsignedchar); + if (type->size == stsignedint.size) + return TYPE(&stsignedint); + if (type->size == stsignedshort.size) + return TYPE(&stsignedshort); + if (type->size == stsignedlong.size) + return TYPE(&stsignedlong); + if (type->size == stsignedlonglong.size) + return TYPE(&stsignedlonglong); +#line 357 + CError_FATAL(); + return NULL; + } + + if (!IS_TYPE_INT(type)) { +#line 363 + CError_FATAL(); + return NULL; + } + + if (type == TYPE(&stbool) && type->size == stsignedchar.size) + return TYPE(&stsignedchar); + + if (type == TYPE(&stwchar) && type->size == stsignedshort.size) + return TYPE(&stsignedshort); + + if (type == TYPE(&stchar) || type == TYPE(&stsignedchar) || type == TYPE(&stunsignedchar)) + return TYPE(&stsignedchar); + if (type == TYPE(&stsignedshort) || type == TYPE(&stunsignedshort)) + return TYPE(&stsignedshort); + if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint)) + return TYPE(&stsignedint); + if (type == TYPE(&stsignedlong) || type == TYPE(&stunsignedlong)) + return TYPE(&stsignedlong); + if (type == TYPE(&stsignedlonglong) || type == TYPE(&stunsignedlonglong)) + return TYPE(&stsignedlonglong); + +#line 399 + CError_FATAL(); + return NULL; +} + +Boolean IRO_is_CPtypeequal(Type *a, Type *b) { + if (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b)) + return 1; + + return is_typeequal(a, b) != 0; +} + +Boolean IRO_ExprsSame(IROLinear *a, IROLinear *b) { + if (a->type == b->type && IRO_TypesEqual(a->rtype, b->rtype)) { + switch (a->type) { + case IROLinearOperand: + return IRO_OperandsSame(a->u.node, b->u.node); + case IROLinearOp1Arg: + if (a->nodetype == b->nodetype) + return IRO_ExprsSame(a->u.monadic, b->u.monadic); + return 0; + case IROLinearOp2Arg: + if (a->nodetype == b->nodetype) + return IRO_ExprsSame(a->u.diadic.left, b->u.diadic.left) && + IRO_ExprsSame(a->u.diadic.right, b->u.diadic.right); + return 0; + case IROLinearOp3Arg: + if (a->nodetype == b->nodetype) + return IRO_ExprsSame(a->u.args3.a, b->u.args3.a) && + IRO_ExprsSame(a->u.args3.b, b->u.args3.b) && + IRO_ExprsSame(a->u.args3.c, b->u.args3.c); + return 0; + case IROLinearFunccall: + return 0; + default: + return 0; + } + } + + return 0; +} + +CLabel *IRO_NewLabel(void) { + CLabel *label = newlabel(); + label->next = Labels; + Labels = label; + return label; +} + +Boolean IRO_ExprsSameSemantically(IROLinear *a, IROLinear *b) { + if (a->type == b->type && IRO_TypesEqual(a->rtype, b->rtype)) { + Boolean flag = 0; + + switch (a->type) { + case IROLinearOperand: + return IRO_OperandsSame(a->u.node, b->u.node); + case IROLinearOp1Arg: + if (a->nodetype == b->nodetype) + return IRO_ExprsSameSemantically(a->u.monadic, b->u.monadic); + return 0; + case IROLinearOp2Arg: + if (a->nodetype == b->nodetype) { + switch (a->nodetype) { + case EMUL: + case EADD: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + if (!IRO_HasSideEffect(a)) { + flag = IRO_ExprsSameSemantically(a->u.diadic.left, b->u.diadic.right) && + IRO_ExprsSameSemantically(a->u.diadic.right, b->u.diadic.left); + } + } + + return flag || (IRO_ExprsSameSemantically(a->u.diadic.left, b->u.diadic.left) && + IRO_ExprsSameSemantically(a->u.diadic.right, b->u.diadic.right)); + } + return 0; + case IROLinearOp3Arg: + if (a->nodetype == b->nodetype) + return IRO_ExprsSameSemantically(a->u.args3.a, b->u.args3.a) && + IRO_ExprsSameSemantically(a->u.args3.b, b->u.args3.b) && + IRO_ExprsSameSemantically(a->u.args3.c, b->u.args3.c); + return 0; + case IROLinearFunccall: + return 0; + default: + return 0; + } + } + + return 0; +} + +IROLinear *IRO_FindPrecedAfter(IROLinear *a, IROLinear *iter) { + IROLinear *prev = iter; + while (iter && iter != a) { + prev = iter; + iter = iter->next; + } + + if (iter) + return prev; + return iter; +} + +IROLinear *IRO_FindPreced(IROLinear *a) { + IROLinear *iter; + IROLinear *prev; + + prev = iter = IRO_FirstLinear; + while (iter && iter != a) { + prev = iter; + iter = iter->next; + } + + if (iter) + return prev; + return iter; +} + +IROLinear *IRO_FindFirst(IROLinear *linear) { + short i; + + switch (linear->type) { + case IROLinearOperand: + return linear; + case IROLinearOp1Arg: + return IRO_FindFirst(linear->u.monadic); + case IROLinearOp2Arg: + if (linear->u.diadic.right->index < linear->u.diadic.left->index) + return IRO_FindFirst(linear->u.diadic.right); + else + return IRO_FindFirst(linear->u.diadic.left); + case IROLinearOp3Arg: + if (linear->u.args3.a->index < linear->u.args3.b->index) { + if (linear->u.args3.b->index < linear->u.args3.c->index) + return IRO_FindFirst(linear->u.args3.a); + else + return IRO_FindFirst(linear->u.args3.c); + } else { + if (linear->u.args3.b->index < linear->u.args3.c->index) + return IRO_FindFirst(linear->u.args3.b); + else + return IRO_FindFirst(linear->u.args3.c); + } + case IROLinearFunccall: + i = linear->u.funccall.argCount - 1; + return IRO_FindFirst(linear->u.funccall.args[i]); + default: +#line 641 + CError_FATAL(); + return NULL; + } +} + +void IRO_CutAndPasteAfter(IROLinear *a, IROLinear *b, IROLinear *c) { + IROLinear *preced = IRO_FindPreced(a); + preced->next = b->next; + b->next = c->next; + c->next = a; +} + +Boolean IRO_IsConstantZero(IROLinear *linear) { + return (IRO_IsIntConstant(linear) && CInt64_IsZero(&linear->u.node->data.intval)) || + (IRO_IsFloatConstant(linear) && CMach_FloatIsZero(linear->u.node->data.floatval)); +} + +Boolean IRO_IsConstantOne(IROLinear *linear) { + return (IRO_IsIntConstant(linear) && CInt64_IsOne(&linear->u.node->data.intval)) || + (IRO_IsFloatConstant(linear) && CMach_FloatIsOne(linear->u.node->data.floatval)); +} + +Boolean IRO_IsConstantNegativeOne(IROLinear *linear) { + CInt64 neg = CInt64_Neg(linear->u.node->data.intval); + return (IRO_IsIntConstant(linear) && CInt64_IsOne(&neg)) || + (IRO_IsFloatConstant(linear) && CMach_FloatIsNegOne(linear->u.node->data.floatval)); +} + +static void ActNop(IROLinear *linear, Boolean isEntry) { + if (!isEntry) { + linear->type = IROLinearNop; + linear->expr = NULL; + } +} + +void IRO_NopOut(IROLinear *linear) { + IRO_WalkTree(linear, ActNop); +} + +static Boolean NotNoppable(IROLinear *linear) { + return ( + (linear->type == IROLinearFunccall) || + IRO_IsAssignment(linear) || + ((linear->type == IROLinearOperand) && ENODE_IS(linear->u.node, EINSTRUCTION)) || + (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) || + ((linear->type == IROLinearOperand) && ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref)) + ); +} + +static void ActNopNonSideEffects(IROLinear *linear, Boolean isEntry) { + if (isEntry) { + if (NotNoppable(linear)) { + if (!FuncLevel) + linear->flags &= ~IROLF_Reffed; + FuncLevel++; + } + } else { + if (NotNoppable(linear)) { + FuncLevel--; + } else if (!FuncLevel) { + linear->type = IROLinearNop; + } + } +} + +void IRO_NopNonSideEffects(IROLinear *linear, SInt32 level) { + FuncLevel = level; + IRO_WalkTree(linear, ActNopNonSideEffects); +} + +void IRO_BuildList(IROLinear *linear, Boolean isEntry) { + if (!isEntry) { + linear->next = NULL; + IRO_AddToList(linear, &IRO_InitLList); + } +} + +void IRO_WalkTree(IROLinear *linear, IROWalkTreeFunc func) { + int i; + + func(linear, 1); + switch (linear->type) { + case IROLinearOperand: + break; + case IROLinearOp1Arg: + IRO_WalkTree(linear->u.monadic, func); + break; + case IROLinearOp2Arg: + IRO_WalkTree(linear->u.diadic.left, func); + IRO_WalkTree(linear->u.diadic.right, func); + break; + case IROLinearOp3Arg: + IRO_WalkTree(linear->u.args3.a, func); + IRO_WalkTree(linear->u.args3.b, func); + IRO_WalkTree(linear->u.args3.c, func); + break; + case IROLinearFunccall: + IRO_WalkTree(linear->u.funccall.linear8, func); + for (i = 0; i < linear->u.funccall.argCount; i++) + IRO_WalkTree(linear->u.funccall.args[i], func); + break; + } + func(linear, 0); +} + +void IRO_WalkTreeToPropagateFlags(IROLinear *linear, IROWalkTreeFunc func) { + int i; + + switch (linear->type) { + case IROLinearOperand: + break; + case IROLinearOp1Arg: + IRO_WalkTreeToPropagateFlags(linear->u.monadic, func); + break; + case IROLinearOp2Arg: + IRO_WalkTreeToPropagateFlags(linear->u.diadic.left, func); + IRO_WalkTreeToPropagateFlags(linear->u.diadic.right, func); + break; + case IROLinearOp3Arg: + IRO_WalkTreeToPropagateFlags(linear->u.args3.a, func); + IRO_WalkTreeToPropagateFlags(linear->u.args3.b, func); + IRO_WalkTreeToPropagateFlags(linear->u.args3.c, func); + break; + case IROLinearFunccall: + IRO_WalkTreeToPropagateFlags(linear->u.funccall.linear8, func); + for (i = 0; i < linear->u.funccall.argCount; i++) + IRO_WalkTreeToPropagateFlags(linear->u.funccall.args[i], func); + break; + } + func(linear, 0); +} + +void IRO_WalkInts(IROLinear *a, IROLinear *b, IROWalkTreeFunc func) { + IROLinear *scan; + + for (scan = a; scan; scan = scan->next) { + switch (scan->type) { + case IROLinearBeginCatch: + case IROLinearEndCatch: + case IROLinearEndCatchDtor: + IRO_WalkTree(scan->u.ctch.linear, func); + break; + case IROLinearOperand: + case IROLinearOp1Arg: + case IROLinearOp2Arg: + case IROLinearOp3Arg: + case IROLinearFunccall: + IRO_WalkTree(scan, func); + break; + case IROLinearIf: + case IROLinearIfNot: + IRO_WalkTree(scan->u.label.x4, func); + break; + case IROLinearReturn: + if (scan->u.monadic) + IRO_WalkTree(scan->u.monadic, func); + break; + case IROLinearSwitch: + IRO_WalkTree(scan->u.swtch.x4, func); + break; + case IROLinearAsm: + func(scan, 1); + func(scan, 0); + break; + case IROLinearEnd: + break; + } + + if (scan == b) + break; + } +} + +void IRO_Cut(IROLinear *a, IROLinear *b) { + IROLinear *scan; + IROLinear *prev; + IRONode *node; + + scan = a; + while (1) { + scan->stmt = NULL; + if (scan == b) + break; + scan = scan->next; + } + + prev = NULL; + for (scan = IRO_FirstLinear; scan && scan != a; scan = scan->next) + prev = scan; + +#line 951 + CError_ASSERT(scan); + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first == a) { + if (node->last == b) { + node->first = node->last = NULL; + break; + } else { + node->first = b->next; + break; + } + } else if (node->last == b) { + node->last = prev; + break; + } + } + + if (prev) + prev->next = b->next; + else + IRO_FirstLinear = b->next; +} + +void IRO_Paste(IROLinear *a, IROLinear *b, IROLinear *c) { + IROLinear *prev; + IROLinear *scan; + IRONode *node; + +#line 1002 + CError_ASSERT(c && c->type != IROLinearLabel); + + prev = NULL; + for (scan = IRO_FirstLinear; scan && scan != c; scan = scan->next) + prev = scan; + +#line 1016 + CError_ASSERT(scan); + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first == c) { + node->first = a; + break; + } + } + + b->next = c; + if (prev) + prev->next = a; + else + IRO_FirstLinear = a; +} + +void IRO_PasteAfter(IROLinear *a, IROLinear *b, IROLinear *c) { + IRONode *node; + + switch (c->type) { + case IROLinearGoto: + case IROLinearIf: + case IROLinearIfNot: + case IROLinearSwitch: +#line 1060 + CError_FATAL(); + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->last == c) { + node->last = b; + break; + } + } + + b->next = c->next; + c->next = a; +} + +static void FindStart(IROLinear *linear, Boolean isEntry) { + IROLinear *scan; + if (isEntry) { + scan = linear; + do { + if (scan == ExprStart) { + ExprStart = linear; + return; + } + if (scan == ExprEnd) + return; + } while ((scan = scan->next)); + } +} + +void IRO_ClipExpr(IROExpr *expr) { + ExprStart = ExprEnd = expr->linear; + IRO_WalkTree(expr->linear, FindStart); + IRO_Cut(ExprStart, ExprEnd); +} + +void IRO_ClipExprTree(IROLinear *linear) { + ExprStart = ExprEnd = linear; + IRO_WalkTree(linear, FindStart); + IRO_Cut(ExprStart, ExprEnd); +} + +static void SetNodeNumInExprList(IROLinear *linear, Boolean isEntry) { + if (isEntry && linear->expr) + linear->expr->node = IRO_Node; +} + +void IRO_MoveExpression(IROExpr *expr, IROLinear *linear) { + IRONode *node; + IROLinear *scan; + + ExprStart = ExprEnd = expr->linear; + IRO_WalkTree(expr->linear, FindStart); + + if (ExprStart != linear) { + IRO_Cut(ExprStart, ExprEnd); + IRO_Paste(ExprStart, ExprEnd, linear); + for (node = IRO_FirstNode; node; node = node->nextnode) { + for (scan = node->first; scan; scan = scan->next) { + if (scan == expr->linear) { + expr->node = node; + break; + } + if (scan == node->last) + break; + } + } + + IRO_Node = expr->node; + IRO_WalkTree(expr->linear, SetNodeNumInExprList); + } +} + +void IRO_InitList(IROList *list) { + list->head = list->tail = NULL; +} + +void IRO_AddToList(IROLinear *linear, IROList *list) { + if (list->head) + list->tail->next = linear; + else + list->head = linear; + + list->tail = linear; + while (list->tail->next) + list->tail = list->tail->next; +} + +IROLinear *IRO_FindLabelNode(CLabel *label, IROLinear *linear) { + IROLinear *scan; + + for (scan = linear; scan; scan = scan->next) { + if (scan->type == IROLinearLabel && scan->u.label.label == label) + break; + } + +#line 1244 + CError_ASSERT(scan); + return scan; +} + +void IRO_DuplicateExprRange(IROLinear *start, IROLinear *end, IROList *list) { + IROLinear *scan; + + for (scan = start; scan; scan = scan->next) { + if (scan->type != IROLinearNop && !(scan->flags & IROLF_Reffed)) + IRO_DuplicateExpr(scan, list); + if (scan == end) + break; + } +} + +IROLinear *IRO_DuplicateExpr(IROLinear *linear, IROList *list) { + IROLinear *copy; + ENode *copynode; + int i; + + copy = IRO_NewLinear(linear->type); + *copy = *linear; + + copy->index = ++IRO_NumLinear; + copy->next = NULL; + copy->expr = NULL; + + switch (copy->type) { + case IROLinearOperand: + copynode = lalloc(sizeof(ENode)); + *copynode = *linear->u.node; + copy->u.node = copynode; + break; + case IROLinearOp1Arg: + copy->u.monadic = IRO_DuplicateExpr(copy->u.monadic, list); + break; + case IROLinearOp2Arg: + if (linear->flags & IROLF_8000) { + copy->u.diadic.right = IRO_DuplicateExpr(copy->u.diadic.right, list); + copy->u.diadic.left = IRO_DuplicateExpr(copy->u.diadic.left, list); + } else { + copy->u.diadic.left = IRO_DuplicateExpr(copy->u.diadic.left, list); + copy->u.diadic.right = IRO_DuplicateExpr(copy->u.diadic.right, list); + } + break; + case IROLinearOp3Arg: + copy->u.args3.a = IRO_DuplicateExpr(copy->u.args3.a, list); + copy->u.args3.b = IRO_DuplicateExpr(copy->u.args3.b, list); + copy->u.args3.c = IRO_DuplicateExpr(copy->u.args3.c, list); + break; + case IROLinearFunccall: + copy->u.funccall.linear8 = IRO_DuplicateExpr(copy->u.funccall.linear8, list); + copy->u.funccall.args = oalloc(sizeof(IROLinear *) * copy->u.funccall.argCount); + for (i = 0; i < copy->u.funccall.argCount; i++) { + copy->u.funccall.args[i] = IRO_DuplicateExpr(linear->u.funccall.args[i], list); + } + break; + case IROLinearAsm: + copy->u.asm_stmt = CodeGen_CopyAsmStat(linear->u.asm_stmt); + break; + } + + IRO_AddToList(copy, list); + return copy; +} + +IROLinear *IRO_TempReference(Object *obj, IROList *list) { + IROLinear *op; + IROLinear *ind; + + op = IRO_NewLinear(IROLinearOperand); + op->u.node = create_objectrefnode(obj); + op->rtype = op->u.node->data.objref->type; + op->index = ++IRO_NumLinear; + op->flags |= IROLF_Reffed | IROLF_Ind; + IRO_AddToList(op, list); + + ind = IRO_NewLinear(IROLinearOp1Arg); + ind->nodetype = EINDIRECT; + ind->rtype = obj->type; + ind->u.monadic = op; + ind->index = ++IRO_NumLinear; + ind->next = NULL; + IRO_AddToList(ind, list); + + return ind; +} + +inline IROLinear *LocateFatherHelper(IROLinear *linear, Boolean a, IROLinear ***b) { + IROLinear *scan; + SInt32 index; + int i; + + for (scan = linear->next, index = 0; index < (a ? 2 : 1); index++) { + while (scan) { + switch (scan->type) { + case IROLinearIf: + case IROLinearIfNot: + if (scan->u.label.x4 == linear) { + if (b) + *b = &scan->u.label.x4; + return scan; + } + break; + case IROLinearReturn: + if (scan->u.monadic == linear) { + if (b) + *b = &scan->u.monadic; + return scan; + } + break; + case IROLinearOp1Arg: + if (scan->u.monadic == linear) { + if (b) + *b = &scan->u.monadic; + return scan; + } + break; + case IROLinearSwitch: + if (scan->u.swtch.x4 == linear) { + if (b) + *b = &scan->u.swtch.x4; + return scan; + } + break; + case IROLinearOp2Arg: + if (scan->u.diadic.left == linear) { + if (b) + *b = &scan->u.diadic.left; + return scan; + } + if (scan->u.diadic.right == linear) { + if (b) + *b = &scan->u.diadic.right; + return scan; + } + break; + case IROLinearOp3Arg: + if (scan->u.args3.a == linear) { + if (b) + *b = &scan->u.args3.a; + return scan; + } + if (scan->u.args3.b == linear) { + if (b) + *b = &scan->u.args3.b; + return scan; + } + if (scan->u.args3.c == linear) { + if (b) + *b = &scan->u.args3.c; + return scan; + } + break; + case IROLinearFunccall: + if (scan->u.funccall.linear8 == linear) { + if (b) + *b = &scan->u.funccall.linear8; + return scan; + } + for (i = 0; i < scan->u.funccall.argCount; i++) { + if (scan->u.funccall.args[i] == linear) { + if (b) + *b = &scan->u.funccall.args[i]; + return scan; + } + } + break; + case IROLinearNop: + case IROLinearOperand: + case IROLinearGoto: + case IROLinearLabel: + case IROLinearEntry: + case IROLinearExit: + case IROLinearBeginCatch: + case IROLinearEndCatch: + case IROLinearEndCatchDtor: + case IROLinearAsm: + case IROLinearEnd: + break; + default: +#line 1536 + CError_FATAL(); + } + scan = scan->next; + } + + scan = IRO_FirstLinear; + } + + if (b) + *b = NULL; + return NULL; +} + +IROLinear *IRO_LocateFather(IROLinear *linear) { + return LocateFatherHelper(linear, 0, NULL); +} + +IROLinear *IRO_LocateFather_Cut_And_Paste(IROLinear *a, IROLinear *b) { + IROLinear **p; + IROLinear *l = LocateFatherHelper(a, 0, &p); + if (l) { +#line 1568 + CError_ASSERT(p && *p); + IRO_NopOut(a); + *p = b; + } + return l; +} + +IROLinear *IRO_LocateFather_Cut_And_Paste_Without_Nopping(IROLinear *a, IROLinear *b) { + IROLinear **p; + IROLinear *l = LocateFatherHelper(a, 0, &p); + if (l) { +#line 1585 + CError_ASSERT(p && *p); + *p = b; + } + return l; +} + +void IRO_ReplaceReference(IROLinear *a, Object *obj, IROLinear *b) { + IROLinear **ptr; + IROList list; + + if (LocateFatherHelper(a, 1, &ptr)) { +#line 1605 + CError_ASSERT(ptr && *ptr); + IRO_InitList(&list); + *ptr = IRO_TempReference(obj, &list); + IRO_PasteAfter(list.head, list.tail, b); + if (a->flags & IROLF_LoopInvariant) + list.tail->flags |= IROLF_LoopInvariant; + } else { + IRO_Dump("Oh, oh, did not find reference to replace\n"); + } +} + +void IRO_ReplaceReferenceWithNode(IROLinear *a, IROLinear *b) { + IROLinear **ptr; + IROList list; + + if (LocateFatherHelper(a, 1, &ptr)) { +#line 1664 + CError_ASSERT(ptr && *ptr); + *ptr = b; + b->flags |= IROLF_Reffed; + } else { + IRO_Dump("Oh, oh, did not find reference to replace\n"); + } +} + +void IRO_GetTemp(IROExpr *expr) { +} + +IROLinear *IRO_AssignToTemp(IROExpr *expr) { +} + +IROLinear *IRO_FindStart(IROLinear *linear) { + ExprStart = ExprEnd = linear; + IRO_WalkTree(linear, FindStart); + return ExprStart; +} + +void IRO_DeleteCommaNode(IROLinear *linear, IROExpr *expr) { + IROLinear *scan; + for (scan = linear; scan; scan = scan->next) { + if (scan->nodetype == ECOMMA) { + if (scan != expr->linear) { + IRO_NopOut(scan->u.diadic.left); + IRO_LocateFather_Cut_And_Paste(scan, scan->u.diadic.right); + } else { + IRO_NopOut(scan->u.diadic.left); + expr->linear = scan->u.diadic.right; + } + } + } +} + +void IRO_RemoveCommaNodeFromIR(void) { + IRONode *node; + IROLinear *linear; + + for (node = IRO_FirstNode; node; node = node->nextnode) { + linear = node->first; + do { + if (!linear) + break; + if (linear->nodetype == ECOMMA) { + linear->u.diadic.left->flags &= ~IROLF_Reffed; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(linear, linear->u.diadic.right); + linear->type = IROLinearNop; + } + linear = linear->next; + } while (linear != node->last); + } +} + +IROAddrRecord *IRO_InitAddrRecordPointer(IROLinear *linear) { + IROAddrRecord *rec = oalloc(sizeof(IROAddrRecord)); + rec->numObjRefs = 0; + rec->objRefs = NULL; + rec->numMisc = 0; + rec->misc = NULL; + rec->numInts = 0; + rec->ints = NULL; + rec->x16 = 0; + rec->linear = linear; + return rec; +} + +IROLinear *IRO_HasSideEffect(IROLinear *linear) { + IROLinear *tmp; + + if (!linear) + return linear; + + if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) + return linear; + + switch (linear->type) { + case IROLinearAsm: + return linear; + case IROLinearOperand: + if (ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref)) + return linear; + return NULL; + case IROLinearOp1Arg: + if (IRO_IsAssignOp[linear->nodetype]) + return linear; + else + return IRO_HasSideEffect(linear->u.monadic); + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) + return linear; + else if ((tmp = IRO_HasSideEffect(linear->u.diadic.left))) + return tmp; + else + return IRO_HasSideEffect(linear->u.diadic.right); + case IROLinearOp3Arg: + if ((tmp = IRO_HasSideEffect(linear->u.args3.a))) + return tmp; + else if ((tmp = IRO_HasSideEffect(linear->u.args3.b))) + return tmp; + else + return IRO_HasSideEffect(linear->u.args3.c); + case IROLinearFunccall: + return linear; + default: + return linear; + } +} + +IROLinear *IRO_CheckSideEffect(IROLinear *linear) { + IROLinear *result; + IROLinear *tmp; + IROLinear *tmp2; + IROLinear *tmp3; + + if (!linear) + return linear; + + if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) { + linear->flags &= ~IROLF_Reffed; + return linear; + } + + result = NULL; + switch (linear->type) { + case IROLinearAsm: + linear->flags &= ~IROLF_Reffed; + return linear; + case IROLinearOperand: + if (ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref)) { + linear->flags &= ~IROLF_Reffed; + return linear; + } + break; + case IROLinearOp1Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + linear->flags &= ~IROLF_Reffed; + return linear; + } + if ((result = IRO_CheckSideEffect(linear->u.monadic))) { + if (linear->nodetype == EINDIRECT && linear->u.monadic->type == IROLinearOperand) { + linear->flags &= ~IROLF_Reffed; + return linear; + } + } + break; + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + linear->flags &= ~IROLF_Reffed; + return linear; + } + tmp = IRO_CheckSideEffect(linear->u.diadic.left); + tmp2 = IRO_CheckSideEffect(linear->u.diadic.right); + if (tmp) + result = tmp; + else + result = tmp2; + break; + case IROLinearOp3Arg: + tmp = IRO_CheckSideEffect(linear->u.args3.a); + tmp2 = IRO_CheckSideEffect(linear->u.args3.b); + tmp3 = IRO_CheckSideEffect(linear->u.args3.c); + result = tmp ? tmp : tmp2 ? tmp2 : tmp3; + break; + case IROLinearFunccall: + linear->flags &= ~IROLF_Reffed; + return linear; + default: + return linear; + } + + linear->type = IROLinearNop; + IRO_Dump("Nop out with side-effects checking at: %d\n", linear->index); + return result; +} + +void IRO_WalkExcActions(ExceptionAction *action, WalkObjFunc func) { + while (action) { + switch (action->type) { + case EAT_DESTROYLOCAL: + func(action->data.destroy_local.local); + break; + case EAT_DESTROYLOCALCOND: + func(action->data.destroy_local_cond.local); + func(action->data.destroy_local_cond.cond); + break; + case EAT_DESTROYLOCALOFFSET: + func(action->data.destroy_local_offset.local); + break; + case EAT_DESTROYLOCALPOINTER: + func(action->data.destroy_local_pointer.pointer); + break; + case EAT_DESTROYLOCALARRAY: + func(action->data.destroy_local_array.localarray); + break; + case EAT_DESTROYPARTIALARRAY: + func(action->data.destroy_partial_array.arraypointer); + func(action->data.destroy_partial_array.arraycounter); + func(action->data.destroy_partial_array.element_size); + break; + case EAT_DESTROYBASE: + func(action->data.destroy_member.objectptr); // wrong union? + break; + case EAT_DESTROYMEMBER: + func(action->data.destroy_member.objectptr); + break; + case EAT_DESTROYMEMBERCOND: + func(action->data.destroy_member_cond.objectptr); + func(action->data.destroy_member_cond.cond); + break; + case EAT_DESTROYMEMBERARRAY: + func(action->data.destroy_member_array.objectptr); + break; + case EAT_DELETEPOINTER: + func(action->data.delete_pointer.pointerobject); + break; + case EAT_DELETEPOINTERCOND: + func(action->data.delete_pointer_cond.pointerobject); + func(action->data.delete_pointer_cond.cond); + break; + } + action = action->prev; + } +} + +Boolean IRO_FunctionCallMightThrowException(IROLinear *linear) { + Object *obj; + if (linear->type == IROLinearFunccall) { + obj = NULL; + if (linear->u.funccall.linear8->type == IROLinearOperand && ENODE_IS(linear->u.funccall.linear8->u.node, EOBJREF)) + obj = linear->u.funccall.linear8->u.node->data.objref; + if (!obj || CExcept_CanThrowException(obj, obj->datatype == DVFUNC && !(linear->nodeflags & ENODE_FLAG_80))) + return 1; + } + return 0; +} + +IROLinear *IRO_NewIntConst(CInt64 val, Type *type) { + ENode *node; + IROLinear *linear; + + node = IRO_NewENode(EINTCONST); + node->data.intval = val; + node->rtype = type; + + linear = IRO_NewLinear(IROLinearOperand); + linear->index = ++IRO_NumLinear; + linear->rtype = type; + linear->u.node = node; + return linear; +} + +IROLinear *IRO_NewFloatConst(Float val, Type *type) { + ENode *node; + IROLinear *linear; + + node = IRO_NewENode(EFLOATCONST); + node->data.floatval = val; + node->rtype = type; + + linear = IRO_NewLinear(IROLinearOperand); + linear->index = ++IRO_NumLinear; + linear->rtype = type; + linear->u.node = node; + return linear; +} + +Boolean IRO_IsAddressMultiply(IROLinear *linear) { + return 0; +} + +void IRO_SetupForUserBreakChecking(void) { + IRO_LastUserBreakTick = 0; +} + +void IRO_CheckForUserBreak(void) { + if (IRO_LastUserBreakTick + 8 < COS_GetTicks()) { + if (CWUserBreak(cparams.context)) + CError_UserBreak(); + IRO_LastUserBreakTick = COS_GetTicks(); + } +} + diff --git a/compiler_and_linker/unsorted/IroVars.c b/compiler_and_linker/unsorted/IroVars.c index e69de29..e306dd0 100644 --- a/compiler_and_linker/unsorted/IroVars.c +++ b/compiler_and_linker/unsorted/IroVars.c @@ -0,0 +1,1449 @@ +#include "compiler/IroVars.h" +#include "compiler/IroDump.h" +#include "compiler/IroFlowgraph.h" +#include "compiler/IroJump.h" +#include "compiler/IroLinearForm.h" +#include "compiler/IroMalloc.h" +#include "compiler/IroPointerAnalysis.h" +#include "compiler/IroUtil.h" +#include "compiler/IROUseDef.h" +#include "compiler/CClass.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CParser.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/objects.h" +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/BitVector.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct IndirectRecordMatch { + IROLinear *nd; + struct IndirectRecordMatch *otherMatches; +} IndirectRecordMatch; + +typedef struct IndirectRecord { + IROLinear *linear; + unsigned char flags; + VarRecord *var; + SInt32 addend; + SInt32 size; + int startbit; + int endbit; + Type *type; + struct IndirectRecord *next; + IndirectRecordMatch *matches; + IROLinear *x26; +} IndirectRecord; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static IndirectRecord *IRO_FirstIndirectRecord; +static IndirectRecord *IRO_LastIndirectRecord; +static IROLinear *TheBaseTerm; +VarRecord *IRO_FirstVar; +VarRecord *IRO_LastVar; +SInt32 IRO_NumVars; +Boolean IRO_IsBitField; +SInt32 IRO_BaseTerms; +SInt32 IRO_VarTerms; +Boolean IRO_IsModifyOp[MAXEXPR]; +Boolean IRO_IsAssignOp[MAXEXPR]; + +// forward decls +static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag); +static Boolean CheckAddressConsistency(IROLinear *nd, VarRecord *var, SInt32 addend, Type *type); +static void DisableEntries(IndirectRecord *irec); +static void DisableAddressedEntries(void); +static UInt32 ObjectIsArg(Object *obj); + +void IRO_InitializeIRO_IsModifyOpArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + IRO_IsModifyOp[i] = 0; + + IRO_IsModifyOp[EPOSTINC] = 1; + IRO_IsModifyOp[EPOSTDEC] = 1; + IRO_IsModifyOp[EPREINC] = 1; + IRO_IsModifyOp[EPREDEC] = 1; + IRO_IsModifyOp[EINDIRECT] = 0; + IRO_IsModifyOp[EMONMIN] = 0; + IRO_IsModifyOp[EBINNOT] = 0; + IRO_IsModifyOp[ELOGNOT] = 0; + IRO_IsModifyOp[EFORCELOAD] = 0; + IRO_IsModifyOp[EMUL] = 0; + IRO_IsModifyOp[EMULV] = 0; + IRO_IsModifyOp[EDIV] = 0; + IRO_IsModifyOp[EMODULO] = 0; + IRO_IsModifyOp[EADDV] = 0; + IRO_IsModifyOp[ESUBV] = 0; + IRO_IsModifyOp[EADD] = 0; + IRO_IsModifyOp[ESUB] = 0; + IRO_IsModifyOp[ESHL] = 0; + IRO_IsModifyOp[ESHR] = 0; + IRO_IsModifyOp[ELESS] = 0; + IRO_IsModifyOp[EGREATER] = 0; + IRO_IsModifyOp[ELESSEQU] = 0; + IRO_IsModifyOp[EGREATEREQU] = 0; + IRO_IsModifyOp[EEQU] = 0; + IRO_IsModifyOp[ENOTEQU] = 0; + IRO_IsModifyOp[EAND] = 0; + IRO_IsModifyOp[EXOR] = 0; + IRO_IsModifyOp[EOR] = 0; + IRO_IsModifyOp[ELAND] = 0; + IRO_IsModifyOp[ELOR] = 0; + IRO_IsModifyOp[EASS] = 0; + IRO_IsModifyOp[EMULASS] = 1; + IRO_IsModifyOp[EDIVASS] = 1; + IRO_IsModifyOp[EMODASS] = 1; + IRO_IsModifyOp[EADDASS] = 1; + IRO_IsModifyOp[ESUBASS] = 1; + IRO_IsModifyOp[ESHLASS] = 1; + IRO_IsModifyOp[ESHRASS] = 1; + IRO_IsModifyOp[EANDASS] = 1; + IRO_IsModifyOp[EXORASS] = 1; + IRO_IsModifyOp[EORASS] = 1; + IRO_IsModifyOp[ECOMMA] = 0; + IRO_IsModifyOp[EPMODULO] = 1; + IRO_IsModifyOp[EROTL] = 1; + IRO_IsModifyOp[EROTR] = 1; + IRO_IsModifyOp[EBCLR] = 1; + IRO_IsModifyOp[EBTST] = 1; + IRO_IsModifyOp[EBSET] = 1; + IRO_IsModifyOp[ETYPCON] = 0; + IRO_IsModifyOp[EBITFIELD] = 0; + IRO_IsModifyOp[EINTCONST] = 0; + IRO_IsModifyOp[EFLOATCONST] = 0; + IRO_IsModifyOp[ESTRINGCONST] = 0; + IRO_IsModifyOp[ECOND] = 0; + IRO_IsModifyOp[EFUNCCALL] = 0; + IRO_IsModifyOp[EFUNCCALLP] = 0; + IRO_IsModifyOp[EOBJREF] = 0; + IRO_IsModifyOp[EMFPOINTER] = 0; + IRO_IsModifyOp[ENULLCHECK] = 0; + IRO_IsModifyOp[EPRECOMP] = 0; + IRO_IsModifyOp[ETEMP] = 0; + IRO_IsModifyOp[EARGOBJ] = 0; + IRO_IsModifyOp[ELOCOBJ] = 0; + IRO_IsModifyOp[ELABEL] = 0; + IRO_IsModifyOp[ESETCONST] = 0; + IRO_IsModifyOp[ENEWEXCEPTION] = 0; + IRO_IsModifyOp[ENEWEXCEPTIONARRAY] = 0; + IRO_IsModifyOp[EOBJLIST] = 0; + IRO_IsModifyOp[EMEMBER] = 0; + IRO_IsModifyOp[ETEMPLDEP] = 0; + IRO_IsModifyOp[EINSTRUCTION] = 0; + IRO_IsModifyOp[EDEFINE] = 0; + IRO_IsModifyOp[EREUSE] = 0; + IRO_IsModifyOp[EASSBLK] = 0; + IRO_IsModifyOp[EVECTOR128CONST] = 0; + IRO_IsModifyOp[ECONDASS] = 1; +} + +void IRO_InitializeIRO_IsAssignOpArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + IRO_IsAssignOp[i] = 0; + + IRO_IsAssignOp[EPOSTINC] = 1; + IRO_IsAssignOp[EPOSTDEC] = 1; + IRO_IsAssignOp[EPREINC] = 1; + IRO_IsAssignOp[EPREDEC] = 1; + IRO_IsAssignOp[EINDIRECT] = 0; + IRO_IsAssignOp[EMONMIN] = 0; + IRO_IsAssignOp[EBINNOT] = 0; + IRO_IsAssignOp[ELOGNOT] = 0; + IRO_IsAssignOp[EFORCELOAD] = 0; + IRO_IsAssignOp[EMUL] = 0; + IRO_IsAssignOp[EMULV] = 0; + IRO_IsAssignOp[EDIV] = 0; + IRO_IsAssignOp[EMODULO] = 0; + IRO_IsAssignOp[EADDV] = 0; + IRO_IsAssignOp[ESUBV] = 0; + IRO_IsAssignOp[EADD] = 0; + IRO_IsAssignOp[ESUB] = 0; + IRO_IsAssignOp[ESHL] = 0; + IRO_IsAssignOp[ESHR] = 0; + IRO_IsAssignOp[ELESS] = 0; + IRO_IsAssignOp[EGREATER] = 0; + IRO_IsAssignOp[ELESSEQU] = 0; + IRO_IsAssignOp[EGREATEREQU] = 0; + IRO_IsAssignOp[EEQU] = 0; + IRO_IsAssignOp[ENOTEQU] = 0; + IRO_IsAssignOp[EAND] = 0; + IRO_IsAssignOp[EXOR] = 0; + IRO_IsAssignOp[EOR] = 0; + IRO_IsAssignOp[ELAND] = 0; + IRO_IsAssignOp[ELOR] = 0; + IRO_IsAssignOp[EASS] = 1; + IRO_IsAssignOp[EMULASS] = 1; + IRO_IsAssignOp[EDIVASS] = 1; + IRO_IsAssignOp[EMODASS] = 1; + IRO_IsAssignOp[EADDASS] = 1; + IRO_IsAssignOp[ESUBASS] = 1; + IRO_IsAssignOp[ESHLASS] = 1; + IRO_IsAssignOp[ESHRASS] = 1; + IRO_IsAssignOp[EANDASS] = 1; + IRO_IsAssignOp[EXORASS] = 1; + IRO_IsAssignOp[EORASS] = 1; + IRO_IsAssignOp[ECOMMA] = 0; + IRO_IsAssignOp[EPMODULO] = 1; + IRO_IsAssignOp[EROTL] = 1; + IRO_IsAssignOp[EROTR] = 1; + IRO_IsAssignOp[EBCLR] = 1; + IRO_IsAssignOp[EBTST] = 1; + IRO_IsAssignOp[EBSET] = 1; + IRO_IsAssignOp[ETYPCON] = 0; + IRO_IsAssignOp[EBITFIELD] = 0; + IRO_IsAssignOp[EINTCONST] = 0; + IRO_IsAssignOp[EFLOATCONST] = 0; + IRO_IsAssignOp[ESTRINGCONST] = 0; + IRO_IsAssignOp[ECOND] = 0; + IRO_IsAssignOp[EFUNCCALL] = 0; + IRO_IsAssignOp[EFUNCCALLP] = 0; + IRO_IsAssignOp[EOBJREF] = 0; + IRO_IsAssignOp[EMFPOINTER] = 0; + IRO_IsAssignOp[ENULLCHECK] = 0; + IRO_IsAssignOp[EPRECOMP] = 0; + IRO_IsAssignOp[ETEMP] = 0; + IRO_IsAssignOp[EARGOBJ] = 0; + IRO_IsAssignOp[ELOCOBJ] = 0; + IRO_IsAssignOp[ELABEL] = 0; + IRO_IsAssignOp[ESETCONST] = 0; + IRO_IsAssignOp[ENEWEXCEPTION] = 0; + IRO_IsAssignOp[ENEWEXCEPTIONARRAY] = 0; + IRO_IsAssignOp[EOBJLIST] = 0; + IRO_IsAssignOp[EMEMBER] = 0; + IRO_IsAssignOp[ETEMPLDEP] = 0; + IRO_IsAssignOp[EINSTRUCTION] = 0; + IRO_IsAssignOp[EDEFINE] = 0; + IRO_IsAssignOp[EREUSE] = 0; + IRO_IsAssignOp[EASSBLK] = 0; + IRO_IsAssignOp[EVECTOR128CONST] = 0; + IRO_IsAssignOp[ECONDASS] = 1; +} + +VarRecord *IRO_FindVar(Object *object, Boolean flag1, Boolean flag2) { + VarRecord *var; + VarInfo *vi; + + var = object->varptr; + if (!var && flag1) { + vi = NULL; + if (object->datatype == DLOCAL) + vi = object->u.var.info; + if (vi) + vi->usage = 0; + var = oalloc(sizeof(VarRecord)); + var->object = object; + var->index = ++IRO_NumVars; + var->x6 = 0; + var->xA = 0; + var->next = NULL; + var->defs = NULL; + var->uses = NULL; + var->x1A = NULL; + var->x1E = NULL; + var->xB = 0; + if (IRO_FirstVar) + IRO_LastVar->next = var; + else + IRO_FirstVar = var; + IRO_LastVar = var; + object->varptr = var; + } + + if (var && !flag2) { + var->xB = 1; + if (object->datatype == DLOCAL && object->u.var.info && object->u.var.info->noregister == 0) + object->u.var.info->noregister = 2; + } + + return var; +} + +static void ResetVars(void) { + VarRecord *var; + + for (var = IRO_FirstVar; var; var = var->next) { + var->xB = 0; + if (var->object && var->object->datatype == DLOCAL && var->object->u.var.info) { + if (var->object->u.var.info->noregister == 2) + var->object->u.var.info->noregister = 0; + } + } +} + +static void IRO_HandleExceptionActions(IROLinear *linear) { + ExceptionAction *action; + + for (action = linear->stmt->dobjstack; action; action = action->prev) { + switch (action->type) { + case EAT_DESTROYLOCAL: + IRO_FindVar(action->data.destroy_local.local, 1, 0); + break; + case EAT_DESTROYLOCALCOND: + IRO_FindVar(action->data.destroy_local_cond.local, 1, 0); + break; + case EAT_DESTROYLOCALOFFSET: + IRO_FindVar(action->data.destroy_local_offset.local, 1, 0); + break; + case EAT_DESTROYLOCALARRAY: + IRO_FindVar(action->data.destroy_local_array.localarray, 1, 0); + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + IRO_FindVar(action->data.destroy_member.objectptr, 1, 0); + break; + case EAT_DESTROYMEMBERCOND: + IRO_FindVar(action->data.destroy_member_cond.objectptr, 1, 0); + break; + case EAT_DESTROYMEMBERARRAY: + IRO_FindVar(action->data.destroy_member_array.objectptr, 1, 0); + break; + case EAT_CATCHBLOCK: + if (action->data.catch_block.catch_object) + IRO_FindVar(action->data.catch_block.catch_object, 1, 0); + IRO_FindVar(action->data.catch_block.catch_info_object, 1, 0); + break; + case EAT_ACTIVECATCHBLOCK: + IRO_FindVar(action->data.active_catch_block.catch_info_object, 1, 0); + break; + } + } +} + +void IRO_FindAllVars(void) { + IROLinear *linear; + VarRecord *var; + + linear = IRO_FirstLinear; + IRO_NumVars = 0; + IRO_FirstVar = IRO_LastVar = NULL; + + while (linear) { + if (IS_LINEAR_ENODE(linear, EOBJREF)) { + if (Inline_IsObjectData(linear->u.node->data.objref) || linear->u.node->data.objref->datatype == DLOCAL) + IRO_FindVar(linear->u.node->data.objref, 1, (linear->flags & IROLF_Ind) != 0); + else + linear->u.node->data.objref->varptr = NULL; + } else if (linear->type == IROLinearFunccall) { + if (linear->stmt && IRO_FunctionCallMightThrowException(linear)) + IRO_HandleExceptionActions(linear); + } else if (linear->type == IROLinearAsm) { + IAEffects effects; + int i; + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) + IRO_FindVar(effects.operands[i].object, 1, effects.operands[i].type != IAEffect_3); + } + linear = linear->next; + } + + var = IRO_FirstVar; + Bv_AllocVector(&IRO_FuncKills, IRO_NumVars + 1); + Bv_SetBit(0, IRO_FuncKills); + while (var) { + if (Inline_IsObjectData(var->object) || var->xB) + Bv_SetBit(var->index, IRO_FuncKills); + var = var->next; + } + + IRO_CheckForUserBreak(); +} + +void IRO_ZapVarPtrs(void) { + VarRecord *var; + + for (var = IRO_FirstVar; var; var = var->next) + var->object->varptr = NULL; +} + +void IRO_UpdateVars(void) { + IROLinear *linear; + VarRecord *var; + + ResetVars(); + + for (linear = IRO_FirstLinear; linear; linear = linear->next) { + if (IS_LINEAR_ENODE(linear, EOBJREF)) { + if (Inline_IsObjectData(linear->u.node->data.objref) || linear->u.node->data.objref->datatype == DLOCAL) + IRO_FindVar(linear->u.node->data.objref, 0, (linear->flags & IROLF_Ind) || !(linear->flags & IROLF_Reffed)); + } else if (linear->type == IROLinearFunccall) { + if (linear->stmt && IRO_FunctionCallMightThrowException(linear)) + IRO_HandleExceptionActions(linear); + } else if (linear->type == IROLinearAsm) { + IAEffects effects; + int i; + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) + IRO_FindVar(effects.operands[i].object, 0, effects.operands[i].type != IAEffect_3); + } + } + + var = IRO_FirstVar; + Bv_AllocVector(&IRO_FuncKills, IRO_NumVars + 1); + Bv_SetBit(0, IRO_FuncKills); + while (var) { + if (Inline_IsObjectData(var->object) || var->xB) + Bv_SetBit(var->index, IRO_FuncKills); + var = var->next; + } +} + +void IRO_AddElmToList(IROLinear *linear, IROElmList **list) { + IROElmList *l = oalloc(sizeof(IROElmList)); + l->element = linear; + l->next = NULL; + if (!*list) { + *list = l; + } else { + l->next = *list; + *list = l; + } +} + +void IRO_DecomposeAddressExpression(IROLinear *linear, IROAddrRecord *rec) { + if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) { + IRO_DecomposeAddressExpression(linear->u.diadic.left, rec); + } else if (IS_LINEAR_ENODE(linear->u.diadic.left, EINTCONST)) { + rec->numInts++; + IRO_AddElmToList(linear->u.diadic.left, &rec->ints); + } else if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) { + rec->numObjRefs++; + IRO_AddElmToList(linear->u.diadic.left, &rec->objRefs); + } else { + rec->numMisc++; + IRO_AddElmToList(linear->u.diadic.left, &rec->misc); + } + + if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) { + IRO_DecomposeAddressExpression(linear->u.diadic.right, rec); + } else if (IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) { + rec->numInts++; + IRO_AddElmToList(linear->u.diadic.right, &rec->ints); + } else if (IS_LINEAR_ENODE(linear->u.diadic.right, EOBJREF)) { + rec->numObjRefs++; + IRO_AddElmToList(linear->u.diadic.right, &rec->objRefs); + } else { + rec->numMisc++; + IRO_AddElmToList(linear->u.diadic.right, &rec->misc); + } +} + +void IRO_DecomposeAddressExpression_Cheap(IROLinear *linear) { + if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) { + IRO_DecomposeAddressExpression_Cheap(linear->u.diadic.left); + } else if (!IS_LINEAR_ENODE(linear->u.diadic.left, EINTCONST)) { + if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) { + IRO_BaseTerms++; + TheBaseTerm = linear->u.diadic.left; + } else { + IRO_VarTerms++; + } + } + + if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) { + IRO_DecomposeAddressExpression_Cheap(linear->u.diadic.right); + } else if (!IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) { + if (IS_LINEAR_ENODE(linear->u.diadic.right, EOBJREF)) { + IRO_BaseTerms++; + TheBaseTerm = linear->u.diadic.right; + } else { + IRO_VarTerms++; + } + } +} + +VarRecord *IRO_FindAssigned(IROLinear *linear) { + VarRecord *rec; + + IRO_IsBitField = 0; + if (linear->type == IROLinearOp2Arg) { + linear = linear->u.diadic.left; + } else if (linear->type == IROLinearOp1Arg) { + linear = linear->u.monadic; + } else { +#line 818 + CError_FATAL(); + } + + if (IS_LINEAR_MONADIC(linear, EINDIRECT)) + linear = linear->u.monadic; + + if (IS_LINEAR_MONADIC(linear, EBITFIELD)) { + IRO_IsBitField = 1; + linear = linear->u.monadic; + } + + if (IS_LINEAR_DIADIC(linear, EADD)) { + if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF) && IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) { + linear = linear->u.diadic.left; + } else { + IRO_BaseTerms = 0; + IRO_DecomposeAddressExpression_Cheap(linear); + if (IRO_BaseTerms == 1) + linear = TheBaseTerm; + } + } + + if (!IS_LINEAR_ENODE(linear, EOBJREF)) + return NULL; + + if ((rec = IRO_FindVar(linear->u.node->data.objref, 0, 1))) + return rec; + else + return NULL; +} + +static void GetKillsByIndirectAssignment(IROLinear *linear) { + IROListNode *resultList; + IROLinear *nd; + IROListNode *list; + IROListNode *scan; + IROLinear *inner; + Boolean result; + Boolean foundLinear; + + result = 0; + + if (linear->type == IROLinearOp2Arg) + linear = linear->u.diadic.left; + else + linear = linear->u.monadic; + + if ( + linear && + linear->type == IROLinearOp1Arg && + linear->nodetype == EINDIRECT && + (inner = linear->u.monadic) && + copts.opt_pointer_analysis && + inner->pointsToFunction && + FunctionName + ) + { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundLinear = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundLinear = 1; + break; + } + } + if (!foundLinear) { + result = 1; + break; + } + } + + if (!result) { + while (list) { + for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + Object *obj; + VarRecord *var; + int index; + + obj = nd->u.node->data.objref; +#line 952 + CError_ASSERT(obj != NULL); + + var = IRO_FindVar(obj, 1, 1); +#line 954 + CError_ASSERT(var != NULL); + + index = var->index; +#line 956 + CError_ASSERT(index != 0); + + Bv_SetBit(index, IRO_VarKills); + } + } + + list = list->nextList; + } + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) + Bv_Or(IRO_FuncKills, IRO_VarKills); +} + +static void GetKillsByFunctionCall(IROLinear *linear) { + IROListNode *resultList; + IROLinear *nd; + IROListNode *list; + IROListNode *scan; + IROLinear *inner; + Boolean result; + Boolean foundLinear; + Object *obj; + ObjectList *killList; + ObjectList *olist; + + result = 0; + + if ( + (inner = linear->u.funccall.linear8) && + copts.opt_pointer_analysis && + inner->pointsToFunction && + FunctionName + ) + { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); + if (resultList) { + for (scan = resultList; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundLinear = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundLinear = 1; + obj = nd->u.node->data.objref; +#line 1028 + CError_ASSERT(obj != NULL); + + killList = NULL; + PointerAnalysis_GetFunctionKills(obj, linear, &killList); + + for (olist = killList; olist; olist = olist->next) { + if (!olist->object) { + result = 1; + break; + } + } + + while (killList) { + ObjectList *next = killList->next; + IRO_free(killList); + killList = next; + } + + if (result) + break; + } + } + + if (!foundLinear) + result = 1; + if (result) + break; + } + + if (!result) { + for (scan = resultList; scan; scan = scan->nextList) { + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + obj = nd->u.node->data.objref; + killList = NULL; + PointerAnalysis_GetFunctionKills(obj, linear, &killList); + + for (olist = killList; olist; olist = olist->next) { + VarRecord *var; + int index; + + var = IRO_FindVar(olist->object, 1, 1); +#line 1079 + CError_ASSERT(var != NULL); + + index = var->index; +#line 1081 + CError_ASSERT(index != 0); + + Bv_SetBit(index, IRO_VarKills); + } + + while (killList) { + ObjectList *next = killList->next; + IRO_free(killList); + killList = next; + } + } + } + } + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) + Bv_Or(IRO_FuncKills, IRO_VarKills); +} + +void IRO_GetKills(IROLinear *linear) { + VarRecord *var; + + switch (linear->type) { + case IROLinearOp1Arg: + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + IROLinear *assigned; + int index; + + var = IRO_FindAssigned(linear); + index = 0; + if (var) index = var->index; + Bv_SetBit(index, IRO_VarKills); + + if (!index) + GetKillsByIndirectAssignment(linear); + } + break; + case IROLinearFunccall: + GetKillsByFunctionCall(linear); + break; + case IROLinearAsm: { + IAEffects effects; + int i; + + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) { + switch (effects.operands[i].type) { + case IAEffect_1: + case IAEffect_2: + case IAEffect_4: + if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) + Bv_SetBit(var->index, IRO_VarKills); + break; + } + } + + if (effects.x1 || effects.x4) + Bv_Or(IRO_FuncKills, IRO_VarKills); + break; + } + } +} + +void IRO_CheckInit(void) { + IRONode *fnode; + IROLinear *nd; + VarRecord *var; + ObjectList *olist; + int flag; + int i; + BitVector *bv; + + IRO_MakeReachable(IRO_FirstNode); + fnode = IRO_FirstNode; + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + + while (fnode) { + Bv_AllocVector(&fnode->x16, IRO_NumVars + 1); + Bv_AllocVector(&fnode->x1E, IRO_NumVars + 1); + + for (nd = fnode->first; nd; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + if (nd->flags & IROLF_Ind) { + if (!(nd->flags & IROLF_Assigned) || (nd->flags & IROLF_Used)) { + if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 1))) { + if (!Bv_IsBitSet(var->index, fnode->x1E)) + Bv_SetBit(var->index, fnode->x16); + } + } + } else { + if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 0))) { + Bv_SetBit(var->index, fnode->x1E); + } + } + } else if (nd->type == IROLinearOp2Arg && nd->nodetype == EASS) { + if ((var = IRO_FindAssigned(nd))) + Bv_SetBit(var->index, fnode->x1E); + } else if (nd->type == IROLinearAsm) { + IAEffects effects; + + CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) { + var = IRO_FindVar(effects.operands[i].object, 0, 1); + switch (effects.operands[i].type) { + case IAEffect_1: + case IAEffect_2: + case IAEffect_4: + Bv_SetBit(var->index, fnode->x1E); + break; + } + } + } + + if (nd == fnode->last) + break; + } + + fnode = fnode->nextnode; + } + + Bv_AllocVector(&bv, IRO_NumVars + 1); + + do { + flag = 0; + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + Bv_Copy(fnode->x1E, bv); + for (i = 0; i < fnode->numpred; i++) + Bv_Or(IRO_NodeTable[fnode->pred[i]]->x1E, bv); + if (!Bv_Compare(bv, fnode->x1E)) { + Bv_Copy(bv, fnode->x1E); + flag = 1; + } + } + } while (flag); + + Bv_Clear(IRO_VarKills); + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (fnode->x36) { + Bv_Copy(fnode->x16, bv); + for (i = 0; i < fnode->numpred; i++) + Bv_Minus(IRO_NodeTable[fnode->pred[i]]->x1E, bv); + Bv_Or(bv, IRO_VarKills); + } + } + + for (olist = locals; olist; olist = olist->next) { + if ((var = IRO_FindVar(olist->object, 0, 1)) && Bv_IsBitSet(var->index, IRO_VarKills)) { + VarInfo *vi = olist->object->u.var.info; + if (!IsTempName(olist->object->name) && !is_volatile_object(olist->object)) { + if (!IS_TYPE_CLASS(olist->object->type) || !CClass_IsEmpty(TYPE_CLASS(olist->object->type))) { + CError_SetErrorToken(&vi->deftoken); + CError_Warning(CErrorStr185, olist->object->name->name); + } + } + } + } + + IRO_CheckForUserBreak(); +} + +static void RewriteIndDec(void) { + IROLinear *add; + IROLinear *indirect; + IROLinear *Int; + IROLinear *nd; + CInt64 value; + IROList list; + + for (nd = IRO_FirstLinear; nd; nd = nd->next) { + if ( + nd->type == IROLinearOp1Arg && + (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) && + !(nd->flags & IROLF_Reffed) + ) { + indirect = nd->u.monadic; + if ( + indirect->type == IROLinearOp1Arg && + indirect->nodetype == EINDIRECT && + indirect->u.monadic->type == IROLinearOp1Arg && + indirect->u.monadic->nodetype == EBITFIELD + ) { + value = IRO_GetSelfAssignmentVal(nd); + IRO_InitList(&list); + + nd->type = IROLinearOp2Arg; + nd->nodetype = EASS; + nd->u.diadic.left = indirect; + IRO_DuplicateExpr(indirect, &list); + + Int = IRO_NewIntConst(value, indirect->rtype); + Int->flags |= IROLF_Used | IROLF_Reffed; + + add = IRO_NewLinear(IROLinearOp2Arg); + add->nodetype = EADD; + add->u.diadic.left = list.tail; + add->u.diadic.left->flags = 0; + add->u.diadic.left->flags |= IROLF_Used | IROLF_Reffed; + add->u.diadic.right = Int; + add->rtype = indirect->rtype; + add->flags = 0; + add->flags |= IROLF_Used | IROLF_Reffed; + + nd->u.diadic.right = add; + + IRO_AddToList(Int, &list); + IRO_AddToList(add, &list); + IRO_PasteAfter(list.head, list.tail, indirect); + } + } + } +} + +void IRO_RewriteBitFieldTemps(void) { + IROLinear *nd; + IROLinear *expr2; + Object *obj; + VarRecord *var; + IROList list; + + for (nd = IRO_FirstLinear; nd; nd = nd->next) { + if ((obj = IRO_IsVariable(nd)) && (nd->flags & IROLF_BitfieldIndirect)) { + var = IRO_FindVar(obj, 0, 1); +#line 1526 + CError_ASSERT(var != NULL); + + expr2 = var->x1E; +#line 1532 + CError_ASSERT(expr2 != NULL); + + IRO_InitList(&list); + IRO_DuplicateExpr(expr2, &list); + IRO_NopOut(nd->u.monadic); + nd->u.monadic = list.tail; + IRO_Paste(list.head, list.tail, nd); + } + } +} + +static Boolean FunctionCallMightUseOrKillAnyAddressedVar(IROLinear *funccall) { + IROLinear *funcnd; + IROLinear *nd; + IROListNode *scan; + IROListNode *resultList; + ObjectList *olist; + ObjectList *killList; + VarRecord *var; + Boolean result; + Boolean foundObjRef; + Object *obj; + + result = 0; + + funcnd = funccall->u.funccall.linear8; + if (funcnd && copts.opt_pointer_analysis && funcnd->pointsToFunction && FunctionName) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, funcnd, &resultList); + + if (resultList) { + for (scan = resultList; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = nd->u.node->data.objref; +#line 1592 + CError_ASSERT(obj != NULL); + + killList = NULL; + PointerAnalysis_GetFunctionKills(obj, funccall, &killList); + for (olist = killList; olist; olist = olist->next) { + if (!olist->object) { + result = 1; + } else { + var = IRO_FindVar(olist->object, 1, 1); +#line 1604 + CError_ASSERT(var != NULL); + if (var->xB) + result = 1; + } + + if (result) + break; + } + + while (killList) { + ObjectList *next = killList->next; + IRO_free(killList); + killList = next; + } + + if (!result) { + killList = NULL; + PointerAnalysis_GetFunctionDependencies(obj, funccall, &killList); + for (olist = killList; olist; olist = olist->next) { + if (!olist->object) { + result = 1; + } else { + var = IRO_FindVar(olist->object, 1, 1); +#line 1632 + CError_ASSERT(var != NULL); + if (var->xB) + result = 1; + } + + if (result) + break; + } + + while (killList) { + ObjectList *next = killList->next; + IRO_free(killList); + killList = next; + } + } + + if (result) + break; + } + } + + if (!foundObjRef) + result = 1; + if (result) + break; + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + return result; +} + +static Boolean IndirectMightUseOrKillAnyAddressedVar(IROLinear *indirect) { + Boolean result; + IROLinear *inner; + IROLinear *nd; + IROListNode *scan; + IROListNode *resultList; + Boolean foundObjRef; + Object *obj; + VarRecord *var; + + result = 0; + + if ( + indirect && + indirect->type == IROLinearOp1Arg && + indirect->nodetype == EINDIRECT && + (inner = indirect->u.monadic) && + copts.opt_pointer_analysis && + inner->pointsToFunction && + FunctionName + ) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); + if (resultList) { + for (scan = resultList; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = nd->u.node->data.objref; +#line 1723 + CError_ASSERT(obj != NULL); + var = IRO_FindVar(obj, 1, 1); +#line 1725 + CError_ASSERT(var != NULL); + + if (var->xB) + result = 1; + } + } + + if (!foundObjRef) + result = 1; + if (result) + break; + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + return result; +} + +void IRO_ScalarizeClassDataMembers(void) { + IROLinear *nd; + VarRecord *var; + Boolean flag; + Object *obj; + IndirectRecord *irec; + IndirectRecordMatch *match; + IROLinear *tmp; + + nd = IRO_FirstLinear; + IRO_FirstIndirectRecord = NULL; + IRO_LastIndirectRecord = NULL; + RewriteIndDec(); + IRO_DumpAfterPhase("RewriteIndDec", 0); + flag = 0; + + while (nd) { + if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT) { + CheckAddress(nd, &flag); + } + if (nd->type == IROLinearAsm) { + IAEffects effects; + int i; + CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) { + if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) { + CheckAddressConsistency(nd, var, -1, &stvoid); + } else { +#line 1823 + CError_FATAL(); + } + } + } + if (nd->type == IROLinearFunccall && !flag) + flag = FunctionCallMightUseOrKillAnyAddressedVar(nd); + + nd = nd->next; + } + + if (flag) + DisableAddressedEntries(); + + for (irec = IRO_FirstIndirectRecord; irec; irec = irec->next) { + if (!(irec->flags & 1)) { + IROList list1; + IROList list2; + + obj = create_temp_object(irec->type); + var = IRO_FindVar(obj, 1, 1); + for (match = irec->matches; match; match = match->otherMatches) { + IRO_InitList(&list1); + IRO_InitList(&list2); + IRO_DuplicateExpr(match->nd, &list1); + IRO_DuplicateExpr(match->nd, &list2); + if (match->nd->type == IROLinearOperand && match->nd->u.node->type == EOBJREF) { + tmp = IRO_LocateFather(match->nd); + if (irec->flags & 2) { + tmp->flags |= IROLF_BitfieldIndirect; + var->x1A = match->nd->rtype; + var->x1E = list2.tail; + } + match->nd->u.node = create_objectrefnode(obj); + irec->x26 = list2.tail; + } else { + tmp = IRO_LocateFather(match->nd); + if (irec->flags & 2) { + tmp->flags |= IROLF_BitfieldIndirect; + var->x1A = match->nd->rtype; + var->x1E = list2.tail; + } + irec->x26 = list2.tail; + + IRO_NopOut(tmp->u.monadic); + tmp->u.monadic = IRO_NewLinear(IROLinearOperand); + tmp->u.monadic->u.node = create_objectrefnode(obj); + tmp->u.monadic->rtype = match->nd->rtype; + tmp->u.monadic->index = ++IRO_NumLinear; + tmp->u.monadic->flags |= IROLF_Ind | IROLF_Reffed; + IRO_NopOut(match->nd); + IRO_PasteAfter(tmp->u.monadic, tmp->u.monadic, match->nd); + } + } + + if (ObjectIsArg(irec->var->object)) { + IROLinear *op1; + IROLinear *op2; + IROLinear *op3; + IROLinear *op4; + IROLinear *op5; + + op1 = IRO_NewLinear(IROLinearOperand); + op1->u.node = create_objectrefnode(obj); + op1->rtype = op1->u.node->data.objref->type; + op1->index = ++IRO_NumLinear; + op1->flags |= IROLF_Ind | IROLF_Assigned; + + op2 = list1.tail; + + op3 = IRO_NewLinear(IROLinearOp1Arg); + op3->nodetype = EINDIRECT; + op3->rtype = irec->type; + op3->u.monadic = op1; + op3->index = ++IRO_NumLinear; + op3->flags |= IROLF_Assigned; + + op4 = IRO_NewLinear(IROLinearOp1Arg); + op4->nodetype = EINDIRECT; + op4->rtype = irec->type; + op4->u.monadic = op2; + op4->index = ++IRO_NumLinear; + op4->flags |= IROLF_Reffed; + + op5 = IRO_NewLinear(IROLinearOp2Arg); + op5->nodetype = EASS; + op5->u.diadic.left = op3; + op5->u.diadic.right = op4; + op5->rtype = irec->type; + op5->index = ++IRO_NumLinear; + + op2->next = op4; + op4->next = op1; + op1->next = op3; + op3->next = op5; + + IRO_PasteAfter(list1.head, op5, IRO_FirstLinear); + } + } + } + + IRO_CheckForUserBreak(); +} + +static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag) { + IROLinear *inner; + VarRecord *var; + Boolean result; + + inner = nd->u.monadic; + if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) + inner = inner->u.monadic; + + result = 0; + + if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF) { + if (IS_TYPE_CLASS(inner->u.node->data.objref->type) || IS_TYPE_STRUCT(inner->u.node->data.objref->type) || + IS_TYPE_ARRAY(inner->u.node->data.objref->type)) { + if (inner->u.node->data.objref->datatype == DLOCAL) { + var = IRO_FindVar(inner->u.node->data.objref, 0, 1); +#line 2240 + CError_ASSERT(var != NULL); + CheckAddressConsistency(nd, var, 0, nd->rtype); + result = 1; + } + } + } else if ( + inner->type == IROLinearOp2Arg && + inner->nodetype == EADD && + inner->u.diadic.left->type == IROLinearOperand && + inner->u.diadic.left->u.node->type == EOBJREF) { + if ( + inner->u.diadic.right->type == IROLinearOperand && + inner->u.diadic.right->u.node->type == EINTCONST && + inner->u.diadic.right->u.node->data.intval.hi == 0) { + if ( + IS_TYPE_CLASS(inner->u.diadic.left->u.node->data.objref->type) || + IS_TYPE_STRUCT(inner->u.diadic.left->u.node->data.objref->type) || + IS_TYPE_ARRAY(inner->u.diadic.left->u.node->data.objref->type) + ) { + if (inner->u.diadic.left->u.node->data.objref->datatype == DLOCAL) { + var = IRO_FindVar(inner->u.diadic.left->u.node->data.objref, 0, 1); +#line 2267 + CError_ASSERT(var != NULL); + CheckAddressConsistency(nd, var, inner->u.diadic.right->u.node->data.intval.lo, nd->rtype); + result = 1; + } + } + } else { + if ( + IS_TYPE_CLASS(inner->u.diadic.left->u.node->data.objref->type) || + IS_TYPE_STRUCT(inner->u.diadic.left->u.node->data.objref->type) || + IS_TYPE_ARRAY(inner->u.diadic.left->u.node->data.objref->type) + ) { + if (inner->u.diadic.left->u.node->data.objref->datatype == DLOCAL) { + var = IRO_FindVar(inner->u.diadic.left->u.node->data.objref, 0, 1); + CheckAddressConsistency(nd, var, -1, nd->rtype); + result = 1; + } + } + } + } + + if (!result && !*resultFlag) { + *resultFlag = IndirectMightUseOrKillAnyAddressedVar(nd); + } + + return 0; +} + +static Boolean CheckAddressConsistency(IROLinear *nd, VarRecord *var, SInt32 addend, Type *type) { + IndirectRecord *rp; + IndirectRecordMatch *match; + UInt32 flag; + IROLinear *inner; + UInt32 start_bit; + UInt32 end_bit; + + flag = 0; + inner = nd->u.monadic; + if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) { + start_bit = TYPE_BITFIELD(inner->rtype)->unkA + 8 * addend; + end_bit = start_bit + TYPE_BITFIELD(inner->rtype)->unkB - 1; + } else { + start_bit = 8 * addend; + end_bit = start_bit + 8 * type->size - 1; + } + + if (var->xB && !copts.opt_pointer_analysis) + return 0; + + if (nd->rtype && CParser_IsVolatile(nd->rtype, nd->nodeflags & ENODE_FLAG_QUALS)) + addend = -1; + if (is_volatile_object(var->object)) + addend = -1; + + for (rp = IRO_FirstIndirectRecord; rp; rp = rp->next) { + if (rp->var->index == var->index) { + if (rp->flags & 1) + return 0; + + if (addend == -1) { + flag = 1; + break; + } + + if (IRO_TypesEqual(rp->type, type) && rp->startbit == start_bit && rp->endbit == end_bit) { + match = oalloc(sizeof(IndirectRecordMatch)); + match->nd = inner; + match->otherMatches = NULL; + if (!rp->matches) { + rp->matches = match; + } else { + match->otherMatches = rp->matches; + rp->matches = match; + } + + IRO_Dump("Exact Match of Type and bits at %d and %d\n", rp->linear->index, nd->index); + IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); + return 1; + } + + if (rp->startbit == start_bit && rp->endbit == end_bit && !IRO_TypesEqual(rp->type, type)) { + IRO_Dump("match on bits but mismatch on type %d and %d\n", rp->linear->index, nd->index); + IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); + flag = 1; + break; + } + + if (rp->startbit >= start_bit && end_bit >= rp->startbit) { + IRO_Dump("Overlap detected --1 %d and %d\n", rp->linear->index, nd->index); + IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); + flag = 1; + break; + } + + if (rp->startbit < start_bit && rp->endbit >= start_bit) { + IRO_Dump("Overlap detected --2 %d and %d\n", rp->linear->index, nd->index); + IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); + flag = 1; + break; + } + } + } + + if (flag) { + DisableEntries(rp); + if (addend >= 0) + return 0; + } + + IRO_Dump("Create Entry at %d\n", nd->index); + IRO_Dump("start_bit=%d,end_bit=%d\n", start_bit, end_bit); + + rp = oalloc(sizeof(IndirectRecord)); + rp->linear = nd; + rp->flags = 0; + rp->var = var; + rp->addend = addend; + rp->size = type->size; + rp->type = type; + rp->next = NULL; + rp->matches = oalloc(sizeof(IndirectRecordMatch)); + rp->matches->nd = inner; + rp->matches->otherMatches = NULL; + rp->startbit = start_bit; + rp->endbit = end_bit; + + if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && + nd->u.monadic->type == IROLinearOp1Arg && nd->u.monadic->nodetype == EBITFIELD) + rp->flags |= 2; + + if (!(IS_TYPE_FLOAT(type) || IS_TYPE_INT(type) || IS_TYPE_POINTER_ONLY(type)) || + addend == -1 || ((inner->flags & IROLF_4000) && ObjectIsArg(var->object))) + rp->flags |= 1; + + if (IRO_FirstIndirectRecord) + IRO_LastIndirectRecord->next = rp; + else + IRO_FirstIndirectRecord = rp; + IRO_LastIndirectRecord = rp; + return 1; +} + +static void DisableEntries(IndirectRecord *irec) { + IndirectRecord *scan; + + for (scan = IRO_FirstIndirectRecord; scan; scan = scan->next) { + if (irec->var->index == scan->var->index) + scan->flags |= 1; + } +} + +static void DisableAddressedEntries(void) { + IndirectRecord *scan; + + for (scan = IRO_FirstIndirectRecord; scan; scan = scan->next) { + if (scan->var->xB) + scan->flags |= 1; + } +} + +static UInt32 ObjectIsArg(Object *obj) { + ObjectList *scan; + + for (scan = arguments; scan; scan = scan->next) { + if (scan->object == obj) + return 1; + } + + return 0; +} + diff --git a/compiler_and_linker/unsorted/LiveInfo.c b/compiler_and_linker/unsorted/LiveInfo.c new file mode 100644 index 0000000..779efed --- /dev/null +++ b/compiler_and_linker/unsorted/LiveInfo.c @@ -0,0 +1,167 @@ +#include "compiler/LiveInfo.h" +#include "compiler/BitVectors.h" +#include "compiler/Coloring.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/Registers.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "compiler/CParser.h" + +LiveInfo *liveinfo; + +static void allocateliveinfo(void) { + UInt32 regs; + LiveInfo *info; + int i; + + regs = used_virtual_registers[coloring_class]; + + liveinfo = oalloc(sizeof(LiveInfo) * pcblockcount); + for (i = 0, info = liveinfo; i < pcblockcount; i++, info++) { + bitvectorinitialize(info->vec0 = oalloc(4 * ((regs + 31) >> 5)), regs, 0); + bitvectorinitialize(info->vec4 = oalloc(4 * ((regs + 31) >> 5)), regs, 0); + bitvectorinitialize(info->vec8 = oalloc(4 * ((regs + 31) >> 5)), regs, 0); + bitvectorinitialize(info->vecC = oalloc(4 * ((regs + 31) >> 5)), regs, 0); + } +} + +static void computelocalusedef(void) { + LiveInfo *info; + PCodeBlock *block; + PCode *instr; + UInt32 *vec0; + UInt32 *vec4; + PCodeArg *op; + int i; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + info = &liveinfo[block->blockIndex]; + vec0 = info->vec0; + vec4 = info->vec4; + + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + (char) op->arg == coloring_class && + (op->data.reg.effect & EffectRead) && + !bitvectorgetbit(op->data.reg.reg, vec4) + ) + bitvectorsetbit(op->data.reg.reg, vec0); + op++; + } + + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + (char) op->arg == coloring_class && + (op->data.reg.effect & EffectWrite) && + !bitvectorgetbit(op->data.reg.reg, vec0) + ) + bitvectorsetbit(op->data.reg.reg, vec4); + op++; + } + } + } +} + +static void computeglobalinout(void) { + UInt32 regs; + LiveInfo *info; + UInt32 *vec0; + UInt32 *vec4; + UInt32 *vec8; + UInt32 *vecC; + int bitvecsize; + int blockIndex; + int i; + int flag; + PCodeBlock *block; + PCLink *link; + UInt32 val; + + regs = used_virtual_registers[coloring_class]; + bitvecsize = (regs + 31) >> 5; + flag = 1; + while (flag) { + flag = 0; + blockIndex = pcblockcount; + while (blockIndex) { + if ((block = depthfirstordering[--blockIndex])) { + info = &liveinfo[block->blockIndex]; + if ((link = block->successors)) { + vecC = info->vecC; + bitvectorcopy(vecC, liveinfo[link->block->blockIndex].vec8, regs); + for (link = link->nextLink; link; link = link->nextLink) + bitvectorunion(vecC, liveinfo[link->block->blockIndex].vec8, regs); + } + + vecC = info->vecC; + vec8 = info->vec8; + vec0 = info->vec0; + vec4 = info->vec4; + for (i = 0; i < bitvecsize; i++) { + val = *vec0 | (*vecC & ~*vec4); + if (val != *vec8) { + *vec8 = val; + flag = 1; + } + vec8++; + vecC++; + vec0++; + vec4++; + } + } + } + } +} + +void computelivevariables(Object *proc) { + Type *returnType; + + returnType = TYPE_FUNC(proc->type)->functype; + computedepthfirstordering(); + allocateliveinfo(); + computelocalusedef(); + + if (coloring_class == RegClass_GPR && TYPE_FITS_IN_REGISTER(returnType)) { + bitvectorsetbit(3, liveinfo[epilogue->blockIndex].vec0); + if (TYPE_IS_8BYTES(returnType)) + bitvectorsetbit(4, liveinfo[pclastblock->blockIndex].vec0); + } else if (coloring_class == RegClass_FPR && IS_TYPE_FLOAT(returnType)) { + bitvectorsetbit(1, liveinfo[epilogue->blockIndex].vec0); + } else if (coloring_class == RegClass_VR && IS_TYPE_VECTOR(returnType)) { + bitvectorsetbit(2, liveinfo[epilogue->blockIndex].vec0); + } + + computeglobalinout(); +} + +int dead(PCode *instr, char rclass, UInt32 *vec) { + int i; + PCodeArg *op; + + if (instr->flags & (fPCodeFlag1 | fPCodeFlag4 | fPCodeFlag8 | fIsVolatile | fSideEffects)) + return 0; + if (instr->block->flags & (fPCBlockFlag1 | fPCBlockFlag2)) + return 0; + + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + (op->data.reg.effect & EffectWrite) && + (rclass != (char) op->arg || bitvectorgetbit(op->data.reg.reg, vec)) + ) + return 0; + op++; + } + + return copts.optimizationlevel > 0; +} diff --git a/compiler_and_linker/unsorted/LoadDeletion.c b/compiler_and_linker/unsorted/LoadDeletion.c index e69de29..316e8c2 100644 --- a/compiler_and_linker/unsorted/LoadDeletion.c +++ b/compiler_and_linker/unsorted/LoadDeletion.c @@ -0,0 +1,46 @@ +#include "compiler/LoadDeletion.h" +#include "compiler/CopyPropagation.h" +#include "compiler/CParser.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" + +int deletedloads; + +static int is_load(PCode *instr) { + return + (instr->op == PC_LI || instr->op == PC_VSPLTISB || instr->op == PC_VSPLTISH || instr->op == PC_VSPLTISW) + && + instr->args[0].data.reg.reg >= n_real_registers[(char) instr->args[0].arg]; +} + +static int loadpropagatestouse(int candidateID, int useID) { + return 0; +} + +static void deleteload(int id) { + Candidate *candidate; + + candidate = Candidates + id; + if (candidate->list || (candidate->pcode->flags & fSideEffects)) + return; + if (candidate->pcode->args[0].data.reg.reg < n_real_registers[(char) candidate->pcode->args[0].arg]) + return; + + deletepcode(candidate->pcode); + deletedloads = 1; +} + +static Propagation load_immediate_prop = { + &is_load, + &loadpropagatestouse, + &deleteload, + "LOAD IMMEDIATE", + "LOAD_IMMEDIATES", + "l%ld", + 0 +}; + +void deletedeadloads(Object *proc) { + propagateinstructions(proc, &load_immediate_prop, (copts.optimizationlevel >= 4) ? 4 : 1, 0); + deletedloads = propagated_instructions; +} diff --git a/compiler_and_linker/unsorted/LoopDetection.c b/compiler_and_linker/unsorted/LoopDetection.c index e69de29..54bc180 100644 --- a/compiler_and_linker/unsorted/LoopDetection.c +++ b/compiler_and_linker/unsorted/LoopDetection.c @@ -0,0 +1,889 @@ +#include "compiler/LoopDetection.h" +#include "compiler/CFunc.h" +#include "compiler/PCode.h" +#include "compiler/TOC.h" +#include "compiler/UseDefChains.h" +#include "compiler/CompilerTools.h" +#include "compiler/BitVectors.h" +#include "compiler/enode.h" +#include "compiler/objects.h" + +Loop *loopsinflowgraph; +int loopdetection_nblocks; +static UInt32 **dominators; +static BlockList *loopheaders; +static int nloopheaders; +static PCodeBlock **loopstack; +BitVector *LoopTemp; +void *LoopList_First; + +static void computedominators(void) { + int i; + PCodeBlock *block; + int blockCount; + int flag; + UInt32 *myvec; + PCLink *link; + + blockCount = pcblockcount; + flag = 1; + + dominators = oalloc(sizeof(UInt32 *) * pcblockcount); + for (i = 0; i < pcblockcount; i++) + dominators[i] = oalloc(4 * ((blockCount + 31) >> 5)); + + myvec = oalloc(4 * ((blockCount + 31) >> 5)); + + bitvectorinitialize(dominators[pcbasicblocks->blockIndex], blockCount, 0); + //dominators[pcbasicblocks->blockIndex][0] |= 1; + bitvectorsetbit(0, dominators[pcbasicblocks->blockIndex]); + + for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) + bitvectorinitialize(dominators[block->blockIndex], blockCount, 0xFFFFFFFF); + + computedepthfirstordering(); + + while (flag) { + flag = 0; + for (i = 0; i < pcblockcount; i++) { + block = depthfirstordering[i]; + if (block && block->blockIndex != pcbasicblocks->blockIndex) { + bitvectorcopy(myvec, dominators[block->predecessors->block->blockIndex], blockCount); + for (link = block->predecessors->nextLink; link; link = link->nextLink) + bitvectorintersect(myvec, dominators[link->block->blockIndex], blockCount); + //myvec[block->blockIndex >> 5] |= 1 << (block->blockIndex & 31); + bitvectorsetbit(block->blockIndex, myvec); + + if (bitvectorchanged(dominators[block->blockIndex], myvec, blockCount)) + flag = 1; + } + } + } +} + +static BlockList *findloopheaders(void) { + PCodeBlock *block; + PCLink *link; + BlockList *list; + + loopheaders = NULL; + nloopheaders = 0; + + for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) { + for (link = block->predecessors; link; link = link->nextLink) { + //if ((1 << (block->blockIndex & 31)) & dominators[link->block->blockIndex][block->blockIndex >> 5]) + if (bitvectorgetbit(block->blockIndex, dominators[link->block->blockIndex])) + break; + } + + if (link) { + list = oalloc(sizeof(BlockList)); + list->block = block; + list->next = loopheaders; + loopheaders = list; + nloopheaders++; + } + } + + return loopheaders; +} + +void addblocktoloop(Loop *loop, PCodeBlock *block) { + BlockList *list = lalloc(sizeof(BlockList)); + + //loop->memberblocks[block->blockIndex >> 5] |= 1 << (block->blockIndex & 31); + bitvectorsetbit(block->blockIndex, loop->memberblocks); + + list->block = block; + list->next = loop->blocks; + loop->blocks = list; +} + +static void findnaturalloop(Loop *loop) { + BlockList *list; + BlockList *list2; + PCLink *link; + PCodeBlock *block; + int i; + + i = 0; + addblocktoloop(loop, loop->body); + for (link = loop->body->predecessors; link; link = link->nextLink) { + if (bitvectorgetbit(loop->body->blockIndex, dominators[link->block->blockIndex]) && link->block != loop->body) { + addblocktoloop(loop, link->block); + loopstack[i++] = link->block; + } + } + + while (i) { + link = loopstack[--i]->predecessors; + while (link) { + if (!bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) { + addblocktoloop(loop, link->block); + loopstack[i++] = link->block; + } + link = link->nextLink; + } + } + + for (list = loop->blocks; list; list = list->next) { + block = list->block; + for (link = block->successors; link; link = link->nextLink) { + if (!bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) { + bitvectorsetbit(block->blockIndex, loop->vec24); + break; + } + } + } + + for (list = loop->blocks; list; list = list->next) { + for (list2 = loop->blocks; list2; list2 = list2->next) { + if (bitvectorgetbit(list2->block->blockIndex, loop->vec24) && + !bitvectorgetbit(list->block->blockIndex, dominators[list2->block->blockIndex])) + break; + } + + if (!list2) + bitvectorsetbit(list->block->blockIndex, loop->vec28); + } + + for (list = loop->blocks; list; list = list->next) { + for (link = loop->body->predecessors; link; link = link->nextLink) { + if (bitvectorgetbit(link->block->blockIndex, loop->memberblocks) && + !bitvectorgetbit(list->block->blockIndex, dominators[link->block->blockIndex])) + break; + } + + if (!link) + bitvectorsetbit(list->block->blockIndex, loop->vec2C); + } +} + +static void addlooptolist(Loop *loop, Loop **list) { + Loop **scan; + Loop *scanloop; + + scan = list; + while ((scanloop = *scan)) { + if (bitvectorgetbit(loop->body->blockIndex, scanloop->memberblocks)) { + loop->parent = scanloop; + addlooptolist(loop, &scanloop->children); + return; + } + + if (bitvectorgetbit(scanloop->body->blockIndex, loop->memberblocks)) { + *scan = scanloop->nextSibling; + scanloop->parent = loop; + scanloop->nextSibling = loop->children; + loop->children = scanloop; + } else { + scan = &scanloop->nextSibling; + } + } + + loop->nextSibling = *list; + *list = loop; +} + +static void findnaturalloops(void) { + Loop *loop; + int size; + + loopdetection_nblocks = pcblockcount + 5 * nloopheaders; + loopstack = oalloc(sizeof(PCodeBlock *) * pcblockcount); + while (loopheaders) { + loop = lalloc(sizeof(Loop)); + loop->parent = loop->nextSibling = loop->children = NULL; + loop->body = loopheaders->block; + loop->preheader = NULL; + loop->blocks = NULL; + loop->basicInductionVars = NULL; + loop->footer = NULL; + loop->pc18 = NULL; + loop->loopWeight = loop->body->loopWeight; + + bitvectorinitialize(loop->memberblocks = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(loop->vec24 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(loop->vec28 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(loop->vec2C = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + + findnaturalloop(loop); + addlooptolist(loop, &loopsinflowgraph); + + loopheaders = loopheaders->next; + } +} + +static PCodeBlock *makepreheaderblock(void) { + PCodeLabel *label; + PCodeBlock *block; + + label = makepclabel(); + block = lalloc(sizeof(PCodeBlock)); + block->nextBlock = NULL; + block->prevBlock = NULL; + block->labels = NULL; + block->successors = NULL; + block->predecessors = NULL; + block->firstPCode = block->lastPCode = NULL; + block->pcodeCount = 0; + block->flags = 0; + block->blockIndex = pcblockcount++; + pclabel(block, label); + return block; +} + +static void insertpreheaderbefore(PCodeBlock *a, PCodeBlock *b) { + a->nextBlock = b; + a->prevBlock = b->prevBlock; + b->prevBlock->nextBlock = a; + b->prevBlock = a; +} + +void insertpreheaderblock(Loop *loop) { + PCodeBlock *preheader; + PCodeBlock *block29; + PCodeBlock *block28; + PCode *pcode27; + PCLink *link; // r26 + PCLink **linkptr; // r25 + PCodeLabel *newlabel; // r23 + PCLink *innerlink; + PCodeBlock *block; + PCodeArg *arg; + int i; + + preheader = loop->preheader = makepreheaderblock(); + block29 = NULL; + block28 = loop->body; + + if (!block28->labels) + pclabel(block28, makepclabel()); + + appendpcode(preheader, makepcode(PC_B, block28->labels)); + preheader->loopWeight = loop->parent ? loop->parent->loopWeight : 1; + + linkptr = &block28->predecessors; + while ((link = *linkptr)) { + if (bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) { + linkptr = &link->nextLink; + } else { + if (link->block->pcodeCount) { + pcode27 = link->block->lastPCode; + if (pcode27->op == PC_B) { +#line 462 + CError_ASSERT(pcode27->args[0].kind == PCOp_LABEL); + if (pcode27->args[0].data.label.label->block == block28) + pcode27->args[0].data.label.label = preheader->labels; + } else if (pcode27->op == PC_BT || pcode27->op == PC_BF) { +#line 474 + CError_ASSERT(pcode27->args[2].kind == PCOp_LABEL); + if (pcode27->args[2].data.label.label->block == block28) + pcode27->args[2].data.label.label = preheader->labels; + } else if (pcode27->op == PC_BCTR) { + if (pcode27->argCount > 1 && pcode27->args[1].kind == PCOp_MEMORY) { + Object *obj = pcode27->args[1].data.mem.obj; + PCodeLabel **array = (PCodeLabel **) obj->u.data.u.switchtable.data; + int i; + for (i = 0; i < obj->u.data.u.switchtable.size; i++) { + if (array[i]->block == block28) + array[i] = preheader->labels; + } + } else { + CodeLabelList *cll; + for (cll = codelabellist; cll; cll = cll->next) { + if (cll->label->pclabel->block == block28) + cll->label->pclabel = preheader->labels; + } + } + } else { +#line 505 + CError_ASSERT(link->block->nextBlock == block28); + } + } + + for (innerlink = link->block->successors; innerlink; innerlink = innerlink->nextLink) { + if (innerlink->block == block28) + innerlink->block = preheader; + } + + *linkptr = link->nextLink;; + link->nextLink = preheader->predecessors; + preheader->predecessors = link; + } + } + + if (!bitvectorgetbit(block28->prevBlock->blockIndex, loop->memberblocks)) { + insertpreheaderbefore(preheader, block28); + + if ( + (!block28->nextBlock || !bitvectorgetbit(block28->nextBlock->blockIndex, loop->memberblocks)) && + block28->lastPCode && + (block28->lastPCode->flags & fPCodeFlag1) && + block28->lastPCode->op != PC_BDNZ + ) { + i = block28->lastPCode->argCount; + arg = block28->lastPCode->args; + while (i && arg->kind != PCOp_LABEL) { + arg++; + i--; + } + + if (i && arg->kind == PCOp_LABEL && arg->data.label.label->block == block28) { + block29 = makepreheaderblock(); + insertpreheaderbefore(block29, block28); + newlabel = makepclabel(); + pclabel(block29, newlabel); + arg->data.label.label = newlabel; + + link = lalloc(sizeof(PCLink)); + link->block = block28; + link->nextLink = block29->predecessors; + block29->predecessors = link; + + link = lalloc(sizeof(PCLink)); + link->block = block28; + link->nextLink = block29->successors; + block29->successors = link; + + for (link = block28->successors; link; link = link->nextLink) { + if (link->block == block28) + link->block = block29; + } + for (link = block28->predecessors; link; link = link->nextLink) { + if (link->block == block28) + link->block = block29; + } + + bitvectorsetbit(block29->blockIndex, loop->vec2C); + addblocktoloop(loop, block29); + } + } + } else { + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (bitvectorgetbit(block->blockIndex, loop->memberblocks)) + break; + } + insertpreheaderbefore(preheader, block); + } + + link = lalloc(sizeof(PCLink)); + link->block = preheader; + link->nextLink = block28->predecessors; + block28->predecessors = link; + + link = lalloc(sizeof(PCLink)); + link->block = block28; + link->nextLink = preheader->successors; + preheader->successors = link; + + for (loop = loop->parent; loop; loop = loop->parent) { + addblocktoloop(loop, preheader); + if (bitvectorgetbit(block28->blockIndex, loop->vec28)) { + bitvectorsetbit(preheader->blockIndex, loop->vec28); + if (block29) + bitvectorsetbit(block29->blockIndex, loop->vec28); + } + if (bitvectorgetbit(block28->blockIndex, loop->vec2C)) { + bitvectorsetbit(preheader->blockIndex, loop->vec2C); + if (block29) + bitvectorsetbit(block29->blockIndex, loop->vec2C); + } + } +} + +static void insertpreheaderblocks(Loop *loop) { + while (loop) { + if (loop->children) + insertpreheaderblocks(loop->children); + insertpreheaderblock(loop); + loop = loop->nextSibling; + } +} + +void findloopsinflowgraph(void) { + loopsinflowgraph = NULL; + computedominators(); + if (findloopheaders()) { + findnaturalloops(); + insertpreheaderblocks(loopsinflowgraph); + } + freeoheap(); +} + +static int checklooplimits(SInt32 opcode, SInt32 condition, SInt32 c, SInt32 d, SInt32 addend, SInt32 *result) { + if (opcode == PC_BT) { + if (condition == 0) { + if (addend <= 0) + return 0; + if (c < d) + *result = (d - c + addend - 1) / addend; + else + *result = 0; + } else if (condition == 1) { + if (addend >= 0) + return 0; + if (c > d) + *result = (c - d - addend - 1) / -addend; + else + *result = 0; + } else { + return 0; + } + } else { + if (condition == 0) { + if (addend >= 0) + return 0; + if (c >= d) + *result = (c - d - addend) / -addend; + else + *result = 0; + } else if (condition == 1) { + if (addend <= 0) + return 0; + if (c <= d) + *result = (d - c + addend) / addend; + else + *result = 0; + } else if (c < d) { + if (addend <= 0) + return 0; + if ((d - c) % addend) + return 0; + *result = (d - c) / addend; + } else if (c > d) { + if (addend >= 0) + return 0; + if ((c - d) % -addend) + return 0; + *result = (c - d) / -addend; + } else { + *result = 0; + } + } + + return 1; +} + +static int checkunsignedlooplimits(SInt32 opcode, SInt32 condition, UInt32 c, UInt32 d, SInt32 addend, UInt32 *result) { + if (opcode == PC_BT) { + if (condition == 0) { + if (addend <= 0) + return 0; + if (c < d) + *result = (d - c + addend - 1) / addend; + else + *result = 0; + } else if (condition == 1) { + if (addend >= 0) + return 0; + if (c > d) + *result = (c - d - addend - 1) / -addend; + else + *result = 0; + } else { + return 0; + } + } else { + if (condition == 0) { + if (addend >= 0) + return 0; + if (c >= d) + *result = (c - d - addend) / -addend; + else + *result = 0; + } else if (condition == 1) { + if (addend <= 0) + return 0; + if (c <= d) + *result = (d - c + addend) / addend; + else + *result = 0; + } else if (c < d) { + if (addend <= 0) + return 0; + if ((d - c) % addend) + return 0; + *result = (d - c) / addend; + } else if (c > d) { + if (addend >= 0) + return 0; + if ((c - d) % -addend) + return 0; + *result = (c - d) / -addend; + } else { + *result = 0; + } + } + + return (*result & 0x80000000) == 0; +} + +static int checkunknownloop(int a, int b, int c, unsigned char *op) { + if (a == PC_BT) { + if (b == 0) { + if (c <= 0) + return 0; + *op = ELESS; + } else if (b == 1) { + if (c >= 0) + return 0; + *op = EGREATER; + } else { + return 0; + } + } else { + if (b == 0) { + if (c >= 0) + return 0; + *op = EGREATEREQU; + } else if (b == 1) { + if (c <= 0) + return 0; + *op = ELESSEQU; + } else if (c == 1) { + *op = ENOTEQU; + } else if (c == -1) { + *op = ENOTEQU; + } else { + return 0; + } + } + + return 1; +} + +static void checkcountingloop(Loop *loop) { + RegUseOrDef *list; + PCode *lastpcode; + PCode *prevpcode; + PCode *pc8; + PCode *check; + short op12; + short reg11; + SInt16 reg4; + short reg11b; + Loop *child; + + if (!(lastpcode = loop->body->lastPCode)) + return; + if (lastpcode->op != PC_BT && lastpcode->op != PC_BF) + return; + if (lastpcode->args[2].kind != PCOp_LABEL) + return; + + if (!bitvectorgetbit(lastpcode->args[2].data.label.label->block->blockIndex, loop->memberblocks)) + return; + if (bitvectorgetbit(loop->body->nextBlock->blockIndex, loop->memberblocks)) + return; + + reg11 = lastpcode->args[0].data.reg.reg; + reg4 = lastpcode->args[1].data.imm.value; + prevpcode = lastpcode->prevPCode; + if (!prevpcode) + return; + + op12 = prevpcode->op; + if (op12 == PC_ADDI && prevpcode->args[2].kind == PCOp_IMMEDIATE) { + pc8 = prevpcode; + prevpcode = prevpcode->prevPCode; + if (!prevpcode) + return; + + op12 = prevpcode->op; + if (pc8->args[0].data.reg.reg != pc8->args[1].data.reg.reg) + return; + if (op12 != PC_CMP && op12 != PC_CMPL && op12 != PC_CMPI && op12 != PC_CMPLI) + return; + if (prevpcode->args[1].data.reg.reg == pc8->args[0].data.reg.reg) + return; + if ((loop->step = pc8->args[2].data.imm.value) == 0) + return; + } + + if (op12 != PC_CMP && op12 != PC_CMPL && op12 != PC_CMPI && op12 != PC_CMPLI) + return; + + if (prevpcode->args[0].data.reg.reg != reg11) + return; + + reg11b = prevpcode->args[1].data.reg.reg; + if (reg11b < 32) + return; + + if (loop->preheader->nextBlock != lastpcode->args[2].data.label.label->block) + return; + + if (op12 == PC_CMPI) { + if (prevpcode->prevPCode) + return; + loop->upper = prevpcode->args[2].data.imm.value; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if (op12 == PC_CMPLI) { + if (prevpcode->prevPCode) + return; + loop->upper = prevpcode->args[2].data.imm.value & 0xFFFF; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if (op12 == PC_CMP || op12 == PC_CMPL) { + if (prevpcode->prevPCode) { + if ( + prevpcode->prevPCode->op == PC_LI && + prevpcode->prevPCode->args[1].kind == PCOp_IMMEDIATE && + prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && + !prevpcode->prevPCode->prevPCode + ) { + loop->upper = prevpcode->prevPCode->args[1].data.imm.value; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if ( + prevpcode->prevPCode->op == PC_LIS && + prevpcode->prevPCode->args[1].kind == PCOp_IMMEDIATE && + prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && + !prevpcode->prevPCode->prevPCode + ) { + loop->upper = prevpcode->prevPCode->args[1].data.imm.value << 16; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if ( + prevpcode->prevPCode->op == PC_ADDI && + prevpcode->prevPCode->args[2].kind == PCOp_IMMEDIATE && + prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && + prevpcode->prevPCode->args[1].data.reg.reg == prevpcode->args[2].data.reg.reg && + prevpcode->prevPCode->prevPCode && + prevpcode->prevPCode->prevPCode->op == PC_LIS && + prevpcode->prevPCode->prevPCode->args[1].kind == PCOp_IMMEDIATE && + prevpcode->prevPCode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && + !prevpcode->prevPCode->prevPCode->prevPCode + ) { + loop->upper = prevpcode->prevPCode->args[2].data.imm.value + + (prevpcode->prevPCode->prevPCode->args[1].data.imm.value << 16); + loop->upperType = LOOP_BOUND_CONSTANT; + } else { + return; + } + } else { + pc8 = NULL; + for (list = reg_Defs[RegClass_GPR][prevpcode->args[2].data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)) + return; + } + for (list = reg_Defs[RegClass_GPR][prevpcode->args[2].data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].defvec8)) { + if (!pc8) { + pc8 = Defs[list->id].pcode; + if ( + pc8->op == PC_LI && + pc8->args[1].kind == PCOp_IMMEDIATE + ) { + loop->upper = pc8->args[1].data.imm.value; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if ( + pc8->op == PC_LIS && + pc8->args[1].kind == PCOp_IMMEDIATE + ) { + loop->upper = pc8->args[1].data.imm.value << 16; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if ( + pc8->op == PC_ADDI && + pc8->args[2].kind == PCOp_IMMEDIATE && + pc8->args[1].data.reg.reg == prevpcode->args[2].data.reg.reg && + pc8->prevPCode && + pc8->prevPCode->op == PC_LIS && + pc8->prevPCode->args[1].kind == PCOp_IMMEDIATE && + pc8->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg + ) { + loop->upper = pc8->args[2].data.imm.value + + (pc8->prevPCode->args[1].data.imm.value << 16); + loop->upperType = LOOP_BOUND_CONSTANT; + } else { + loop->upperType = LOOP_BOUND_VARIABLE; + break; + } + } else { + loop->upperType = LOOP_BOUND_VARIABLE; + break; + } + } + } + + if (loop->upperType == LOOP_BOUND_INDETERMINATE) + loop->upperType = LOOP_BOUND_VARIABLE; + } + } + + pc8 = NULL; + + for (list = reg_Defs[RegClass_GPR][reg11b]; list; list = list->next) { + check = Defs[list->id].pcode; + if (bitvectorgetbit(check->block->blockIndex, loop->memberblocks)) { + if (!pc8) { + pc8 = check; + if (check->op != PC_ADDI) + return; + if (check->args[1].data.reg.reg != reg11b) + return; + if (check->args[2].kind != PCOp_IMMEDIATE) + return; + if ((loop->step = check->args[2].data.imm.value) == 0) + return; + } else { + return; + } + } + } + + if (!pc8) + return; + + if (pc8->block != prevpcode->block && !bitvectorgetbit(prevpcode->block->blockIndex, loop->vec2C)) + return; + + if (loop->children) { + for (child = loop->children; child; child = child->nextSibling) { + if (bitvectorgetbit(pc8->block->blockIndex, child->memberblocks)) + return; + } + } + + loop->pc18 = pc8; + + pc8 = NULL; + + for (list = reg_Defs[RegClass_GPR][reg11b]; list; list = list->next) { + if (bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].defvec8)) { + if (!pc8) { + pc8 = Defs[list->id].pcode; + if ( + pc8->op == PC_LI && + pc8->args[1].kind == PCOp_IMMEDIATE + ) { + loop->lower = pc8->args[1].data.imm.value; + loop->lowerType = LOOP_BOUND_CONSTANT; + } else if ( + pc8->op == PC_LIS && + pc8->args[1].kind == PCOp_IMMEDIATE + ) { + loop->lower = pc8->args[1].data.imm.value << 16; + loop->lowerType = LOOP_BOUND_CONSTANT; + } else if ( + pc8->op == PC_ADDI && + pc8->args[2].kind == PCOp_IMMEDIATE && + pc8->args[1].data.reg.reg == reg11b && + pc8->prevPCode && + pc8->prevPCode->op == PC_LIS && + pc8->prevPCode->args[1].kind == PCOp_IMMEDIATE && + pc8->prevPCode->args[0].data.reg.reg == reg11b + ) { + loop->lower = pc8->args[2].data.imm.value + + (pc8->prevPCode->args[1].data.imm.value << 16); + loop->lowerType = LOOP_BOUND_CONSTANT; + } else { + loop->lowerType = LOOP_BOUND_VARIABLE; + break; + } + } else { + loop->lowerType = LOOP_BOUND_INDETERMINATE; + break; + } + } + } + + if (loop->lowerType == LOOP_BOUND_INDETERMINATE) + loop->lowerType = LOOP_BOUND_VARIABLE; + + if (loop->lowerType == LOOP_BOUND_CONSTANT && loop->upperType == LOOP_BOUND_CONSTANT) { + if (op12 == PC_CMP || op12 == PC_CMPI) { + if (!checklooplimits(lastpcode->op, reg4, loop->lower, loop->upper, loop->step, &loop->iterationCount)) + return; + } else { + if (!checkunsignedlooplimits(lastpcode->op, reg4, loop->lower, loop->upper, loop->step, (UInt32 *) &loop->iterationCount)) + return; + } + loop->isKnownCountingLoop = 1; + } else if (loop->lowerType != LOOP_BOUND_INDETERMINATE || loop->upperType != LOOP_BOUND_INDETERMINATE) { + if (!checkunknownloop(lastpcode->op, reg4, loop->step, &loop->unknownCondition)) + return; + loop->isUnknownCountingLoop = 1; + } +} + +void analyzeForCountableLoops(Loop *loop) { + if (!loop) + return; + + while (loop) { + if (loop->children) + analyzeForCountableLoops(loop->children); + checkcountingloop(loop); + loop = loop->nextSibling; + } +} + +void analyzeloop(Loop *loop) { + BlockList *list; + PCodeBlock *block; + PCode *pcode; + + loop->bodySize = 0; + loop->x4D = 0; + loop->x4E = 0; + loop->x4F = 1; + loop->isKnownCountingLoop = 0; + loop->isUnknownCountingLoop = 0; + loop->lowerType = LOOP_BOUND_INDETERMINATE; + loop->upperType = LOOP_BOUND_INDETERMINATE; + loop->iterationCount = -1; + loop->x57 = 0; + loop->x52 = 0; + + for (list = loop->blocks; list; list = list->next) { + block = list->block; + if (!loop->children) + block->flags |= fPCBlockFlag2000; + loop->bodySize += block->pcodeCount; + + if (block != loop->body) { + if (!block->successors || !block->predecessors || block->successors->nextLink || block->predecessors->nextLink) + loop->x4F = 0; + } + + if ((block->flags & fPCBlockFlag4000) == fPCBlockFlag4000) + loop->x52 = 1; + + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if (PCODE_FLAG_SET_T(pcode) & fLink) + loop->x4D = 1; + + if (pcode->op == PC_BCTRL || pcode->op == PC_BCTR || pcode->op == PC_BCCTR || pcode->op == PC_MTCTR || pcode->op == PC_MFCTR) { + loop->x4E = 1; + } else if (pcode->flags & fPCodeFlag2) { + if (pcode->op == PC_LBZX || pcode->op == PC_LHZX || pcode->op == PC_LHAX || pcode->op == PC_LWZX || pcode->op == PC_LFSX || pcode->op == PC_LFDX) + loop->x53 = 1; + } else if (pcode->flags & fPCodeFlag4) { + if (pcode->op == PC_STBX || pcode->op == PC_STHX || pcode->op == PC_STWX || pcode->op == PC_STFSX || pcode->op == PC_STFDX) + loop->x54 = 1; + } else { + if (pcode->op == PC_EIEIO || pcode->op == PC_SYNC || pcode->op == PC_ISYNC) + loop->x57 = 1; + } + } + } + + if (!loop->children && !loop->x4D && loop->bodySize < 32) { + for (list = loop->blocks; list; list = list->next) + list->block->flags |= fPCBlockFlag2000; + } +} + +static void analyzeloops(Loop *loop) { + while (loop) { + if (loop->children) + analyzeloops(loop->children); + analyzeloop(loop); + loop = loop->nextSibling; + } +} + +void analyzeloopsinflowgraph(void) { + if (loopsinflowgraph) + analyzeloops(loopsinflowgraph); +} + diff --git a/compiler_and_linker/unsorted/LoopOptimization.c b/compiler_and_linker/unsorted/LoopOptimization.c index e69de29..6472119 100644 --- a/compiler_and_linker/unsorted/LoopOptimization.c +++ b/compiler_and_linker/unsorted/LoopOptimization.c @@ -0,0 +1,1565 @@ +#include "compiler/LoopOptimization.h" +#include "compiler/CFunc.h" +#include "compiler/CParser.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/LoopDetection.h" +#include "compiler/PCode.h" +#include "compiler/UseDefChains.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +int optimizedloops; +int optimizedloop_full_unroll; +int optimizedloop_trans_regs; +static UInt32 *liveonexit; +static UInt32 *inductionvariables; +static int last_virtual_GPR; + +static int ispowerof2(SInt32 value) { + int bit = getbit(value); + return (bit > 0 && bit < 31) ? bit : 0; +} + +static void insertupdateinstructions(Loop *loop) { + // nothing +} + +static void computeliveonexit(Loop *loop) { + UInt32 *usevec; + UInt32 *defvec; + BlockList *blocklist; + RegUseOrDef *list; + int gpr; + + bitvectorinitialize(usevec = oalloc(4 * ((number_of_Uses + 31) >> 5)), number_of_Uses, 0); + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + if (bitvectorgetbit(blocklist->block->blockIndex, loop->vec24)) + bitvectorunion(usevec, usedefinfo[blocklist->block->blockIndex].usevec1C, number_of_Uses); + } + + bitvectorinitialize(defvec = oalloc(4 * ((number_of_Defs + 31) >> 5)), number_of_Defs, 0); + if (loop->preheader) + bitvectorunion(defvec, usedefinfo[loop->preheader->blockIndex].defvec8, number_of_Defs); + + bitvectorinitialize(liveonexit, last_virtual_GPR, 0); + + for (gpr = 32; gpr < last_virtual_GPR; gpr++) { + for (list = reg_Defs[RegClass_GPR][gpr]; list; list = list->next) { + if (bitvectorgetbit(list->id, defvec)) { + if (!Defs[list->id].pcode->block || bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)) { + bitvectorsetbit(gpr, liveonexit); + break; + } + } + } + + for (list = reg_Uses[RegClass_GPR][gpr]; list; list = list->next) { + if (bitvectorgetbit(list->id, usevec)) { + if (!Uses[list->id].pcode->block || !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)) { + bitvectorsetbit(gpr, liveonexit); + break; + } + } + } + } +} + +static void eliminateinductionvariables(Loop *loop) { + BlockList *blocklist; + PCode *instr; + PCode *nextInstr; + PCodeArg *op; + int i; + + bitvectorinitialize(inductionvariables, last_virtual_GPR, 0xFFFFFFFF); + + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + for (instr = blocklist->block->firstPCode; instr; instr = instr->nextPCode) { + if ( + instr->op != PC_ADDI || + instr->args[0].data.reg.reg < 32 || + instr->args[0].data.reg.reg >= last_virtual_GPR || + instr->args[1].data.reg.reg != instr->args[0].data.reg.reg + ) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg >= n_real_registers[RegClass_GPR] && + op->data.reg.reg < last_virtual_GPR + ) + bitvectorclearbit(op->data.reg.reg, inductionvariables); + op++; + } + } + } + } + + if (loop->parent) { + for (instr = loop->preheader->firstPCode; instr; instr = nextInstr) { + nextInstr = instr->nextPCode; + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg >= n_real_registers[RegClass_GPR] && + op->data.reg.reg < last_virtual_GPR + ) + bitvectorsetbit(op->data.reg.reg, liveonexit); + op++; + } + } + } + + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + for (instr = blocklist->block->firstPCode; instr; instr = nextInstr) { + nextInstr = instr->nextPCode; + if ( + instr->op == PC_ADDI && + instr->args[0].data.reg.reg >= 32 && + instr->args[0].data.reg.reg < last_virtual_GPR && + instr->args[1].data.reg.reg == instr->args[0].data.reg.reg && + bitvectorgetbit(instr->args[0].data.reg.reg, inductionvariables) && + !bitvectorgetbit(instr->args[0].data.reg.reg, liveonexit) + ) { + deletepcode(instr); + optimizedloops = 1; + } + } + } +} + +static void skiplooptest(Loop *loop) { + PCodeBlock *preheader; + PCodeLabel *label; + PCLink **ptr; + PCLink *link; + PCode *lastInstr; + PCode *instr; + + preheader = loop->preheader; + lastInstr = loop->body->lastPCode; +#line 340 + CError_ASSERT(lastInstr->args[2].kind == PCOp_LABEL); + + label = lastInstr->args[2].data.label.label; + preheader->lastPCode->args[0].data.label.label = label; + preheader->successors->block = label->block; + + ptr = &loop->body->predecessors; + while ((link = *ptr)) { + if (link->block == preheader) { + *ptr = link->nextLink; + break; + } + ptr = &link->nextLink; + } + + link->nextLink = label->block->predecessors; + label->block->predecessors = link; + + while (1) { + instr = loop->body->firstPCode; +#line 369 + CError_ASSERT(instr); + + if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) + break; + + deletepcode(instr); + insertpcodebefore(loop->preheader->lastPCode, instr); + loop->bodySize--; + } + + for (instr = instr->nextPCode; instr && !(instr->flags & fPCodeFlag1); instr = instr->nextPCode) + insertpcodebefore(loop->preheader->lastPCode, copypcode(instr)); +} + +static void unrollloop(Loop *loop) { + PCodeBlock *newBlock; + int i; + int factor; + PCode *instr; + PCodeBlock *block; + PCode *firstInstr; + PCode *nextInstr; + + for (factor = copts.ppc_unroll_factor_limit; factor > 1; factor--) { + if ((loop->iterationCount % factor) == 0 && (loop->bodySize - 2) * factor <= copts.ppc_unroll_instructions_limit) + break; + } + + if (factor == 1) + return; + if ((loop->iterationCount / factor) != 1 && loop->bodySize < 4) + return; + + newBlock = oalloc(sizeof(PCodeBlock)); + newBlock->firstPCode = newBlock->lastPCode = NULL; + for (i = 0; i < factor - 1; i++) { + firstInstr = loop->body->firstPCode; +#line 448 + CError_ASSERT(firstInstr); + if (firstInstr->op != PC_CMP && firstInstr->op != PC_CMPL && firstInstr->op != PC_CMPI && firstInstr->op != PC_CMPLI) { +#line 450 + CError_FATAL(); + } + + for (instr = firstInstr->nextPCode; instr && !(instr->flags & fPCodeFlag1); instr = instr->nextPCode) + appendpcode(newBlock, copypcode(instr)); + + for (block = loop->preheader->successors->block; block != loop->body; block = block->successors->block) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (instr->op != PC_B) + appendpcode(newBlock, copypcode(instr)); + } + } + } + + block = loop->body->predecessors->block; + for (instr = newBlock->firstPCode; instr; instr = nextInstr) { + nextInstr = instr->nextPCode; + appendpcode(block, instr); + } + loop->iterationCount /= factor; +} + +void pccomputepredecessors1(PCodeBlock *block) { + PCLink *succ; + PCLink *pred; + + for (succ = block->successors; succ; succ = succ->nextLink) { + if (!succ->block) { +#line 496 + CError_FATAL(); + } else { + for (pred = succ->block->predecessors; pred; pred = pred->nextLink) { + if (pred->block == block) + break; + } + + if (!pred) { + pred = lalloc(sizeof(PCLink)); + pred->block = block; + pred->nextLink = succ->block->predecessors; + succ->block->predecessors = pred; + } + } + } +} + +static PCodeBlock *insertnewpcblock(PCodeBlock *block, int loopWeight) { + PCodeBlock *newBlock; + PCodeBlock *nextBlock; + PCodeLabel *label; + PCLink *prev; + PCLink *link; + + label = makepclabel(); + newBlock = lalloc(sizeof(PCodeBlock)); + + nextBlock = block->nextBlock; + newBlock->nextBlock = nextBlock; + block->nextBlock = newBlock; + + newBlock->prevBlock = block; + nextBlock->prevBlock = newBlock; + + newBlock->labels = NULL; + newBlock->predecessors = newBlock->successors = NULL; + newBlock->firstPCode = newBlock->lastPCode = NULL; + newBlock->pcodeCount = 0; + newBlock->loopWeight = loopWeight; + newBlock->flags = 0; + newBlock->blockIndex = pcblockcount++; + pclabel(newBlock, label); + + prev = NULL; + for (link = block->successors; link; link = link->nextLink) { + if (link->block == nextBlock) { + if (!prev) + block->successors = link->nextLink; + else + prev->nextLink = link->nextLink; + link->nextLink = NULL; + newBlock->successors = link; + break; + } + prev = link; + } + + prev = NULL; + for (link = nextBlock->predecessors; link; link = link->nextLink) { + if (link->block == block) { + if (!prev) + nextBlock->predecessors = link->nextLink; + else + prev->nextLink = link->nextLink; + link->nextLink = NULL; + newBlock->predecessors = link; + break; + } + prev = link; + } + + link = lalloc(sizeof(PCLink)); + link->block = newBlock; + link->nextLink = block->successors; + block->successors = link; + + link = lalloc(sizeof(PCLink)); + link->block = newBlock; + link->nextLink = nextBlock->predecessors; + nextBlock->predecessors = link; + + return newBlock; +} + +static void unrollloopconditional(Loop *loop) { + PCodeBlock *lastBlock; + PCodeLabel *label24; + PCode *instr; + PCode *instrCopy; + int outputBlockCount; + int inputBlockCount; + PCodeBlock **blocks; + PCodeBlock **blocks2; + PCodeBlock **blocks3; + PCode *firstInstr; + int factor; + PCodeBlock *block; + PCLink *link; + PCLink *prev; + int i; + int j; + int k; + int instructionCount; + + label24 = NULL; + outputBlockCount = 0; + instructionCount = 0; + + for (factor = copts.ppc_unroll_factor_limit; factor > 1; factor--) { + if ((loop->iterationCount % factor) == 0 && (loop->bodySize - 2) * factor <= copts.ppc_unroll_instructions_limit) + break; + } + + if (factor == 1) + return; + + inputBlockCount = 0; + for (block = loop->preheader->successors->block; block != loop->body; block = block->nextBlock) { + inputBlockCount++; + if (!bitvectorgetbit(block->blockIndex, loop->memberblocks)) + instructionCount += block->pcodeCount; + } + + if ((loop->bodySize - instructionCount - 2) < instructionCount || instructionCount > 8) + return; + + blocks = oalloc(inputBlockCount * sizeof(PCodeBlock *)); + blocks2 = oalloc(inputBlockCount * sizeof(PCodeBlock *)); + blocks3 = oalloc(factor * (inputBlockCount * sizeof(PCodeBlock *))); + memclrw(blocks, inputBlockCount * sizeof(PCodeBlock *)); + memclrw(blocks2, inputBlockCount * sizeof(PCodeBlock *)); + memclrw(blocks3, factor * (inputBlockCount * sizeof(PCodeBlock *))); + + block = loop->preheader->nextBlock; + for (i = 0; i < inputBlockCount; i++) { + blocks[i] = block; + block = block->nextBlock; + } + + lastBlock = blocks[inputBlockCount - 1]; + for (i = 0; i < factor - 1; i++) { + for (j = 0; j < inputBlockCount; j++) { + blocks2[j] = insertnewpcblock(lastBlock, loop->loopWeight); + blocks3[outputBlockCount++] = blocks2[j]; + lastBlock = blocks2[j]; + } + if (label24) { + pclabel(blocks2[0], label24); + label24 = NULL; + } + + for (j = 0; j < inputBlockCount; j++) { + for (instr = blocks[j]->firstPCode; instr; instr = instr->nextPCode) { + if (instr->flags & fPCodeFlag1) { + PCodeArg *op; + int opID; + instrCopy = copypcode(instr); + op = NULL; + for (opID = 0; opID < instr->argCount; opID++) { + if (instr->args[opID].kind == PCOp_LABEL) { + op = &instr->args[opID]; + break; + } + } + + if (op) { + if (op->data.label.label->block == loop->body) { + if (!label24) + label24 = makepclabel(); + instrCopy->args[opID].data.label.label = label24; + } else { + for (k = 0; k < inputBlockCount; k++) { + if (op->data.label.label->block == blocks[k]) { + instrCopy->args[opID].data.label.label = blocks2[k]->labels; + break; + } + } + } + } + + appendpcode(blocks2[j], instrCopy); + if (op) + pcbranch(blocks2[j], instrCopy->args[opID].data.label.label); + } else { + appendpcode(blocks2[j], copypcode(instr)); + } + } + } + + firstInstr = loop->body->firstPCode; +#line 762 + CError_ASSERT(firstInstr != NULL); + if (firstInstr->op != PC_CMP && firstInstr->op != PC_CMPL && firstInstr->op != PC_CMPI && firstInstr->op != PC_CMPLI) { +#line 764 + CError_FATAL(); + } + + for (instr = firstInstr->nextPCode; instr && !(instr->flags & fPCodeFlag1); instr = instr->nextPCode) + appendpcode(blocks2[inputBlockCount - 1], copypcode(instr)); + + for (j = 0; j < inputBlockCount; j++) { + for (link = blocks[j]->successors; link; link = link->nextLink) { + if (link->block == blocks[j]->nextBlock) + break; + } + + if (!link) { + for (link = blocks2[j]->successors, prev = NULL; link; link = link->nextLink) { + if (link->block == blocks2[j]->nextBlock) { + if (prev) + prev->nextLink = link->nextLink; + else + blocks2[j]->successors = link->nextLink; + } else { + prev = link; + } + } + + for (link = blocks2[j]->nextBlock->predecessors, prev = NULL; link; link = link->nextLink) { + if (link->block == blocks2[j]) { + if (prev) + prev->nextLink = link->nextLink; + else + blocks2[j]->nextBlock->predecessors = link->nextLink; + } else { + prev = link; + } + } + } + } + } + + if (label24) + pclabel(loop->body, label24); + + for (i = 0; i < inputBlockCount; i++) { + for (instr = blocks[i]->firstPCode; instr; instr = instr->nextPCode) { + if (instr->flags & fPCodeFlag1) { + PCodeArg *op; + int opID; + op = NULL; + for (opID = 0; opID < instr->argCount; opID++) { + if (instr->args[opID].kind == PCOp_LABEL) { + op = &instr->args[opID]; + break; + } + } + + if (op && op->data.label.label->block == loop->body) { + instr->args[opID].data.label.label = blocks3[0]->labels; + + for (link = blocks[i]->successors, prev = NULL; link; link = link->nextLink) { + if (link->block == loop->body) { + if (prev) + prev->nextLink = link->nextLink; + else + blocks[i]->successors = link->nextLink; + } else { + prev = link; + } + } + + for (link = loop->body->predecessors, prev = NULL; link; link = link->nextLink) { + if (link->block == blocks[i]) { + if (prev) + prev->nextLink = link->nextLink; + else + loop->body->predecessors = link->nextLink; + } else { + prev = link; + } + } + + link = blocks[i]->successors; + while (link && link->block != blocks3[0]) + link = link->nextLink; + + if (!link) { + pcbranch(blocks[i], op->data.label.label); + pccomputepredecessors1(blocks[i]); + } + } + } + } + } + + for (i = 0; i < outputBlockCount; i++) + pccomputepredecessors1(blocks3[i]); + + loop->iterationCount /= factor; +} + +static void unrollunknownBDNZ(Loop *loop) { + int factor; // r29 + PCodeBlock *preheader; // r17 + PCodeBlock *blockA; // r23 + PCodeBlock *postheader; // r22 + PCodeBlock *newblock1; // r26 + PCodeBlock *newblock2; // r31 + PCodeBlock *newblock3; // r19 + PCodeBlock *newblock4; // r20 + PCodeBlock *newblock5; // r24 + PCode *mtctr; // r21 + int mtctr_reg; // r27 + PCode *instr28; // r28 + PCode *instr6; // r6 + PCodeBlock *block; + PCode *instr; + PCodeArg *op; + int i; + int val; + short mtctr_shifted_reg; // r16 + short reg25; // r25 + PCLink *link; + + if (loop->bodySize < 4) + return; + + factor = 128; + while (factor > copts.ppc_unroll_factor_limit) + factor >>= 1; + while (factor > 1 && (loop->bodySize - 2) * factor > copts.ppc_unroll_instructions_limit) + factor >>= 1; + + if (factor < 2) + return; + + preheader = loop->preheader; + blockA = loop->body->nextBlock; + postheader = preheader->nextBlock; + + newblock1 = insertnewpcblock(preheader, loop->loopWeight); + newblock2 = insertnewpcblock(newblock1, loop->loopWeight); + newblock3 = insertnewpcblock(newblock2, loop->loopWeight); + newblock4 = insertnewpcblock(newblock3, loop->loopWeight); + newblock5 = insertnewpcblock(newblock4, loop->loopWeight); + addblocktoloop(loop, newblock1); + addblocktoloop(loop, newblock2); + addblocktoloop(loop, newblock3); + addblocktoloop(loop, newblock4); + addblocktoloop(loop, newblock5); + + for (instr = preheader->lastPCode; instr; instr = instr->prevPCode) { + if (instr->op == PC_MTCTR) { + mtctr = instr; + mtctr_reg = instr->args[0].data.reg.reg; + } + } + + if (!mtctr) + return; + + instr28 = NULL; + for (block = postheader; block != loop->body; block = block->successors->block) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (instr->op != PC_B) { + appendpcode(newblock2, copypcode(instr)); + if (instr == loop->pc18) + instr28 = newblock2->lastPCode; + } + } + } + + if (!instr28) { + appendpcode(newblock2, copypcode(loop->pc18)); + instr28 = newblock2->lastPCode; + } + + instr6 = NULL; + for (instr = newblock2->firstPCode; instr; instr = instr->nextPCode) { + if (instr != instr28) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg == loop->pc18->args[0].data.reg.reg && + (op->data.reg.effect & (EffectRead | EffectWrite)) + ) { + instr6 = instr; + break; + } + op++; + } + } + if (instr6) + break; + } + + if (!instr6) { + deletepcode(instr28); + deletepcode(loop->pc18); + if (loop->footer) + blockA = loop->footer; + else + blockA = insertnewpcblock(loop->body, loop->loopWeight); + } else { + instr28 = NULL; + } + + for (i = 1; i < factor; i++) { + for (block = postheader; block != loop->body; block = block->successors->block) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (instr->op != PC_B) + appendpcode(newblock2, copypcode(instr)); + } + } + } + + mtctr_shifted_reg = used_virtual_registers[RegClass_GPR]++; + appendpcode(newblock1, makepcode( + PC_RLWINM, + mtctr_shifted_reg, + mtctr_reg, + 32 - ispowerof2(factor), + ispowerof2(factor), + 31)); + + appendpcode(newblock1, makepcode(PC_CMPLI, 0, mtctr_shifted_reg, 0)); + + if (instr28) { + reg25 = used_virtual_registers[RegClass_GPR]++; + if (loop->step == 1) { + instr = makepcode(PC_MR, reg25, mtctr_reg); + } else if (loop->step == -1) { + instr = makepcode(PC_NEG, reg25, mtctr_reg); + } else { + val = ispowerof2(abs(loop->step)); + if (val > 0) { + instr = makepcode(PC_RLWINM, reg25, mtctr_reg, val, 0, 31 - val); + if (loop->step < 0) { + appendpcode(newblock1, instr); + instr = makepcode(PC_NEG, reg25, reg25); + } + } else { + instr = makepcode(PC_MULLI, reg25, mtctr_reg, loop->step); + } + } + appendpcode(newblock1, instr); + } + + appendpcode(newblock1, makepcode(PC_MTCTR, mtctr_shifted_reg)); + appendpcode(newblock1, makepcode(PC_BT, 0, 2, newblock5->labels)); + pcbranch(newblock1, newblock5->labels); + + link = lalloc(sizeof(PCLink)); + link->block = newblock1; + link->nextLink = newblock5->predecessors; + newblock5->predecessors = link; + + appendpcode(newblock3, makepcode(PC_BDNZ, newblock2->labels)); + pcbranch(newblock3, newblock2->labels); + + link = lalloc(sizeof(PCLink)); + link->block = newblock3; + link->nextLink = newblock2->predecessors; + newblock2->predecessors = link; + + appendpcode(newblock4, makepcode(PC_ANDI, mtctr_reg, mtctr_reg, factor - 1)); + appendpcode(newblock4, makepcode(PC_BT, 0, 2, blockA->labels)); + pcbranch(newblock4, blockA->labels); + + link = lalloc(sizeof(PCLink)); + link->block = newblock4; + link->nextLink = blockA->predecessors; + blockA->predecessors = link; + + deletepcode(mtctr); + appendpcode(newblock5, mtctr); + + if (instr28 && bitvectorgetbit(instr28->args[0].data.reg.reg, liveonexit)) { + instr = makepcode(PC_ADD, instr28->args[0].data.reg.reg, instr28->args[0].data.reg.reg, reg25); + if (blockA->firstPCode) + insertpcodebefore(blockA->firstPCode, instr); + else + appendpcode(blockA, instr); + } +} + +static void deleteloop(Loop *loop) { + PCodeBlock *body; + PCodeBlock *preheader; + PCodeBlock *nextblock; + PCodeLabel *label; + PCode *instr; + PCLink **ptr; + PCLink *link; + PCodeBlock *block; + + body = loop->body; + preheader = loop->preheader; + nextblock = body->nextBlock; + label = makepclabel(); + + while (1) { + instr = body->firstPCode; +#line 1294 + CError_ASSERT(instr != NULL); + + if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) + break; + + deletepcode(instr); + insertpcodebefore(loop->preheader->lastPCode, instr); + loop->bodySize--; + } + + pclabel(nextblock, label); + preheader->lastPCode->args[0].data.label.label = label; + preheader->successors->block = nextblock; + + ptr = &nextblock->predecessors; + while ((link = *ptr)) { + if (link->block == body) { + link->block = preheader; + break; + } + ptr = &link->nextLink; + } + + block = pcbasicblocks; + while ((nextblock = block->nextBlock)) { + if (bitvectorgetbit(nextblock->blockIndex, loop->memberblocks)) + block->nextBlock = nextblock->nextBlock; + else + block = nextblock; + } +} + +static void deleteloopheader(Loop *loop) { + PCLink *link; + PCLink **ptr; + + ptr = &loop->body->successors; + while ((link = *ptr)) { + if (link->block == loop->body->lastPCode->args[2].data.label.label->block) { + *ptr = link->nextLink; + break; + } + ptr = &link->nextLink; + } + + ptr = &loop->body->lastPCode->args[2].data.label.label->block->predecessors; + while ((link = *ptr)) { + if (link->block == loop->body) { + *ptr = link->nextLink; + break; + } + ptr = &link->nextLink; + } + + deletepcode(loop->body->firstPCode); + deletepcode(loop->body->lastPCode); + optimizedloop_full_unroll = 1; +} + +static void rewriteloopwithBDNZ(Loop *loop) { + PCode *instr; + + if (!FITS_IN_SHORT(loop->iterationCount)) { + instr = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(loop->iterationCount)); + insertpcodebefore(loop->preheader->lastPCode, instr); + + if (loop->iterationCount != 0) + insertpcodeafter(instr, makepcode(PC_ADDI, instr->args[0].data.reg.reg, instr->args[0].data.reg.reg, 0, LOW_PART(loop->iterationCount))); + } else { + instr = makepcode(PC_LI, used_virtual_registers[RegClass_GPR]++, loop->iterationCount); + insertpcodebefore(loop->preheader->lastPCode, instr); + } + + insertpcodebefore(loop->preheader->lastPCode, makepcode(PC_MTCTR, instr->args[0].data.reg.reg)); + + instr = makepcode(PC_BDNZ, loop->body->lastPCode->args[2].data.label.label); + deletepcode(loop->body->firstPCode); + deletepcode(loop->body->lastPCode); + appendpcode(loop->body, instr); + + for (loop = loop->parent; loop; loop = loop->parent) + loop->x4E = 1; +} + +static void rewriteunknownloopwithBDNZ(Loop *loop) { + SInt32 value1; // r24 + SInt32 value2; // r30 + Opcode branchOpcode; // r19 + SInt32 absStep; // r28 + int branchCondition; // r20 + int counterReg; // r27 + int reg1; // r26 + int reg2; // r22 + unsigned char mode; // r23 + PCodeBlock *afterLoop; // r25 + PCode *addiInstr; + PCode *instr; + PCLink *link; + PCLink **ptr; + + absStep = abs(loop->step); + afterLoop = NULL; + + for (addiInstr = loop->body->lastPCode->prevPCode; addiInstr->op == PC_ADDI; addiInstr = loop->body->lastPCode->prevPCode) { + deletepcode(addiInstr); + if (loop->body->lastPCode->args[2].data.label.label->block->firstPCode) + insertpcodebefore(loop->body->lastPCode->args[2].data.label.label->block->firstPCode, addiInstr); + else + appendpcode(loop->body->lastPCode->args[2].data.label.label->block, addiInstr); + + afterLoop = insertnewpcblock(loop->body, loop->loopWeight); + appendpcode(afterLoop, copypcode(addiInstr)); + loop->footer = afterLoop; + } + + if (loop->unknownCondition == ELESS) { + branchOpcode = PC_BF; + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + branchCondition = 1; + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1 - loop->lower; + mode = 0; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + branchCondition = 0; + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep - 1 + loop->upper; + mode = 1; + } else { + branchCondition = 0; + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1; + mode = 2; + } + } else if (loop->unknownCondition == ELESSEQU) { + branchOpcode = PC_BT; + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + branchCondition = 0; + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep - loop->lower; + mode = 0; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + branchCondition = 1; + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep + loop->upper; + mode = 1; + } else { + branchCondition = 1; + value1 = 0; + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep; + mode = 2; + } + } else if (loop->unknownCondition == EGREATER) { + branchOpcode = PC_BF; + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + branchCondition = 0; + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1 + loop->lower; + mode = 1; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + branchCondition = 1; + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep - 1 - loop->upper; + mode = 0; + } else { + branchCondition = 1; + value1 = 0; + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1; + mode = 3; + } + } else if (loop->unknownCondition == EGREATEREQU) { + branchOpcode = PC_BT; + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + branchCondition = 1; + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep + loop->lower; + mode = 1; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + branchCondition = 0; + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep - loop->upper; + mode = 0; + } else { + branchCondition = 0; + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep; + mode = 3; + } + } else if (loop->unknownCondition == ENOTEQU) { + branchOpcode = PC_BT; + branchCondition = 2; + if (loop->step > 0) { + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1 - loop->lower; + mode = 0; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep - 1 + loop->upper; + mode = 1; + } else { + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1; + mode = 2; + } + } else { + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1 + loop->lower; + mode = 1; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep - 1 - loop->upper; + mode = 0; + } else { + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1; + mode = 3; + } + } + } + + while (1) { + instr = loop->body->firstPCode; +#line 1857 + CError_ASSERT(instr); + + if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) + break; + + deletepcode(instr); + insertpcodebefore(loop->preheader->lastPCode, instr); + loop->bodySize--; + } + + // build a value for mtctr + counterReg = used_virtual_registers[RegClass_GPR]++; + + if (mode == 1) { + if (value2 == 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_NEG, counterReg, reg1)); + } else if (FITS_IN_SHORT(value2)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBFIC, counterReg, reg1, value2)); + } else { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_LIS, counterReg, 0, HIGH_PART(value2))); + if (value2 != 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); + } + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg1, counterReg)); + } + } else if (mode == 0) { + if (value2 == 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_MR, counterReg, reg1)); + } else if (FITS_IN_SHORT(value2)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, reg1, 0, value2)); + } else { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDIS, counterReg, reg1, 0, HIGH_PART(value2))); + if (value2 != 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); + } + } + } else if (mode == 2) { + if (value2 == 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg1, reg2)); + } else if (FITS_IN_SHORT(value2)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, reg2, 0, value2)); + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg1, counterReg)); + } else { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDIS, counterReg, reg2, 0, HIGH_PART(value2))); + if (value2 != 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); + } + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg1, counterReg)); + } + } else { + if (value2 == 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg2, reg1)); + } else { + if (FITS_IN_SHORT(value2)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, reg1, 0, value2)); + } else { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDIS, counterReg, reg1, 0, HIGH_PART(value2))); + if (value2 != 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); + } + } + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg2, counterReg)); + } + } + + if (absStep > 1) { + unsigned char bits; + if ((bits = ispowerof2(absStep))) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_RLWINM, counterReg, counterReg, 32 - bits, bits, 31)); + } else { + int reg = used_virtual_registers[RegClass_GPR]++; + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_LI, reg, absStep)); + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_DIVWU, counterReg, counterReg, reg)); + } + } + + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_MTCTR, counterReg)); + + if (mode < 2) { + if (addiInstr->op == PC_CMPL || addiInstr->op == PC_CMPLI) { + if (FITS_IN_USHORT(value1)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMPLI, 0, reg1, value1)); + } else { + PCode *tmp; + tmp = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(value1)); + insertpcodebefore(loop->preheader->lastPCode, tmp); + + if (loop->iterationCount != 0) + insertpcodeafter(tmp, + makepcode(PC_ADDI, + tmp->args[0].data.reg.reg, + tmp->args[0].data.reg.reg, + 0, LOW_PART(value1))); + + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMPL, 0, reg1, tmp->args[0].data.reg.reg)); + } + } else { + if (FITS_IN_SHORT(value1)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMPI, 0, reg1, value1)); + } else { + PCode *tmp; + tmp = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(value1)); + insertpcodebefore(loop->preheader->lastPCode, tmp); + + if (loop->iterationCount != 0) + insertpcodeafter(tmp, + makepcode(PC_ADDI, + tmp->args[0].data.reg.reg, + tmp->args[0].data.reg.reg, + 0, LOW_PART(value1))); + + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMP, 0, reg1, tmp->args[0].data.reg.reg)); + } + } + } else { + if (addiInstr->op == PC_CMPL || addiInstr->op == PC_CMPLI) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMPL, 0, reg1, reg2)); + } else { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMP, 0, reg1, reg2)); + } + } + + if (!afterLoop) + afterLoop = loop->body->nextBlock; + + instr = makepcode(branchOpcode, 0, branchCondition, afterLoop->labels); + deletepcode(loop->preheader->lastPCode); + appendpcode(loop->preheader, instr); + + instr = makepcode(PC_BDNZ, loop->body->lastPCode->args[2].data.label.label); + deletepcode(loop->body->firstPCode); + deletepcode(loop->body->lastPCode); + appendpcode(loop->body, instr); + + loop->preheader->successors = NULL; + ptr = &loop->body->predecessors; + while ((link = *ptr)) { + if (link->block == loop->preheader) { + *ptr = link->nextLink; + break; + } + ptr = &link->nextLink; + } + + link = lalloc(sizeof(PCLink)); + link->block = loop->preheader->nextBlock; + link->nextLink = loop->preheader->successors; + loop->preheader->successors = link; + + link = lalloc(sizeof(PCLink)); + link->block = loop->preheader; + link->nextLink = loop->preheader->nextBlock->predecessors; + loop->preheader->nextBlock->predecessors = link; + + link = lalloc(sizeof(PCLink)); + link->block = afterLoop; + link->nextLink = loop->preheader->successors; + loop->preheader->successors = link; + + link = lalloc(sizeof(PCLink)); + link->block = loop->preheader; + link->nextLink = afterLoop->predecessors; + afterLoop->predecessors = link; + + for (loop = loop->parent; loop; loop = loop->parent) + loop->x4E = 1; +} + +static void optimizeloop(Loop *loop) { + computeliveonexit(loop); + + if (loop->x53 || loop->x54) + insertupdateinstructions(loop); + + if (loop->isKnownCountingLoop) { + if (loop->iterationCount > 0) { + skiplooptest(loop); + if (!copts.optimize_for_size && !loop->x4D && !loop->x57) { + if (loop->x4F) + unrollloop(loop); + else if (!loop->x4E) + unrollloopconditional(loop); + } + } + + if (loop->iterationCount != 0) { + if (loop->iterationCount == 1) + deleteloopheader(loop); + else if (!loop->x4E && !loop->x4D) + rewriteloopwithBDNZ(loop); + } + + optimizedloops = 1; + } else if (loop->isUnknownCountingLoop && !loop->x4E && !loop->x4D) { + rewriteunknownloopwithBDNZ(loop); + if (copts.ppc_unroll_speculative && !copts.optimize_for_size) { + if (loop->x4F && !loop->x57 && !loop->x52) + unrollunknownBDNZ(loop); + } + optimizedloops = 1; + } + + eliminateinductionvariables(loop); +} + +typedef struct LocalArray { + struct LocalArray *next; + Object *object; + unsigned int invalid:1; + unsigned int isFloat:1; + unsigned int isSigned:1; + SInt32 elementSize; + SInt32 arraySize; + SInt32 elementCount; + int totalUses; + int elements[1]; +} LocalArray; + +static LocalArray *scanforlocalarrays(void) { + SInt32 elementCount; + LocalArray *head; + LocalArray *array; + ObjectList *list; + int i; + SInt32 arraySize; + SInt32 elementSize; + + head = NULL; + + for (list = locals; list; list = list->next) { + if ( + list->object && + !(IS_TYPE_POINTER(list->object->type) ? (TPTR_QUAL(list->object->type) & Q_VOLATILE) : (list->object->qual & Q_VOLATILE)) && + list->object->type && + IS_TYPE_ARRAY(list->object->type) && + TPTR_TARGET(list->object->type) && + TPTR_TARGET(list->object->type)->type < TYPESTRUCT + ) { + arraySize = list->object->type->size; + elementSize = TPTR_TARGET(list->object->type)->size; + elementCount = arraySize / elementSize; + if (elementCount > 0 && elementCount <= 8) { + array = oalloc(sizeof(int) * (elementCount - 1) + sizeof(LocalArray)); + array->next = head; + head = array; + + array->object = list->object; + array->elementSize = elementSize; + array->arraySize = arraySize; + array->elementCount = elementCount; + array->totalUses = 0; + array->isSigned = 1; + array->isFloat = IS_TYPE_FLOAT(TPTR_TARGET(list->object->type)); + array->invalid = 0; + array->isSigned = 1; + if (!array->isFloat && is_unsigned(TPTR_TARGET(list->object->type))) + array->isSigned = 0; + + for (i = 0; i < elementCount; i++) { + array->elements[i] = 0; + } + } + } + } + + return head; +} + +static LocalArray *lookup_array_object(LocalArray *arrays, Object *object) { + while (arrays) { + if (arrays->object == object) + return arrays; + arrays = arrays->next; + } + return NULL; +} + +void changearraytoregisters(void) { + LocalArray *arrays; + PCodeBlock *block; + PCode *instr; + int i; + PCodeArg *op; + LocalArray **ptr; + LocalArray *array; + int intCounter; + int floatCounter; + int reg; + int reg2; + PCode *newInstr; + + arrays = NULL; + if ((arrays = scanforlocalarrays())) { + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (!(instr->flags & fPCodeFlag1) && instr->argCount) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_MEMORY && + (unsigned char) op->arg == 1 && + (array = lookup_array_object(arrays, op->data.mem.obj)) && + !array->invalid + ) { + if ( + (instr->flags & (fPCodeFlag2 | fPCodeFlag4)) && + (op->data.mem.offset % array->elementSize) == 0 && + op->data.mem.offset < array->arraySize + ) { + switch (instr->op) { + case PC_LBZ: + case PC_STB: + if (array->elementSize != 1) + array->invalid = 1; + break; + case PC_LHZ: + case PC_LHA: + case PC_STH: + if (array->elementSize != 2) + array->invalid = 1; + break; + case PC_LWZ: + case PC_STW: + if (array->elementSize != 4) + array->invalid = 1; + break; + case PC_LFD: + case PC_STFD: + if (array->elementSize != 8) + array->invalid = 1; + break; + default: + array->invalid = 1; + break; + } + + if (!array->invalid) + array->elements[op->data.mem.offset / array->elementSize]++; + } else { + array->invalid = 1; + } + } + op++; + } + } + } + } + + intCounter = 0; + floatCounter = 0; + ptr = &arrays; + array = *ptr; + while (array) { + if (array->invalid) { + *ptr = array = array->next; + continue; + } + + if (array->isFloat) + floatCounter += array->elementCount; + if (!array->isFloat) + intCounter += array->elementCount; + + for (i = 0; i < array->elementCount; i++) + array->totalUses += array->elements[i]; + + array = array->next; + } + + if (arrays) { + while (intCounter > 8) { + LocalArray *best; + int score; + score = 0; + best = NULL; + for (array = arrays; array; array = array->next) { + if (!array->isFloat) { + if (best) { + if (array->totalUses < score) { + score = array->totalUses; + best = array; + } + } else { + best = array; + score = array->totalUses; + } + } + } + + if (!best) + break; + + if (best == arrays) { + arrays = best->next; + } else { + for (array = arrays; array; array = array->next) { + if (array->next == best) { + array->next = best->next; + break; + } + } + } + + intCounter -= best->elementCount; + } + + while (floatCounter > 8) { + LocalArray *best; + int score; + score = 0; + best = NULL; + for (array = arrays; array; array = array->next) { + if (array->isFloat) { + if (best) { + if (array->totalUses < score) { + score = array->totalUses; + best = array; + } + } else { + best = array; + score = array->totalUses; + } + } + } + + if (!best) + break; + + if (best == arrays) { + arrays = best->next; + } else { + for (array = arrays; array; array = array->next) { + if (array->next == best) { + array->next = best->next; + break; + } + } + } + + floatCounter -= best->elementCount; + } + +#line 2394 + CError_ASSERT(intCounter <= 8 && floatCounter <= 8); + + if (!arrays) + return; + + optimizedloop_trans_regs = 1; + + for (array = arrays; array; array = array->next) { + for (i = 0; i < array->elementCount; i++) { + if (array->isFloat) + array->elements[i] = used_virtual_registers[RegClass_FPR]++; + else + array->elements[i] = used_virtual_registers[RegClass_GPR]++; + } + } + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if ( + !(instr->flags & fPCodeFlag1) && + instr->argCount && + (instr->flags & (fPCodeFlag2 | fPCodeFlag4)) && + instr->args[2].kind == PCOp_MEMORY && + (unsigned char) instr->args[2].arg == 1 && + (array = lookup_array_object(arrays, instr->args[2].data.mem.obj)) && + !(array->invalid) + ) + { + reg2 = instr->args[0].data.reg.reg; + reg = array->elements[instr->args[2].data.mem.offset / array->elementSize]; + newInstr = NULL; + switch (instr->op) { + case PC_LBZ: + if (array->isSigned) + newInstr = makepcode(PC_MR, reg2, reg); + else + newInstr = makepcode(PC_RLWINM, reg2, reg, 0, 24, 31); + break; + case PC_STB: + if (array->isSigned) + newInstr = makepcode(PC_EXTSB, reg, reg2); + else + newInstr = makepcode(PC_RLWINM, reg, reg2, 0, 24, 31); + break; + case PC_LHZ: + newInstr = makepcode(PC_RLWINM, reg2, reg, 0, 16, 31); + break; + case PC_LHA: + newInstr = makepcode(PC_EXTSH, reg2, reg); + break; + case PC_STH: + if (array->isSigned) + newInstr = makepcode(PC_EXTSH, reg, reg2); + else + newInstr = makepcode(PC_RLWINM, reg, reg2, 0, 16, 31); + break; + case PC_LWZ: + newInstr = makepcode(PC_MR, reg2, reg); + break; + case PC_STW: + newInstr = makepcode(PC_MR, reg, reg2); + break; + case PC_LFD: + newInstr = makepcode(PC_FMR, reg2, reg); + break; + case PC_STFD: + newInstr = makepcode(PC_FMR, reg, reg2); + break; + default: +#line 2494 + CError_FATAL(); + break; + } + + if (newInstr) { + insertpcodebefore(instr, newInstr); + deletepcode(instr); + instr = newInstr; + } + } + } + } + } + } + + freeoheap(); +} + +static void optimizenestedloops(Loop *loop) { + while (loop) { + if (loop->children) + optimizenestedloops(loop->children); + optimizeloop(loop); + loop = loop->nextSibling; + } +} + +void optimizeloops(void) { + optimizedloops = 0; + optimizedloop_full_unroll = 0; + optimizedloop_trans_regs = 0; + if (loopsinflowgraph) { + computeusedefchains(0); + last_virtual_GPR = used_virtual_registers[RegClass_GPR]; + liveonexit = oalloc(4 * ((used_virtual_registers[RegClass_GPR] + 31) >> 5)); + inductionvariables = oalloc(4 * ((last_virtual_GPR + 31) >> 5)); + optimizenestedloops(loopsinflowgraph); + freeoheap(); + } +} + diff --git a/compiler_and_linker/unsorted/PCode.c b/compiler_and_linker/unsorted/PCode.c index f53030b..c35cac4 100644 --- a/compiler_and_linker/unsorted/PCode.c +++ b/compiler_and_linker/unsorted/PCode.c @@ -60,7 +60,7 @@ PCode *copypcode(PCode *pcode) { newpc->op = pcode->op; newpc->flags = pcode->flags; newpc->argCount = pcode->argCount; - newpc->_18 = pcode->_18; + newpc->alias = pcode->alias; for (i = 0; i < pcode->argCount; i++) { newpc->args[i] = pcode->args[i]; } diff --git a/compiler_and_linker/unsorted/PCodeAssembly.c b/compiler_and_linker/unsorted/PCodeAssembly.c index e69de29..2ebb3c1 100644 --- a/compiler_and_linker/unsorted/PCodeAssembly.c +++ b/compiler_and_linker/unsorted/PCodeAssembly.c @@ -0,0 +1,27 @@ +#include "compiler/PCodeAssembly.h" + +static UInt32 codebase; + +static void pcode_update_mem_labeldiff_imm() { +} + +UInt32 assemblepcode(PCode *instr, UInt32 offset, PCodeArg *dummyArg) { +} + +static void targetinstruction() { +} + +static void invertybit() { +} + +static void insertlongbranches() { +} + +void optimizefinalbranches() { +} + +static void insert_align_nops() { +} + +void assemblefunction() { +} diff --git a/compiler_and_linker/unsorted/PCodeListing.c b/compiler_and_linker/unsorted/PCodeListing.c index e69de29..9ce9621 100644 --- a/compiler_and_linker/unsorted/PCodeListing.c +++ b/compiler_and_linker/unsorted/PCodeListing.c @@ -0,0 +1,527 @@ +#include "compiler/PCodeListing.h" +#include "compiler/CError.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/Alias.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/InterferenceGraph.h" +#include "compiler/LiveInfo.h" +#include "compiler/PCode.h" +#include "compiler/PCodeAssembly.h" +#include "compiler/Registers.h" +#include "compiler/Scheduler.h" +#include "compiler/objects.h" + +static FILE *pcfile; +static int ptime; +static int sourcetext; +static int sourcetext_is_main; +static int sourcelength; +int pclist_bad_operand; + +static void formatdataflowset(char *name, UInt32 *vec, UInt32 size, char *format) { + UInt32 i; + UInt32 counter; + char *separator; + + separator = ""; + fprintf(pcfile, "%s = {", name); + + for (i = 0, counter = 0; i < size; i++) { + if (bitvectorgetbit(i, vec)) { + if (i) + fprintf(pcfile, separator); + if (counter++ == 10) { + fprintf(pcfile, "\n\t\t"); + counter = 0; + } + fprintf(pcfile, format, i); + separator = ","; + } + } + + fprintf(pcfile, "}\n"); +} + +static void pclistblock(PCodeBlock *block, char *format, UInt32 vecSize) { + PCLink *link; + PCodeLabel *label; + int cpu; + int chr; // r21 + PCode *instr; // r20 + int offset; // r19 + int latency; // r18 + UInt32 opcode; + MachineInfo *mi; + char buf[500]; + PCodeArg dummyArg; + + fprintf(pcfile, ":{%4.4x}::::::::::::::::::::::::::::::::::::::::LOOPWEIGHT=%ld\n", block->flags, block->loopWeight); + fprintf(pcfile, "B%ld: ", block->blockIndex); + + fprintf(pcfile, "Successors = { "); + for (link = block->successors; link; link = link->nextLink) { + if (link->block) + fprintf(pcfile, "B%ld ", link->block->blockIndex); + } + fprintf(pcfile, "} "); + + fprintf(pcfile, "Predecessors = { "); + for (link = block->predecessors; link; link = link->nextLink) { + if (link->block) + fprintf(pcfile, "B%ld ", link->block->blockIndex); + } + + if (block->labels) { + fprintf(pcfile, "} Labels = { "); + for (label = block->labels; label; label = label->nextLabel) + fprintf(pcfile, "L%ld ", label->index); + } + + fprintf(pcfile, "}\n\n"); + + cpu = copts.schedule_cpu; + if (cpu == 10) { + mi = &machine7450; + } else if (copts.altivec_model != 0 || cpu == 7) { + mi = &machine7400; + } else if (cpu == 2) { + mi = &machine603; + } else if (cpu == 5) { + mi = &machine603e; + } else if (cpu == 3) { + mi = &machine604; + } else if (cpu == 6) { + mi = &machine604; + } else if (cpu == 4) { + mi = &machine750; + } else if (cpu == 1) { + mi = &machine601; + } else if (cpu == 9) { + mi = &machine821; + } else { + mi = &machine603; + } + + for (offset = block->codeOffset, instr = block->firstPCode; instr; instr = instr->nextPCode, offset += 4) { + latency = mi->latency(instr); + formatoperands(instr, buf, 1); + chr = (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) ? '.' : ' '; + if (coloring) + opcode = 0; + else + opcode = assemblepcode(instr, offset, &dummyArg); + + fprintf( + pcfile, + " %.8lX %.8lX %4ld %-7s%c %s\n", + offset, opcode, latency, + opcodeinfo[instr->op].name, chr, buf + ); + + if (instr->alias) + dumpalias(instr->alias, 0, 1, 0); + } + + if (vecSize) { + fprintf(pcfile, "............................................................\n"); + formatdataflowset("use", liveinfo[block->blockIndex].vec0, vecSize, format); + formatdataflowset("def", liveinfo[block->blockIndex].vec4, vecSize, format); + formatdataflowset("in ", liveinfo[block->blockIndex].vec8, vecSize, format); + formatdataflowset("out", liveinfo[block->blockIndex].vecC, vecSize, format); + } + + fflush(pcfile); + + if (pclist_bad_operand) { +#line 252 + CError_FATAL(); + } +} + +static void pclistonoff(int flag) { + if (flag) + fprintf(pcfile, "On\n"); + else + fprintf(pcfile, "Off\n"); +} + +void pcinitlisting(void) { + // unknown args, etc +} + +void pccleanuplisting(void) { +} + +void pclistblocks(char *name1, char *name2) { +} + +void pclistdataflow(void) { + // unknown args +} + +void pclistinterferences(char *class_format, int regcount) { +} + +void pclistspill(void) { + // unknown args +} + +void pclistcopypropitem(void) { + // unknown args +} + +void pclistcoalesce(void) { + // unknown args +} + +void pclistusedefs(void) { + // unknown args +} + +void pclistpropinfo(void) { + // unknown args +} + +static void listloop(void) { + // unknown args +} + +static void listloops(void) { + // unknown args +} + +void pclistloops(void) { + // unknown args +} + +static void listswitchtables(void) { + // unknown args +} + +void pclistswitchtables(void) { + // unknown args +} + +void pclistdominators(void) { + // unknown args +} + +void pclistbackedge(void) { + // unknown args +} + +static char *GetInterferenceFlags(IGNode *node) { + char *buf; + Boolean first; + + first = 1; + buf = oalloc(512); + buf[0] = 0; + + if (node->flags & fSpilled) { + strcat(buf, "fSpilled"); + first = 0; + } + + if (node->flags & fPushed) { + if (!first) + strcat(buf, "|"); + strcat(buf, "fPushed"); + first = 0; + } + + if (node->flags & fCoalesced) { + if (!first) + strcat(buf, "|"); + strcat(buf, "fCoalesced"); + first = 0; + } + + if (node->flags & fCoalescedInto) { + if (!first) + strcat(buf, "|"); + strcat(buf, "fCoalescedInto"); + first = 0; + } + + if (node->flags & fPairHigh) { + if (!first) + strcat(buf, "|"); + strcat(buf, "fPairHigh"); + first = 0; + } + + if (node->flags & fPairLow) { + if (!first) + strcat(buf, "|"); + strcat(buf, "fPairLow"); + first = 0; + } + + if (!*buf) + strcat(buf, "no_flags"); + + return buf; +} + +void pclistinterferencegraphnode(void) { + // unknown args +} + +void pclistinterferencegraph(void) { + // unknown args +} + +void pclistblock_scheduler(void) { + // unknown args +} + +void pclistblocks_start_scheduler(char *str1, char *str2) { +} + +void pclistblocks_end_scheduler(void) { + if (pclist_bad_operand) { +#line 1318 + CError_FATAL(); + } +} + +static void printheapsize(void) { + // unknown args +} + +void pctotalheap(void) { + // unknown args +} + +void pctotalmemory(void) { + // unknown args +} + +void pcmessage(char *probably_a_string, ...) { +} + +int formatalias(Alias *alias, char *buf, int bufSize) { + char *name; + char *typestr; + int len; + int len2; + + if (bufSize < 16) + return sprintf(buf, "..."); + + switch (alias->type) { + case AliasType0: + case AliasType1: + name = CMangler_GetLinkName(alias->object)->name; + if (!strlen(name) || name[0] < 0) { +#line 1458 + CError_FATAL(); + } + + if (strlen(name) + 16 > bufSize) + return sprintf(buf, "..."); + + switch (alias->object->datatype) { + case DNONLAZYPTR: + typestr = "{NL}"; + break; + case DDATA: + typestr = "{RW}"; + break; + case DLOCAL: + typestr = "{SP}"; + break; + default: + typestr = ""; + } + + len = sprintf(buf, "%0.*s%s", bufSize - 20, name, typestr, alias->size); + buf += len; + if (alias->type == AliasType0) + return len; + + if (alias->offset == 0) + len2 = sprintf(buf, ":%d", alias->size); + else if (alias->offset > 0) + len2 = sprintf(buf, "+%d:%d", alias->offset, alias->size); + else + len2 = sprintf(buf, "-%d:%d", -alias->offset, alias->size); + + return len + len2; + + case AliasType2: + len = 0; + + len2 = sprintf(buf, "{"); + buf += len2; + len += len2; + + len2 = sprintf(buf, "*"); + buf += len2; + len += len2; + + len2 = sprintf(buf, "}"); + buf += len2; + len += len2; + return len; + + default: +#line 1543 + CError_FATAL(); + return 0; + } +} + +int dumpalias(Alias *alias, int len, Boolean flag1, Boolean flag2) { + char *name; + char *typestr; + AliasMember *member; + Boolean notFirst; + + if (!flag2 && alias == worst_case) { + fprintf(pcfile, " ALIAS = {worst_case}"); + if (flag1) + fprintf(pcfile, "\n"); + return 0; + } + + if (flag1) { + if (alias == worst_case) + fprintf(pcfile, "ALIAS worst_case = "); + else + fprintf(pcfile, " ALIAS = "); + } + + switch (alias->type) { + case AliasType0: + case AliasType1: + name = CMangler_GetLinkName(alias->object)->name; + if (!strlen(name) || name[0] < 0) { +#line 1581 + CError_FATAL(); + } + + switch (alias->object->datatype) { + case DNONLAZYPTR: + typestr = "{NL}"; + break; + case DDATA: + typestr = "{RW}"; + break; + case DLOCAL: + typestr = "{SP}"; + break; + default: + typestr = ""; + } + + len += fprintf(pcfile, "%0.80s%s", name, typestr); + + if (alias->type == AliasType0) { + if (flag1) + fprintf(pcfile, "\n"); + return len; + } + + if (alias->offset == 0) + len += fprintf(pcfile, ":%d", alias->size); + else if (alias->offset > 0) + len += fprintf(pcfile, "+%d:%d", alias->offset, alias->size); + else + len += fprintf(pcfile, "-%d:%d", -alias->offset, alias->size); + + if (flag1) + fprintf(pcfile, "\n"); + + return len; + + case AliasType2: + len += fprintf(pcfile, "{"); + notFirst = 0; + for (member = alias->parents; member; member = member->nextParent) { + if (member->child->type == AliasType0) { + if (notFirst) + len += fprintf(pcfile, ","); + if (len > 60) { + fprintf(pcfile, "\n "); + len = 0; + } + len = dumpalias(member->child, len, 0, 0); + notFirst = 1; + } + } + for (member = alias->parents; member; member = member->nextParent) { + if (member->child->type != AliasType0) { + if (notFirst) + len += fprintf(pcfile, ","); + if (len > 60) { + fprintf(pcfile, "\n "); + len = 0; + } + len = dumpalias(member->child, len, 0, 0); + notFirst = 1; + } + } + + len += fprintf(pcfile, "}"); + if (flag1) + fprintf(pcfile, "\n"); + return len; + + default: +#line 1661 + CError_FATAL(); + return 0; + } +} + +void pcformatset(void) { + // unknown args +} + +int GetLineEndOffset(char *str, int lineNum, int len) { + int offset; + char *work; + + offset = GetLineOffset(str, lineNum, len); + if (offset < 0) + return offset; + + work = str + offset; + while (*work) { + if (*work == '\n') + return work - str - 1; + work++; + } + return -1; +} + +int GetLineOffset(char *str, int lineNum, int len) { + char *work = str; + char *end; + + if (lineNum < 0) + return -1; + + end = str + len; + while (work < end) { + if (*work == '\n' && --lineNum <= 0) + return work - str; + work++; + } + + return 0; +} + +void DumpSourceCode(void) { + // unknown args +} + +int DumpIR_SrcBreak(void) { + // unknown args + return 0; +} + diff --git a/compiler_and_linker/unsorted/Scheduler.c b/compiler_and_linker/unsorted/Scheduler.c index e69de29..5a26a20 100644 --- a/compiler_and_linker/unsorted/Scheduler.c +++ b/compiler_and_linker/unsorted/Scheduler.c @@ -0,0 +1,548 @@ +#include "compiler/Scheduler.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/Alias.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/Registers.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct DGNode { + struct DGNode *x0; + struct DGNode *x4; + struct DGSuccessor *successors; + PCode *instr; + UInt16 x10; + UInt16 x12; + UInt16 x14; + UInt16 x16; + short predCount; +} DGNode; + +typedef struct DGSuccessor { + struct DGSuccessor *next; + DGNode *node; + UInt16 x8; +} DGSuccessor; + +typedef struct DGNodeList { + struct DGNodeList *next; + DGNode *node; +} DGNodeList; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static DGNodeList **register_uses[RegClassMax]; +static DGNodeList **register_defs[RegClassMax]; +static DGNodeList *memory_uses; +static DGNodeList *memory_defs; +static DGNodeList *side_effects; +static DGNodeList *volatile_refs; +static DGNode *defaultsuccessor; +static UInt16 criticalpath; +static MachineInfo *MI; + +static void initresources(void) { + int rclass; + int i; + + for (rclass = 0; (char) rclass < RegClassMax; rclass++) { + register_uses[(char) rclass] = oalloc(sizeof(DGNodeList *) * used_virtual_registers[(char) rclass]); + register_defs[(char) rclass] = oalloc(sizeof(DGNodeList *) * used_virtual_registers[(char) rclass]); + for (i = 0; i < used_virtual_registers[(char) rclass]; i++) { + register_uses[(char) rclass][i] = register_defs[(char) rclass][i] = NULL; + } + } + + memory_uses = memory_defs = NULL; + side_effects = NULL; + volatile_refs = NULL; + criticalpath = 0; +} + +static DGNode *makedgnode(PCode *instr) { + DGNode *node; + + node = oalloc(sizeof(DGNode)); + node->x0 = NULL; + node->x4 = NULL; + node->successors = NULL; + node->instr = instr; + node->x10 = node->x16 = MI->latency(instr); + node->x12 = 0; + node->x14 = 0; + node->predCount = 0; + return node; +} + +static DGNode *adddgnode(DGNode *head, DGNode *node) { + if (head) + head->x4 = node; + node->x0 = head; + return node; +} + +static DGNode *removedgnode(DGNode *head, DGNode *node) { + if (node->x4) + node->x4->x0 = node->x0; + else + head = node->x0; + + if (node->x0) + node->x0->x4 = node->x4; + + return head; +} + +static void addtolist(DGNodeList **list, DGNode *node) { + DGNodeList *entry = oalloc(sizeof(DGNodeList)); + entry->node = node; + entry->next = *list; + *list = entry; +} + +static DGNodeList *makedglistnode(DGNode *node) { + DGNodeList *list = oalloc(sizeof(DGNodeList)); + list->next = NULL; + list->node = node; + return list; +} + +int is_same_operand(PCodeArg *a, PCodeArg *b) { + if (a->kind != b->kind) + return 0; + + switch (a->kind) { + case PCOp_IMMEDIATE: + if (a->data.imm.value != b->data.imm.value) + return 0; + break; + case PCOp_REGISTER: + if ((char) a->arg != (char) b->arg) + return 0; + if (a->data.reg.reg != b->data.reg.reg) + return 0; + break; + case PCOp_MEMORY: + if (a->data.mem.offset != b->data.mem.offset) + return 0; + if (a->data.mem.obj != b->data.mem.obj) + return 0; + break; + case PCOp_LABEL: + if (a->data.label.label != b->data.label.label) + return 0; + break; + } + + return 1; +} + +static void addsuccessor(DGNode *a, DGNode *b, Boolean flag) { + int v6; + int r29; + DGSuccessor *succ; + + if (flag) + v6 = a->x10; + else + v6 = 0; + + if (a != b) { + r29 = (v6 > 0) ? v6 : 0; + for (succ = a->successors; succ; succ = succ->next) { + if (succ->node == b) { + if (succ->x8 < r29) { + succ->x8 = r29; + if (b->x16 + succ->x8 > a->x16) + a->x16 = b->x16 + succ->x8; + } + return; + } + } + + succ = oalloc(sizeof(DGSuccessor)); + succ->node = b; + succ->next = a->successors; + a->successors = succ; + succ->x8 = r29; + + if (flag && (succ->node->instr->flags & fPCodeFlag1)) + succ->x8 += MI->x8; + + b->predCount++; + + if (b->x16 + succ->x8 > a->x16) + a->x16 = b->x16 + succ->x8; + } +} + +static void serializeall(DGNode *nodes, DGNode *node) { + DGNode *scan; + + for (scan = nodes; scan; scan = scan->x0) + addsuccessor(node, scan, 0); +} + +static void serializelist(DGNode *node, DGNodeList *list) { + while (list) { + if (list->node != node) + addsuccessor(node, list->node, 0); + list = list->next; + } +} + +static void serializeregister(int rclass, DGNode *node, DGNodeList **defs, DGNodeList **uses, int isWrite) { + DGNodeList *list; + + if (isWrite) { + for (list = *uses; list; list = list->next) { + if (list->node != node) + addsuccessor(node, list->node, 1); + } + for (list = *defs; list; list = list->next) { + if (list->node != node) + addsuccessor(node, list->node, ((char) rclass == RegClass_SPR) || (MI->x4 == 0)); + } + + list = makedglistnode(node); + list->next = *defs; + *defs = list; + } else { + for (list = *defs; list; list = list->next) { + if (list->node != node) + addsuccessor(node, list->node, ((char) rclass == RegClass_SPR) || (MI->x4 == 0)); + } + + list = makedglistnode(node); + list->next = *uses; + *uses = list; + } +} + +static void serialize_load(DGNode *node) { + DGNodeList *list; + + for (list = memory_defs; list; list = list->next) { + if (may_alias(node->instr, list->node->instr)) + addsuccessor(node, list->node, 1); + } + + addtolist(&memory_uses, node); +} + +static void serialize_store(DGNode *node) { + DGNodeList *list; + + for (list = memory_uses; list; list = list->next) { + if (may_alias(node->instr, list->node->instr)) + addsuccessor(node, list->node, 1); + } + for (list = memory_defs; list; list = list->next) { + if (may_alias(node->instr, list->node->instr)) + addsuccessor(node, list->node, 1); + } + + addtolist(&memory_defs, node); + if (node->instr->flags & fPCodeFlag40000) + addtolist(&memory_uses, node); +} + +static void findsuccessors(DGNode *nodes, DGNode *node) { + PCode *instr; + PCodeArg *op; + int i; + + instr = node->instr; + for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { + switch (op->kind) { + case PCOp_IMMEDIATE: + case PCOp_MEMORY: + break; + case PCOp_REGISTER: + if ( + op->data.reg.reg < 0 || + op->data.reg.reg > used_virtual_registers[(char) op->arg] + ) + { +#line 491 + CError_FATAL(); + } + + if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { + if (op->data.reg.reg == Register2) + break; + if (op->data.reg.reg == Register0 && !(op->data.reg.effect & (EffectRead | EffectWrite))) + break; + } + + serializeregister( + op->arg, + node, + ®ister_defs[(char) op->arg][op->data.reg.reg], + ®ister_uses[(char) op->arg][op->data.reg.reg], + op->data.reg.effect & EffectWrite + ); + + break; + } + } + + if (instr->flags & (fPCodeFlag2 | fPCodeFlag20000)) + serialize_load(node); + else if (instr->flags & (fPCodeFlag4 | fPCodeFlag40000)) + serialize_store(node); + + if (instr->flags & fIsVolatile) { + serializelist(node, volatile_refs); + addtolist(&volatile_refs, node); + } + + if ( + ((instr->flags & fPCodeFlag8 | fPCodeFlag1) && (instr->flags & fLink)) || + (instr->flags & fSideEffects) || + MI->serializes(instr) + ) + { + serializeall(nodes, node); + addtolist(&side_effects, node); + } + + if (side_effects) + serializelist(node, side_effects); + + if (!node->successors && defaultsuccessor) + addsuccessor(node, defaultsuccessor, 0); + + if (node->x16 > criticalpath) + criticalpath = node->x16; +} + +static void computedeadlines(DGNode *nodes) { + while (nodes) { + nodes->x14 = criticalpath - nodes->x16; + nodes = nodes->x0; + } +} + +static int uncovering(DGNode *node) { + int counter; + DGSuccessor *succ; + + counter = 0; + for (succ = node->successors; succ; succ = succ->next) { + if (succ->node->predCount == 1) + counter++; + } + + return counter; +} + +static DGNode *selectinstruction(DGNode *nodes, UInt16 counter) { + DGNode *node; + DGNode *node2; + int a; + int b; + + node = nodes; + while (node) { + if (node->predCount == 0 && node->x12 <= counter && MI->can_issue(node->instr)) + break; + node = node->x0; + } + + if (!node) + return NULL; + + for (node2 = node->x0; node2; node2 = node2->x0) { + if ( + node2->predCount == 0 && + node2->x12 <= counter && + MI->can_issue(node2->instr) && + (node->x14 > counter || node2->x14 <= counter) + ) + { + if (node->x14 > counter && node2->x14 <= counter) { + node = node2; + continue; + } + + if ((a = uncovering(node)) > (b = uncovering(node2))) + continue; + + if (a < b) { + node = node2; + continue; + } + + if (node->x16 > node2->x16) + continue; + + if (node->x16 < node2->x16) { + node = node2; + continue; + } + + if (coloring) { + if (opcodeinfo[node->instr->op].x9 < opcodeinfo[node2->instr->op].x9) + continue; + + if (opcodeinfo[node->instr->op].x9 > opcodeinfo[node2->instr->op].x9) + node = node2; + } + } + } + + return node; +} + +static void holdoffsuccessors(DGNode *node, UInt16 counter) { + DGSuccessor *succ; + DGNode *n; + + for (succ = node->successors; succ; succ = succ->next) { + n = succ->node; + n->predCount--; + if (n->x12 < counter + succ->x8) + n->x12 = counter + succ->x8; + } +} + +static void scheduleblock(PCodeBlock *block) { + DGNode *node; + UInt16 counter; + PCode *instr; + UInt16 i; + DGNode *head; + + initresources(); + defaultsuccessor = NULL; + head = NULL; + + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + DGNode *n = makedgnode(instr); + findsuccessors(head, n); + if (instr->flags & fPCodeFlag1) + defaultsuccessor = n; + head = adddgnode(head, n); + } + + computedeadlines(head); + block->firstPCode = block->lastPCode = NULL; + block->pcodeCount = 0; + + MI->initialize(); + counter = 0; + while (head != NULL) { + for (i = 0; i < MI->x0; i++) { + if (head == NULL) + break; + + node = selectinstruction(head, counter); + if (!node) + break; + + instr = node->instr; + if (node->successors) + holdoffsuccessors(node, counter); + + appendpcode(block, instr); + MI->issue(instr); + head = removedgnode(head, node); + } + + MI->advance_clock(); + counter++; + } + + freeoheap(); +} + +void scheduleinstructions(Boolean flag) { + PCodeBlock *block; + int cpu; + + cpu = copts.schedule_cpu; + if (cpu == 10) { + MI = &machine7450; + } else if (copts.altivec_model != 0 || cpu == 7) { + MI = &machine7400; + } else if (cpu == 2) { + MI = &machine603; + } else if (cpu == 5) { + MI = &machine603e; + } else if (cpu == 3) { + MI = &machine604; + } else if (cpu == 6) { + MI = &machine604; + } else if (cpu == 4) { + MI = &machine750; + } else if (cpu == 1) { + MI = &machine601; + } else if (cpu == 9) { + MI = &machine821; + } else { + MI = &machine603; + } + + gather_alias_info(); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if ( + block->pcodeCount > 2 && + (flag || !(block->flags & (fPCBlockFlag1 | fPCBlockFlag2))) && + !(block->flags & fPCBlockFlag8) + ) + { + scheduleblock(block); + block->flags |= fPCBlockFlag8; + } + } +} + +int is_dependent(PCode *a, PCode *b, char rclass) { + int i; + int reg; + PCodeArg *op; + + if ( + b && + b->argCount >= 1 && + b->args[0].kind == PCOp_REGISTER && + (char) b->args[0].arg == rclass && + (b->args[0].data.reg.effect & EffectWrite) + ) + { + reg = b->args[0].data.reg.reg; + for (i = 0; i < a->argCount; i++) { + op = &a->args[i]; + if ( + op->kind == PCOp_REGISTER && + (char) op->arg == rclass && + (op->data.reg.effect & (EffectRead | EffectWrite)) && + op->data.reg.reg == reg + ) + return 1; + } + } + + return 0; +} + +int uses_vpermute_unit(PCode *instr) { + int cpu; + + cpu = copts.schedule_cpu; + if (cpu == 10) + return machine7450.uses_vpermute_unit(instr); + if (copts.altivec_model != 0 || cpu == 7) + return machine7400.uses_vpermute_unit(instr); + return 0; +} + +int default_uses_vpermute_unit(PCode *instr) { + return 0; +} diff --git a/compiler_and_linker/unsorted/SpillCode.c b/compiler_and_linker/unsorted/SpillCode.c index e69de29..e583613 100644 --- a/compiler_and_linker/unsorted/SpillCode.c +++ b/compiler_and_linker/unsorted/SpillCode.c @@ -0,0 +1,464 @@ +#include "compiler/SpillCode.h" +#include "compiler/CError.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/Coloring.h" +#include "compiler/InterferenceGraph.h" +#include "compiler/Operands.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/Registers.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/objects.h" + +static int last_unused_vreg_before_spilling; +static short rTEMP_for_VR_spill; + +void estimatespillcosts(void) { + PCodeBlock *block; + PCode *instr; + IGNode *node; + PCodeArg *op; + int i; + int weight; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (copts.optimize_for_size) + weight = 1; + else + weight = block->loopWeight; + + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if (PC_OP_IS_READ_ANY_REGISTER(op, coloring_class)) { + node = interferencegraph[op->data.reg.reg]; + if (node->instr8 || copts.optimize_for_size) + node->spillCost += weight; + else + node->spillCost += weight * 2; + } + op++; + } + + op = instr->args; + i = instr->argCount; + while (i--) { + if (PC_OP_IS_WRITE_ANY_REGISTER(op, coloring_class)) { + node = interferencegraph[op->data.reg.reg]; + if (node->instr8 || (instr->flags & fPCodeFlag8000)) + node->spillCost -= weight; + else + node->spillCost += weight; + } + op++; + } + } + } +} + +static Object *makespilltemporary(Type *type) { + Object *obj = lalloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + + obj->otype = OT_OBJECT; + obj->access = ACCESSPUBLIC; + obj->datatype = DLOCAL; + obj->type = type; + obj->name = CParser_GetUniqueName(); + obj->u.var.info = CodeGen_GetNewVarInfo(); + obj->u.var.uid = 0; + + return obj; +} + +static PCode *rematerialize_spilled_register(short reg, IGNode *node) { + PCode *instr = copypcode(node->instr8); + +#line 128 + CError_ASSERT(instr->args[0].kind == PCOp_REGISTER); + + instr->args[0].data.reg.reg = reg; + return instr; +} + +static void insert_load_spilled_register(PCode *instr, short reg, IGNode *node) { + Type *type; + Opcode opcode; + Object *object; + PCode *newInstr; + PCode *newInstr2; + SInt32 offset; + Operand operand; + + type = node->spillTemporary->type; + switch (coloring_class) { + case RegClass_CRFIELD: + case RegClass_GPR: + switch (type->size) { + case 1: + opcode = PC_LBZ; + break; + case 2: + opcode = is_unsigned(type) ? PC_LHZ : PC_LHA; + break; + case 4: + opcode = PC_LWZ; + break; + case 8: + opcode = PC_LWZ; + break; + default: +#line 187 + CError_FATAL(); + } + + memclrw(&operand, sizeof(Operand)); + operand.optype = OpndType_Symbol; + operand.object = node->spillTemporary; +#line 222 + CError_ASSERT(node->spillTemporary->datatype == DLOCAL); + + coerce_to_addressable(&operand); + +#line 233 + CError_ASSERT(operand.optype == OpndType_GPR_ImmOffset); + +#line 237 + CError_ASSERT(node->spillTemporary->datatype == DLOCAL); + + if (node->flags & fPairLow) + offset = low_offset; + else if (node->flags & fPairHigh) + offset = high_offset; + else + offset = 0; + insertpcodebefore(instr, makepcode(opcode, reg, operand.reg, operand.object, operand.immOffset + offset)); + break; + + case RegClass_FPR: +#line 253 + CError_ASSERT(node->spillTemporary->datatype == DLOCAL); + + if (node->flags & fPairLow) + offset = low_offset; + else if (node->flags & fPairHigh) + offset = high_offset; + else + offset = 0; + + object = node->spillTemporary; + insertpcodebefore( + instr, + makepcode( + (type->size == 8) ? PC_LFD : PC_LFS, + reg, + local_base_register(object), + object, + offset + ) + ); + break; + + case RegClass_VR: +#line 320 + CError_ASSERT(node->spillTemporary->datatype == DLOCAL); + + object = node->spillTemporary; + newInstr = makepcode(PC_ADDI, rTEMP_for_VR_spill, local_base_register(object), object, 0); + newInstr2 = makepcode(PC_LVX, reg, 0, rTEMP_for_VR_spill); + insertpcodebefore(instr, newInstr); + insertpcodeafter(newInstr, newInstr2); + break; + + default: +#line 333 + CError_FATAL(); + } +} + +static void insert_store_spilled_register(PCode *instr, Boolean flag, short reg, IGNode *node) { + Object *object; // r31 + Opcode opcode; // r30 + SInt32 offset; // r26 + PCode *newInstr2; // r26 + PCode *newInstr; // r25 + Type *type; // r25 + + object = node->spillTemporary; + type = object->type; + + switch (coloring_class) { + case RegClass_CRFIELD: + case RegClass_GPR: + switch (type->size) { + case 1: + opcode = PC_STB; + break; + case 2: + opcode = PC_STH; + break; + case 4: + opcode = PC_STW; + break; + case 8: + opcode = PC_STW; + break; + default: +#line 391 + CError_FATAL(); + } + + if (node->flags & fPairLow) + offset = low_offset; + else if (node->flags & fPairHigh) + offset = high_offset; + else + offset = 0; + + newInstr = makepcode(opcode, reg, local_base_register(object), object, offset); + if (flag) + insertpcodebefore(instr, newInstr); + else + insertpcodeafter(instr, newInstr); + + break; + + case RegClass_FPR: + newInstr = makepcode((type->size == 8) ? PC_STFD : PC_STFS, reg, local_base_register(object), object, 0); + if (flag) + insertpcodebefore(instr, newInstr); + else + insertpcodeafter(instr, newInstr); + + break; + + case RegClass_VR: + newInstr = makepcode(PC_ADDI, rTEMP_for_VR_spill, local_base_register(object), object, 0); + newInstr2 = makepcode(PC_STVX, reg, 0, rTEMP_for_VR_spill); + if (flag) + insertpcodebefore(instr, newInstr); + else + insertpcodeafter(instr, newInstr); + insertpcodeafter(newInstr, newInstr2); + + break; + + default: +#line 527 + CError_FATAL(); + } +} + +static void spillinstruction(PCodeBlock *block, PCode *instr) { + int reg; + int reg2; + int regs; + IGNode *node; + PCodeArg *op; + int i; + PCodeArg *op2; + int j; + int readCounter; + int writeCounter; + Boolean flag; + + regs = used_virtual_registers[coloring_class]; + flag = 0; + for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { +#line 563 + CError_ASSERT(instr->block != NULL); + + if ( + PC_OP_IS_ANY_REGISTER(op, coloring_class) && + (reg = op->data.reg.reg) < regs && + ((node = interferencegraph[op->data.reg.reg])->flags & fSpilled) + ) + { + reg2 = used_virtual_registers[coloring_class]++; + readCounter = 0; + writeCounter = 0; + + for (j = i, op2 = op; j < instr->argCount; j++, op2++) { + if (PC_OP_IS_REGISTER(op2, coloring_class, reg)) { + if (op2->data.reg.effect & EffectRead) + readCounter++; + if (op2->data.reg.effect & EffectWrite) + writeCounter++; + op2->data.reg.reg = reg2; + op2->data.reg.effect |= Effect40; + } + } + + if (readCounter) { + if (node->instr8) + insertpcodebefore(instr, rematerialize_spilled_register(reg2, node)); + else + insert_load_spilled_register(instr, reg2, node); + } + + if (writeCounter) { + if (node->instr8 || (instr->flags & fPCodeFlag8000)) + flag = 1; + else + insert_store_spilled_register(instr, 0, reg2, node); + } + } + } + + if (flag) + deletepcode(instr); +} + +static void spillcopy(PCodeBlock *block, PCode *instr) { + IGNode *node1; + IGNode *node2; + int reg; + + node1 = interferencegraph[instr->args[1].data.reg.reg]; + node2 = interferencegraph[instr->args[0].data.reg.reg]; + + if (node1->flags & fSpilled) { + if (node2->flags & fSpilled) { + reg = used_virtual_registers[coloring_class]++; + if (node1->instr8) + insertpcodebefore(instr, rematerialize_spilled_register(reg, node1)); + else + insert_load_spilled_register(instr, reg, node1); + insert_store_spilled_register(instr, 1, reg, node2); + } else { + if (node1->instr8) + insertpcodebefore(instr, rematerialize_spilled_register(instr->args[0].data.reg.reg, node1)); + else + insert_load_spilled_register(instr, instr->args[0].data.reg.reg, node1); + } + } else { + insert_store_spilled_register(instr, 1, instr->args[1].data.reg.reg, node2); + } + + deletepcode(instr); +} + +static void spillcall(PCodeBlock *block, PCode *instr) { + PCodeArg *opSrc; + PCodeArg *opDst; + int opCount; + int volatileCount; + int i; + + opCount = instr->argCount; + volatileCount = branch_count_volatiles(); + + opDst = instr->args + volatileCount; + opSrc = instr->args + volatileCount; + for (i = volatileCount; i < opCount; i++) { + if ( + PC_OP_IS_ANY_REGISTER(opSrc, coloring_class) && + opSrc->data.reg.reg >= n_real_registers[coloring_class] && + (interferencegraph[opSrc->data.reg.reg]->flags & fSpilled) + ) + { + instr->argCount--; + } else { + *opDst = *opSrc; + opDst++; + } + opSrc++; + } + + spillinstruction(block, instr); +} + +static void assign_spill_locations(void) { + UInt32 i; + IGNode *node; + Type *type; + + last_unused_vreg_before_spilling = used_virtual_registers[coloring_class]; + for (i = n_real_registers[coloring_class]; i < last_unused_vreg_before_spilling; i++) { + node = interferencegraph[i]; + if (node->flags & fCoalesced) + continue; + if (!(node->flags & fSpilled)) + continue; + + if (!node->spillTemporary) { + switch (coloring_class) { + case RegClass_GPR: + type = TYPE(&stunsignedlong); + break; + case RegClass_CRFIELD: + type = TYPE(&stunsignedlong); + break; + case RegClass_FPR: + type = TYPE(&stunsignedlong); + break; + case RegClass_VR: + type = TYPE(&stvectorunsignedchar); + break; + default: +#line 771 + CError_FATAL(); + } + + node->spillTemporary = makespilltemporary(type); + } + + if (node->spillTemporary->datatype == DLOCAL && !(node->spillTemporary->u.var.info->flags & VarInfoFlag1)) + assign_local_memory(node->spillTemporary); + + if (node->flags & fPairHigh) + Registers_GetVarInfo(node->spillTemporary)->regHi = Register0; + else + Registers_GetVarInfo(node->spillTemporary)->reg = Register0; + } +} + +void insertspillcode(void) { + PCodeBlock *block; + PCode *instr; + PCode *nextInstr; + PCodeArg *op; + UInt32 i; + int flag; + + rTEMP_for_VR_spill = 0; + assign_spill_locations(); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = nextInstr) { + nextInstr = instr->nextPCode; + flag = 0; + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + PC_OP_IS_ANY_REGISTER(op, coloring_class) && + op->data.reg.reg < last_unused_vreg_before_spilling && + (interferencegraph[op->data.reg.reg]->flags & fSpilled) + ) + { + flag = 1; + break; + } + op++; + } + + if (flag) { + if (coloring_class == RegClass_VR && rTEMP_for_VR_spill == 0) + rTEMP_for_VR_spill = used_virtual_registers[RegClass_GPR]++; + + if (instr->flags & fPCodeFlag10) + spillcopy(block, instr); + else if (instr->flags & fPCodeFlag8) + spillcall(block, instr); + else + spillinstruction(block, instr); + } + } + } +} diff --git a/compiler_and_linker/unsorted/StrengthReduction.c b/compiler_and_linker/unsorted/StrengthReduction.c index e69de29..9b6117d 100644 --- a/compiler_and_linker/unsorted/StrengthReduction.c +++ b/compiler_and_linker/unsorted/StrengthReduction.c @@ -0,0 +1,752 @@ +#include "compiler/StrengthReduction.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/LoopDetection.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/UseDefChains.h" + +int strengthreducedloops; + +static PCode *findinitializer(Loop *loop, short reg) { + UInt32 *vec; + PCode *best; + RegUseOrDef *list; + + vec = usedefinfo[loop->body->blockIndex].defvec8; + best = NULL; + + for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) { + if ( + !(bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)) && + bitvectorgetbit(list->id, vec) + ) + { + if (best) + return NULL; + best = Defs[list->id].pcode; + } + } + + if (best) { + if (best->op == PC_LI || best->op == PC_ADDI || best->op == PC_ADD) + return best; + } + + return NULL; +} + +static int isbasicinductionvariable(Loop *loop, short reg, SInt32 step) { + RegUseOrDef *list; + PCode *instr; + + for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) { + instr = Defs[list->id].pcode; + if (bitvectorgetbit(instr->block->blockIndex, loop->memberblocks)) { + if (instr->op != PC_ADDI) + return 0; + if (instr->args[1].data.reg.reg != reg) + return 0; + if (instr->args[2].data.imm.value != step) + return 0; + } + } + + return 1; +} + +static void addbasicinductionvariable(Loop *loop, short reg, SInt32 step) { + BasicInductionVar *biv; + RegUseOrDef *list; + PCode *instr; + InstrList *instrList; + + for (biv = loop->basicInductionVars; biv; biv = biv->next) { + if (biv->reg == reg) + return; + } + + biv = oalloc(sizeof(BasicInductionVar)); + biv->next = loop->basicInductionVars; + loop->basicInductionVars = biv; + + biv->loop = loop; + biv->inductionVars = NULL; + biv->instrsC = NULL; + biv->step = step; + biv->reg = reg; + + for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) { + instr = Defs[list->id].pcode; + if (bitvectorgetbit(instr->block->blockIndex, loop->memberblocks)) { + instrList = oalloc(sizeof(InstrList)); + instrList->next = biv->instrsC; + biv->instrsC = instrList; + instrList->instr = instr; + } + } + + biv->initializer = findinitializer(loop, reg); +} + +static void findbasicinductionvariables(Loop *loop) { + SInt16 step; + BlockList *block; + PCode *instr; + short reg; + + for (block = loop->blocks; block; block = block->next) { + for (instr = block->block->firstPCode; instr; instr = instr->nextPCode) { + if (instr->op == PC_ADDI) { + if ( + (reg = instr->args[0].data.reg.reg) >= 32 && + instr->args[1].data.reg.reg == reg && + isbasicinductionvariable(loop, reg, step = instr->args[2].data.imm.value) + ) + addbasicinductionvariable(loop, reg, step); + } + } + } +} + +static void findallbasicinductionvariables(Loop *loop) { + while (loop) { + if (loop->children) + findallbasicinductionvariables(loop->children); + findbasicinductionvariables(loop); + loop = loop->nextSibling; + } +} + +static int isinductionvariable(BasicInductionVar *biv, int useID, SInt32 *result1, short *result2, short *result3, Loop **result4) { + RegUseOrDef *list; + int counter; + Loop *loop; + Loop *scanloop; + PCode *instr; + + instr = Uses[useID].pcode; + *result2 = 0; + *result3 = 0; + *result4 = NULL; + + switch (instr->op) { + case PC_MULLI: + *result1 = instr->args[2].data.imm.value; + break; + + case PC_RLWINM: + if (instr->args[3].data.imm.value) + return 0; + if (instr->args[2].data.imm.value > 15) + return 0; + if (instr->args[4].data.imm.value != (31 - instr->args[2].data.imm.value)) + return 0; + if (PCODE_FLAG_SET_F(instr) & fPCodeFlag20000000) + return 0; + *result1 = 1 << instr->args[2].data.imm.value; + break; + + case PC_LBZX: + case PC_LHZX: + case PC_LHAX: + case PC_LWZX: + case PC_STBX: + case PC_STHX: + case PC_STWX: + case PC_LFSX: + case PC_LFDX: + case PC_STFSX: + case PC_STFDX: + *result2 = 0; + *result3 = 0; + if (instr->args[1].data.reg.reg == biv->reg) { + *result2 = 1; + *result3 = 2; + } else if (instr->args[2].data.reg.reg == biv->reg) { + *result2 = 2; + *result3 = 1; + } + + counter = 0; + for (list = reg_Defs[RegClass_GPR][instr->args[*result3].data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, biv->loop->memberblocks)) + counter++; + } + if (counter) + return 0; + + loop = biv->loop; + for (scanloop = loop->parent; scanloop; scanloop = scanloop->parent) { + counter = 0; + for (list = reg_Defs[RegClass_GPR][instr->args[*result3].data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, scanloop->memberblocks)) + counter++; + } + if (!biv->initializer || bitvectorgetbit(biv->initializer->block->blockIndex, scanloop->memberblocks)) + counter++; + if (counter) + break; + loop = scanloop; + } + + *result4 = loop; + *result1 = 1; + return 1; + + default: + return 0; + } + + counter = 0; + for (list = reg_Defs[RegClass_GPR][instr->args[0].data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, biv->loop->memberblocks)) + counter++; + } + + return counter == 1; +} + +static void addinductionvariable(BasicInductionVar *biv, PCode *instr, SInt32 val1, short val2, short val3, Loop *val4) { + InductionVar *iv; + + iv = oalloc(sizeof(InductionVar)); + iv->next = biv->inductionVars; + biv->inductionVars = iv; + + iv->basicVar = biv; + iv->instr = instr; + iv->instrC = NULL; + iv->step = val1; + iv->x18 = val2; + iv->x1A = val3; + iv->someloop = val4; + if (instr->flags & (fPCodeFlag2 | fPCodeFlag4)) + iv->x1C = -1; + else + iv->x1C = instr->args[0].data.reg.reg; + iv->x1E = -1; +} + +static void findnonbasicinductionvariables(Loop *loop) { + BasicInductionVar *biv; + RegUseOrDef *list; + SInt32 result1; + short result2; + short result3; + Loop *result4; + + for (biv = loop->basicInductionVars; biv; biv = biv->next) { + for (list = reg_Uses[RegClass_GPR][biv->reg]; list; list = list->next) { + if (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)) { + if (isinductionvariable(biv, list->id, &result1, &result2, &result3, &result4)) + addinductionvariable(biv, Uses[list->id].pcode, result1, result2, result3, result4); + } + } + } +} + +static void findallnonbasicinductionvariables(Loop *loop) { + while (loop) { + if (loop->children) + findallnonbasicinductionvariables(loop->children); + if (loop->basicInductionVars) + findnonbasicinductionvariables(loop); + loop = loop->nextSibling; + } +} + +static void initializeinductionvariable(InductionVar *iv) { + BasicInductionVar *biv; // r31 + PCode *instr; // r27 + PCodeBlock *preheader; // r30 + SInt32 value30; // r30 + short reg29; // r29 + short reg26; // r26 + + biv = iv->basicVar; + preheader = biv->loop->preheader; + + if (iv->x1A) { + reg29 = iv->instr->args[iv->x1A].data.reg.reg; + reg26 = iv->instr->args[iv->x18].data.reg.reg; + instr = NULL; + + if ( + biv->initializer && + biv->initializer->op == PC_LI && + biv->initializer->block == preheader + ) + { + if (biv->initializer->args[1].data.imm.value == 0) + instr = makepcode(PC_MR, iv->x1E, reg29); + else if (FITS_IN_SHORT(biv->initializer->args[1].data.imm.value)) + instr = makepcode(PC_ADDI, iv->x1E, reg29, 0, biv->initializer->args[1].data.imm.value); + } + + if (!instr) + instr = makepcode(PC_ADD, iv->x1E, reg29, reg26); + + if (biv->initializer && instr->op != PC_ADD) + insertpcodeafter(biv->initializer, instr); + else if (iv->someloop && iv->someloop->preheader->lastPCode) + insertpcodebefore(iv->someloop->preheader->lastPCode, instr); + else + insertpcodebefore(preheader->lastPCode, instr); + + iv->instrC = instr; + iv->x1C = reg29; + return; + } + + if (!biv->initializer || biv->initializer->op != PC_LI) { + instr = copypcode(iv->instr); + instr->args[0].data.reg.reg = iv->x1E; + insertpcodebefore(preheader->lastPCode, instr); + } else { + value30 = biv->initializer->args[1].data.imm.value * iv->step; + if (!FITS_IN_SHORT(value30)) { + instr = makepcode(PC_LIS, iv->x1E, 0, HIGH_PART(value30)); + insertpcodeafter(biv->initializer, instr); + if (value30 != 0) + insertpcodeafter(instr, makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, LOW_PART(value30))); + } else { + instr = makepcode(PC_LI, iv->x1E, value30); + insertpcodeafter(biv->initializer, instr); + } + } +} + +static void incrementinductionvariable(InductionVar *iv) { + SInt32 value; + BasicInductionVar *biv; + PCode *instr; + InstrList *list; + + biv = iv->basicVar; + value = iv->step * biv->step; + for (list = biv->instrsC; list; list = list->next) { + if (!FITS_IN_SHORT(value)) { + instr = makepcode(PC_ADDIS, iv->x1E, iv->x1E, 0, HIGH_PART(value)); + insertpcodeafter(list->instr, instr); + + if (value != 0) { + instr = makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, LOW_PART(value)); + insertpcodeafter(list->instr->nextPCode, instr); + } + } else { + instr = makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, value); + insertpcodeafter(list->instr, instr); + } + } +} + +static void copyinductionvariable(InductionVar *iv) { + if (iv->instr->flags & (fPCodeFlag2 | fPCodeFlag4)) { + iv->instr->op -= 2; + iv->instr->args[1].data.reg.reg = iv->x1E; + iv->instr->args[2].kind = PCOp_IMMEDIATE; + iv->instr->args[2].data.imm.value = 0; + iv->instr->args[2].data.imm.obj = NULL; + } else { + insertpcodeafter(iv->instr, makepcode(PC_MR, iv->x1C, iv->x1E)); + deletepcode(iv->instr); + } +} + +static int testnestediv(InductionVar *iv, SInt32 step1, int reg, SInt32 step2, Loop *loop1, Loop *loop2) { + SInt32 addend; + BlockList *list; + PCode *instr; + PCodeArg *op; + int i; + + if (iv->instrC && iv->x1C == reg) { + if (iv->instrC->op == PC_MR) + addend = 0; + else if (iv->instrC->op == PC_ADDI) + addend = iv->instrC->args[2].data.imm.value; + else + return 0; + + if (step2 == (addend + (step1 * iv->step * loop2->iterationCount))) { + for (list = loop1->blocks; list && list->block != loop2->blocks->block; list = list->next) { + for (instr = list->block->firstPCode; instr; instr = instr->nextPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg == reg + ) + return 0; + op++; + } + } + } + return 1; + } + } + + return 0; +} + +static void strengthreducenestediv(short reg, SInt32 step, PCode *initializer, Loop *loop) { + Loop *scanloop; + BasicInductionVar *biv; + InductionVar *iv; + PCode *instr; + PCodeArg *op; + int i; + + for (scanloop = loop->children; scanloop; scanloop = scanloop->nextSibling) { + if ( + scanloop->isKnownCountingLoop && + scanloop->x4F && + bitvectorgetbit(scanloop->body->blockIndex, loop->vec2C) + ) + { + for (biv = scanloop->basicInductionVars; biv; biv = biv->next) { + for (iv = biv->inductionVars; iv; iv = iv->next) { + if (testnestediv(iv, biv->step, reg, step, loop, scanloop)) { + deletepcode(iv->instrC); + if (initializer) { + insertpcodeafter(initializer, iv->instrC); + } else if (loop->body->lastPCode) { + for (instr = loop->body->lastPCode; instr; instr = instr->prevPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) && + op->data.reg.reg == reg + ) + break; + op++; + } + } + + if (instr) + insertpcodeafter(instr, iv->instrC); + else + insertpcodebefore(loop->body->firstPCode, iv->instrC); + } else { + appendpcode(loop->body, iv->instrC); + } + } + } + } + } + } +} + +static void strengthreducenestedbiv(BasicInductionVar *biv) { + Loop *loop; + InductionVar *iv; + + loop = biv->loop; + for (iv = biv->inductionVars; iv; iv = iv->next) + strengthreducenestediv(iv->x1E, iv->step * biv->step, iv->instrC, loop); + + strengthreducenestediv(biv->reg, biv->step, biv->initializer, loop); +} + +static void strengthreduceinductionvariable(BasicInductionVar *biv) { + int counter; + InductionVar *iv; + InductionVar *otherIv; + short reg; + + counter = 0; + for (iv = biv->inductionVars; iv; iv = iv->next) { + if (iv->step == 1) + counter++; + } + + for (iv = biv->inductionVars; iv; iv = iv->next) { + if ( + (counter <= 4 || iv->step != 1) && + iv->instr->block && + (iv->x1A == 0 || iv->instr->args[2].kind != PCOp_IMMEDIATE) + ) + { + if (iv->x1E == -1) { + iv->x1E = used_virtual_registers[RegClass_GPR]++; + initializeinductionvariable(iv); + incrementinductionvariable(iv); + if (iv->step == 1) { + reg = iv->instr->args[iv->x1A].data.reg.reg; + for (otherIv = iv->next; otherIv; otherIv = otherIv->next) { + if (otherIv->x1A != 0 && otherIv->instr->args[otherIv->x1A].data.reg.reg == reg) + otherIv->x1E = iv->x1E; + } + } else { + for (otherIv = iv->next; otherIv; otherIv = otherIv->next) { + if (otherIv->step == iv->step) + otherIv->x1E = iv->x1E; + } + } + } + + copyinductionvariable(iv); + strengthreducedloops = 1; + } + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct BivInit { + SInt32 x0; + short x4; + short x6; + short x8; + Object *xA; +} BivInit; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void calc_biv_init(BasicInductionVar *biv, BivInit *init) { + PCode *instr; + PCode *scan; + PCodeArg *op; + int i; + + instr = biv->initializer; + init->x0 = 0; + init->x4 = -1; + init->x6 = -1; + init->x8 = 0; + init->xA = NULL; + + if (!biv->initializer || (biv->initializer->op != PC_ADDI && biv->initializer->op != PC_ADD)) + return; + + if (instr->op == PC_ADDI) { + if (instr->args[1].data.reg.reg == biv->reg) { + init->x0 = instr->args[2].data.imm.value; + for (scan = instr->prevPCode; scan; scan = scan->prevPCode) { + op = scan->args; + i = scan->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg == biv->reg && + (op->data.reg.effect & EffectWrite) + ) + { + if (scan->op == PC_ADD) { + init->x4 = scan->args[1].data.reg.reg; + init->x6 = scan->args[2].data.reg.reg; + } else if (scan->op == PC_ADDI) { + if (scan->args[2].kind == PCOp_IMMEDIATE) { + init->x4 = scan->args[1].data.reg.reg; + init->x8 = scan->args[2].data.imm.value; + } else if (scan->args[2].kind == PCOp_MEMORY) { + init->x4 = scan->args[1].data.reg.reg; + init->x8 = scan->args[2].data.mem.offset; + init->xA = scan->args[2].data.mem.obj; + } + } + return; + } + op++; + } + } + } else { + if (instr->args[2].kind == PCOp_IMMEDIATE) { + init->x4 = instr->args[1].data.reg.reg; + init->x8 = instr->args[2].data.imm.value; + } else if (instr->args[2].kind == PCOp_MEMORY) { + init->x4 = instr->args[1].data.reg.reg; + init->x8 = instr->args[2].data.mem.offset; + init->xA = instr->args[2].data.mem.obj; + } + } + } else if (instr->op == PC_ADD) { + if (instr->args[1].data.reg.reg == biv->reg) { + init->x6 = instr->args[2].data.reg.reg; + for (scan = instr->prevPCode; scan; scan = scan->prevPCode) { + op = scan->args; + i = scan->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg == biv->reg && + (op->data.reg.effect & EffectWrite) && + scan->op == PC_ADDI + ) + { + if (scan->args[2].kind == PCOp_IMMEDIATE) { + init->x4 = scan->args[1].data.reg.reg; + init->x8 = scan->args[2].data.imm.value; + } else if (scan->args[2].kind == PCOp_MEMORY) { + init->x4 = scan->args[1].data.reg.reg; + init->x8 = scan->args[2].data.mem.offset; + init->xA = scan->args[2].data.mem.obj; + } + return; + } + op++; + } + } + } else { + init->x4 = instr->args[1].data.reg.reg; + init->x6 = instr->args[2].data.reg.reg; + } + } +} + +static void combineinductionvariables(Loop *loop, BasicInductionVar *biv1, BasicInductionVar *biv2, SInt32 difference) { + PCode *instr1; // r31 + int reg1; // r30 + int reg2; // r29 + PCode *instr2; // r24 + PCodeBlock *nextBlock; // r24 + BlockList *list; + PCodeArg *op; + int i; + PCode *instr; + + instr1 = NULL; + instr2 = NULL; + + reg1 = biv1->reg; +#line 930 + CError_ASSERT(reg1 >= 0); + + reg2 = biv2->reg; +#line 934 + CError_ASSERT(reg2 >= 0); + + if (!FITS_IN_SHORT(difference)) + return; + + for (list = loop->blocks; list; list = list->next) { + for (instr = list->block->firstPCode; instr; instr = instr->nextPCode) { + if (instr1) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg == reg1 + ) + return; + op++; + } + } + + if (instr->op == PC_ADDI) { + if (instr->args[0].data.reg.reg == reg1) { + if (instr1) + return; + instr1 = instr; + } else if (instr->args[0].data.reg.reg == reg2) { + if (instr2) + return; + instr2 = instr; + } + } + } + } + + if (loop->body->lastPCode->flags & fPCodeFlag1) { + nextBlock = NULL; + + for (i = 0; i < loop->body->lastPCode->argCount; i++) { + if (loop->body->lastPCode->args[i].kind == PCOp_LABEL) { + nextBlock = loop->body->lastPCode->args[i].data.label.label->block; + break; + } + } + + if (!nextBlock) + return; + } else { + nextBlock = loop->body->nextBlock; + } + + deletepcode(instr1); + instr1->args[1].data.reg.reg = reg2; + instr1->args[2].data.imm.value = difference; + + if (nextBlock->firstPCode) + insertpcodebefore(nextBlock->firstPCode, instr1); + else + appendpcode(nextBlock, instr1); + + biv1->reg = -1; + strengthreducedloops = 1; +} + +static void strengthreduceinductionvariables(Loop *loop) { + BasicInductionVar *biv1; + BasicInductionVar *biv2; + BivInit init1; + BivInit init2; + + for (biv1 = loop->basicInductionVars; biv1; biv1 = biv1->next) { + if (biv1->inductionVars) + strengthreduceinductionvariable(biv1); + strengthreducenestedbiv(biv1); + } + + for (biv1 = loop->basicInductionVars; biv1; biv1 = biv1->next) { + if (biv1->reg != -1) { + calc_biv_init(biv1, &init1); + if (init1.x4 != -1) { + for (biv2 = loop->basicInductionVars; biv2; biv2 = biv2->next) { + if (biv2->reg != -1 && biv2 != biv1) { + calc_biv_init(biv2, &init2); + if ( + init2.x4 != -1 && + init1.x4 == init2.x4 && + init1.x6 == init2.x6 && + init1.x8 == init2.x8 && + init1.xA == init2.xA && + biv1->step == biv2->step + ) + { + if (init1.x0 < init2.x0) { + combineinductionvariables(loop, biv2, biv1, init2.x0 - init1.x0); + } else { + combineinductionvariables(loop, biv1, biv2, init1.x0 - init2.x0); + break; + } + } + } + } + } + } + } +} + +static void strengthreduceallinductionvariables(Loop *loop) { + while (loop) { + if (loop->children) + strengthreduceallinductionvariables(loop->children); + if (loop->basicInductionVars) + strengthreduceinductionvariables(loop); + loop = loop->nextSibling; + } +} + +void strengthreduceloops(void) { + strengthreducedloops = 0; + if (loopsinflowgraph) { + computeusedefchains(0); + findallbasicinductionvariables(loopsinflowgraph); + findallnonbasicinductionvariables(loopsinflowgraph); + strengthreduceallinductionvariables(loopsinflowgraph); + freeoheap(); + } +} diff --git a/compiler_and_linker/unsorted/Switch.c b/compiler_and_linker/unsorted/Switch.c index af62eb3..185ec71 100644 --- a/compiler_and_linker/unsorted/Switch.c +++ b/compiler_and_linker/unsorted/Switch.c @@ -2,13 +2,20 @@ #include "compiler/CError.h" #include "compiler/CFunc.h" #include "compiler/CInt64.h" -#include "compiler/objects.h" #include "compiler/CParser.h" +#include "compiler/InstrSelection.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/Operands.h" #include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/RegisterInfo.h" +#include "compiler/TOC.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" ObjectList *switchtables; -static void *caselabels; -static void *caseranges; +static SwitchCase **caselabels; +static CaseRange *caseranges; static SInt32 ncases; static SInt32 nranges_minus1; static CInt64 min; @@ -20,25 +27,446 @@ static Type *selector_type; static PCodeLabel *defaultlabel; static CInt64 range; -static void compare_cases() { +static int compare_cases(const void *a, const void *b) { + const SwitchCase **casea = (const SwitchCase **) a; + const SwitchCase **caseb = (const SwitchCase **) b; + + if (CInt64_Less((*casea)->min, (*caseb)->min)) + return -1; + if (CInt64_Greater((*casea)->min, (*caseb)->min)) + return 1; + return 0; } static void build_case_ranges(Type *type, SwitchCase *cases, CLabel *label) { + SwitchCase **caseptr; + SInt32 i; + SwitchCase *curcase; + CaseRange *currange; + + if (type->size == 8) { + min.lo = 0; + min.hi = 0x80000000; + max.lo = 0xFFFFFFFF; + max.hi = 0x7FFFFFFF; + } else if (type->size == 4) { + CInt64_SetLong(&min, 0x80000000); + CInt64_SetLong(&max, 0x7FFFFFFF); + } else if (is_unsigned(type)) { + min.hi = 0; + min.lo = 0; + max.hi = 0; + max.lo = 0xFFFF; + } else { + CInt64_SetLong(&min, -0x8000); + CInt64_SetLong(&max, 0x7FFF); + } + + caselabels = lalloc(sizeof(SwitchCase *) * ncases); + caseptr = caselabels; + while (cases) { + *caseptr = cases; + cases = cases->next; + ++caseptr; + } + + caseranges = lalloc(((ncases * 2) + 2) * sizeof(CaseRange)); + if (type->size < 8) { + for (i = 0; i < ncases; i++) + CInt64_SetLong(&caselabels[i]->min, caselabels[i]->min.lo); + } + + qsort(caselabels, ncases, sizeof(SwitchCase *), &compare_cases); + + currange = caseranges; + currange->min = min; + currange->range = CInt64_Sub(max, min); + currange->label = label->pclabel; + + for (i = 0; i < ncases; i++) { + curcase = caselabels[i]; + if (CInt64_GreaterEqual(curcase->min, min) && CInt64_LessEqual(curcase->min, max)) { + if (CInt64_Equal(currange->min, min)) + first = curcase->min; + range = CInt64_Sub(curcase->min, first); + + if (CInt64_Greater(curcase->min, currange->min)) { + currange->range = CInt64_Sub(CInt64_Sub(curcase->min, currange->min), cint64_one); + (++currange)->min = curcase->min; + } else if (CInt64_Greater(currange->min, min) && curcase->label->pclabel == currange[-1].label) { + currange[-1].range = CInt64_Add(currange[-1].range, cint64_one); + if (CInt64_Equal(currange->range, cint64_zero)) { + currange--; + } else { + currange->min = CInt64_Add(currange->min, cint64_one); + currange->range = CInt64_Sub(currange->range, cint64_one); + } + continue; + } + + currange->range = cint64_zero; + currange->label = curcase->label->pclabel; + + if (CInt64_Less(curcase->min, max)) { + currange++; + currange->min = CInt64_Add(curcase->min, cint64_one); + currange->range = CInt64_Sub(max, currange->min); + currange->label = label->pclabel; + } + } + } + + nranges_minus1 = currange - caseranges; } -static void treecompare() { +static void treecompare(SInt32 start, SInt32 end) { + SInt32 r30; + SInt32 r29; + CaseRange *currange; + int count; + + count = end - start; +#line 175 + CError_ASSERT(selector_type->size <= 4); + + r29 = start + (count >> 1) + 1; + currange = caseranges + r29; + + if (CInt64_Equal(currange[-1].range, cint64_zero) && (!(count & 1) || (CInt64_NotEqual(currange->range, cint64_zero) && count > 1))) { + currange--; + r29--; + } + + r30 = r29 - 1; + + if (selector_type->size < 4 && is_unsigned(selector_type)) { + emitpcode(PC_CMPLI, 0, selector_gpr, CInt64_GetULong(&currange->min)); + } else if (FITS_IN_SHORT((SInt32) CInt64_GetULong(&currange->min))) { + emitpcode(PC_CMPI, 0, selector_gpr, CInt64_GetULong(&currange->min)); + } else { + SInt32 value = CInt64_GetULong(&currange->min); + int reg = ALLOC_GPR(); + load_immediate(reg, value); + emitpcode(PC_CMP, 0, selector_gpr, reg); + } + + if (CInt64_Equal(currange->range, cint64_zero) && r29 < end) { + branch_conditional(0, EEQU, 1, currange->label); + r29++; + } + + if (r29 == end) { + if (start == r30) { + if (caseranges[start].label == caseranges[end].label) { + branch_always(caseranges[start].label); + } else { + branch_conditional(0, EGREATEREQU, 1, caseranges[end].label); + branch_always(caseranges[start].label); + } + } else { + branch_conditional(0, EGREATEREQU, 1, caseranges[end].label); + treecompare(start, r30); + } + } else { + if (start == r30) { + branch_conditional(0, ELESS, 1, caseranges[start].label); + treecompare(r29, end); + } else { + PCodeLabel *label = makepclabel(); + branch_conditional(0, EGREATEREQU, 1, label); + treecompare(start, r30); + branch_label(label); + treecompare(r29, end); + } + } } -static void I8_treecompare() { +static void I8_treecompare(SInt32 start, SInt32 end) { + SInt32 r30; + SInt32 r29; + CaseRange *currange; + int count; + + count = end - start; + + r29 = start + (count >> 1) + 1; + currange = caseranges + r29; + + if (CInt64_Equal(currange[-1].range, cint64_zero) && (!(count & 1) || (CInt64_NotEqual(currange->range, cint64_zero) && count > 1))) { + currange--; + r29--; + } + + r30 = r29 - 1; + + if (CInt64_Equal(currange->range, cint64_zero) && r29 < end) { + short a = ALLOC_GPR(); + short b = ALLOC_GPR(); + load_immediate(a, currange->min.lo); + load_immediate(b, currange->min.hi); + emitpcode(PC_XOR, a, selector_gpr, a); + emitpcode(PC_XOR, b, selector_gprHi, b); + emitpcode(PC_OR, b, a, b); + emitpcode(PC_CMPI, 0, b, 0); + branch_conditional(0, EEQU, 1, currange->label); + r29++; + } + + if (r29 == end) { + if (start == r30) { + if (caseranges[start].label == caseranges[end].label) { + branch_always(caseranges[start].label); + } else { + short a = ALLOC_GPR(); + short b = ALLOC_GPR(); + short c = ALLOC_GPR(); + short d = ALLOC_GPR(); + load_immediate(a, currange->min.lo); + load_immediate(b, currange->min.hi); + if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { + emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); + emitpcode(PC_XORIS, d, b, 0x8000); + } else { + c = selector_gprHi; + d = b; + } + emitpcode(PC_SUBFC, a, a, selector_gpr); + emitpcode(PC_SUBFE, b, d, c); + emitpcode(PC_SUBFE, b, a, a); + emitpcode(PC_NEG, b, b); + emitpcode(PC_CMPI, 0, b, 0); + branch_conditional(0, EEQU, 1, caseranges[end].label); + branch_always(caseranges[start].label); + } + } else { + short a = ALLOC_GPR(); + short b = ALLOC_GPR(); + short c = ALLOC_GPR(); + short d = ALLOC_GPR(); + load_immediate(a, currange->min.lo); + load_immediate(b, currange->min.hi); + if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { + emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); + emitpcode(PC_XORIS, d, b, 0x8000); + } else { + c = selector_gprHi; + d = b; + } + emitpcode(PC_SUBFC, a, a, selector_gpr); + emitpcode(PC_SUBFE, b, d, c); + emitpcode(PC_SUBFE, b, a, a); + emitpcode(PC_NEG, b, b); + emitpcode(PC_CMPI, 0, b, 0); + branch_conditional(0, EEQU, 1, caseranges[end].label); + I8_treecompare(start, r30); + } + } else { + if (start == r30) { + short a = ALLOC_GPR(); + short b = ALLOC_GPR(); + short c = ALLOC_GPR(); + short d = ALLOC_GPR(); + load_immediate(a, currange->min.lo); + load_immediate(b, currange->min.hi); + if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { + emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); + emitpcode(PC_XORIS, d, b, 0x8000); + } else { + c = selector_gprHi; + d = b; + } + emitpcode(PC_SUBFC, a, selector_gpr, a); + emitpcode(PC_SUBFE, b, c, d); + emitpcode(PC_SUBFE, b, a, a); + emitpcode(PC_NEG, b, b); + emitpcode(PC_CMPI, 0, b, 0); + branch_conditional(0, ENOTEQU, 1, caseranges[end].label); + I8_treecompare(r29, end); + } else { + PCodeLabel *label; + short a = ALLOC_GPR(); + short b = ALLOC_GPR(); + short c = ALLOC_GPR(); + short d = ALLOC_GPR(); + load_immediate(a, currange->min.lo); + load_immediate(b, currange->min.hi); + if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { + emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); + emitpcode(PC_XORIS, d, b, 0x8000); + } else { + c = selector_gprHi; + d = b; + } + emitpcode(PC_SUBFC, a, a, selector_gpr); + emitpcode(PC_SUBFE, b, d, b); + emitpcode(PC_SUBFE, b, a, a); + emitpcode(PC_NEG, b, b); + emitpcode(PC_CMPI, 0, b, 0); + label = makepclabel(); + branch_conditional(0, EEQU, 1, label); + I8_treecompare(start, r30); + branch_label(label); + I8_treecompare(r29, end); + } + } } static void generate_tree(ENode *expr) { + Operand op; + + memclrw(&op, sizeof(Operand)); + if (TYPE_IS_8BYTES(expr->rtype)) { + GEN_NODE(expr, &op); + coerce_to_register_pair(&op, expr->rtype, 0, 0); + selector_type = expr->rtype; + selector_gpr = op.reg; + selector_gprHi = op.regHi; + I8_treecompare(0, nranges_minus1); + } else { + GEN_NODE(expr, &op); + if (expr->rtype->size < 4) + extend32(&op, expr->rtype, 0); + ENSURE_GPR(&op, expr->rtype, 0); + selector_type = expr->rtype; + selector_gpr = op.reg; + treecompare(0, nranges_minus1); + } } -static void create_switch_table() { +static Object *create_switch_table(void) { + Object *obj; + ObjectList *list; + CaseRange *currange; + UInt32 *outptr; + CInt64 value; + + obj = galloc(sizeof(Object)); + list = galloc(sizeof(ObjectList)); + memclrw(obj, sizeof(Object)); + memclrw(list, sizeof(ObjectList)); + + obj->otype = OT_OBJECT; + obj->access = ACCESSPUBLIC; + obj->datatype = DDATA; + obj->name = CParser_GetUniqueName(); + obj->toc = NULL; + obj->sclass = TK_STATIC; + obj->qual = Q_CONST; + obj->flags |= OBJECT_FLAGS_2 | OBJECT_FLAGS_4; + obj->u.data.linkname = obj->name; + obj->type = NULL; + createIndirect(obj, 0, 0); + obj->type = TYPE(&void_ptr); + + obj->u.data.u.switchtable.size = CInt64_GetULong(&range) + 1; + obj->u.data.u.switchtable.data = lalloc(4 * obj->u.data.u.switchtable.size); + + currange = caseranges; + outptr = (UInt32 *) obj->u.data.u.switchtable.data; + value = cint64_zero; + while (CInt64_LessEqual(value, range)) { + while (CInt64_Greater(CInt64_Add(first, value), CInt64_Add(currange->min, currange->range))) + currange++; + // HACK - this will not work properly on 64-bit systems + *outptr = (UInt32) currange->label; + value = CInt64_Add(value, cint64_one); + outptr++; + } + + list->object = obj; + list->next = switchtables; + switchtables = list; + return list->object; } static void generate_table(ENode *expr, SwitchInfo *info) { + Object *table; + short reg; + short reg2; + short reg3; + SwitchCase *curcase; + Operand op1; + Operand op2; + + CInt64 val3 = {0, 3}; + memclrw(&op1, sizeof(Operand)); + memclrw(&op2, sizeof(Operand)); + + if (CInt64_Greater(first, cint64_zero) && CInt64_Less(first, val3)) { + range = CInt64_Add(range, first); + first = cint64_zero; + } + + table = create_switch_table(); +#line 553 + CError_ASSERT(!TYPE_IS_8BYTES(expr->rtype)); + + GEN_NODE(expr, &op1); + if (expr->rtype->size < 4) + extend32(&op1, expr->rtype, 0); + ENSURE_GPR(&op1, expr->rtype, 0); + + reg = op1.reg; + if (CInt64_NotEqual(first, cint64_zero)) { + SInt32 value; + SInt32 valueext; + reg = ALLOC_GPR(); + value = -CInt64_GetULong(&first); + valueext = (SInt16) value; + if (value != valueext) { + emitpcode(PC_ADDIS, reg, op1.reg, 0, HIGH_PART(value)); + if (value) + emitpcode(PC_ADDI, reg, reg, 0, valueext); + } else { + emitpcode(PC_ADDI, reg, op1.reg, 0, value); + } + } + + if (FITS_IN_SHORT(CInt64_GetULong(&range))) { + short tmp = ALLOC_GPR(); + load_immediate(tmp, CInt64_GetULong(&range)); + emitpcode(PC_CMPL, 0, reg, tmp); + } else { + emitpcode(PC_CMPLI, 0, reg, CInt64_GetULong(&range)); + } + + branch_conditional(0, EGREATER, 0, defaultlabel); + if (table->toc) { + op2.optype = OpndType_Symbol; + op2.object = table->toc; + indirect(&op2, NULL); + } else { + op2.optype = OpndType_Symbol; + op2.object = table; + } + + if (op2.optype != OpndType_GPR) { + reg2 = ALLOC_GPR(); + Coerce_to_register(&op2, TYPE(&void_ptr), reg2); + } + + if (op2.optype != OpndType_GPR) { +#line 599 + CError_FATAL(); + } else { + if (op2.reg != reg2) + emitpcode(PC_MR, reg2, op2.reg); + } + + if (CInt64_Equal(first, cint64_zero)) { + reg = ALLOC_GPR(); + emitpcode(PC_RLWINM, reg, op1.reg, 2, 0, 29); + } else { + emitpcode(PC_RLWINM, reg, reg, 2, 0, 29); + } + + reg3 = reg2; + emitpcode(PC_LWZX, reg3, reg3, reg); + for (curcase = info->cases; curcase; curcase = curcase->next) + pcbranch(pclastblock, curcase->label->pclabel); + pcbranch(pclastblock, info->defaultlabel->pclabel); + emitpcode(PC_MTCTR, reg3); + branch_indirect(table); } void switchstatement(ENode *expr, SwitchInfo *info) { @@ -55,7 +483,7 @@ void switchstatement(ENode *expr, SwitchInfo *info) { } #line 656 - CError_ASSERT(ncases >= 0 && ncases <= 0x3333332); + CError_ASSERT(ncases >= 0 && ncases <= 0x3333332U); if (!info->defaultlabel->pclabel) info->defaultlabel->pclabel = makepclabel(); @@ -68,11 +496,30 @@ void switchstatement(ENode *expr, SwitchInfo *info) { return; } - if (!use_table || nranges_minus1 < 8 || (nranges_minus1 * 2) < ((range.lo / 1) + 4)) + if (!use_table || nranges_minus1 < 8 || (nranges_minus1 * 2) < ((range.lo / 2) + 4)) generate_tree(expr); else generate_table(expr, info); } void dumpswitchtables(Object *funcobj) { + Object *table; + ObjectList *list; + SInt32 size; + UInt32 *array; + + for (list = switchtables; list; list = list->next) { + table = list->object; +#line 694 + CError_ASSERT(table->otype == OT_OBJECT && table->access == ACCESSPUBLIC && table->datatype == DDATA); + + size = table->u.data.u.switchtable.size; + array = (UInt32 *) table->u.data.u.switchtable.data; + while (size--) { + *array = CTool_EndianConvertWord32(((PCodeLabel *) *array)->block->codeOffset); + array++; + } + + ObjGen_DeclareSwitchTable(table, funcobj); + } } diff --git a/compiler_and_linker/unsorted/TOC.c b/compiler_and_linker/unsorted/TOC.c index 0f3024f..94ecb27 100644 --- a/compiler_and_linker/unsorted/TOC.c +++ b/compiler_and_linker/unsorted/TOC.c @@ -8,6 +8,7 @@ #include "compiler/CMangler.h" #include "compiler/CParser.h" #include "compiler/CodeGen.h" +#include "compiler/InstrSelection.h" #include "compiler/Operands.h" #include "compiler/PCode.h" #include "compiler/PCodeInfo.h" diff --git a/compiler_and_linker/unsorted/UseDefChains.c b/compiler_and_linker/unsorted/UseDefChains.c index e69de29..1840548 100644 --- a/compiler_and_linker/unsorted/UseDefChains.c +++ b/compiler_and_linker/unsorted/UseDefChains.c @@ -0,0 +1,563 @@ +#include "compiler/UseDefChains.h" +#include "compiler/Alias.h" +#include "compiler/PCode.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "compiler/BitVectors.h" + +int number_of_Defs; +UseOrDef *Defs; +RegUseOrDef **reg_Defs[RegClassMax]; +int number_of_Uses; +UseOrDef *Uses; +RegUseOrDef **reg_Uses[RegClassMax]; +UseDefInfo *usedefinfo; +ObjectUseDef *objectusedefs; +ObjectUseDef *objectusedeflist; + +ObjectUseDef *findobjectusedef(Object *object) { + ObjectUseDef *oud; + + oud = objectusedefs; + while (oud) { + if (((unsigned long) object) < ((unsigned long) oud->object)) + oud = oud->leftchild; + else if (((unsigned long) object) > ((unsigned long) oud->object)) + oud = oud->rightchild; + else + return oud; + } + + return NULL; +} + +static void addobjectusedef(Object *object) { + ObjectUseDef **ptr; + ObjectUseDef *list; + + ptr = &objectusedefs; + while (*ptr) { + if (((unsigned long) object) < ((unsigned long) (*ptr)->object)) + ptr = &(*ptr)->leftchild; + else if (((unsigned long) object) > ((unsigned long) (*ptr)->object)) + ptr = &(*ptr)->rightchild; + else + return; + } + + list = oalloc(sizeof(ObjectUseDef)); + list->leftchild = list->rightchild = NULL; + list->object = object; + list->uses = list->defs = NULL; + list->next = objectusedeflist; + objectusedeflist = list; + *ptr = list; +} + +static void addaliasusedef(Alias *alias) { + AliasMember *member; + + if (alias && alias != worst_case) { + if (alias->type == AliasType2) { + for (member = alias->parents; member; member = member->nextParent) + addaliasusedef(member->child); + } else { + addobjectusedef(alias->object); + } + } +} + +static void addworstcase(void) { + addobjectusedef(&worst_case_obj); +} + +static void precomputememoryusedefs(void) { + PCodeBlock *block; + PCode *pcode; + + objectusedeflist = NULL; + objectusedefs = NULL; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4)) { + if (pcode->alias) { + if (pcode->alias->type == AliasType2 || pcode->alias->size != nbytes_loaded_or_stored_by(pcode)) + pcode->flags |= fPCodeFlag20; + addaliasusedef(pcode->alias); + } else { + pcode->flags |= fPCodeFlag20; + } + } + } + } + + addworstcase(); +} + +static void precomputeusedefcounts(int flag) { + PCodeBlock *block; + PCode *pcode; + PCodeArg *op; + int i; + ObjectUseDef *oud; + + number_of_Defs = 0; + number_of_Uses = 0; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) { + pcode->useID = number_of_Uses; + pcode->defID = number_of_Defs; + op = pcode->args; + i = pcode->argCount; + while (i--) { + if (op->kind == PCOp_REGISTER && op->data.reg.reg >= n_real_registers[op->arg]) { + if (op->data.reg.effect & EffectRead) + number_of_Uses++; + if (op->data.reg.effect & EffectWrite) + number_of_Defs++; + } + op++; + } + + if (flag) { + if (pcode->flags & fPCodeFlag2) { + if (pcode->flags & fPCodeFlag20) { + for (oud = objectusedeflist; oud; oud = oud->next) { + if (may_alias_object(pcode, oud->object)) + number_of_Uses++; + } + } else { + number_of_Uses++; + } + } else if (pcode->flags & fPCodeFlag4) { + if (pcode->flags & fPCodeFlag20) { + for (oud = objectusedeflist; oud; oud = oud->next) { + if (may_alias_object(pcode, oud->object)) + number_of_Defs++; + } + } else { + number_of_Defs++; + } + } else if (pcode->flags & fPCodeFlag8) { + for (oud = objectusedeflist; oud; oud = oud->next) { + if ( + oud->object->datatype == DDATA || + oud->object->datatype == DNONLAZYPTR || + (oud->object->datatype == DLOCAL && ( + oud->object->u.var.info->noregister || + IS_TYPE_ARRAY(oud->object->type) || + IS_TYPE_NONVECTOR_STRUCT(oud->object->type) || + IS_TYPE_CLASS(oud->object->type) || + IS_TYPE_12BYTES_MEMBERPOINTER(oud->object->type) + )) + ) { + number_of_Uses++; + number_of_Defs++; + } + } + } + } + } + } + } +} + +static void computeusedeflists(int flag) { + ObjectUseDef *oud; + RegUseOrDef *list; + PCodeBlock *block; + PCode *pcode; + PCodeArg *op; + int i; + UseOrDef *use; + UseOrDef *def; + int useID; + int defID; + ObjectUseDef *tmp; + Object *object; + + Uses = oalloc(sizeof(UseOrDef) * number_of_Uses); + Defs = oalloc(sizeof(UseOrDef) * number_of_Defs); + + reg_Uses[RegClass_GPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_GPR]); + reg_Defs[RegClass_GPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_GPR]); + for (i = 0; i < used_virtual_registers[RegClass_GPR]; i++) { + reg_Uses[RegClass_GPR][i] = NULL; + reg_Defs[RegClass_GPR][i] = NULL; + } + + reg_Uses[RegClass_FPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_FPR]); + reg_Defs[RegClass_FPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_FPR]); + for (i = 0; i < used_virtual_registers[RegClass_FPR]; i++) { + reg_Uses[RegClass_FPR][i] = NULL; + reg_Defs[RegClass_FPR][i] = NULL; + } + + reg_Uses[RegClass_VR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_VR]); + reg_Defs[RegClass_VR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_VR]); + for (i = 0; i < used_virtual_registers[RegClass_VR]; i++) { + reg_Uses[RegClass_VR][i] = NULL; + reg_Defs[RegClass_VR][i] = NULL; + } + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) { + use = &Uses[useID = pcode->useID]; + def = &Defs[defID = pcode->defID]; + + op = pcode->args; + i = pcode->argCount; + while (i--) { + if (op->kind == PCOp_REGISTER && op->data.reg.reg >= n_real_registers[op->arg]) { + if (op->data.reg.effect & EffectRead) { + use->pcode = pcode; + use->v.kind = op->kind; + use->v.arg = op->arg; + use->v.u.reg = op->data.reg.reg; + list = oalloc(sizeof(RegUseOrDef)); + list->id = useID; + list->next = reg_Uses[op->arg][op->data.reg.reg]; + reg_Uses[op->arg][op->data.reg.reg] = list; + use++; + useID++; + } + if (op->data.reg.effect & EffectWrite) { + def->pcode = pcode; + def->v.kind = op->kind; + def->v.arg = op->arg; + def->v.u.reg = op->data.reg.reg; + list = oalloc(sizeof(RegUseOrDef)); + list->id = defID; + list->next = reg_Defs[op->arg][op->data.reg.reg]; + reg_Defs[op->arg][op->data.reg.reg] = list; + def++; + defID++; + } + } + op++; + } + + if (flag) { + if (pcode->flags & fPCodeFlag2) { + if (pcode->flags & fPCodeFlag20) { + for (oud = objectusedeflist; oud; oud = oud->next) { + if (may_alias_object(pcode, object = oud->object)) { + use->pcode = pcode; + use->v.kind = PCOp_MEMORY; + use->v.arg = 1; + use->v.u.object = object; + list = oalloc(sizeof(RegUseOrDef)); + list->id = useID; + list->next = oud->uses; + oud->uses = list; + use++; + useID++; + } + } + } else { + object = pcode->alias->object; + use->pcode = pcode; + use->v.kind = PCOp_MEMORY; + use->v.arg = 0; + use->v.u.object = object; + list = oalloc(sizeof(RegUseOrDef)); + list->id = useID; + tmp = findobjectusedef(object); + list->next = tmp->uses; + tmp->uses = list; + } + } else if (pcode->flags & fPCodeFlag4) { + if (pcode->flags & fPCodeFlag20) { + for (oud = objectusedeflist; oud; oud = oud->next) { + if (may_alias_object(pcode, object = oud->object)) { + def->pcode = pcode; + def->v.kind = PCOp_MEMORY; + def->v.arg = 1; + def->v.u.object = object; + list = oalloc(sizeof(RegUseOrDef)); + list->id = defID; + list->next = oud->defs; + oud->defs = list; + def++; + defID++; + } + } + } else { + object = pcode->alias->object; + def->pcode = pcode; + def->v.kind = PCOp_MEMORY; + def->v.arg = 0; + def->v.u.object = object; + list = oalloc(sizeof(RegUseOrDef)); + list->id = useID; + tmp = findobjectusedef(object); + list->next = tmp->defs; + tmp->defs = list; + } + } else if (pcode->flags & fPCodeFlag8) { + for (oud = objectusedeflist; oud; oud = oud->next) { + object = oud->object; + if ( + object->datatype == DDATA || + object->datatype == DNONLAZYPTR || + (object->datatype == DLOCAL && ( + object->u.var.info->noregister || + IS_TYPE_ARRAY(object->type) || + IS_TYPE_NONVECTOR_STRUCT(object->type) || + IS_TYPE_CLASS(oud->object->type) || + IS_TYPE_12BYTES_MEMBERPOINTER(object->type) + )) + ) { + use->pcode = pcode; + use->v.kind = PCOp_MEMORY; + use->v.arg = 1; + use->v.u.object = object; + + list = oalloc(sizeof(RegUseOrDef)); + list->id = useID; + list->next = oud->uses; + oud->uses = list; + + def->pcode = pcode; + def->v.kind = PCOp_MEMORY; + def->v.arg = 1; + def->v.u.object = object; + + use++; + useID++; + + list = oalloc(sizeof(RegUseOrDef)); + list->id = defID; + list->next = oud->defs; + oud->defs = list; + + def++; + defID++; + } + } + } + } + } + } + } +} + +static void allocateusedefinfo(void) { + UseDefInfo *info; + int i; + + usedefinfo = oalloc(pcblockcount * sizeof(UseDefInfo)); + for (i = 0, info = usedefinfo; i < pcblockcount; i++, info++) { + info->defvec0 = oalloc(4 * ((number_of_Defs + 31) >> 5)); + info->defvec4 = oalloc(4 * ((number_of_Defs + 31) >> 5)); + info->defvec8 = oalloc(4 * ((number_of_Defs + 31) >> 5)); + info->defvecC = oalloc(4 * ((number_of_Defs + 31) >> 5)); + info->usevec10 = oalloc(4 * ((number_of_Uses + 31) >> 5)); + info->usevec14 = oalloc(4 * ((number_of_Uses + 31) >> 5)); + info->usevec18 = oalloc(4 * ((number_of_Uses + 31) >> 5)); + info->usevec1C = oalloc(4 * ((number_of_Uses + 31) >> 5)); + } +} + +static void computelocalusedefinfo(void) { + PCodeBlock *block; // r28 + PCode *pcode; // r27 + UInt32 *defvec0; // r26 + UInt32 *defvec4; // r25 + UInt32 *usevec10; // r24 + UInt32 *usevec14; // r23 + UseOrDef *use; // r22 + UseOrDef *def; // r22 + int useID; // r15 + int defID; // r21 + ObjectUseDef *oud; // r17 + RegUseOrDef *list; // r16 + UseDefInfo *info; // r15 + + for (block = pcbasicblocks; block; block = block->nextBlock) { + info = &usedefinfo[block->blockIndex]; + defvec0 = info->defvec0; + defvec4 = info->defvec4; + usevec10 = info->usevec10; + usevec14 = info->usevec14; + bitvectorinitialize(defvec0, number_of_Defs, 0); + bitvectorinitialize(defvec4, number_of_Defs, 0); + bitvectorinitialize(usevec10, number_of_Uses, 0); + bitvectorinitialize(usevec14, number_of_Uses, 0); + bitvectorinitialize(info->defvec8, number_of_Defs, 0); + bitvectorinitialize(info->defvecC, number_of_Defs, 0); + bitvectorinitialize(info->usevec18, number_of_Uses, 0); + bitvectorinitialize(info->usevec1C, number_of_Uses, 0); + + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if (!(pcode->flags & fPCodeFlag1) && pcode->argCount) { + for (use = &Uses[useID = pcode->useID]; useID < number_of_Uses && use->pcode == pcode; use++, useID++) { + bitvectorsetbit(useID, usevec10); + if (use->v.kind == PCOp_REGISTER) { + for (list = reg_Defs[use->v.arg][use->v.u.reg]; list; list = list->next) { + if (bitvectorgetbit(list->id, defvec0)) + bitvectorclearbit(useID, usevec10); + } + } else { + for (list = findobjectusedef(use->v.u.object)->defs; list; list = list->next) { + if (uniquely_aliases(pcode, Defs[list->id].pcode)) { + if (Defs[list->id].v.arg == 0 && bitvectorgetbit(list->id, defvec0)) + bitvectorclearbit(useID, usevec10); + } + } + } + } + + for (def = &Defs[defID = pcode->defID]; defID < number_of_Defs && def->pcode == pcode; def++, defID++) { + if (def->v.kind == PCOp_REGISTER) { + for (list = reg_Uses[def->v.arg][def->v.u.reg]; list; list = list->next) { + if (Uses[list->id].pcode->block != block) + bitvectorsetbit(list->id, usevec14); + } + for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) { + if (Defs[list->id].pcode->block != block) + bitvectorsetbit(list->id, defvec4); + else + bitvectorclearbit(list->id, defvec0); + } + } else if (def->v.arg == 0) { + oud = findobjectusedef(use->v.u.object); + for (list = oud->uses; list; list = list->next) { + if (may_alias(pcode, Uses[list->id].pcode)) { + if (Uses[list->id].pcode->block != block) + bitvectorsetbit(list->id, usevec14); + } + } + for (list = oud->defs; list; list = list->next) { + if (uniquely_aliases(pcode, Defs[list->id].pcode)) { + if (Defs[list->id].pcode->block != block) + bitvectorsetbit(list->id, defvec4); + else + bitvectorclearbit(list->id, defvec0); + } + } + } + + bitvectorsetbit(defID, defvec0); + } + } + } + } +} + +static void computeglobalusedefinfo(void) { + UseDefInfo *udi; + UInt32 *defVec0; + UInt32 *defVec4; + UInt32 *defVec8; + UInt32 *defVecC; + int bitvecsize; + int i; + int j; + int flag; + PCLink *preds; + UInt32 val; + + bitvecsize = (number_of_Defs + 31) >> 5; + flag = 1; + while (flag) { + flag = 0; + for (i = 0; i < pcblockcount; i++) { + if (depthfirstordering[i]) { + udi = &usedefinfo[depthfirstordering[i]->blockIndex]; + if ((preds = depthfirstordering[i]->predecessors)) { + defVec8 = udi->defvec8; + bitvectorcopy(defVec8, usedefinfo[preds->block->blockIndex].defvecC, number_of_Defs); + for (preds = preds->nextLink; preds; preds = preds->nextLink) + bitvectorunion(defVec8, usedefinfo[preds->block->blockIndex].defvecC, number_of_Defs); + } + + defVecC = udi->defvecC; + defVec8 = udi->defvec8; + defVec0 = udi->defvec0; + defVec4 = udi->defvec4; + for (j = 0; j < bitvecsize; j++) { + val = *defVec0 | (*defVec8 & ~*defVec4); + if (val != *defVecC) { + *defVecC = val; + flag = 1; + } + defVec8++; + defVecC++; + defVec4++; + defVec0++; + } + } + } + } +} + +static void computeglobaldefuseinfo(void) { + UseDefInfo *udi; + UInt32 *useVec10; + UInt32 *useVec14; + UInt32 *useVec18; + UInt32 *useVec1C; + int bitvecsize; + int i; + int j; + int flag; + PCLink *succs; + UInt32 val; + PCodeBlock *block; + + bitvecsize = (number_of_Uses + 31) >> 5; + flag = 1; + while (flag) { + flag = 0; + i = pcblockcount; + while (i) { + if ((block = depthfirstordering[--i])) { + udi = &usedefinfo[block->blockIndex]; + if ((succs = block->successors)) { + useVec1C = udi->usevec1C; + bitvectorcopy(useVec1C, usedefinfo[succs->block->blockIndex].usevec18, number_of_Uses); + for (succs = succs->nextLink; succs; succs = succs->nextLink) + bitvectorunion(useVec1C, usedefinfo[succs->block->blockIndex].usevec18, number_of_Uses); + } + + useVec1C = udi->usevec1C; + useVec18 = udi->usevec18; + useVec10 = udi->usevec10; + useVec14 = udi->usevec14; + for (j = 0; j < bitvecsize; j++) { + val = *useVec10 | (*useVec1C & ~*useVec14); + if (val != *useVec18) { + *useVec18 = val; + flag = 1; + } + useVec18++; + useVec1C++; + useVec14++; + useVec10++; + } + } + } + } +} + +void computeusedefchains(int flag) { + if (flag) { + gather_alias_info(); + precomputememoryusedefs(); + } + + precomputeusedefcounts(flag); + computeusedeflists(flag); + allocateusedefinfo(); + computelocalusedefinfo(); + computedepthfirstordering(); + computeglobalusedefinfo(); + computeglobaldefuseinfo(); +} + diff --git a/compiler_and_linker/unsorted/ValueNumbering.c b/compiler_and_linker/unsorted/ValueNumbering.c index e69de29..e8e05c6 100644 --- a/compiler_and_linker/unsorted/ValueNumbering.c +++ b/compiler_and_linker/unsorted/ValueNumbering.c @@ -0,0 +1,664 @@ +#include "compiler/ValueNumbering.h" +#include "compiler/Alias.h" +#include "compiler/PCode.h" +#include "compiler/Registers.h" +#include "compiler/RegisterInfo.h" +#include "compiler/CompilerTools.h" +#include "compiler/CError.h" + +typedef struct ValueLabel { + struct ValueLabel *next; + PCodeArg op; +} ValueLabel; + +typedef struct AvailableValue { + struct AvailableValue *next; + ValueLabel *labelled; + PCode *pcode; + int killedregister; + int aliasnumber; + int opnumbers[0]; +} AvailableValue; + +typedef struct RegValue { + int number; + int x4; + AvailableValue *available; +} RegValue; + +typedef struct State { + void *stackedvalues; + int valueceiling; +} State; + +typedef struct StackedValue { + struct StackedValue *next; + PCodeArg op; + RegValue value; + Alias *alias; + PCode *valuepcode; +} StackedValue; + +int removedcommonsubexpressions; +int nextvaluenumber; +static AvailableValue *opvalue[428]; +static RegValue *regvalue[RegClassMax]; +static StackedValue *stackedvalues; +static int valueceiling; +static int moreaggressiveoptimization; + +static void allocatecsedatastructures(void) { + char rclass; + + for (rclass = 0; rclass < RegClassMax; rclass++) + regvalue[(char) rclass] = oalloc(sizeof(RegValue) * used_virtual_registers[(char) rclass]); +} + +static void initializecsedatastructures(void) { + RegValue *rv; + char rclass; + int i; + + nextvaluenumber = 0; + + for (i = 0; i < 428; i++) + opvalue[i] = NULL; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + rv = regvalue[(char) rclass]; + for (i = 0; i < used_virtual_registers[(char) rclass]; i++, rv++) { + rv->number = nextvaluenumber++; + rv->x4 = 0; + rv->available = NULL; + } + } + + initialize_alias_values(); + stackedvalues = NULL; + valueceiling = 0x7FFFFFFF; +} + +static void labelvalue(AvailableValue *av, PCodeArg *op) { + ValueLabel *label = oalloc(sizeof(ValueLabel)); + label->op = *op; + label->next = av->labelled; + av->labelled = label; +} + +static void unlabelvalue(AvailableValue *av, PCodeArg *op) { + ValueLabel *labelled; + ValueLabel **ptr; + + ptr = &av->labelled; + while ((labelled = *ptr)) { + if (labelled->op.data.reg.reg == op->data.reg.reg) + *ptr = labelled->next; + else + ptr = &labelled->next; + } +} + +static void stackregistervalue(PCodeArg *op, RegValue *value) { + StackedValue *stacked = oalloc(sizeof(StackedValue)); + stacked->next = stackedvalues; + stackedvalues = stacked; + + stacked->op = *op; + stacked->value = *value; +} + +static void stackmemoryvalue(Alias *alias) { + StackedValue *stacked = oalloc(sizeof(StackedValue)); + stacked->next = stackedvalues; + stackedvalues = stacked; + + stacked->op.kind = PCOp_MEMORY; + stacked->alias = alias; + stacked->value.number = alias->valuenumber; + stacked->valuepcode = alias->valuepcode; +} + +static void unstackvalue(StackedValue *stacked) { + PCodeArg *op = &stacked->op; + RegValue *value; + + if (stacked->op.kind == PCOp_MEMORY) { + stacked->alias->valuenumber = stacked->value.number; + stacked->alias->valuepcode = stacked->valuepcode; + } else { + value = ®value[op->arg][op->data.reg.reg]; + if (value->available) + unlabelvalue(value->available, op); + value->number = stacked->value.number; + value->x4 = stacked->value.x4; + value->available = stacked->value.available; + if (value->available) + labelvalue(value->available, op); + } +} + +static int samevalue(PCodeArg *op1, PCodeArg *op2) { + return regvalue[op1->arg][op1->data.reg.reg].number == regvalue[op2->arg][op2->data.reg.reg].number; +} + +static int killregister(PCodeArg *op) { + RegValue *value; + + value = ®value[op->arg][op->data.reg.reg]; + if (value->number < valueceiling && nextvaluenumber >= valueceiling) + stackregistervalue(op, value); + + if (value->available) + unlabelvalue(value->available, op); + value->available = NULL; + value->x4 = 0; + return value->number = nextvaluenumber++; +} + +void killmemory(Alias *alias, PCode *newValue) { + if (alias->valuenumber < valueceiling && nextvaluenumber >= valueceiling) + stackmemoryvalue(alias); + + if (newValue) { + alias->valuenumber = regvalue[newValue->args[0].arg][newValue->args[0].data.reg.reg].number; + alias->valuepcode = newValue; + } else { + alias->valuenumber = nextvaluenumber++; + alias->valuepcode = NULL; + } +} + +static void killspecificCSEs(short op) { + AvailableValue *av; + ValueLabel *labelled; + + for (av = opvalue[op]; av; av = av->next) { + for (labelled = av->labelled; labelled; labelled = labelled->next) + killregister(&labelled->op); + } +} + +static void killallCSEs(void) { + AvailableValue *av; + ValueLabel *labelled; + int i; + + for (i = 0; i < 428; i++) { + for (av = opvalue[i]; av; av = av->next) { + for (labelled = av->labelled; labelled; labelled = labelled->next) + killregister(&labelled->op); + } + } +} + +static void killregisters(PCode *pcode) { + PCodeArg *op; + int i; + + for (i = 0, op = pcode->args; i < pcode->argCount; i++, op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) + killregister(op); + } +} + +static void copyregister(PCodeArg *src, PCodeArg *dest) { + RegValue *srcvalue; + RegValue *destvalue; + + srcvalue = ®value[src->arg][src->data.reg.reg]; + destvalue = ®value[dest->arg][dest->data.reg.reg]; + + if (destvalue->number < valueceiling && nextvaluenumber >= valueceiling) + stackregistervalue(dest, destvalue); + + if (destvalue->available) + unlabelvalue(destvalue->available, dest); + destvalue->available = srcvalue->available; + if (destvalue->available) + labelvalue(destvalue->available, dest); + + destvalue->number = srcvalue->number; + + if (srcvalue->x4 && srcvalue->number == regvalue[src->arg][srcvalue->x4].number) + destvalue->x4 = srcvalue->x4; + else + destvalue->x4 = src->data.reg.reg; +} + +static int matchvalues(AvailableValue *av, PCode *match) { + PCodeArg *avOp; + PCodeArg *matchOp; + int i; + + for (avOp = &av->pcode->args[0], matchOp = &match->args[0], i = 0; i < match->argCount; i++, avOp++, matchOp++) { + if (i != 0) { + switch (avOp->kind) { + case PCOp_REGISTER: + if (av->opnumbers[i] != regvalue[matchOp->arg][matchOp->data.reg.reg].number) + return 0; + break; + case PCOp_MEMORY: + if (matchOp->kind != PCOp_MEMORY) + return 0; + if (matchOp->data.mem.obj != avOp->data.mem.obj) + return 0; + if (matchOp->data.mem.offset != avOp->data.mem.offset) + return 0; + if ((unsigned char) matchOp->arg != (unsigned char) avOp->arg) + return 0; + break; + case PCOp_IMMEDIATE: + if (matchOp->kind != PCOp_IMMEDIATE) + return 0; + if (matchOp->data.imm.value != avOp->data.imm.value) + return 0; + break; + case PCOp_LABEL: + if (matchOp->kind != PCOp_LABEL) + return 0; + if (matchOp->data.label.label != avOp->data.label.label) + return 0; + break; + case PCOp_SYSREG: +#line 572 + CError_FATAL(); + } + } + } + + if ((match->flags & (fPCodeFlag2 | fPCodeFlag20000)) && match->alias->valuenumber != av->aliasnumber) + return 0; + + return 1; +} + +static void chooselocation(AvailableValue *av, PCodeArg *op) { + ValueLabel *labelled; + PCodeArg *baseop; + + baseop = &av->pcode->args[0]; + labelled = av->labelled; + while (labelled) { + if (labelled->op.data.reg.reg == baseop->data.reg.reg) { + *op = labelled->op; + return; + } + labelled = labelled->next; + } + + *op = av->labelled[0].op; +} + +static int findavailablevalue(PCode *pcode, PCodeArg *op) { + AvailableValue *av; + PCodeArg tmp1; + PCodeArg tmp2; + + for (av = opvalue[pcode->op]; av; av = av->next) { + if (av->labelled && av->pcode->flags == pcode->flags && av->pcode->argCount == pcode->argCount) { + if (!matchvalues(av, pcode)) { + if (!(pcode->flags & fCommutative)) + continue; + + tmp1 = pcode->args[1]; + pcode->args[1] = pcode->args[2]; + pcode->args[2] = tmp1; + + if (!matchvalues(av, pcode)) { + tmp2 = pcode->args[1]; + pcode->args[1] = pcode->args[2]; + pcode->args[2] = tmp2; + continue; + } + } + chooselocation(av, op); + return 1; + } + } + + return 0; +} + +static void addavailablevalue(PCode *pcode) { + AvailableValue *av; + PCodeArg *op; + int i; + + av = oalloc(sizeof(AvailableValue) + sizeof(int) * pcode->argCount); + av->labelled = NULL; + av->pcode = pcode; + for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { + if (op->kind == PCOp_REGISTER) + av->opnumbers[i] = regvalue[op->arg][op->data.reg.reg].number; + } + + if (pcode->flags & (fPCodeFlag2 | fPCodeFlag20000)) + av->aliasnumber = pcode->alias->valuenumber; + + op = &pcode->args[0]; + av->killedregister = killregister(op); + labelvalue(av, op); + regvalue[op->arg][op->data.reg.reg].available = av; + av->next = opvalue[pcode->op]; + opvalue[pcode->op] = av; +} + +static int isCSEop(PCode *pcode) { + PCodeArg *baseOp; + PCodeArg *op; + int i; + + baseOp = &pcode->args[0]; + + switch (pcode->op) { + case PC_CMPI: + case PC_CMP: + case PC_CMPLI: + case PC_CMPL: + case PC_FCMPU: + case PC_FCMPO: + if (!moreaggressiveoptimization) + return 0; + break; + case PC_LI: + case PC_LIS: + if (!moreaggressiveoptimization) + return 0; + if (pcode->args[0].data.reg.reg < first_fe_temporary_register[RegClass_GPR] || pcode->args[0].data.reg.reg > last_temporary_register[RegClass_GPR]) + return 0; + break; + } + + if (PCODE_FLAG_SET_F(pcode) & (fIsVolatile | fSideEffects | fOverflow | fPCodeFlag10000000 | fPCodeFlag20000000)) + return 0; + + for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { + if (op != baseOp && + op->kind == baseOp->kind && + op->arg == baseOp->arg && + op->data.reg.reg == baseOp->data.reg.reg) + return 0; + } + + return 1; +} + +static int isCSEload(PCode *pcode) { + PCodeArg *op; + int i; + int count; + + count = 0; + for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) + count++; + } + + return count == 1; +} + +static void registercopy(PCode *pcode) { + PCodeArg *op1; + PCodeArg *op2; + + op1 = &pcode->args[0]; + op2 = &pcode->args[1]; + if (samevalue(op2, op1)) + deletepcode(pcode); + else + copyregister(op2, op1); +} + +static PCode *recentlystored(Alias *alias, PCodeArg *op) { + PCode *pc; + if ((pc = alias->valuepcode) && alias->valuenumber == regvalue[pc->args[0].arg][pc->args[0].data.reg.reg].number) { + *op = pc->args[0]; + return pc; + } else { + return NULL; + } +} + +static void simpleload(PCode *pcode) { + PCodeArg *origOp; + PCodeArg op; + PCode *rs; + + origOp = &pcode->args[0]; + if ((pcode->flags & fIsVolatile) || !isCSEload(pcode)) { + killregisters(pcode); + return; + } + + if (findavailablevalue(pcode, &op)) { + if (!samevalue(origOp, &op)) { + insertpcodebefore(pcode, makecopyinstruction(&op, origOp)); + copyregister(&op, origOp); + } + deletepcode(pcode); + removedcommonsubexpressions = 1; + } else if ((rs = recentlystored(pcode->alias, &op)) && can_reuse_stored_value(rs, pcode)) { + if (!samevalue(origOp, &op)) { + insertpcodebefore(pcode, makecopyinstruction(&op, origOp)); + copyregister(&op, origOp); + } + deletepcode(pcode); + removedcommonsubexpressions = 1; + } else { + addavailablevalue(pcode); + } +} + +static void simplestore(PCode *pcode) { + update_alias_value(pcode->alias, pcode); + killregisters(pcode); +} + +static void pointerload(PCode *pcode) { + PCodeArg *op; + PCodeArg buf; + + op = &pcode->args[0]; + + if ((pcode->flags & fIsVolatile) || !isCSEload(pcode)) { + killregisters(pcode); + return; + } + + if (findavailablevalue(pcode, &buf)) { + if (!samevalue(op, &buf)) { + insertpcodebefore(pcode, makecopyinstruction(&buf, op)); + copyregister(&buf, op); + } + deletepcode(pcode); + removedcommonsubexpressions = 1; + } else { + addavailablevalue(pcode); + } +} + +static void pointerstore(PCode *pcode) { + update_alias_value(pcode->alias, NULL); + killregisters(pcode); +} + +static void arithmeticop(PCode *pcode) { + PCodeArg *op; + PCodeArg buf; + + op = &pcode->args[0]; + + if (findavailablevalue(pcode, &buf)) { + if (!samevalue(op, &buf)) { + insertpcodebefore(pcode, makecopyinstruction(&buf, op)); + copyregister(&buf, op); + } + deletepcode(pcode); + removedcommonsubexpressions = 1; + } else { + addavailablevalue(pcode); + } +} + +static void functioncall(PCode *pcode) { + killregisters(pcode); + if (coloring) { + update_all_alias_values(); + killallCSEs(); + } else { + update_alias_value(pcode->alias, NULL); + } +} + +static void operatefrommemory(PCode *pcode) { +#line 980 + CError_FATAL(); +} + +static void operatetomemory(PCode *pcode) { +#line 1011 + CError_FATAL(); +} + +static void propagatecopiesto(PCode *pcode) { + PCodeArg *op; + int i; + + for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { + if ( + op->kind == PCOp_REGISTER && + (op->data.reg.effect & (EffectRead | EffectWrite | Effect8)) == EffectRead && + op->data.reg.reg >= n_real_registers[op->arg] && + regvalue[op->arg][op->data.reg.reg].x4 && + regvalue[op->arg][op->data.reg.reg].x4 >= n_real_registers[op->arg] && + regvalue[op->arg][op->data.reg.reg].number == regvalue[op->arg][regvalue[op->arg][op->data.reg.reg].x4].number + ) { + op->data.reg.reg = regvalue[op->arg][op->data.reg.reg].x4; + } + } +} + +static void removecsesfrombasicblock(PCodeBlock *block) { + PCode *pcode; + PCode *next; + + for (pcode = block->firstPCode; pcode; pcode = next) { + next = pcode->nextPCode; + propagatecopiesto(pcode); + if (pcode->flags & fPCodeFlag10) { + registercopy(pcode); + } else if ((pcode->flags & fPCodeFlag8) && (pcode->flags & (fLink | fSideEffects))) { + functioncall(pcode); + } else if (pcode->flags & fPCodeFlag2) { + if (pcode->flags & fPCodeFlag20) + pointerload(pcode); + else + simpleload(pcode); + } else if (pcode->flags & fPCodeFlag4) { + if (pcode->flags & fPCodeFlag20) + pointerstore(pcode); + else + simplestore(pcode); + } else if (pcode->flags & fPCodeFlag20000) { + operatefrommemory(pcode); + } else if (pcode->flags & fPCodeFlag40000) { + operatetomemory(pcode); + } else if ((pcode->flags & fIsCSE) && isCSEop(pcode)) { + arithmeticop(pcode); + } else { + killregisters(pcode); + } + } + + block->flags |= fPCBlockFlag4; +} + +static void getvaluestate(State *state) { + state->stackedvalues = stackedvalues; + state->valueceiling = valueceiling; +} + +static void setvaluestate(State *state) { + stackedvalues = state->stackedvalues; + valueceiling = state->valueceiling; +} + +static void forkvaluestate(int number) { + stackedvalues = NULL; + valueceiling = number; +} + +static void regressvaluestate(void) { + AvailableValue *av; + AvailableValue **ptr; + int i; + StackedValue *stacked; + + for (i = 0; i < 428; i++) { + ptr = &opvalue[i]; + while ((av = *ptr)) { + if (av->killedregister >= valueceiling) + *ptr = av->next; + else + ptr = &av->next; + } + } + + for (stacked = stackedvalues; stacked; stacked = stacked->next) + unstackvalue(stacked); +} + +static void removecsesfromextendedbasicblock(PCodeBlock *block) { + PCLink *succ; + int counter; + State state; + + removecsesfrombasicblock(block); + while (block->successors && + !block->successors->nextLink && + block->successors->block->predecessors && + !block->successors->block->predecessors->nextLink) { + block = block->successors->block; + removecsesfrombasicblock(block); + } + + counter = 0; + for (succ = block->successors; succ; succ = succ->nextLink) { + if (!(succ->block->flags & fPCBlockFlag4) && succ->block->predecessors && !succ->block->predecessors->nextLink) + counter++; + } + + if (counter) { + getvaluestate(&state); + forkvaluestate(nextvaluenumber); + for (succ = block->successors; succ; succ = succ->nextLink) { + if (!(succ->block->flags & fPCBlockFlag4) && succ->block->predecessors && !succ->block->predecessors->nextLink) { + removecsesfromextendedbasicblock(succ->block); + regressvaluestate(); + } + } + setvaluestate(&state); + } +} + +void removecommonsubexpressions(Object *proc, int flag) { + PCodeBlock *block; + + moreaggressiveoptimization = flag; + removedcommonsubexpressions = 0; + gather_alias_info(); + allocatecsedatastructures(); + + for (block = pcbasicblocks; block; block = block->nextBlock) + block->flags &= ~fPCBlockFlag4; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (!(block->flags & fPCBlockFlag4)) { + initializecsedatastructures(); + removecsesfromextendedbasicblock(block); + } + } + + freeoheap(); +} + diff --git a/compiler_and_linker/unsorted/VectorArraysToRegs.c b/compiler_and_linker/unsorted/VectorArraysToRegs.c index e69de29..3f95cac 100644 --- a/compiler_and_linker/unsorted/VectorArraysToRegs.c +++ b/compiler_and_linker/unsorted/VectorArraysToRegs.c @@ -0,0 +1,549 @@ +#include "compiler/VectorArraysToRegs.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/Registers.h" +#include "compiler/UseDefChains.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +typedef struct LocalVectorArray { + struct LocalVectorArray *next; + Object *object; + unsigned int invalid:1; + SInt32 arraySize; + SInt32 elementCount; + int totalUses; + int elements[1]; +} LocalVectorArray; + +typedef struct VectorPropInfo { + UInt32 *vec0; + UInt32 *vec4; + UInt32 *vec8; + UInt32 *vecC; +} VectorPropInfo; + +typedef struct ADDI { + PCode *instr; + RegUseOrDef *list; +} ADDI; + +static int number_of_ADDIs; +static ADDI *ADDIs; +static VectorPropInfo *vectorpropinfo; +static int *naddsinblock; +static int *firstaddinblock; +static Boolean converted_arrays; + +static LocalVectorArray *scanforlocalvectorarrays(void) { + SInt32 elementCount; + LocalVectorArray *head; + LocalVectorArray *array; + ObjectList *list; + int i; + SInt32 arraySize; + + head = NULL; + + for (list = locals; list; list = list->next) { + if ( + list->object && + !(IS_TYPE_POINTER(list->object->type) ? (TPTR_QUAL(list->object->type) & Q_VOLATILE) : (list->object->qual & Q_VOLATILE)) && + list->object->type && + IS_TYPE_ARRAY(list->object->type) && + IS_TYPE_VECTOR(TPTR_TARGET(list->object->type)) + ) { + arraySize = list->object->type->size; + elementCount = arraySize / 16; + if (elementCount > 0 && elementCount <= 8) { + array = oalloc(sizeof(int) * (elementCount - 1) + sizeof(LocalVectorArray)); + array->next = head; + head = array; + + array->object = list->object; + array->arraySize = arraySize; + array->elementCount = elementCount; + array->totalUses = 0; + array->invalid = 0; + + for (i = 0; i < elementCount; i++) { + array->elements[i] = 0; + } + } + } + } + + return head; +} + +static LocalVectorArray *lookup_vector_array_object(LocalVectorArray *arrays, Object *object) { + while (arrays) { + if (arrays->object == object) + return arrays; + arrays = arrays->next; + } + return NULL; +} + +static void scaninstructions(LocalVectorArray *arrays) { + PCodeBlock *block; + PCode *instr; + int counter; + int i; + PCodeArg *op; + LocalVectorArray *array; + int element; + + naddsinblock = oalloc(sizeof(int) * pcblockcount); + memclrw(naddsinblock, sizeof(int) * pcblockcount); + + firstaddinblock = oalloc(sizeof(int) * pcblockcount); + memclrw(firstaddinblock, sizeof(int) * pcblockcount); + + number_of_ADDIs = 0; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + firstaddinblock[block->blockIndex] = number_of_ADDIs; + counter = 0; + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (!(instr->flags & fPCodeFlag1) && instr->argCount) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_MEMORY && + op->arg == PCOpMemory1 && + (array = lookup_vector_array_object(arrays, op->data.mem.obj)) && + !array->invalid + ) + { + if (instr->op != PC_ADDI) { + array->invalid = 1; + } else if (instr->args[0].data.reg.reg < n_real_registers[RegClass_GPR]) { + array->invalid = 1; + } else { + number_of_ADDIs++; + counter++; + } + + if (!array->invalid) { + element = op->data.mem.offset / 16; + if (element < array->elementCount) + array->elements[element]++; + else + array->invalid = 1; + } + } + op++; + } + } + } + naddsinblock[block->blockIndex] = counter; + } +} + +static void computeaddilist(LocalVectorArray *arrays) { + PCodeBlock *block; + PCode *instr; + RegUseOrDef *list; + ADDI *addi; + UInt32 *vec; + LocalVectorArray *array; + UseOrDef *def; + int defID; + UseOrDef *use; + int useID; + + ADDIs = oalloc(sizeof(ADDI) * number_of_ADDIs); + memclrw(ADDIs, sizeof(ADDI) * number_of_ADDIs); + + vec = oalloc(4 * ((number_of_Uses + 31) >> 5)); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (naddsinblock[block->blockIndex]) { + bitvectorcopy(vec, usedefinfo[block->blockIndex].usevec1C, number_of_Uses); + addi = &ADDIs[firstaddinblock[block->blockIndex] + naddsinblock[block->blockIndex] - 1]; + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + if (!(instr->flags & fPCodeFlag1) && instr->argCount) { + int reg; // r18 + if ( + instr->op == PC_ADDI && + (reg = instr->args[0].data.reg.reg) >= n_real_registers[RegClass_GPR] && + instr->args[2].kind == PCOp_MEMORY && + (unsigned char) instr->args[2].arg == 1 && + (array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) && + !array->invalid + ) + { + addi->instr = instr; + addi->list = NULL; + for (list = reg_Uses[RegClass_GPR][reg]; list; list = list->next) { + if (bitvectorgetbit(list->id, vec)) { + RegUseOrDef *node = oalloc(sizeof(RegUseOrDef)); + node->id = list->id; + node->next = addi->list; + addi->list = node; + } + } + addi--; + } + + for (def = &Defs[defID = instr->defID]; defID < number_of_Defs && def->pcode == instr; def++, defID++) { + if (def->v.kind == PCOp_REGISTER) { + RegUseOrDef *l; + for (l = reg_Uses[(char) def->v.arg][def->v.u.reg]; l; l = l->next) + bitvectorclearbit(l->id, vec); + } + } + + for (use = &Uses[useID = instr->useID]; useID < number_of_Uses && use->pcode == instr; use++, useID++) { + if (use->v.kind == PCOp_REGISTER) + bitvectorsetbit(useID, vec); + } + } + } + } + } +} + +static void allocatevectorpropinfo(void) { + VectorPropInfo *info; + int i; + + vectorpropinfo = oalloc(sizeof(VectorPropInfo) * pcblockcount); + for (i = 0, info = vectorpropinfo; i < pcblockcount; i++, info++) { + info->vec0 = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); + info->vec4 = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); + info->vec8 = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); + info->vecC = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); + } +} + +static void computelocalvectorpropinfo(LocalVectorArray *arrays) { + VectorPropInfo *info; + PCodeBlock *block; + PCode *instr; + UInt32 *vec0; + UInt32 *vec4; + int index; + PCodeArg *op; + int i; + int addi_i; + ADDI *addi; + LocalVectorArray *array; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + info = &vectorpropinfo[block->blockIndex]; + vec0 = info->vec0; + vec4 = info->vec4; + bitvectorinitialize(vec0, number_of_ADDIs, 0); + bitvectorinitialize(vec4, number_of_ADDIs, 0); + index = firstaddinblock[block->blockIndex]; + + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (!(instr->flags & fPCodeFlag1) && instr->argCount) { + i = instr->argCount; + op = instr->args; + while (i--) { + if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR && (op->data.reg.effect & EffectWrite)) { + for (addi_i = 0, addi = ADDIs; addi_i < number_of_ADDIs; addi_i++, addi++) { + if ( + addi->instr && + (char) addi->instr->args[0].arg == (char) op->arg && + addi->instr->args[0].data.reg.reg == op->data.reg.reg + ) + { + if (addi->instr->block == block) + bitvectorclearbit(addi_i, vec0); + else + bitvectorsetbit(addi_i, vec4); + } + } + } + op++; + } + + if ( + instr->op == PC_ADDI && + instr->args[2].kind == PCOp_MEMORY && + instr->args[2].arg == PCOpMemory1 && + (array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) && + !array->invalid + ) + { + bitvectorsetbit(index, vec0); + index++; + } + } + } + } +} + +static void computeglobalvectorpropinfo(void) { + VectorPropInfo *info; + PCodeBlock *block; + UInt32 *vec0; + UInt32 *vec4; + UInt32 *vec8; + UInt32 *vecC; + int bitvecsize; + int blockIndex; + int i; + int j; + int flag; + PCLink *preds; + UInt32 val; + + bitvecsize = (number_of_ADDIs + 31) >> 5; + flag = 1; + info = &vectorpropinfo[pcbasicblocks->blockIndex]; + bitvectorinitialize(info->vec8, number_of_ADDIs, 0); + bitvectorcopy(info->vecC, info->vec0, number_of_ADDIs); + + for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) { + info = &vectorpropinfo[block->blockIndex]; + vecC = info->vecC; + vec4 = info->vec4; + for (i = 0; i < bitvecsize; vecC++, vec4++, i++) + *vecC = ~*vec4; + } + + while (flag) { + flag = 0; + for (blockIndex = 0; blockIndex < pcblockcount; blockIndex++) { + if (depthfirstordering[blockIndex]) { + info = &vectorpropinfo[depthfirstordering[blockIndex]->blockIndex]; + if ((preds = depthfirstordering[blockIndex]->predecessors)) { + vec8 = info->vec8; + bitvectorcopy(vec8, vectorpropinfo[preds->block->blockIndex].vecC, number_of_ADDIs); + for (preds = preds->nextLink; preds; preds = preds->nextLink) + bitvectorintersect(vec8, vectorpropinfo[preds->block->blockIndex].vecC, number_of_ADDIs); + } + + vecC = info->vecC; + vec8 = info->vec8; + vec0 = info->vec0; + vec4 = info->vec4; + for (j = 0; j < bitvecsize; j++) { + val = *vec0 | (*vec8 & ~*vec4); + if (val != *vecC) { + *vecC = val; + flag = 1; + } + vec8++; + vecC++; + vec4++; + vec0++; + } + } + } + } +} + +static int precedes(PCode *a, PCode *b) { + PCode *scan; + + for (scan = a->nextPCode; scan; scan = scan->nextPCode) { + if (scan == b) + return 1; + } + + return 0; +} + +static int checkvectorstoreorload(int addiID, int useID) { + PCode *addiInstr; + UseOrDef *use; + + addiInstr = ADDIs[addiID].instr; + use = Uses + useID; + if (!addiInstr) + return 0; + + if (addiInstr->args[0].data.reg.reg < n_real_registers[RegClass_GPR]) + return 0; + + if (use->pcode->op != PC_LVX && use->pcode->op != PC_STVX) + return 0; + + if ( + use->pcode->args[1].kind != PCOp_REGISTER || + use->pcode->args[1].arg != RegClass_GPR || + use->pcode->args[1].data.reg.reg != 0 + ) + return 0; + + return use->pcode->args[2].data.reg.reg == addiInstr->args[0].data.reg.reg; +} + +static int checkalluses(LocalVectorArray *arrays, int addiID) { + RegUseOrDef *list; + PCode *instr; + LocalVectorArray *array; + + instr = ADDIs[addiID].instr; + for (list = ADDIs[addiID].list; list; list = list->next) { + if (list && !checkvectorstoreorload(addiID, list->id)) { + array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj); + array->invalid = 1; + return 0; + } + } + + return 1; +} + +static void convert_array_to_register(LocalVectorArray *arrays, int addiID) { + ADDI *addi; + int newReg; + RegUseOrDef *list; + PCode *instr; + PCode *useInstr; + LocalVectorArray *array; + int element; + + addi = ADDIs + addiID; + + if (!(instr = addi->instr)) + return; + + if ( + !(array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) || + array->invalid + ) + return; + + element = instr->args[2].data.mem.offset / 16; + if (element > array->elementCount) + return; + + newReg = array->elements[element]; + for (list = addi->list; list; list = list->next) { + useInstr = Uses[list->id].pcode; + if (useInstr->op == PC_LVX) { + converted_arrays = 1; + change_opcode(useInstr, PC_VMR); + change_num_operands(useInstr, 2); + useInstr->args[1].kind = PCOp_REGISTER; + useInstr->args[1].arg = RegClass_VR; + useInstr->args[1].data.reg.reg = newReg; + useInstr->args[1].data.reg.effect = EffectRead; + } else if (useInstr->op == PC_STVX) { + converted_arrays = 1; + change_opcode(useInstr, PC_VMR); + change_num_operands(useInstr, 2); + useInstr->args[1] = useInstr->args[0]; + useInstr->args[0].kind = PCOp_REGISTER; + useInstr->args[0].arg = RegClass_VR; + useInstr->args[0].data.reg.reg = newReg; + useInstr->args[0].data.reg.effect = EffectWrite; + } else { +#line 661 + CError_FATAL(); + } + } + deletepcode(addi->instr); +} + +static void convert_arrays_to_registers(LocalVectorArray *arrays) { + int i; + int counter; + LocalVectorArray **ptr; + LocalVectorArray *array; + + for (i = 0; i < number_of_ADDIs; i++) + checkalluses(arrays, i); + + counter = 0; + ptr = &arrays; + array = *ptr; + while (array) { + if (array->invalid) { + *ptr = array->next; + array = *ptr; + continue; + } + + counter += array->elementCount; + + for (i = 0; i < array->elementCount; i++) + array->totalUses += array->elements[i]; + + array = array->next; + } + + if (arrays) { + while (counter > 32) { + LocalVectorArray *best; + int score; + score = 0; + best = NULL; + for (array = arrays; array; array = array->next) { + if (best) { + if (array->totalUses < score) { + score = array->totalUses; + best = array; + } + } else { + best = array; + score = array->totalUses; + } + } + + if (!best) + break; + + if (best == arrays) { + arrays = best->next; + } else { + for (array = arrays; array; array = array->next) { + if (array->next == best) { + array->next = best->next; + break; + } + } + } + + counter -= best->elementCount; + } + + if (!(array = arrays)) + return; + + while (array) { + for (i = 0; i < array->elementCount; i++) + array->elements[i] = used_virtual_registers[RegClass_VR]++; + array = array->next; + } + + if (arrays) { + for (i = 0; i < number_of_ADDIs; i++) + convert_array_to_register(arrays, i); + } + } +} + +int vectorarraystoregs(void) { + LocalVectorArray *arrays; + + converted_arrays = 0; + if ((arrays = scanforlocalvectorarrays())) { + scaninstructions(arrays); + if (number_of_ADDIs > 0) { + computeusedefchains(0); + computeaddilist(arrays); + allocatevectorpropinfo(); + computelocalvectorpropinfo(arrays); + computedepthfirstordering(); + computeglobalvectorpropinfo(); + convert_arrays_to_registers(arrays); + } + } + + freeoheap(); + return converted_arrays; +} -- cgit v1.2.3