haha it's been a while since i last committed, hasn't it

This commit is contained in:
Ash Wolf 2022-12-14 00:16:59 +00:00
parent 9d2728a560
commit 25bab8b1fb
102 changed files with 36344 additions and 103 deletions

View File

@ -158,6 +158,7 @@ add_executable(mwcc
compiler_and_linker/unsorted/UseDefChains.c compiler_and_linker/unsorted/UseDefChains.c
compiler_and_linker/unsorted/LoadDeletion.c compiler_and_linker/unsorted/LoadDeletion.c
compiler_and_linker/unsorted/VectorArraysToRegs.c compiler_and_linker/unsorted/VectorArraysToRegs.c
compiler_and_linker/unsorted/LiveInfo.c
compiler_and_linker/unsorted/InterferenceGraph.c compiler_and_linker/unsorted/InterferenceGraph.c
compiler_and_linker/unsorted/SpillCode.c compiler_and_linker/unsorted/SpillCode.c

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -904,6 +904,8 @@ static COptBlock *newblock(void) {
block->set1[i] = 0; block->set1[i] = 0;
block->set2[i] = 0; block->set2[i] = 0;
} }
return block;
} }
static void MarkFollow(COptBlock *block) { static void MarkFollow(COptBlock *block) {
@ -1369,6 +1371,8 @@ static CLabel *finallabel(CLabel *label, Statement *stmt) {
return label; return label;
} }
} }
return label;
} }
static void optimizegoto(Statement *stmt) { static void optimizegoto(Statement *stmt) {
@ -1399,6 +1403,76 @@ static void removeif(Statement *stmt, Boolean flag) {
} }
static void optimizeif(Statement *stmt) { 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) { static void optimizeswitch(Statement *stmt) {

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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,
&copypropagatestouse,
&propagateandremovecopy,
"COPY",
"COPIES",
"c%ld",
0
};
void propagatecopyinstructions(Object *proc, int flag) {
moreaggressiveoptimization = flag;
propagateinstructions(proc, &copy_prop, 1, 0);
propagatedcopies = propagated_instructions;
}

File diff suppressed because it is too large Load Diff

View File

@ -22,11 +22,11 @@
#include "compiler/PCodeUtilities.h" #include "compiler/PCodeUtilities.h"
#include "compiler/StackFrame.h" #include "compiler/StackFrame.h"
#include "compiler/CompilerTools.h" #include "compiler/CompilerTools.h"
#include "compiler/Alias.h"
// TODO: move me // TODO: move me
extern int countexceptionactionregisters(ExceptionAction *); extern int countexceptionactionregisters(ExceptionAction *);
extern void noteexceptionactionregisters(ExceptionAction *, PCodeArg *); extern void noteexceptionactionregisters(ExceptionAction *, PCodeArg *);
extern void *make_alias(Object *obj, SInt32 offset, SInt32 size);
char asm_alloc_flags[10]; char asm_alloc_flags[10];
unsigned char sm_section; 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.obj = src->u.obj.obj;
dest->data.mem.offset = src->u.obj.offset; dest->data.mem.offset = src->u.obj.offset;
if (pc->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) { 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)) if (is_volatile_object(dest->data.mem.obj))
pc->flags |= fIsVolatile; pc->flags |= fIsVolatile;
if (OBJ_GET_TARGET_CONST(dest->data.mem.obj)) if (OBJ_GET_TARGET_CONST(dest->data.mem.obj))

View File

@ -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();
}

View File

@ -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;
}

View File

@ -1,4 +1,4 @@
#include "compiler/IroBitVect.h" #include "compiler/BitVector.h"
#include "compiler/CompilerTools.h" #include "compiler/CompilerTools.h"
void Bv_AllocVector(BitVector **bv, UInt32 size) { void Bv_AllocVector(BitVector **bv, UInt32 size) {

File diff suppressed because it is too large Load Diff

View File

@ -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, " <assigned>");
if (linear->flags & IROLF_Used) fprintf(DumpFile, " <used>");
if (linear->flags & IROLF_Ind) fprintf(DumpFile, " <ind>");
if (linear->flags & IROLF_Subs) fprintf(DumpFile, " <subs>");
if (linear->flags & IROLF_LoopInvariant) fprintf(DumpFile, " <loop invariant>");
if (linear->flags & IROLF_BeginLoop) fprintf(DumpFile, " <begin loop>");
if (linear->flags & IROLF_EndLoop) fprintf(DumpFile, " <end loop>");
if (linear->flags & IROLF_Ris) fprintf(DumpFile, " <ris>");
if (linear->flags & IROLF_Immind) fprintf(DumpFile, " <immind>");
if (linear->flags & IROLF_Reffed) fprintf(DumpFile, " <reffed>");
if (linear->flags & IROLF_VecOp) fprintf(DumpFile, " <vec op>");
if (linear->flags & IROLF_VecOpBase) fprintf(DumpFile, " <vec op_base>");
if (linear->flags & IROLF_CounterLoop) fprintf(DumpFile, " <counter loop>");
if (linear->flags & IROLF_BitfieldIndirect) fprintf(DumpFile, " <bitfield_indirect>");
if (linear->flags & IROLF_CouldError) fprintf(DumpFile, " <could_error>");
if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS))
fprintf(DumpFile, " <volatile>");
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, " <volatile obj>");
}
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 ? "<addressed>" : "");
}
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;
}
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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)
);
}

View File

@ -0,0 +1,3 @@
#include "compiler/IroTransform.h"
// TODO

View File

@ -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() {
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -60,7 +60,7 @@ PCode *copypcode(PCode *pcode) {
newpc->op = pcode->op; newpc->op = pcode->op;
newpc->flags = pcode->flags; newpc->flags = pcode->flags;
newpc->argCount = pcode->argCount; newpc->argCount = pcode->argCount;
newpc->_18 = pcode->_18; newpc->alias = pcode->alias;
for (i = 0; i < pcode->argCount; i++) { for (i = 0; i < pcode->argCount; i++) {
newpc->args[i] = pcode->args[i]; newpc->args[i] = pcode->args[i];
} }

View File

@ -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() {
}

View File

@ -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;
}

View File

@ -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,
&register_defs[(char) op->arg][op->data.reg.reg],
&register_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;
}

View File

@ -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);
}
}
}
}

View File

@ -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();
}
}

View File

@ -2,13 +2,20 @@
#include "compiler/CError.h" #include "compiler/CError.h"
#include "compiler/CFunc.h" #include "compiler/CFunc.h"
#include "compiler/CInt64.h" #include "compiler/CInt64.h"
#include "compiler/objects.h"
#include "compiler/CParser.h" #include "compiler/CParser.h"
#include "compiler/InstrSelection.h"
#include "compiler/ObjGenMachO.h"
#include "compiler/Operands.h"
#include "compiler/PCode.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; ObjectList *switchtables;
static void *caselabels; static SwitchCase **caselabels;
static void *caseranges; static CaseRange *caseranges;
static SInt32 ncases; static SInt32 ncases;
static SInt32 nranges_minus1; static SInt32 nranges_minus1;
static CInt64 min; static CInt64 min;
@ -20,25 +27,446 @@ static Type *selector_type;
static PCodeLabel *defaultlabel; static PCodeLabel *defaultlabel;
static CInt64 range; 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) { 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) { 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) { 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) { void switchstatement(ENode *expr, SwitchInfo *info) {
@ -55,7 +483,7 @@ void switchstatement(ENode *expr, SwitchInfo *info) {
} }
#line 656 #line 656
CError_ASSERT(ncases >= 0 && ncases <= 0x3333332); CError_ASSERT(ncases >= 0 && ncases <= 0x3333332U);
if (!info->defaultlabel->pclabel) if (!info->defaultlabel->pclabel)
info->defaultlabel->pclabel = makepclabel(); info->defaultlabel->pclabel = makepclabel();
@ -68,11 +496,30 @@ void switchstatement(ENode *expr, SwitchInfo *info) {
return; 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); generate_tree(expr);
else else
generate_table(expr, info); generate_table(expr, info);
} }
void dumpswitchtables(Object *funcobj) { 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);
}
} }

View File

@ -8,6 +8,7 @@
#include "compiler/CMangler.h" #include "compiler/CMangler.h"
#include "compiler/CParser.h" #include "compiler/CParser.h"
#include "compiler/CodeGen.h" #include "compiler/CodeGen.h"
#include "compiler/InstrSelection.h"
#include "compiler/Operands.h" #include "compiler/Operands.h"
#include "compiler/PCode.h" #include "compiler/PCode.h"
#include "compiler/PCodeInfo.h" #include "compiler/PCodeInfo.h"

View File

@ -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();
}

View File

