aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--sparse-llvm.c131
-rw-r--r--validation/backend/loop2.c14
2 files changed, 54 insertions, 91 deletions
diff --git a/sparse-llvm.c b/sparse-llvm.c
index 6f2fbd69..81ac7643 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -18,21 +18,11 @@
#include "linearize.h"
#include "flow.h"
-struct phi_fwd {
- struct phi_fwd *next;
-
- LLVMValueRef phi;
- pseudo_t pseudo;
- bool resolved;
-};
-
struct function {
LLVMBuilderRef builder;
LLVMTypeRef type;
LLVMValueRef fn;
LLVMModuleRef module;
-
- struct phi_fwd *fwd_list;
};
static inline bool symbol_is_fp_type(struct symbol *sym)
@@ -839,100 +829,39 @@ static void output_op_call(struct function *fn, struct instruction *insn)
insn->target->priv = target;
}
-static void store_phi_fwd(struct function *fn, LLVMValueRef phi,
- pseudo_t pseudo)
-{
- struct phi_fwd *fwd;
-
- fwd = calloc(1, sizeof(*fwd));
- fwd->phi = phi;
- fwd->pseudo = pseudo;
-
- /* append fwd ref to function-wide list */
- if (!fn->fwd_list)
- fn->fwd_list = fwd;
- else {
- struct phi_fwd *last = fn->fwd_list;
-
- while (last->next)
- last = last->next;
- last->next = fwd;
- }
-}
-
-static void output_phi_fwd(struct function *fn, pseudo_t pseudo, LLVMValueRef v)
-{
- struct phi_fwd *fwd = fn->fwd_list;
-
- while (fwd) {
- struct phi_fwd *tmp;
-
- tmp = fwd;
- fwd = fwd->next;
-
- if (tmp->pseudo == pseudo && !tmp->resolved) {
- LLVMValueRef phi_vals[1];
- LLVMBasicBlockRef phi_blks[1];
-
- phi_vals[0] = v;
- phi_blks[0] = pseudo->def->bb->priv;
-
- LLVMAddIncoming(tmp->phi, phi_vals, phi_blks, 1);
-
- tmp->resolved = true;
- }
- }
-}
-
static void output_op_phisrc(struct function *fn, struct instruction *insn)
{
LLVMValueRef v;
+ struct instruction *phi;
assert(insn->target->priv == NULL);
/* target = src */
v = pseudo_to_value(fn, insn, insn->phi_src);
- insn->target->priv = v;
- assert(insn->target->priv != NULL);
+ FOR_EACH_PTR(insn->phi_users, phi) {
+ LLVMValueRef load, ptr;
- /* resolve forward references to this phi source, if present */
- output_phi_fwd(fn, insn->target, v);
+ assert(phi->opcode == OP_PHI);
+ /* phi must be load from alloca */
+ load = phi->target->priv;
+ assert(LLVMGetInstructionOpcode(load) == LLVMLoad);
+ ptr = LLVMGetOperand(load, 0);
+ /* store v to alloca */
+ LLVMBuildStore(fn->builder, v, ptr);
+ } END_FOR_EACH_PTR(phi);
}
static void output_op_phi(struct function *fn, struct instruction *insn)
{
- pseudo_t phi;
- LLVMValueRef target;
-
- target = LLVMBuildPhi(fn->builder, insn_symbol_type(fn->module, insn),
- "phi");
- int pll = 0;
- FOR_EACH_PTR(insn->phi_list, phi) {
- if (pseudo_to_value(fn, insn, phi)) /* skip VOID, fwd refs*/
- pll++;
- } END_FOR_EACH_PTR(phi);
-
- LLVMValueRef *phi_vals = calloc(pll, sizeof(LLVMValueRef));
- LLVMBasicBlockRef *phi_blks = calloc(pll, sizeof(LLVMBasicBlockRef));
-
- int idx = 0;
- FOR_EACH_PTR(insn->phi_list, phi) {
- LLVMValueRef v;
-
- v = pseudo_to_value(fn, insn, phi);
- if (v) { /* skip VOID, fwd refs */
- phi_vals[idx] = v;
- phi_blks[idx] = phi->def->bb->priv;
- idx++;
- }
- else if (phi->type == PSEUDO_PHI) /* fwd ref */
- store_phi_fwd(fn, target, phi);
- } END_FOR_EACH_PTR(phi);
-
- LLVMAddIncoming(target, phi_vals, phi_blks, pll);
-
- insn->target->priv = target;
+ LLVMValueRef load = insn->target->priv;
+
+ /* forward load */
+ assert(LLVMGetInstructionOpcode(load) == LLVMLoad);
+ /* forward load has no parent block */
+ assert(!LLVMGetInstructionParent(load));
+ /* finalize load in current block */
+ LLVMInsertIntoBuilder(fn->builder, load);
}
static void output_op_ptrcast(struct function *fn, struct instruction *insn)
@@ -1095,7 +1024,6 @@ static void output_insn(struct function *fn, struct instruction *insn)
assert(0);
break;
case OP_DEATHNOTE:
- assert(0);
break;
case OP_ASM:
assert(0);
@@ -1174,11 +1102,30 @@ static void output_fn(LLVMModuleRef module, struct entrypoint *ep)
LLVMBasicBlockRef bbr;
char bbname[32];
+ struct instruction *insn;
sprintf(bbname, "L%d", nr_bb++);
bbr = LLVMAppendBasicBlock(function.fn, bbname);
bb->priv = bbr;
+
+ /* allocate alloca for each phi */
+ FOR_EACH_PTR(bb->insns, insn) {
+ LLVMBasicBlockRef entrybbr;
+ LLVMTypeRef phi_type;
+ LLVMValueRef ptr;
+
+ if (!insn->bb || insn->opcode != OP_PHI)
+ continue;
+ /* insert alloca into entry block */
+ entrybbr = LLVMGetEntryBasicBlock(function.fn);
+ LLVMPositionBuilderAtEnd(function.builder, entrybbr);
+ phi_type = insn_symbol_type(module, insn);
+ ptr = LLVMBuildAlloca(function.builder, phi_type, "");
+ /* emit forward load for phi */
+ LLVMClearInsertionPosition(function.builder);
+ insn->target->priv = LLVMBuildLoad(function.builder, ptr, "phi");
+ } END_FOR_EACH_PTR(insn);
}
END_FOR_EACH_PTR(bb);
@@ -1267,6 +1214,8 @@ int main(int argc, char **argv)
compile(module, sparse_initialize(argc, argv, &filelist));
+ /* need ->phi_users */
+ dbg_dead = 1;
FOR_EACH_PTR_NOTAG(filelist, file) {
compile(module, sparse(file));
} END_FOR_EACH_PTR_NOTAG(file);
diff --git a/validation/backend/loop2.c b/validation/backend/loop2.c
new file mode 100644
index 00000000..279af214
--- /dev/null
+++ b/validation/backend/loop2.c
@@ -0,0 +1,14 @@
+extern int op(void);
+
+static void test(void)
+{
+ int i;
+ for (i = 0; ; i++) {
+ op();
+ }
+}
+
+/*
+ * check-name: Loops with unused counter
+ * check-command: ./sparsec -c $file -o tmp.o
+ */