diff options
| -rw-r--r-- | linearize.c | 6 | ||||
| -rw-r--r-- | linearize.h | 2 | ||||
| -rw-r--r-- | simplify.c | 53 | ||||
| -rw-r--r-- | sparse-llvm.c | 75 | ||||
| -rw-r--r-- | validation/optim/simplify-neg-add-cte.c | 11 | ||||
| -rw-r--r-- | validation/optim/simplify-neg-not.c | 9 | ||||
| -rw-r--r-- | validation/optim/simplify-neg-sub.c | 9 | ||||
| -rw-r--r-- | validation/optim/simplify-not-add-cte.c | 11 | ||||
| -rw-r--r-- | validation/optim/simplify-not-neg.c | 9 | ||||
| -rw-r--r-- | validation/optim/simplify-not-sub-cte.c | 11 | ||||
| -rw-r--r-- | validation/optim/simplify-not-xor-cte.c | 11 |
11 files changed, 152 insertions, 55 deletions
diff --git a/linearize.c b/linearize.c index 1081bda8..b7da35fa 100644 --- a/linearize.c +++ b/linearize.c @@ -426,10 +426,10 @@ const char *show_instruction(struct instruction *insn) break; } case OP_LOAD: - buf += sprintf(buf, "%s <- %d[%s]", show_pseudo(insn->target), insn->offset, show_pseudo(insn->src)); + buf += sprintf(buf, "%s <- %lld[%s]", show_pseudo(insn->target), insn->offset, show_pseudo(insn->src)); break; case OP_STORE: - buf += sprintf(buf, "%s -> %d[%s]", show_pseudo(insn->target), insn->offset, show_pseudo(insn->src)); + buf += sprintf(buf, "%s -> %lld[%s]", show_pseudo(insn->target), insn->offset, show_pseudo(insn->src)); break; case OP_INLINED_CALL: case OP_CALL: { @@ -925,7 +925,7 @@ struct access_data { struct symbol *type; // ctype struct symbol *btype; // base type of bitfields pseudo_t address; // pseudo containing address .. - unsigned int offset; // byte offset + long long offset; // byte offset }; static int linearize_simple_address(struct entrypoint *ep, diff --git a/linearize.h b/linearize.h index 76efd0b4..d8cbc3f3 100644 --- a/linearize.h +++ b/linearize.h @@ -117,7 +117,7 @@ struct instruction { }; struct /* memops */ { pseudo_t addr; /* alias .src */ - unsigned int offset; + long long offset; unsigned int is_volatile:1; }; struct /* binops and sel */ { @@ -1481,21 +1481,64 @@ static int simplify_constant_unop(struct instruction *insn) static int simplify_unop(struct instruction *insn) { + struct instruction *def; + pseudo_t src = insn->src; + if (dead_insn(insn, &insn->src1, NULL, NULL)) return REPEAT_CSE; - if (constant(insn->src1)) + if (constant(src)) return simplify_constant_unop(insn); switch (insn->opcode) { - struct instruction *def; - case OP_NOT: - if (DEF_OPCODE(def, insn->src) == OP_NOT) + switch (DEF_OPCODE(def, src)) { + case OP_ADD: + if (!constant(def->src2)) + break; + insn->opcode = OP_SUB; // ~(x + C) --> ~C - x + src = eval_unop(OP_NOT, insn->size, def->src2); + use_pseudo(insn, def->src1, &insn->src2); + return replace_pseudo(insn, &insn->src1, src); + case OP_NEG: + insn->opcode = OP_SUB; // ~(-x) --> x - 1 + insn->src2 = value_pseudo(1); + return replace_pseudo(insn, &insn->src1, def->src); + case OP_NOT: // ~(~x) --> x return replace_with_pseudo(insn, def->src); + case OP_SUB: + if (!constant(def->src1)) + break; + insn->opcode = OP_ADD; // ~(C - x) --> x + ~C + insn->src2 = eval_unop(OP_NOT, insn->size, def->src1); + return replace_pseudo(insn, &insn->src1, def->src2); + case OP_XOR: + if (!constant(def->src2)) + break; + insn->opcode = OP_XOR; // ~(x ^ C) --> x ^ ~C + insn->src2 = eval_unop(OP_NOT, insn->size, def->src2); + return replace_pseudo(insn, &insn->src1, def->src1); + } break; case OP_NEG: - if (DEF_OPCODE(def, insn->src) == OP_NEG) + switch (DEF_OPCODE(def, src)) { + case OP_ADD: + if (!constant(def->src2)) + break; + insn->opcode = OP_SUB; // -(x + C) --> (-C - x) + src = eval_unop(OP_NEG, insn->size, def->src2); + use_pseudo(insn, def->src1, &insn->src2); + return replace_pseudo(insn, &insn->src1, src); + case OP_NEG: // -(-x) --> x return replace_with_pseudo(insn, def->src); + case OP_NOT: + insn->opcode = OP_ADD; // -(~x) --> x + 1 + insn->src2 = value_pseudo(1); + return replace_pseudo(insn, &insn->src1, def->src); + case OP_SUB: + insn->opcode = OP_SUB; // -(x - y) --> y - x + use_pseudo(insn, def->src1, &insn->src2); + return replace_pseudo(insn, &insn->src1, def->src2); + } break; default: return 0; diff --git a/sparse-llvm.c b/sparse-llvm.c index c7a9fbb7..c984dc87 100644 --- a/sparse-llvm.c +++ b/sparse-llvm.c @@ -826,37 +826,14 @@ static void output_op_call(struct function *fn, struct instruction *insn) static void output_op_phisrc(struct function *fn, struct instruction *insn) { - LLVMValueRef v; - struct instruction *phi; - - assert(insn->target->priv == NULL); - - /* target = src */ - v = get_operand(fn, insn->type, insn->phi_src); - - FOR_EACH_PTR(insn->phi_users, phi) { - LLVMValueRef load, ptr; - - 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); + insn->src->priv = get_operand(fn, insn->type, insn->src); } static void output_op_phi(struct function *fn, struct instruction *insn) { - 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); + LLVMTypeRef dst_type = insn_symbol_type(insn); + + insn->target->priv = LLVMBuildPhi(fn->builder, dst_type, ""); } static void output_op_ptrcast(struct function *fn, struct instruction *insn) @@ -1161,30 +1138,11 @@ static void output_fn(LLVMModuleRef module, struct entrypoint *ep) static int nr_bb; 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(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); @@ -1194,6 +1152,31 @@ static void output_fn(LLVMModuleRef module, struct entrypoint *ep) output_bb(&function, bb); } END_FOR_EACH_PTR(bb); + + FOR_EACH_PTR(ep->bbs, bb) { // complete the OP_PHIs + struct instruction *insn; + + FOR_EACH_PTR(bb->insns, insn) { + pseudo_t phi; + + if (!insn->bb || insn->opcode != OP_PHI) + continue; + + FOR_EACH_PTR(insn->phi_list, phi) { + struct instruction *phisrc; + LLVMBasicBlockRef bref; + LLVMValueRef vref; + + if (phi == VOID) + continue; + + phisrc = phi->def; + bref = phisrc->bb->priv; + vref = phisrc->src->priv; + LLVMAddIncoming(insn->target->priv, &vref, &bref, 1); + } END_FOR_EACH_PTR(phi); + } END_FOR_EACH_PTR(insn); + } END_FOR_EACH_PTR(bb); } static LLVMValueRef output_data(LLVMModuleRef module, struct symbol *sym) diff --git a/validation/optim/simplify-neg-add-cte.c b/validation/optim/simplify-neg-add-cte.c new file mode 100644 index 00000000..a02c474f --- /dev/null +++ b/validation/optim/simplify-neg-add-cte.c @@ -0,0 +1,11 @@ +#define C 3 + +int foo(int x) { return -(x + C) == (-3 - x); } + +/* + * check-name: simplify-neg-add-cte + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-contains: ret\\..*\\$1 + */ diff --git a/validation/optim/simplify-neg-not.c b/validation/optim/simplify-neg-not.c new file mode 100644 index 00000000..e92352cf --- /dev/null +++ b/validation/optim/simplify-neg-not.c @@ -0,0 +1,9 @@ +int foo(int x) { return -(~x) == x + 1; } + +/* + * check-name: simplify-neg-not + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-contains: ret\\..*\\$1 + */ diff --git a/validation/optim/simplify-neg-sub.c b/validation/optim/simplify-neg-sub.c new file mode 100644 index 00000000..9a824f09 --- /dev/null +++ b/validation/optim/simplify-neg-sub.c @@ -0,0 +1,9 @@ +int foo(int x, int y) { return -(x - y) == (y - x); } + +/* + * check-name: simplify-neg-sub + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-contains: ret\\..*\\$1 + */ diff --git a/validation/optim/simplify-not-add-cte.c b/validation/optim/simplify-not-add-cte.c new file mode 100644 index 00000000..6594012b --- /dev/null +++ b/validation/optim/simplify-not-add-cte.c @@ -0,0 +1,11 @@ +#define C 3 + +int foo(int x) { return ~(x + C) == (~C - x); } + +/* + * check-name: simplify-not-add-cte + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-contains: ret\\..*\\$1 + */ diff --git a/validation/optim/simplify-not-neg.c b/validation/optim/simplify-not-neg.c new file mode 100644 index 00000000..3fd8400d --- /dev/null +++ b/validation/optim/simplify-not-neg.c @@ -0,0 +1,9 @@ +int foo(int x) { return ~(-x) == (x - 1); } + +/* + * check-name: simplify-not-neg + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-contains: ret\\..*\\$1 + */ diff --git a/validation/optim/simplify-not-sub-cte.c b/validation/optim/simplify-not-sub-cte.c new file mode 100644 index 00000000..1ea73ece --- /dev/null +++ b/validation/optim/simplify-not-sub-cte.c @@ -0,0 +1,11 @@ +#define C 3 + +int foo(int x) { return ~(C - x) == (x + ~C); } + +/* + * check-name: simplify-not-sub-cte + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-contains: ret\\..*\\$1 + */ diff --git a/validation/optim/simplify-not-xor-cte.c b/validation/optim/simplify-not-xor-cte.c new file mode 100644 index 00000000..c3c803b3 --- /dev/null +++ b/validation/optim/simplify-not-xor-cte.c @@ -0,0 +1,11 @@ +#define C 3 + +int foo(int x) { return ~(x ^ C) == (x ^ ~C); } + +/* + * check-name: simplify-not-xor-cte + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-contains: ret\\..*\\$1 + */ |