@ -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 = &regvalue[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 = &regvalue[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 = &regvalue[src->arg][src->data.reg.reg];
destvalue = &regvalue[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();
}

View File

@ -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;
}

View File

@ -5,6 +5,7 @@
* Common imports and Mac OS types * Common imports and Mac OS types
*/ */
#include <ctype.h> #include <ctype.h>
#include <float.h>
#include <setjmp.h> #include <setjmp.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>

View File

@ -3,4 +3,8 @@
#include "compiler/common.h" #include "compiler/common.h"
extern int propagatedadds;
extern void propagateaddinstructions(Object *proc);
#endif #endif

View File

@ -3,4 +3,57 @@
#include "compiler/common.h" #include "compiler/common.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct AliasMember AliasMember;
typedef enum AliasType {
AliasType0,
AliasType1,
AliasType2
} AliasType;
struct Alias {
Alias *next;
Alias *hashNext;
AliasMember *children;
AliasMember *parents;
Object *object;
SInt32 offset;
SInt32 size;
int valuenumber;
PCode *valuepcode;
UInt32 *vec24;
int index;
AliasType type;
};
struct AliasMember {
AliasMember *nextParent;
AliasMember *nextChild;
Alias *parent;
Alias *child;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern Alias *worst_case;
extern Object worst_case_obj;
extern void initialize_aliases(void);
extern Alias *make_alias(Object *object, SInt32 offset, SInt32 size);
extern Alias *make_alias_set(void);
extern void add_alias_member(Alias *parent, Alias *child);
extern Alias *make_alias_set_from_IR(void);
extern void gather_alias_info(void);
extern Boolean may_alias(PCode *a, PCode *b);
extern Boolean uniquely_aliases(PCode *a, PCode *b);
extern Boolean may_alias_worst_case(PCode *pcode);
extern Boolean may_alias_object(PCode *pcode, Object *object);
extern void initialize_alias_values(void);
extern void update_alias_value(Alias *alias, PCode *pcode);
extern void update_all_alias_values(void);
#endif #endif

View File

@ -25,11 +25,13 @@ extern Boolean Bv_IsEmpty(const BitVector *bv);
inline void Bv_SetBit(UInt32 bit, BitVector *bv) { inline void Bv_SetBit(UInt32 bit, BitVector *bv) {
if ((bit / 32) < bv->size) { if ((bit / 32) < bv->size) {
bv->data[bit / 32] |= ~(1 << (bit & 31)); bv->data[bit / 32] |= 1 << (bit & 31);
} else { } else {
#line 56 #line 56
CError_FATAL(); CError_FATAL();
} }
} }
#define Bv_IsBitSet(_bit, _bv) ( (((_bit) >> 5) < (_bv)->size) && ((_bv)->data[(_bit) >> 5] & (1 << ((_bit) & 31))) )
#endif #endif

View File

@ -3,4 +3,19 @@
#include "compiler/common.h" #include "compiler/common.h"
extern void bitvectorcopy(UInt32 *dst, UInt32 *src, int len);
extern int bitvectorchanged(UInt32 *dst, UInt32 *src, int len);
extern void bitvectorinitialize(UInt32 *vec, int len, UInt32 initval);
extern void bitvectorintersect(UInt32 *dst, UInt32 *src, int len);
extern void bitvectorunion(UInt32 *dst, UInt32 *src, int len);
extern void bitvectordifference(UInt32 *dst, UInt32 *src, int len);
extern void bitvectorcomplement(UInt32 *dst, UInt32 *src, int len);
extern int bitvectorcount(UInt32 *vec, int len);
extern int bitvectorisempty(UInt32 *vec, int len);
extern int bitvectorintersectionisempty(UInt32 *a, UInt32 *b, int len);
#define bitvectorgetbit(_bit, _vec) ((1 << ((_bit) & 31)) & (_vec)[(_bit) >> 5])
#define bitvectorsetbit(_bit, _vec) ((_vec)[(_bit) >> 5] |= 1 << ((_bit) & 31))
#define bitvectorclearbit(_bit, _vec) ((_vec)[(_bit) >> 5] &= ~(1 << ((_bit) & 31)))
#endif #endif

View File

@ -3,4 +3,7 @@
#include "compiler/common.h" #include "compiler/common.h"
// TODO
extern Boolean CExcept_CanThrowException(Object *obj, Boolean flag);
#endif #endif

View File

@ -10,7 +10,7 @@ extern const CInt64 cint64_one;
extern const CInt64 cint64_max; extern const CInt64 cint64_max;
extern const CInt64 cint64_min; extern const CInt64 cint64_min;
inline int CInt64_IsNegative(const CInt64 *n) { inline Boolean CInt64_IsNegative(const CInt64 *n) {
return (n->hi & 0x80000000) != 0; return (n->hi & 0x80000000) != 0;
} }
inline UInt32 CInt64_GetULong(const CInt64 *n) { // 42E660 in mwcppc.exe inline UInt32 CInt64_GetULong(const CInt64 *n) { // 42E660 in mwcppc.exe
@ -33,6 +33,9 @@ inline Boolean CInt64_IsZero(CInt64 *n) {
// return 0; // return 0;
return n->hi == 0 && n->lo == 0; return n->hi == 0 && n->lo == 0;
} }
inline Boolean CInt64_IsOne(CInt64 *n) { // assumed name
return n->hi == 0 && n->lo == 1;
}
inline void CInt64_Extend32(CInt64 *n) { // assumed name inline void CInt64_Extend32(CInt64 *n) { // assumed name
n->hi = (n->lo >> 31) ? 0xFFFFFFFF : 0; n->hi = (n->lo >> 31) ? 0xFFFFFFFF : 0;
} }

View File

@ -71,7 +71,7 @@ typedef struct COpts {
Boolean disable_registers; Boolean disable_registers;
Boolean fp_contract; Boolean fp_contract;
Boolean no_register_save_helpers; Boolean no_register_save_helpers;
char ppc_unroll_speculative; Boolean ppc_unroll_speculative;
short ppc_unroll_instructions_limit; short ppc_unroll_instructions_limit;
short ppc_unroll_factor_limit; short ppc_unroll_factor_limit;
Boolean altivec_model; Boolean altivec_model;
@ -206,20 +206,20 @@ typedef struct COpts {
Boolean optimize_for_size; Boolean optimize_for_size;
Boolean optimizewithasm; Boolean optimizewithasm;
Boolean crippled; Boolean crippled;
char opt_common_subs; Boolean opt_common_subs;
char opt_loop_invariants; Boolean opt_loop_invariants;
char opt_propagation; char opt_propagation;
char opt_dead_assignments; char opt_dead_assignments;
char opt_strength_reduction; Boolean opt_strength_reduction;
char opt_strength_reduction_strict; Boolean opt_strength_reduction_strict;
char opt_dead_code; char opt_dead_code;
char opt_lifetimes; char opt_lifetimes;
char _B1; // unused? char _B1; // unused?
char opt_unroll_loops; char opt_unroll_loops;
char opt_vectorize_loops; char opt_vectorize_loops;
char _B4; // amount of IRO passes? char _B4; // amount of IRO passes?
char opt_pointer_analysis; Boolean opt_pointer_analysis;
char opt_pointer_analysis_mode; unsigned char opt_pointer_analysis_mode;
char loop_unroll_count; char loop_unroll_count;
char loop_unroll_size_threshold; char loop_unroll_size_threshold;
Boolean isGeneratingDebugInfo; Boolean isGeneratingDebugInfo;

View File

@ -3,4 +3,9 @@
#include "compiler/common.h" #include "compiler/common.h"
extern int movedloopinvariantcode;
extern int unswitchedinvariantcode;
extern void moveloopinvariantcode(void);
#endif #endif

View File

@ -2,5 +2,11 @@
#define COMPILER_COLORING_H #define COMPILER_COLORING_H
#include "compiler/common.h" #include "compiler/common.h"
#include "compiler/Registers.h"
//extern RegClass coloring_class;
extern char coloring_class;
extern void colorinstructions(Object *proc);
#endif #endif

View File

@ -119,6 +119,12 @@ extern void memclr(void *ptr, SInt32 size);
extern void memclrw(void *ptr, SInt32 size); extern void memclrw(void *ptr, SInt32 size);
extern void CToLowercase(char *a, char *b); extern void CToLowercase(char *a, char *b);
extern short getbit(SInt32 l); extern short getbit(SInt32 l);
extern inline SInt32 CTool_EndianReadWord32(void *value) {
return *((SInt32 *) value);
}
extern inline UInt32 CTool_EndianConvertWord32(UInt32 value) {
return value;
}
extern void CTool_EndianConvertWord64(CInt64 ci, char *result); extern void CTool_EndianConvertWord64(CInt64 ci, char *result);
extern UInt16 CTool_EndianConvertInPlaceWord16Ptr(UInt16 *x); extern UInt16 CTool_EndianConvertInPlaceWord16Ptr(UInt16 *x);
extern UInt32 CTool_EndianConvertInPlaceWord32Ptr(UInt32 *x); extern UInt32 CTool_EndianConvertInPlaceWord32Ptr(UInt32 *x);

View File

@ -3,4 +3,8 @@
#include "compiler/common.h" #include "compiler/common.h"
extern int propagatedconstants;
extern void propagateconstants(void);
#endif #endif

View File

@ -2,5 +2,51 @@
#define COMPILER_COPYPROPAGATION_H #define COMPILER_COPYPROPAGATION_H
#include "compiler/common.h" #include "compiler/common.h"
#include "compiler/UseDefChains.h"
typedef int (*IsCandidateFunc)(PCode *);
typedef int (*PropagatesToUseFunc)(int a, int b);
typedef void (*PropagateAndFinishFunc)(int id);
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct Propagation {
IsCandidateFunc is_candidate;
PropagatesToUseFunc propagatestouse;
PropagateAndFinishFunc propagateandfinish;
char *name;
char *nameplural;
char *format;
Boolean computesUseDefChains;
} Propagation;
typedef struct Candidate {
PCode *pcode;
RegUseOrDef *list;
} Candidate;
typedef struct PropInfo {
UInt32 *vec0;
UInt32 *vec4;
UInt32 *vec8;
UInt32 *vecC;
} PropInfo;
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern int propagatedcopies;
extern int propagated_instructions;
extern int recursive_propagation;
extern int number_of_candidates;
extern Candidate *Candidates;
extern PropInfo *propinfo;
extern int *ncandidatesinblock;
extern int *firstcandidateinblock;
extern int precedes(PCode *a, PCode *b);
extern void propagateinstructions(Object *proc, Propagation *config, int passCount, Boolean localflag);
extern void propagatecopyinstructions(Object *proc, int flag);
#endif #endif

View File

@ -1,6 +1,48 @@
#ifndef COMPILER_IROUSEDEF_H #ifndef COMPILER_IROUSEDEF_H
#define COMPILER_IROUSEDEF_H #define COMPILER_IROUSEDEF_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
#include "compiler/BitVector.h"
#include "compiler/enode.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct IROUse {
SInt32 index;
IRONode *node;
IROLinear *linear;
VarRecord *var;
IROUse *globalnext;
IROUse *varnext;
BitVector *x18;
UInt16 x1C;
};
struct IRODef {
SInt32 index;
IRONode *node;
IROLinear *linear;
VarRecord *var;
IRODef *globalnext;
IRODef *varnext;
UInt16 x18;
Boolean x1A;
Boolean x1B;
Boolean x1C;
Boolean x1D;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern ENodeType IRO_NonAssignmentOp[MAXEXPR];
extern IROUse *IRO_FirstVarUse;
extern IROUse *IRO_LastVarUse;
extern CInt64 IRO_GetSelfAssignmentVal(IROLinear *linear);
extern void IRO_InitializeNonAssignmentOpArray(void);
extern void IRO_InitializeAssignmentFoldingFunctionArray(void);
extern Boolean IRO_UseDef(Boolean optDeadAssignments, Boolean optPropagation);
extern void IRO_SplitLifetimes(void);
#endif #endif

View File

@ -150,7 +150,8 @@ typedef enum IAEffectType {
IAEffect_0, IAEffect_0,
IAEffect_1, IAEffect_1,
IAEffect_2, IAEffect_2,
IAEffect_3 IAEffect_3,
IAEffect_4
} IAEffectType; } IAEffectType;
typedef struct IAEffect { typedef struct IAEffect {
IAEffectType type; IAEffectType type;
@ -166,8 +167,8 @@ typedef struct IAEffects {
Boolean x3; Boolean x3;
Boolean x4; Boolean x4;
Boolean x5; Boolean x5;
UInt32 numoperands; SInt32 numoperands;
UInt32 numlabels; SInt32 numlabels;
IAEffect operands[16]; IAEffect operands[16];
CLabel *labels[16]; CLabel *labels[16];
} IAEffects; } IAEffects;

View File

@ -3,4 +3,39 @@
#include "compiler/common.h" #include "compiler/common.h"
enum {
fSpilled = 1,
fPushed = 2,
fCoalesced = 4,
fCoalescedInto = 8,
fPairHigh = 0x10,
fPairLow = 0x20,
fIGNode40 = 0x40
};
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct IGNode {
struct IGNode *next;
Object *spillTemporary;
PCode *instr8;
int spillCost;
short x10;
short x12;
short x14;
UInt16 flags;
short arraySize;
short array[1];
} IGNode;
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern IGNode **interferencegraph;
extern Boolean coalesced_nregisters;
extern int interferes(UInt32 a, UInt32 b);
extern void buildinterferencegraph(Object *proc);
#endif #endif

View File

@ -3,7 +3,28 @@
#include "compiler/common.h" #include "compiler/common.h"
// do me typedef struct IROAddrRecord IROAddrRecord;
typedef struct IROAssign IROAssign;
typedef struct IRODef IRODef;
typedef struct IROElmList IROElmList;
typedef struct IROExpr IROExpr;
typedef struct IROLinear IROLinear;
typedef struct IROList IROList;
typedef struct IROListNode IROListNode;
typedef struct IROLoop IROLoop;
typedef struct IRONode IRONode;
typedef struct IROUse IROUse;
extern Boolean DoScalarize;
extern Boolean DoLinearize;
extern Boolean EarlyReturn;
extern Boolean IRO_CPFirstTime;
extern Boolean VectorPhaseCalledFromUnroll;
extern Boolean IRO_Log;
extern Statement *IRO_Optimizer(Object *obj, Statement *stmt); extern Statement *IRO_Optimizer(Object *obj, Statement *stmt);
extern void IRO_Setup(void);
extern void IRO_Cleanup(void);
extern void CodeGen_UpdateOptimizerOptions(void);
#endif #endif

View File

@ -1,6 +1,45 @@
#ifndef COMPILER_IROCSE_H #ifndef COMPILER_IROCSE_H
#define COMPILER_IROCSE_H #define COMPILER_IROCSE_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
#include "compiler/BitVector.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct IROExpr {
Boolean x0;
UInt16 index;
IROLinear *linear;
Object *x8;
IRONode *node;
BitVector *depends;
IROExpr *x14;
Boolean couldError;
Boolean notSubable;
IROLinear *x1A;
VarRecord *x1E;
IROLinear *x22;
IROExpr *next;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern BitVector *IRO_Depends;
extern Boolean IRO_NotSubable;
extern Boolean IRO_IsVolatile;
extern Boolean IRO_CouldError;
extern IROExpr *IRO_FirstExpr;
extern IROExpr *IRO_LastExpr;
extern SInt32 IRO_NumExprs;
extern void IRO_FindDepends_NoAlloc(IROLinear *linear);
extern void IRO_FindDepends(IROLinear *linear);
extern void IRO_FindExpressions(BitVector *bv, Boolean flag);
extern void IRO_RemoveExpr(IROExpr *expr);
extern void IRO_ComputeAvail(void);
extern void IRO_CommonSubs(void);
extern void IRO_GenerateTopLevelExprsForSubableOperands(void);
#endif #endif

View File

@ -1,6 +1,27 @@
#ifndef COMPILER_IRODUMP_H #ifndef COMPILER_IRODUMP_H
#define COMPILER_IRODUMP_H #define COMPILER_IRODUMP_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
#include "compiler/BitVector.h"
#include "compiler/enode.h"
extern char *IRO_NodeName(ENodeType nodetype);
extern void IRO_InitializeNodeNamesArray(void);
extern void IRO_DumpIntTree(IROLinear *linear);
extern void IRO_DumpLinearList(IROLinear *linear);
extern void IRO_DumpBits(char *name, BitVector *bv);
extern void IRO_DumpAfterPhase(char *str, Boolean flag);
extern void IRO_LogForFunction(char *name);
extern void IRO_DumpFlowgraph(void);
extern void IRO_DumpNode(IRONode *node);
extern void IRO_DumpAssignments(void);
extern void IRO_DumpVars(void);
extern void IRO_DumpDf(void);
extern void IRO_DumpExprs(void);
extern void IRO_SetupDump(void);
extern void IRO_CleanupDump(void);
extern void IRO_Dump(char *format, ...);
extern void IRO_DumpAddr(IROAddrRecord *rec);
extern void IRO_SpellType(Type *type, char *buf);
#endif #endif

View File

@ -1,6 +1,8 @@
#ifndef COMPILER_IROEMPTYLOOP_H #ifndef COMPILER_IROEMPTYLOOP_H
#define COMPILER_IROEMPTYLOOP_H #define COMPILER_IROEMPTYLOOP_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
extern void IRO_FindEmptyLoops(void);
#endif #endif

View File

@ -1,6 +1,10 @@
#ifndef COMPILER_IROEVAL_H #ifndef COMPILER_IROEVAL_H
#define COMPILER_IROEVAL_H #define COMPILER_IROEVAL_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
// TODO
extern void IRO_TruncateBitfieldValueToType(CInt64 *val, Type *type, Type *type2);
extern void IRO_TruncateValueToType(CInt64 *val, Type *type);
#endif #endif

View File

@ -1,6 +1,8 @@
#ifndef COMPILER_IROEXPRREGENERATION_H #ifndef COMPILER_IROEXPRREGENERATION_H
#define COMPILER_IROEXPRREGENERATION_H #define COMPILER_IROEXPRREGENERATION_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
extern void IRO_RegenerateExpressions(void);
#endif #endif

View File

@ -1,6 +1,98 @@
#ifndef COMPILER_IROFLOWGRAPH_H #ifndef COMPILER_IROFLOWGRAPH_H
#define COMPILER_IROFLOWGRAPH_H #define COMPILER_IROFLOWGRAPH_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
#include "compiler/BitVector.h"
#include "compiler/CError.h"
#include "compiler/CompilerTools.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct IRONode {
UInt16 index;
UInt16 numsucc;
UInt16 *succ;
UInt16 numpred;
UInt16 *pred;
IROLinear *first;
IROLinear *last;
BitVector *x16; // In
BitVector *x1A; // Out
BitVector *x1E; // Gen
BitVector *x22; // Kill
UInt32 x26;
BitVector *x2A; // AA
BitVector *dom;
IRONode *nextnode;
Boolean x36;
Boolean x37;
Boolean mustreach;
Boolean x39;
UInt16 loopdepth;
Boolean x3C;
struct ObjectSet *addressed;
Boolean mustreach1;
};
typedef struct IRONodes {
UInt16 *indices;
UInt16 num;
UInt16 base;
} IRONodes;
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern UInt16 IRO_NumNodes;
extern IRONode *IRO_FirstNode;
extern IRONode *IRO_LastNode;
extern IRONode *IRO_EndNode;
extern IRONode **IRO_NodeTable;
extern BitVector *IRO_VarKills;
extern BitVector *IRO_Avail;
extern BitVector *IRO_FuncKills;
extern BitVector *IRO_ExprKills;
extern void IRO_ComputeSuccPred(void);
extern void IRO_ComputeDom(void);
extern void IRO_BuildFlowgraph(IROLinear *linear);
extern IRONode *IRO_NewFlowGraphNode(void);
extern IRONode *IRO_MergeFlowGraphNodes(IRONode *a, IRONode *b);
inline void IROFlowgraph_sub_4C2140(IRONodes *nodes) {
nodes->indices = oalloc(sizeof(UInt16) * IRO_NumNodes);
nodes->num = 0;
nodes->base = 0;
}
inline void IROFlowgraph_sub_4C20E0(IRONodes *nodes) {
}
inline UInt16 IROFlowgraph_sub_4C2040(IRONodes *nodes) {
return nodes->num;
}
inline UInt16 IROFlowgraph_sub_4C2100(IRONodes *nodes) {
UInt16 result = -1;
if (nodes->num) {
result = nodes->indices[nodes->base];
nodes->base = (nodes->base + 1) % IRO_NumNodes;
nodes->num--;
}
return result;
}
inline void IROFlowgraph_sub_4C3880(IRONodes *nodes, UInt16 index) {
if (nodes->num < IRO_NumNodes) {
nodes->indices[(nodes->base + nodes->num) % IRO_NumNodes] = index;
nodes->num++;
} else {
#line 93
CError_FATAL();
}
}
#endif #endif

View File

@ -1,6 +1,12 @@
#ifndef COMPILER_IROJUMP_H #ifndef COMPILER_IROJUMP_H
#define COMPILER_IROJUMP_H #define COMPILER_IROJUMP_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
extern Boolean IRO_DoJumpChaining(void);
extern void IRO_MakeReachable(IRONode *node);
extern Boolean IRO_RemoveUnreachable(void);
extern Boolean IRO_RemoveRedundantJumps(void);
extern Boolean IRO_RemoveLabels(void);
#endif #endif

View File

@ -1,6 +1,163 @@
#ifndef COMPILER_IROLINEARFORM_H #ifndef COMPILER_IROLINEARFORM_H
#define COMPILER_IROLINEARFORM_H #define COMPILER_IROLINEARFORM_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
#include "compiler/Switch.h"
#include "compiler/enode.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct IROLinearIRSave {
IROLinear *firstLinear;
IROLinear *lastLinear;
UInt32 numLinear;
Statement *curStat;
Boolean disableDueToAsm;
Boolean isLeafFunction;
Boolean functionHasReturn;
void *nullCheckList;
Statement *currStmt;
Statement *prevStmt;
} IROLinearIRSave;
typedef enum IROLinearType {
IROLinearNop,
IROLinearOperand,
IROLinearOp1Arg,
IROLinearOp2Arg,
IROLinearGoto,
IROLinearIf,
IROLinearIfNot,
IROLinearReturn,
IROLinearLabel,
IROLinearSwitch,
IROLinearOp3Arg,
IROLinearFunccall,
IROLinearEntry,
IROLinearExit,
IROLinearBeginCatch,
IROLinearEndCatch,
IROLinearEndCatchDtor,
IROLinearAsm,
IROLinear18,
IROLinear19,
IROLinearEnd
} IROLinearType;
enum {
IROLF_1 = 0x1,
IROLF_Reffed = 0x2,
IROLF_Assigned = 0x4,
IROLF_8 = 0x8,
IROLF_Used = 0x10,
IROLF_Ind = 0x20,
IROLF_Subs = 0x40,
IROLF_80 = 0x80,
IROLF_LoopInvariant = 0x100,
IROLF_BeginLoop = 0x200,
IROLF_EndLoop = 0x400,
IROLF_Ris = 0x800,
IROLF_Immind = 0x1000,
IROLF_VecOp = 0x2000,
IROLF_4000 = 0x4000,
IROLF_8000 = 0x8000,
IROLF_VecOpBase = 0x10000,
IROLF_20000 = 0x20000,
IROLF_CounterLoop = 0x40000,
IROLF_BitfieldIndirect = 0x80000,
IROLF_CouldError = 0x100000
};
// actual name is LinearNode as per mwccppc v8
struct IROLinear {
IROLinearType type;
ENodeType nodetype;
SInt32 flags;
UInt16 nodeflags;
unsigned short index;
Statement *stmt;
Type *rtype;
IROExpr *expr;
struct ERange *x16;
PointsToFunction *pointsToFunction;
Boolean x1E;
union {
struct {
void *data1;
void *data2;
void *data3;
void *data4;
void *data5;
} idk;
// Operand
ENode *node;
// Op1Arg
IROLinear *monadic;
// Op2Arg
struct {
IROLinear *left;
IROLinear *right;
} diadic;
// Op3Arg
struct {
IROLinear *a;
IROLinear *b;
IROLinear *c;
} args3;
// Funccall
struct {
char ispascal;
short argCount;
IROLinear **args;
IROLinear *linear8; // funcref
TypeFunc *functype;
struct LocationSetSet *returnedLocs;
} funccall;
// Asm
Statement *asm_stmt;
// If, IfNot, Goto, Label
struct {
CLabel *label;
IROLinear *x4; // if,ifnot only??
} label;
struct {
SwitchInfo *info;
IROLinear *x4;
} swtch;
// BeginCatch, EndCatch, EndCatchDtor
struct {
IROLinear *linear;
int x4;
int x8;
} ctch;
} u;
IROLinear *next;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern IROLinear *IRO_FirstLinear;
extern IROLinear *IRO_LastLinear;
extern UInt32 IRO_NumLinear;
extern Statement *CurStat;
extern IROLinear *IRO_NewLinear(IROLinearType type);
extern void IRO_PreLinearize(Statement *stmt);
extern void IRO_Linearize(Statement *stmt);
extern ENode *IRO_NewENode(ENodeType nodetype);
extern Statement *IRO_Delinearize(IRONode *node, IROLinear *linear);
extern void IRO_RenumberInts(void);
extern void IRO_UpdateFlagsOnInts(void);
extern void IRO_SaveLinearIR(IROLinearIRSave *save);
extern void IRO_RestoreLinearIR(IROLinearIRSave *save);
#define IS_LINEAR_ENODE(_linear, _nodetype) ( ((_linear)->type == IROLinearOperand) && ((_linear)->u.node->type) == (_nodetype) )
#define IS_LINEAR_MONADIC(_linear, _nodetype) ( ((_linear)->type == IROLinearOp1Arg) && ((_linear)->nodetype) == (_nodetype) )
#define IS_LINEAR_DIADIC(_linear, _nodetype) ( ((_linear)->type == IROLinearOp2Arg) && ((_linear)->nodetype) == (_nodetype) )
#define IS_LINEAR_DIADIC_2(_linear, _nodetype1, _nodetype2) ( ((_linear)->type == IROLinearOp2Arg) && (((_linear)->nodetype) == (_nodetype1) || ((_linear)->nodetype) == (_nodetype2)) )
#endif #endif

View File

@ -1,6 +1,111 @@
#ifndef COMPILER_IROLOOP_H #ifndef COMPILER_IROLOOP_H
#define COMPILER_IROLOOP_H #define COMPILER_IROLOOP_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
#include "compiler/BitVector.h"
typedef enum IROLoopIndFlags {
LoopInd_1 = 1,
LoopInd_2 = 2,
LoopInd_4 = 4,
LoopInd_8 = 8
} IROLoopIndFlags;
typedef enum IROLoopFlags {
LoopFlags_1 = 1,
LP_LOOP_HAS_CALLS = 2,
LP_LOOP_HAS_CNTRLFLOW = 4,
LoopFlags_8 = 8,
LP_INDUCTION_NOT_FOUND = 0x10,
LP_IFEXPR_NON_CANONICAL = 0x20,
LP_HAS_MULTIPLE_INDUCTIONS = 0x40,
LP_LOOP_HDR_HAS_SIDEEFFECTS = 0x80,
LoopFlags_100 = 0x100,
LoopFlags_200 = 0x200,
LP_LOOP_STEP_ISPOS = 0x400,
LoopFlags_800 = 0x800,
LoopFlags_1000 = 0x1000,
LoopFlags_2000 = 0x2000,
LP_LOOP_STEP_ISNEG = 0x4000,
LP_LOOP_HAS_ASM = 0x8000,
LoopFlags_10000 = 0x10000,
LoopFlags_20000 = 0x20000,
LoopFlags_40000 = 0x40000
} IROLoopFlags;
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct IROLoopInd {
IROLoopIndFlags flags;
VarRecord *var;
IRONode *fnode;
IROLinear *nd;
SInt32 addConst;
IROLinear *addNode;
struct IROLoopInd *next;
} IROLoopInd;
struct IROLoop {
SInt32 flags;
IRONode *fnode;
int x8;
int xC;
int x10;
IROLinear *nd14; // assignment expression that sets the initial value of induction
IROLinear *nd18;
IROLoopInd *induction;
int index20;
int index24;
CInt64 x28;
CInt64 x30;
int sizeBySomeMeasurement;
};
typedef enum IROLoopMemRefFlags {
LoopMemRef_1 = 1,
LoopMemRef_2 = 2,
LoopMemRef_4 = 4,
LoopMemRef_8 = 8,
LoopMemRef_10 = 0x10
} IROLoopMemRefFlags;
typedef struct IROLoopMemRef {
IROLoopMemRefFlags flags;
IROLinear *nd;
IROElmList *list;
IROAddrRecord *rec;
struct IROLoopMemRef *next;
} IROLoopMemRef;
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern IRONode *LoopNode;
extern Boolean ConditionalHeaderAtBottom;
extern IROLoopInd *FirstInd;
extern BitVector *InLoop;
extern IROList IRO_InitLList;
extern BitVector *InLoop_Exits;
extern BitVector *InLoop_Tails;
extern UInt32 LoopExitNumber;
extern UInt32 LoopTailNum;
extern IRONode *LoopExitSuccessor;
extern IRONode *LoopTail;
extern IROLoopMemRef *IRO_LoopMemRefFirst;
extern IROLoopMemRef *IRO_LoopMemRefCurrent;
extern void FindMustReach(void);
extern void FindMustReach1(IRONode *checkfnode);
extern void AddPreds(IRONode *fnode);
extern void IncLoopDepth(void);
extern void IRO_SetLoopDepth(void);
extern void IRO_FindLoops(void);
extern void ComputeLoopKills(void);
extern void ComputeLoopInvariance(void);
extern void ComputeLoopInduction(void);
extern void FindAssignmenttoInductionVar(IROLoop *loop, IRONode *fnode);
extern IROLoop *ExtractLoopInfo(IRONode *fnode);
extern CLabel *BuildLabel(IROList *list);
#endif #endif

View File

@ -1,6 +1,15 @@
#ifndef COMPILER_IROMALLOC_H #ifndef COMPILER_IROMALLOC_H
#define COMPILER_IROMALLOC_H #define COMPILER_IROMALLOC_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
extern size_t IRO_msize(void *buf);
extern void *IRO_malloc(size_t size);
extern void IRO_free(void *buf);
extern void *IRO_realloc(void *buf, size_t newsize);
extern void *IRO_calloc(size_t a, size_t b);
extern void IRO_pool_free_all(void);
extern void IRO_InitializeAllocator(void);
extern void IRO_TerminateAllocator(void);
#endif #endif

View File

@ -1,6 +1,25 @@
#ifndef COMPILER_IROPOINTERANALYSIS_H #ifndef COMPILER_IROPOINTERANALYSIS_H
#define COMPILER_IROPOINTERANALYSIS_H #define COMPILER_IROPOINTERANALYSIS_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
extern void PointerAnalysis_Setup(void);
extern void PointerAnalysis_Cleanup(void);
extern void IRO_AnalyzePointers(Object *function);
extern Boolean PointerAnalysis_TwoLinearNodePointerExprsMightAlias(Object *proc, IROLinear *nd1, IROLinear *nd2);
extern Boolean PointerAnalysis_TwoENodePointerExprsMightAlias(Object *proc, ENode *nd1, ENode *nd2);
extern Boolean PointerAnalysis_IsLinearNodePointerExprDefinite(Object *proc, IROLinear *nd);
extern Boolean PointerAnalysis_IsENodePointerExprDefinite(Object *proc, ENode *nd);
extern Boolean PointerAnalysis_IsVariableValueDefinite(Object *proc, VarRecord *var, PointsToFunction *pointsTo);
extern void PointerAnalysis_LookupLinearNodePointerExpr(Object *proc, IROLinear *indirect, IROListNode **list);
extern void PointerAnalysis_LookupENodePointerExpr(Object *proc, ENode *indirect, ENodeList **list);
extern void PointerAnalysis_LookupVariableIntoLinearNodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, IROList **list);
extern void PointerAnalysis_LookupVariableIntoENodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, ENodeList **list);
extern void PointerAnalysis_GetFunctionKills(Object *proc, IROLinear *funccall, ObjectList **list);
extern void PointerAnalysis_GetFunctionDependencies(Object *proc, IROLinear *funccall, ObjectList **list);
extern void PointerAnalysis_PragmaMode(void);
extern void PointerAnalysis_ParseEntryPointsToSpecifier(DeclInfo *di);
extern void PointerAnalysis_ParseExitPointsToSpecifier(DeclInfo *di);
extern void PointerAnalysis_ParseFunctionModifiesSpecifier(DeclInfo *di);
#endif #endif

