aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--lib.h5
-rw-r--r--linearize.c10
-rw-r--r--linearize.h2
-rw-r--r--parse.c15
-rw-r--r--simplify.c140
-rw-r--r--sparse-llvm.c75
-rw-r--r--validation/asm-bad0.c2
-rw-r--r--validation/bad-type-twice0.c3
-rw-r--r--validation/badtype2.c1
-rw-r--r--validation/badtype3.c1
-rw-r--r--validation/implicit-KR-arg-type1.c11
-rw-r--r--validation/linear/inline-definition.c30
-rw-r--r--validation/optim/set-uimm0.c14
-rw-r--r--validation/optim/simplify-neg-add-cte.c11
-rw-r--r--validation/optim/simplify-neg-not.c9
-rw-r--r--validation/optim/simplify-neg-sub.c9
-rw-r--r--validation/optim/simplify-not-add-cte.c11
-rw-r--r--validation/optim/simplify-not-neg.c9
-rw-r--r--validation/optim/simplify-not-sub-cte.c11
-rw-r--r--validation/optim/simplify-not-xor-cte.c11
20 files changed, 267 insertions, 113 deletions
diff --git a/lib.h b/lib.h
index 0b1d4492..b4c3db93 100644
--- a/lib.h
+++ b/lib.h
@@ -204,6 +204,11 @@ static inline pseudo_t first_pseudo(struct pseudo_list *head)
return first_ptr_list((struct ptr_list *)head);
}
+static inline struct symbol *first_symbol(struct symbol_list *head)
+{
+ return first_ptr_list((struct ptr_list *)head);
+}
+
static inline void concat_symbol_list(struct symbol_list *from, struct symbol_list **to)
{
concat_ptr_list((struct ptr_list *)from, (struct ptr_list **)to);
diff --git a/linearize.c b/linearize.c
index 978d1e41..d9a3ac49 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,
@@ -1520,8 +1520,6 @@ static pseudo_t linearize_call_expression(struct entrypoint *ep, struct expressi
}
ctype = &fntype->ctype;
- if (fntype->type == SYM_NODE)
- fntype = fntype->ctype.base_type;
add_symbol(&insn->fntypes, fntype);
FOR_EACH_PTR(expr->args, arg) {
@@ -2058,7 +2056,7 @@ static pseudo_t linearize_inlined_call(struct entrypoint *ep, struct statement *
pseudo = linearize_fn_statement(ep, stmt);
insn->target = pseudo;
- use_pseudo(insn, symbol_pseudo(ep, stmt->inline_fn), &insn->func);
+ insn->func = symbol_pseudo(ep, stmt->inline_fn);
bb = ep->active;
if (!bb->insns)
bb->pos = stmt->pos;
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 */ {
diff --git a/parse.c b/parse.c
index 31ecef0f..0b268570 100644
--- a/parse.c
+++ b/parse.c
@@ -2468,6 +2468,11 @@ static struct token *statement(struct token *token, struct statement **tree)
warn_label_usage(stmt->pos, s->label_pos, s->ident);
}
s->stmt = stmt;
+ if (match_op(token, '}')) {
+ warning(token->pos, "statement expected after label");
+ stmt->label_statement = alloc_statement(token->pos, STMT_NONE);
+ return token;
+ }
return statement(token, &stmt->label_statement);
}
}
@@ -2713,6 +2718,14 @@ static void declare_argument(struct symbol *sym, struct symbol *fn)
sparse_error(sym->pos, "no identifier for function argument");
return;
}
+ if (sym->ctype.base_type == &incomplete_ctype) {
+ sym->ctype.base_type = &int_ctype;
+
+ if (Wimplicit_int) {
+ sparse_error(sym->pos, "missing type declaration for parameter '%s'",
+ show_ident(sym->ident));
+ }
+ }
bind_symbol(sym, sym->ident, NS_SYMBOL);
}
@@ -2804,7 +2817,7 @@ static void apply_k_r_types(struct symbol_list *argtypes, struct symbol *fn)
goto match;
} END_FOR_EACH_PTR(type);
if (Wimplicit_int) {
- sparse_error(arg->pos, "missing type declaration for parameter '%s'",
+ warning(arg->pos, "missing type declaration for parameter '%s'",
show_ident(arg->ident));
}
type = alloc_symbol(arg->pos, SYM_NODE);
diff --git a/simplify.c b/simplify.c
index 6caf6cbc..307787d0 100644
--- a/simplify.c
+++ b/simplify.c
@@ -351,9 +351,9 @@ int kill_insn(struct instruction *insn, int force)
case OP_CALL:
if (!force) {
/* a "pure" function can be killed too */
- if (!(insn->func->type == PSEUDO_SYM))
- return 0;
- if (!(insn->func->sym->ctype.modifiers & MOD_PURE))
+ struct symbol *fntype = first_symbol(insn->fntypes);
+
+ if (!(fntype->ctype.modifiers & MOD_PURE))
return 0;
}
kill_use_list(insn->arguments);
@@ -388,20 +388,6 @@ int kill_insn(struct instruction *insn, int force)
return repeat_phase |= REPEAT_CSE;
}
-///
-// kill trivially dead instructions
-static int dead_insn(struct instruction *insn, pseudo_t *src1, pseudo_t *src2, pseudo_t *src3)
-{
- if (has_users(insn->target))
- return 0;
-
- insn->bb = NULL;
- kill_use(src1);
- kill_use(src2);
- kill_use(src3);
- return REPEAT_CSE;
-}
-
static inline bool has_target(struct instruction *insn)
{
return opcode_table[insn->opcode].flags & OPF_TARGET;
@@ -1173,6 +1159,36 @@ static int simplify_constant_rightside(struct instruction *insn)
case OP_SET_NE:
case OP_SET_EQ:
return simplify_seteq_setne(insn, value);
+ case OP_SET_B:
+ if (!value) { // (x < 0) --> 0
+ return replace_with_pseudo(insn, value_pseudo(0));
+ } else if (value == 1) { // (x < 1) --> (x == 0)
+ insn->src2 = value_pseudo(0);
+ insn->opcode = OP_SET_EQ;
+ return REPEAT_CSE;
+ }
+ break;
+ case OP_SET_AE:
+ if (!value) { // (x >= 0) --> 1
+ return replace_with_pseudo(insn, value_pseudo(1));
+ } else if (value == 1) { // (x >= 1) --> (x != 0)
+ insn->src2 = value_pseudo(0);
+ insn->opcode = OP_SET_NE;
+ return REPEAT_CSE;
+ }
+ break;
+ case OP_SET_BE:
+ if (!value) { // (x <= 0) --> (x == 0)
+ insn->opcode = OP_SET_EQ;
+ return REPEAT_CSE;
+ }
+ break;
+ case OP_SET_A:
+ if (!value) { // (x > 0) --> (x != 0)
+ insn->opcode = OP_SET_NE;
+ return REPEAT_CSE;
+ }
+ break;
}
return 0;
}
@@ -1270,8 +1286,6 @@ static int simplify_binop_same_args(struct instruction *insn, pseudo_t arg)
static int simplify_binop(struct instruction *insn)
{
- if (dead_insn(insn, &insn->src1, &insn->src2, NULL))
- return REPEAT_CSE;
if (constant(insn->src1)) {
if (constant(insn->src2))
return simplify_constant_binop(insn);
@@ -1451,21 +1465,62 @@ static int simplify_constant_unop(struct instruction *insn)
static int simplify_unop(struct instruction *insn)
{
- if (dead_insn(insn, &insn->src1, NULL, NULL))
- return REPEAT_CSE;
- if (constant(insn->src1))
+ struct instruction *def;
+ pseudo_t src = insn->src;
+
+ 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;
@@ -1543,16 +1598,11 @@ static int simplify_cast(struct instruction *insn)
{
unsigned long long mask;
struct instruction *def;
- pseudo_t src;
+ pseudo_t src = insn->src;
pseudo_t val;
int osize;
int size;
- if (dead_insn(insn, &insn->src, NULL, NULL))
- return REPEAT_CSE;
-
- src = insn->src;
-
/* A cast of a constant? */
if (constant(src))
return simplify_constant_unop(insn);
@@ -1687,9 +1737,6 @@ static int simplify_select(struct instruction *insn)
{
pseudo_t cond, src1, src2;
- if (dead_insn(insn, &insn->src1, &insn->src2, &insn->src3))
- return REPEAT_CSE;
-
cond = insn->src1;
src1 = insn->src2;
src2 = insn->src3;
@@ -1861,6 +1908,10 @@ int simplify_instruction(struct instruction *insn)
return 0;
flags = opcode_table[insn->opcode].flags;
+ if (flags & OPF_TARGET) {
+ if (!has_users(insn->target))
+ return kill_instruction(insn);
+ }
if (flags & OPF_COMMU)
canonicalize_commutative(insn) ;
if (flags & OPF_COMPARE)
@@ -1906,14 +1957,9 @@ int simplify_instruction(struct instruction *insn)
case OP_SET_AE:
break;
case OP_LOAD:
- if (!has_users(insn->target))
- return kill_instruction(insn);
- /* fall-through */
case OP_STORE:
return simplify_memop(insn);
case OP_SYMADDR:
- if (dead_insn(insn, &insn->src, NULL, NULL))
- return REPEAT_CSE | REPEAT_SYMBOL_CLEANUP;
return replace_with_pseudo(insn, insn->src);
case OP_SEXT: case OP_ZEXT:
case OP_TRUNC:
@@ -1923,30 +1969,18 @@ int simplify_instruction(struct instruction *insn)
case OP_UCVTF: case OP_SCVTF:
case OP_FCVTF:
case OP_PTRCAST:
- if (dead_insn(insn, &insn->src, NULL, NULL))
- return REPEAT_CSE;
break;
case OP_UTPTR:
case OP_PTRTU:
return replace_with_pseudo(insn, insn->src);
case OP_SLICE:
- if (dead_insn(insn, &insn->src, NULL, NULL))
- return REPEAT_CSE;
break;
case OP_SETVAL:
case OP_SETFVAL:
- if (dead_insn(insn, NULL, NULL, NULL))
- return REPEAT_CSE;
break;
case OP_PHI:
- if (dead_insn(insn, NULL, NULL, NULL)) {
- kill_use_list(insn->phi_list);
- return REPEAT_CSE;
- }
return clean_up_phi(insn);
case OP_PHISOURCE:
- if (dead_insn(insn, &insn->phi_src, NULL, NULL))
- return REPEAT_CSE;
break;
case OP_SEL:
return simplify_select(insn);
@@ -1960,8 +1994,6 @@ int simplify_instruction(struct instruction *insn)
case OP_FSUB:
case OP_FMUL:
case OP_FDIV:
- if (dead_insn(insn, &insn->src1, &insn->src2, NULL))
- return REPEAT_CSE;
break;
}
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/asm-bad0.c b/validation/asm-bad0.c
index aa9bf28d..4ba78575 100644
--- a/validation/asm-bad0.c
+++ b/validation/asm-bad0.c
@@ -16,7 +16,7 @@ static void icons(void)
asm("template" : [out] "=r" (var): [in] string (0));
}
-static void oexpr(oid)
+static void oexpr(void)
{
asm("template" : [out] "=" (var[) : [in] "r" (0));
}
diff --git a/validation/bad-type-twice0.c b/validation/bad-type-twice0.c
index 9e834d47..e7ec7b75 100644
--- a/validation/bad-type-twice0.c
+++ b/validation/bad-type-twice0.c
@@ -7,7 +7,6 @@ static int foo(a)
* check-name: bad-type-twice0
*
* check-error-start
-bad-type-twice0.c:3:16: error: non-scalar type in conditional:
-bad-type-twice0.c:3:16: incomplete type a
+bad-type-twice0.c:1:16: error: missing type declaration for parameter 'a'
* check-error-end
*/
diff --git a/validation/badtype2.c b/validation/badtype2.c
index 49fec87c..173dbfda 100644
--- a/validation/badtype2.c
+++ b/validation/badtype2.c
@@ -18,6 +18,7 @@ badtype2.c:2:14: error: got bar
badtype2.c:3:14: error: Expected ; at end of declaration
badtype2.c:3:14: error: got foo
badtype2.c:6:3: error: Trying to use reserved word 'switch' as identifier
+badtype2.c:6:11: error: missing type declaration for parameter 'p'
badtype2.c:7:3: error: not in switch scope
badtype2.c:10:1: error: Expected ; at the end of type declaration
badtype2.c:10:1: error: got }
diff --git a/validation/badtype3.c b/validation/badtype3.c
index 20f346c5..c111d94e 100644
--- a/validation/badtype3.c
+++ b/validation/badtype3.c
@@ -16,6 +16,7 @@ badtype3.c:2:18: warning: identifier list not in definition
badtype3.c:2:24: error: Expected ) in function declarator
badtype3.c:2:24: error: got ,
badtype3.c:5:3: error: Trying to use reserved word 'while' as identifier
+badtype3.c:5:10: error: missing type declaration for parameter 'cur'
badtype3.c:7:7: error: break/continue not in iterator scope
badtype3.c:9:3: error: Trying to use reserved word 'return' as identifier
badtype3.c:9:10: error: Expected ; at end of declaration
diff --git a/validation/implicit-KR-arg-type1.c b/validation/implicit-KR-arg-type1.c
index fe199ef5..c7eb39ae 100644
--- a/validation/implicit-KR-arg-type1.c
+++ b/validation/implicit-KR-arg-type1.c
@@ -1,16 +1,23 @@
-int foo(a, b)
+static int foo(a, b)
int a;
{
if (b)
return a;
}
+static int bar(a)
+{
+ if (a)
+ return a;
+}
+
/*
* check-name: implicit-KR-arg-type1
* check-command: sparse -Wold-style-definition -Wimplicit-int $file
*
* check-error-start
implicit-KR-arg-type1.c:2:9: warning: non-ANSI definition of function 'foo'
-implicit-KR-arg-type1.c:1:12: error: missing type declaration for parameter 'b'
+implicit-KR-arg-type1.c:1:19: warning: missing type declaration for parameter 'b'
+implicit-KR-arg-type1.c:8:16: error: missing type declaration for parameter 'a'
* check-error-end
*/
diff --git a/validation/linear/inline-definition.c b/validation/linear/inline-definition.c
new file mode 100644
index 00000000..2918bd5d
--- /dev/null
+++ b/validation/linear/inline-definition.c
@@ -0,0 +1,30 @@
+extern void use(void *);
+
+static inline int inl0(int a);
+static inline int inl1(int a);
+
+static inline int inl0(int a)
+{
+ return a;
+}
+
+void foo(void)
+{
+ use(inl0);
+ use(inl1);
+}
+
+static inline int inl1(int a)
+{
+ return a;
+}
+
+/*
+ * check-name: inline-definition
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-contains: inl0:
+ * check-output-contains: inl1:
+ */
diff --git a/validation/optim/set-uimm0.c b/validation/optim/set-uimm0.c
new file mode 100644
index 00000000..ded8fc82
--- /dev/null
+++ b/validation/optim/set-uimm0.c
@@ -0,0 +1,14 @@
+static _Bool setlt0(unsigned int a) { return (a < 0u) == 0; }
+static _Bool setge0(unsigned int a) { return (a >= 0u) == 1; }
+static _Bool setle0(unsigned int a) { return (a <= 0u) == (a == 0); }
+static _Bool setgt0(unsigned int a) { return (a > 0u) == (a != 0); }
+static _Bool setlt1(unsigned int a) { return (a < 1u) == (a == 0); }
+static _Bool setge1(unsigned int a) { return (a >= 1u) == (a != 0); }
+
+/*
+ * check-name: set-uimm0
+ * check-command: test-linearize $file
+ *
+ * check-output-ignore
+ * check-output-pattern(6): ret\\.1 *\\$1
+ */
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
+ */