View File

@ -1,6 +1,35 @@
#ifndef COMPILER_IROPROPAGATE_H #ifndef COMPILER_IROPROPAGATE_H
#define COMPILER_IROPROPAGATE_H #define COMPILER_IROPROPAGATE_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
#include "compiler/BitVector.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct IROAssign {
IROLinear *linear;
UInt16 index;
UInt16 varIndex;
IROLinear *linear2;
BitVector *depends;
Object *varObj;
VarRecord *var;
IROAssign *next;
IROAssign *prev;
UInt16 x20;
IRONode *node;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern IROAssign *IRO_FirstAssign;
extern IROAssign *IRO_LastAssign;
extern SInt32 IRO_NumAssign;
extern int IRO_IsRegable(Object *obj);
extern Boolean IRO_CopyAndConstantPropagation(void);
extern void IRO_ExpressionPropagation(void);
#endif #endif

View File

@ -1,6 +1,8 @@
#ifndef COMPILER_IRORANGEPROPAGATION_H #ifndef COMPILER_IRORANGEPROPAGATION_H
#define COMPILER_IRORANGEPROPAGATION_H #define COMPILER_IRORANGEPROPAGATION_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
extern Boolean IRO_RangePropagateInFNode(void);
#endif #endif

View File

@ -1,6 +1,10 @@
#ifndef COMPILER_IROSUBABLE_H #ifndef COMPILER_IROSUBABLE_H
#define COMPILER_IROSUBABLE_H #define COMPILER_IROSUBABLE_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
extern void IRO_InitializeIsSubableOpArray(void);
extern Boolean IRO_IsSubableExpression(IROLinear *nd);
extern Boolean IRO_IsVectorTempCandidate(IROLinear *nd);
#endif #endif

View File

@ -0,0 +1,9 @@
#ifndef COMPILER_IROTRANSFORM_H
#define COMPILER_IROTRANSFORM_H
#include "compiler/IrOptimizer.h"
// TODO
extern Boolean IRO_TransformSelfAssignmentToAssignment(IROLinear *linear);
#endif

View File

@ -1,6 +1,22 @@
#ifndef COMPILER_IROUNROLLLOOP_H #ifndef COMPILER_IROUNROLLLOOP_H
#define COMPILER_IROUNROLLLOOP_H #define COMPILER_IROUNROLLLOOP_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
extern void IRO_LoopUnroller(void);
extern void IRO_IterateForLoopBody();
extern void IRO_LinearizeForLoopPostLoop();
extern void BuildEarlyLoopExitTest();
extern void BuildLoopExitTest();
extern void IsIterationCountConstant();
extern void NoOpBlock();
extern void IRO_TestConstantIterationCount();
extern void BuildOrigIterationCount();
extern void BuildNewFinalvalue();
extern void BuildUnrolledBodyEntryTest();
extern void ChangeInductionReference();
extern void UpdateInductionIncrement();
extern void GenInitialAssignment();
extern void GenNewInduction();
#endif #endif

View File

@ -1,6 +1,112 @@
#ifndef COMPILER_IROUTIL_H #ifndef COMPILER_IROUTIL_H
#define COMPILER_IROUTIL_H #define COMPILER_IROUTIL_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
#include "compiler/CParser.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct IROList {
IROLinear *head;
IROLinear *tail;
};
struct IROListNode {
IROList list;
IROListNode *nextList;
};
struct IROElmList {
void *element;
IROElmList *next;
};
struct IROAddrRecord {
IROLinear *linear;
unsigned short numObjRefs;
IROElmList *objRefs;
unsigned short numMisc;
IROElmList *misc;
unsigned short numInts;
IROElmList *ints;
int x16;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern Object *FunctionName;
extern Boolean IRO_IsLeafFunction;
extern Boolean IRO_FunctionHasReturn;
extern Boolean DisableDueToAsm;
extern Boolean LoopOptimizerRun;
extern Object *IRO_IsVariable(IROLinear *linear);
extern Boolean IRO_IsConstant(IROLinear *linear);
extern Boolean IRO_IsPow2(IROLinear *linear, SInt32 *powvalue);
extern Boolean IRO_IsIntConstant(IROLinear *linear);
extern Boolean IRO_IsFloatConstant(IROLinear *linear);
extern Boolean IRO_IsVector128Constant(IROLinear *linear);
extern Boolean IRO_IsAssignment(IROLinear *linear);
extern Boolean IRO_TypesEqual(Type *a, Type *b);
extern Type *IRO_UnsignedType(Type *type);
extern Type *IRO_SignedType(Type *type);
extern Boolean IRO_is_CPtypeequal(Type *a, Type *b);
extern Boolean IRO_ExprsSame(IROLinear *a, IROLinear *b);
extern CLabel *IRO_NewLabel(void);
extern Boolean IRO_ExprsSameSemantically(IROLinear *a, IROLinear *b);
extern IROLinear *IRO_FindPrecedAfter(IROLinear *a, IROLinear *iter);
extern IROLinear *IRO_FindPreced(IROLinear *a);
extern IROLinear *IRO_FindFirst(IROLinear *linear);
extern void IRO_CutAndPasteAfter(IROLinear *a, IROLinear *b, IROLinear *c);
extern Boolean IRO_IsConstantZero(IROLinear *linear);
extern Boolean IRO_IsConstantOne(IROLinear *linear);
extern Boolean IRO_IsConstantNegativeOne(IROLinear *linear);
extern void IRO_NopOut(IROLinear *linear);
extern void IRO_NopNonSideEffects(IROLinear *linear, SInt32 level);
extern void IRO_BuildList(IROLinear *linear, Boolean isEntry);
typedef void (*IROWalkTreeFunc)(IROLinear *linear, Boolean isEntry);
extern void IRO_WalkTree(IROLinear *linear, IROWalkTreeFunc func);
extern void IRO_WalkTreeToPropagateFlags(IROLinear *linear, IROWalkTreeFunc func);
extern void IRO_WalkInts(IROLinear *a, IROLinear *b, IROWalkTreeFunc func);
extern void IRO_Cut(IROLinear *a, IROLinear *b);
extern void IRO_Paste(IROLinear *a, IROLinear *b, IROLinear *c);
extern void IRO_PasteAfter(IROLinear *a, IROLinear *b, IROLinear *c);
extern void IRO_ClipExpr(IROExpr *expr);
extern void IRO_ClipExprTree(IROLinear *linear);
extern void IRO_MoveExpression(IROExpr *expr, IROLinear *linear);
extern void IRO_InitList(IROList *list);
extern void IRO_AddToList(IROLinear *linear, IROList *list);
extern IROLinear *IRO_FindLabelNode(CLabel *label, IROLinear *linear);
extern void IRO_DuplicateExprRange(IROLinear *start, IROLinear *end, IROList *list);
extern IROLinear *IRO_DuplicateExpr(IROLinear *linear, IROList *list);
extern IROLinear *IRO_TempReference(Object *obj, IROList *list);
extern IROLinear *IRO_LocateFather(IROLinear *linear);
extern IROLinear *IRO_LocateFather_Cut_And_Paste(IROLinear *a, IROLinear *b);
extern IROLinear *IRO_LocateFather_Cut_And_Paste_Without_Nopping(IROLinear *a, IROLinear *b);
extern void IRO_ReplaceReference(IROLinear *a, Object *obj, IROLinear *b);
extern void IRO_ReplaceReferenceWithNode(IROLinear *a, IROLinear *b);
extern void IRO_GetTemp(IROExpr *expr);
extern IROLinear *IRO_AssignToTemp(IROExpr *expr);
extern IROLinear *IRO_FindStart(IROLinear *linear);
extern void IRO_DeleteCommaNode(IROLinear *linear, IROExpr *expr);
extern void IRO_RemoveCommaNodeFromIR(void);
extern IROAddrRecord *IRO_InitAddrRecordPointer(IROLinear *linear);
extern IROLinear *IRO_HasSideEffect(IROLinear *linear);
extern IROLinear *IRO_CheckSideEffect(IROLinear *linear);
typedef void (*WalkObjFunc)(Object *obj);
extern void IRO_WalkExcActions(ExceptionAction *action, WalkObjFunc func);
extern Boolean IRO_FunctionCallMightThrowException(IROLinear *linear);
extern IROLinear *IRO_NewIntConst(CInt64 val, Type *type);
extern IROLinear *IRO_NewFloatConst(Float val, Type *type);
extern Boolean IRO_IsAddressMultiply(IROLinear *linear);
extern void IRO_SetupForUserBreakChecking(void);
extern void IRO_CheckForUserBreak(void);
// TODO is this elsewhere?
inline Boolean IRO_IsUnsignedType(Type *type) {
return is_unsigned(type);
}
#endif #endif

View File

@ -1,6 +1,51 @@
#ifndef COMPILER_IROVARS_H #ifndef COMPILER_IROVARS_H
#define COMPILER_IROVARS_H #define COMPILER_IROVARS_H
#include "compiler/common.h" #include "compiler/IrOptimizer.h"
#include "compiler/enode.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
struct VarRecord {
UInt16 index;
Object *object;
int x6;
Boolean xA;
Boolean xB;
Boolean xC;
VarRecord *next;
IRODef *defs;
IROUse *uses;
Type *x1A; // bitfield-related
IROLinear *x1E;
};
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern VarRecord *IRO_FirstVar;
extern VarRecord *IRO_LastVar;
extern SInt32 IRO_NumVars;
extern Boolean IRO_IsBitField;
extern SInt32 IRO_BaseTerms;
extern SInt32 IRO_VarTerms;
extern Boolean IRO_IsModifyOp[MAXEXPR];
extern Boolean IRO_IsAssignOp[MAXEXPR];
extern void IRO_InitializeIRO_IsModifyOpArray(void);
extern void IRO_InitializeIRO_IsAssignOpArray(void);
extern VarRecord *IRO_FindVar(Object *object, Boolean flag1, Boolean flag2);
extern void IRO_FindAllVars(void);
extern void IRO_ZapVarPtrs(void);
extern void IRO_UpdateVars(void);
extern void IRO_AddElmToList(IROLinear *linear, IROElmList **list);
extern void IRO_DecomposeAddressExpression(IROLinear *linear, IROAddrRecord *rec);
extern void IRO_DecomposeAddressExpression_Cheap(IROLinear *linear);
extern VarRecord *IRO_FindAssigned(IROLinear *linear);
extern void IRO_GetKills(IROLinear *linear);
extern void IRO_CheckInit(void);
extern void IRO_RewriteBitFieldTemps(void);
extern void IRO_ScalarizeClassDataMembers(void);
#endif #endif

View File

@ -0,0 +1,18 @@
#ifndef COMPILER_LIVEINFO_H
#define COMPILER_LIVEINFO_H
#include "compiler/common.h"
typedef struct LiveInfo {
UInt32 *vec0; // use
UInt32 *vec4; // def
UInt32 *vec8; // in
UInt32 *vecC; // out
} LiveInfo;
extern LiveInfo *liveinfo;
extern void computelivevariables(Object *proc);
extern int dead(PCode *instr, char rclass, UInt32 *vec);
#endif

View File

@ -3,4 +3,8 @@
#include "compiler/common.h" #include "compiler/common.h"
extern int deletedloads;
extern void deletedeadloads(Object *proc);
#endif #endif

View File

@ -2,5 +2,97 @@
#define COMPILER_LOOPDETECTION_H #define COMPILER_LOOPDETECTION_H
#include "compiler/common.h" #include "compiler/common.h"
#include "compiler/BitVector.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct BlockList {
struct BlockList *next;
PCodeBlock *block;
} BlockList;
typedef struct InstrList {
struct InstrList *next;
PCode *instr;
} InstrList;
typedef enum LoopBound {
LOOP_BOUND_INDETERMINATE,
LOOP_BOUND_CONSTANT,
LOOP_BOUND_VARIABLE
} LoopBound;
typedef struct Loop {
struct Loop *parent;
struct Loop *nextSibling;
struct Loop *children;
PCodeBlock *body; // repeated block
PCodeBlock *preheader; // block at the start of the loop
PCodeBlock *footer; // block at the end of the loop
PCode *pc18;
BlockList *blocks;
UInt32 *memberblocks;
UInt32 *vec24;
UInt32 *vec28;
UInt32 *vec2C;
struct BasicInductionVar *basicInductionVars;
int loopWeight;
int bodySize; // amount of instructions in the body
SInt32 iterationCount;
SInt32 lower;
SInt32 upper;
SInt32 step; // value added in each iteration
unsigned char unknownCondition;
Boolean x4D;
Boolean x4E;
Boolean x4F;
Boolean isUnknownCountingLoop; // is a counting loop with non-constant iteration count
Boolean isKnownCountingLoop;
Boolean x52;
Boolean x53;
Boolean x54;
LoopBound lowerType;
LoopBound upperType;
Boolean x57;
} Loop;
typedef struct BasicInductionVar {
struct BasicInductionVar *next;
Loop *loop;
struct InductionVar *inductionVars;
InstrList *instrsC;
PCode *initializer;
SInt32 step;
short reg;
} BasicInductionVar;
typedef struct InductionVar {
struct InductionVar *next;
BasicInductionVar *basicVar;
PCode *instr;
PCode *instrC;
Loop *someloop;
SInt32 step;
short x18; // arg index within instr
short x1A; // arg index within instr
short x1C; // reg
short x1E; // reg
} InductionVar;
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern Loop *loopsinflowgraph;
extern int loopdetection_nblocks;
extern BitVector *LoopTemp;
extern void *LoopList_First;
extern void addblocktoloop(Loop *loop, PCodeBlock *block);
extern void insertpreheaderblock(Loop *loop);
extern void findloopsinflowgraph(void);
extern void analyzeForCountableLoops(Loop *loop);
extern void analyzeloop(Loop *loop);
extern void analyzeloopsinflowgraph(void);
#endif #endif

View File

@ -3,4 +3,12 @@
#include "compiler/common.h" #include "compiler/common.h"
extern int optimizedloops;
extern int optimizedloop_full_unroll;
extern int optimizedloop_trans_regs;
extern void pccomputepredecessors1(PCodeBlock *block);
extern void changearraytoregisters(void);
extern void optimizeloops(void);
#endif #endif

View File

@ -3,4 +3,7 @@
#include "compiler/common.h" #include "compiler/common.h"
// more stuff goes here
extern void ObjGen_DeclareSwitchTable(Object *a, Object *b);
#endif #endif

View File

@ -16,7 +16,10 @@
enum { enum {
EffectRead = 1, EffectRead = 1,
EffectWrite = 2 EffectWrite = 2,
Effect4 = 4,
Effect8 = 8,
Effect40 = 0x40 // spilled register?
}; };
/*typedef enum { /*typedef enum {
@ -48,7 +51,7 @@ typedef enum {
struct PCodeArg { struct PCodeArg {
PCOpKind kind; PCOpKind kind;
char arg; unsigned char arg;
union { union {
struct { struct {
unsigned short effect; unsigned short effect;
@ -74,14 +77,46 @@ struct PCodeArg {
} data; } data;
}; };
#define PC_OP_IS_REGISTER(_op, _rclass, _reg) \
((_op)->kind == PCOp_REGISTER && \
(char) (_op)->arg == (_rclass) && \
(_op)->data.reg.reg == (_reg))
#define PC_OP_IS_READ_REGISTER(_op, _rclass, _reg) \
((_op)->kind == PCOp_REGISTER && \
(char) (_op)->arg == (_rclass) && \
(_op)->data.reg.reg == (_reg) && \
((_op)->data.reg.effect & EffectRead))
#define PC_OP_IS_WRITE_REGISTER(_op, _rclass, _reg) \
((_op)->kind == PCOp_REGISTER && \
(char) (_op)->arg == (_rclass) && \
(_op)->data.reg.reg == (_reg) && \
((_op)->data.reg.effect & EffectWrite))
#define PC_OP_IS_ANY_REGISTER(_op, _rclass) \
((_op)->kind == PCOp_REGISTER && \
(char) (_op)->arg == (_rclass))
#define PC_OP_IS_READ_ANY_REGISTER(_op, _rclass) \
((_op)->kind == PCOp_REGISTER && \
(char) (_op)->arg == (_rclass) && \
((_op)->data.reg.effect & EffectRead))
#define PC_OP_IS_WRITE_ANY_REGISTER(_op, _rclass) \
((_op)->kind == PCOp_REGISTER && \
(char) (_op)->arg == (_rclass) && \
((_op)->data.reg.effect & EffectWrite))
struct PCode { struct PCode {
PCode *nextPCode; PCode *nextPCode;
PCode *prevPCode; PCode *prevPCode;
PCodeBlock *block; PCodeBlock *block;
unsigned int xx_C; int useID;
unsigned int _10; int defID;
int flags; UInt32 flags;
void *_18; struct Alias *alias;
SInt32 sourceoffset; SInt32 sourceoffset;
short op; short op;
short argCount; short argCount;
@ -92,7 +127,7 @@ struct PCodeLabel {
PCodeLabel *nextLabel; PCodeLabel *nextLabel;
PCodeBlock *block; PCodeBlock *block;
short resolved; short resolved;
short index; unsigned short index;
}; };
typedef struct _PCLink { typedef struct _PCLink {
@ -118,8 +153,8 @@ struct PCodeBlock {
/* PCode Flags */ /* PCode Flags */
enum { enum {
fPCodeFlag1 = 1, fPCodeFlag1 = 1,
fPCodeFlag2 = 2, fPCodeFlag2 = 2, // some kinda load
fPCodeFlag4 = 4, fPCodeFlag4 = 4, // some kinda store
fPCodeFlag8 = 8, fPCodeFlag8 = 8,
fPCodeFlag10 = 0x10, fPCodeFlag10 = 0x10,
fPCodeFlag20 = 0x20, fPCodeFlag20 = 0x20,
@ -134,8 +169,8 @@ enum {
fCommutative = 0x2000, fCommutative = 0x2000,
fIsCSE = 0x4000, fIsCSE = 0x4000,
fPCodeFlag8000 = 0x8000, fPCodeFlag8000 = 0x8000,
fPCodeFlag20000 = 0x20000, // ? fPCodeFlag20000 = 0x20000, // some kinda load?
fPCodeFlag40000 = 0x40000, // ? fPCodeFlag40000 = 0x40000, // some kinda store?
// Set 1 only // Set 1 only
fLink = 0x1000000, fLink = 0x1000000,
fBranchNotTaken = 0x4000000, fBranchNotTaken = 0x4000000,
@ -150,7 +185,7 @@ enum {
fPCodeFlag4000000 = 0x4000000, fPCodeFlag4000000 = 0x4000000,
fPCodeFlag8000000 = 0x8000000, fPCodeFlag8000000 = 0x8000000,
fPCodeFlag10000000 = 0x10000000, fPCodeFlag10000000 = 0x10000000,
fPCodeFlag20000000 = 0x20000000, fPCodeFlag20000000 = 0x20000000, // record bit?
fPCodeFlag40000000 = 0x40000000, fPCodeFlag40000000 = 0x40000000,
fPCodeFlag80000000 = 0x80000000 fPCodeFlag80000000 = 0x80000000
}; };
@ -159,9 +194,10 @@ enum {
fPCBlockFlag1 = 1, // prologue fPCBlockFlag1 = 1, // prologue
fPCBlockFlag2 = 2, // epilogue fPCBlockFlag2 = 2, // epilogue
fPCBlockFlag4 = 4, fPCBlockFlag4 = 4,
fPCBlockFlag8 = 8, fPCBlockFlag8 = 8, // scheduled?
fPCBlockFlag10 = 0x10, fPCBlockFlag10 = 0x10,
fPCBlockFlag20 = 0x20, fPCBlockFlag20 = 0x20,
fPCBlockFlag2000 = 0x2000,
fPCBlockFlag4000 = 0x4000 fPCBlockFlag4000 = 0x4000
}; };

View File

@ -3,4 +3,8 @@
#include "compiler/common.h" #include "compiler/common.h"
extern UInt32 assemblepcode(PCode *instr, UInt32 offset, PCodeArg *dummyArg);
extern void optimizefinalbranches();
extern void assemblefunction();
#endif #endif

View File

@ -17,6 +17,10 @@ typedef enum {
PCOp_PLACEHOLDEROPERAND PCOp_PLACEHOLDEROPERAND
} PCOpKind; } PCOpKind;
typedef enum {
PCOpMemory1 = 1
} PCOpMemoryArg;
typedef struct _OpcodeInfo { typedef struct _OpcodeInfo {
const char *name; const char *name;
const char *format; const char *format;

View File

@ -3,4 +3,36 @@
#include "compiler/common.h" #include "compiler/common.h"
extern int pclist_bad_operand;
extern void pcinitlisting(void);
extern void pccleanuplisting(void);
extern void pclistblocks(char *name1, char *name2);
extern void pclistdataflow(void);
extern void pclistinterferences(char *class_format, int regcount);
extern void pclistspill(void);
extern void pclistcopypropitem(void);
extern void pclistcoalesce(void);
extern void pclistusedefs(void);
extern void pclistpropinfo(void);
extern void pclistloops(void);
extern void pclistswitchtables(void);
extern void pclistdominators(void);
extern void pclistbackedge(void);
extern void pclistinterferencegraphnode(void);
extern void pclistinterferencegraph(void);
extern void pclistblock_scheduler(void);
extern void pclistblocks_start_scheduler(char *str1, char *str2);
extern void pclistblocks_end_scheduler(void);
extern void pctotalheap(void);
extern void pctotalmemory(void);
extern void pcmessage(char *probably_a_string, ...);
extern int formatalias(Alias *alias, char *buf, int bufSize);
extern int dumpalias(Alias *alias, int len, Boolean flag1, Boolean flag2);
extern void pcformatset(void);
extern int GetLineEndOffset(char *str, int lineNum, int len);
extern int GetLineOffset(char *str, int lineNum, int len);
extern void DumpSourceCode(void);
extern int DumpIR_SrcBreak(void);
#endif #endif

View File

@ -4,16 +4,29 @@
#include "compiler/common.h" #include "compiler/common.h"
enum { enum {
Register0 = 0,
Register2 = 2,
RegisterMax = 32 RegisterMax = 32
}; };
const char RegClass_SPR = 0; /*const char RegClass_SPR = 0;
const char RegClass_CRFIELD = 1; const char RegClass_CRFIELD = 1;
const char RegClass_VR = 2; const char RegClass_VR = 2;
const char RegClass_FPR = 3; const char RegClass_FPR = 3;
const char RegClass_GPR = 4; const char RegClass_GPR = 4;
const char RegClassMax = 5; const char RegClassMax = 5;
const char RegClass_6 = 6; const char RegClass_6 = 6;
const char RegClass_DCR = 7; const char RegClass_DCR = 7;*/
typedef enum RegClass {
RegClass_Invalid = -1,
RegClass_SPR = 0,
RegClass_CRFIELD = 1,
RegClass_VR = 2,
RegClass_FPR = 3,
RegClass_GPR = 4,
RegClassMax = 5,
RegClass_6 = 6,
RegClass_DCR = 7
} RegClass;
enum { enum {
RegState0 = 0, RegState0 = 0,

View File

@ -3,4 +3,46 @@
#include "compiler/common.h" #include "compiler/common.h"
typedef int (*LatencyFunc)(PCode *instr);
typedef void (*InitializeFunc)(void);
typedef int (*CanIssueFunc)(PCode *instr);
typedef void (*IssueFunc)(PCode *instr);
typedef void (*AdvanceClockFunc)(void);
typedef int (*SerializesFunc)(PCode *instr);
typedef int (*UsesVPermuteUnitFunc)(PCode *instr);
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct MachineInfo {
int x0;
int x4;
int x8;
LatencyFunc latency;
InitializeFunc initialize;
CanIssueFunc can_issue;
IssueFunc issue;
AdvanceClockFunc advance_clock;
SerializesFunc serializes;
UsesVPermuteUnitFunc uses_vpermute_unit;
} MachineInfo;
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern MachineInfo machine601;
extern MachineInfo machine603;
extern MachineInfo machine603e;
extern MachineInfo machine604;
extern MachineInfo machine7400;
extern MachineInfo machine7450;
extern MachineInfo machine750;
extern MachineInfo machine821;
extern int is_same_operand(PCodeArg *a, PCodeArg *b);
extern void scheduleinstructions(Boolean flag);
extern int is_dependent(PCode *a, PCode *b, char rclass);
extern int uses_vpermute_unit(PCode *instr);
extern int default_uses_vpermute_unit(PCode *instr);
#endif #endif

View File

@ -3,4 +3,7 @@
#include "compiler/common.h" #include "compiler/common.h"
extern void estimatespillcosts(void);
extern void insertspillcode(void);
#endif #endif

View File

@ -3,4 +3,8 @@
#include "compiler/common.h" #include "compiler/common.h"
extern int strengthreducedloops;
extern void strengthreduceloops(void);
#endif #endif

View File

@ -2,5 +2,65 @@
#define COMPILER_USEDEFCHAINS_H #define COMPILER_USEDEFCHAINS_H
#include "compiler/common.h" #include "compiler/common.h"
#include "compiler/Registers.h"
#include "compiler/PCodeInfo.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct TinyValue {
PCOpKind kind;
unsigned char arg;
union {
short reg;
Object *object;
} u;
} TinyValue;
typedef struct UseDefInfo {
UInt32 *defvec0;
UInt32 *defvec4;
UInt32 *defvec8;
UInt32 *defvecC;
UInt32 *usevec10;
UInt32 *usevec14;
UInt32 *usevec18;
UInt32 *usevec1C;
} UseDefInfo;
typedef struct UseOrDef {
PCode *pcode;
TinyValue v;
} UseOrDef;
typedef struct RegUseOrDef {
struct RegUseOrDef *next;
int id;
} RegUseOrDef;
typedef struct ObjectUseDef {
struct ObjectUseDef *next;
struct ObjectUseDef *leftchild;
struct ObjectUseDef *rightchild;
Object *object;
RegUseOrDef *uses;
RegUseOrDef *defs;
} ObjectUseDef;
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern int number_of_Defs;
extern UseOrDef *Defs;
extern RegUseOrDef **reg_Defs[RegClassMax];
extern int number_of_Uses;
extern UseOrDef *Uses;
extern RegUseOrDef **reg_Uses[RegClassMax];
extern UseDefInfo *usedefinfo;
extern ObjectUseDef *objectusedefs;
extern ObjectUseDef *objectusedeflist;
extern ObjectUseDef *findobjectusedef(Object *object);
extern void computeusedefchains(int flag);
#endif #endif

View File

@ -3,4 +3,17 @@
#include "compiler/common.h" #include "compiler/common.h"
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
#ifdef __MWERKS__
#pragma options align=reset
#endif
extern int removedcommonsubexpressions;
extern int nextvaluenumber;
extern void killmemory(Alias *alias, PCode *newValue);
extern void removecommonsubexpressions(Object *proc, int flag);
#endif #endif

View File

@ -3,4 +3,6 @@
#include "compiler/common.h" #include "compiler/common.h"
extern int vectorarraystoregs(void);
#endif #endif

View File

@ -112,6 +112,7 @@ typedef enum Section {
N_SECTIONS = 45 N_SECTIONS = 45
} Section; } Section;
typedef struct Alias Alias;
typedef struct BClassList BClassList; typedef struct BClassList BClassList;
typedef struct CI_FuncData CI_FuncData; typedef struct CI_FuncData CI_FuncData;
typedef struct CLabel CLabel; typedef struct CLabel CLabel;

View File

@ -279,14 +279,67 @@ enum {
}; };
#define ENODE_IS(_enode, _etype) ( (_enode)->type == (_etype) ) #define ENODE_IS(_enode, _etype) ( (_enode)->type == (_etype) )
#define ENODE_IS2(_enode, _etype1, _etype2) ( ENODE_IS((_enode), (_etype1)) || ENODE_IS(_enode, (_etype2)) ) #define ENODE_IS2(_enode, _etype1, _etype2) ( ENODE_IS((_enode), (_etype1)) || ENODE_IS((_enode), (_etype2)) )
#define ENODE_IS3(_enode, _etype1, _etype2, _etype3) ( ENODE_IS((_enode), (_etype1)) || ENODE_IS(_enode, (_etype2)) || ENODE_IS(_enode, (_etype3)) ) #define ENODE_IS3(_enode, _etype1, _etype2, _etype3) ( ENODE_IS((_enode), (_etype1)) || ENODE_IS((_enode), (_etype2)) || ENODE_IS((_enode), (_etype3)) )
#define ENODE_IS4(_enode, _etype1, _etype2, _etype3, _etype4) ( ENODE_IS((_enode), (_etype1)) || ENODE_IS((_enode), (_etype2)) || ENODE_IS((_enode), (_etype3)) || ENODE_IS((_enode), (_etype4)) )
#define ENODE_IS_RANGE(_enode, _lo, _hi) ( ((_enode)->type >= (_lo)) && ((_enode)->type <= (_hi)) ) #define ENODE_IS_RANGE(_enode, _lo, _hi) ( ((_enode)->type >= (_lo)) && ((_enode)->type <= (_hi)) )
#define ENODE_QUALS(_enode) ( (UInt32) ( (_enode)->flags & ENODE_FLAG_QUALS ) ) #define ENODE_QUALS(_enode) ( (UInt32) ( (_enode)->flags & ENODE_FLAG_QUALS ) )
#define ENODE_IS_INDIRECT_TO(_enode, _etype) ( ENODE_IS((_enode), EINDIRECT) && ENODE_IS((_enode)->data.monadic, (_etype)) ) #define ENODE_IS_INDIRECT_TO(_enode, _etype) ( ENODE_IS((_enode), EINDIRECT) && ENODE_IS((_enode)->data.monadic, (_etype)) )
#define ENODE_IS_ASSIGN(_enode) ( ENODE_IS_RANGE((_enode), EASS, EORASS) ) #define ENODE_IS_ASSIGN(_enode) ( ENODE_IS_RANGE((_enode), EASS, EORASS) )
#define ENODE_IS_ASSIGN_TO(_enode, _etype) ( ENODE_IS_RANGE((_enode), EASS, EORASS) && ENODE_IS((_enode)->data.diadic.left->data.monadic, (_etype)) ) #define ENODE_IS_ASSIGN_TO(_enode, _etype) ( ENODE_IS_RANGE((_enode), EASS, EORASS) && ENODE_IS((_enode)->data.diadic.left->data.monadic, (_etype)) )
// 0 to 8, 0x30 to 0x31
#define ENODE_CASE_MONADIC \
case EPOSTINC: \
case EPOSTDEC: \
case EPREINC: \
case EPREDEC: \
case EINDIRECT: \
case EMONMIN: \
case EBINNOT: \
case ELOGNOT: \
case EFORCELOAD: \
case ETYPCON: \
case EBITFIELD:
// 9 to 0x1B
#define ENODE_CASE_DIADIC_1 \
case EMUL: \
case EMULV: \
case EDIV: \
case EMODULO: \
case EADDV: \
case ESUBV: \
case EADD: \
case ESUB: \
case ESHL: \
case ESHR: \
case ELESS: \
case EGREATER: \
case ELESSEQU: \
case EGREATEREQU: \
case EEQU: \
case ENOTEQU: \
case EAND: \
case EXOR: \
case EOR:
// 0x1E to 0x28, 0x2D, 0x2F
#define ENODE_CASE_ASSIGN \
case EASS: \
case EMULASS: \
case EDIVASS: \
case EMODASS: \
case EADDASS: \
case ESUBASS: \
case ESHLASS: \
case ESHRASS: \
case EANDASS: \
case EXORASS: \
case EORASS: \
case EBCLR: \
case EBSET:
#ifdef __MWERKS__ #ifdef __MWERKS__
#pragma options align=reset #pragma options align=reset
#endif #endif

Some files were not shown because too many files have changed in this diff Show More