aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-08-22 09:27:00 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-08-22 09:27:00 +0200
commita4ae84a892b6e5a8b563f0bb125fcc5a3448b383 (patch)
treea916fa4abdd7d16ffbac5dbe87dfb8c5e4c2d406
parent3d30b78ec7efa501ad3ea4c5f077ef653ed5b231 (diff)
parent9feb4b16da637978ce4abdfe23bf9779521a8b77 (diff)
downloadsparse-dev-a4ae84a892b6e5a8b563f0bb125fcc5a3448b383.tar.gz
Merge branches 'optim-shift-and' and 'optim-bitfield' into tip
-rw-r--r--simplify.c140
-rw-r--r--validation/optim/and-or-bf0.c24
-rw-r--r--validation/optim/and-or-bf1.c18
-rw-r--r--validation/optim/and-or-bf2.c27
-rw-r--r--validation/optim/and-or-bfs.c24
-rw-r--r--validation/optim/and-or-bfu.c22
-rw-r--r--validation/optim/and-or-bfx.c18
-rw-r--r--validation/optim/and-or-constant0.c12
-rw-r--r--validation/optim/and-or-constant1.c14
-rw-r--r--validation/optim/and-or-constant2.c13
-rw-r--r--validation/optim/and-or-crash.c5
-rw-r--r--validation/optim/and-or-lsr0.c13
-rw-r--r--validation/optim/and-or-lsr1.c13
-rw-r--r--validation/optim/and-or-lsr2.c13
-rw-r--r--validation/optim/and-or-lsrx.c13
-rw-r--r--validation/optim/and-or-mask.c18
-rw-r--r--validation/optim/and-or-mask0.c12
-rw-r--r--validation/optim/and-or-mask1.c13
-rw-r--r--validation/optim/and-or-mask2.c13
-rw-r--r--validation/optim/and-or-mask3s.c25
-rw-r--r--validation/optim/and-or-mask3u.c25
-rw-r--r--validation/optim/and-or-mask4.c25
-rw-r--r--validation/optim/and-or-maskx.c13
-rw-r--r--validation/optim/and-or-shl0.c12
-rw-r--r--validation/optim/and-or-shl1.c13
-rw-r--r--validation/optim/and-or-shl2.c13
-rw-r--r--validation/optim/and-or-shlx.c13
-rw-r--r--validation/optim/and-or-trunc0.c14
-rw-r--r--validation/optim/and-or-trunc1.c13
-rw-r--r--validation/optim/and-or-trunc2.c14
-rw-r--r--validation/optim/and-or-truncx.c14
-rw-r--r--validation/optim/bitfield-store-load0.c (renamed from validation/optim/store-load-bitfield.c)0
-rw-r--r--validation/optim/bitfield-store-loads.c24
-rw-r--r--validation/optim/bitfield-store-loadu.c22
-rw-r--r--validation/optim/or-and-constant1.c29
-rw-r--r--validation/optim/sh-or-and0.c20
-rw-r--r--validation/optim/sh-or-and1.c20
-rw-r--r--validation/optim/sh-or-and2.c21
-rw-r--r--validation/optim/trunc-or-shl.c13
39 files changed, 723 insertions, 45 deletions
diff --git a/simplify.c b/simplify.c
index b814a23e..737da650 100644
--- a/simplify.c
+++ b/simplify.c
@@ -577,6 +577,95 @@ undef:
return NULL;
}
+///
+// Simplifications
+// ^^^^^^^^^^^^^^^
+
+///
+// try to simplify OP(OR(AND(x, M'), b), K)
+// @insn: the 'masking' instruction
+// @mask: the mask associated to @insn (M)
+// @ora: one of the OR's operands, guaranteed to be PSEUDO_REG
+// @orb: the other OR's operand
+// @return: 0 if no changes have been made, one or more REPEAT_* flags otherwise.
+static int simplify_mask_or_and(struct instruction *insn, unsigned long long mask,
+ pseudo_t ora, pseudo_t orb)
+{
+ unsigned long long omask, nmask;
+ struct instruction *and = ora->def;
+ pseudo_t src2 = and->src2;
+
+ if (and->opcode != OP_AND)
+ return 0;
+ if (!constant(src2))
+ return 0;
+ omask = src2->value;
+ nmask = omask & mask;
+ if (nmask == 0) {
+ // if (M' & M) == 0: ((a & M') | b) -> b
+ return replace_pseudo(insn, &insn->src1, orb);
+ }
+ if (multi_users(insn->src1))
+ return 0; // can't modify anything inside the OR
+ if (nmask == mask) {
+ struct instruction *or = insn->src1->def;
+ pseudo_t *arg = (ora == or->src1) ? &or->src1 : &or->src2;
+ // if (M' & M) == M: ((a & M') | b) -> (a | b)
+ return replace_pseudo(or, arg, and->src1);
+ }
+ if (nmask != omask && !multi_users(ora)) {
+ // if (M' & M) != M': AND(a, M') -> AND(a, (M' & M))
+ and->src2 = value_pseudo(nmask);
+ return REPEAT_CSE;
+ }
+ return 0;
+}
+
+///
+// try to simplify OP(OR(a, b), K)
+// @insn: the 'masking' instruction
+// @mask: the mask associated to @insn (M):
+// @or: the OR instruction
+// @return: 0 if no changes have been made, one or more REPEAT_* flags otherwise.
+//
+// For the @mask (M):
+// * if OP(x, K) == AND(x, M), @mask M is K
+// * if OP(x, K) == LSR(x, S), @mask M is (-1 << S)
+// * if OP(x, K) == SHL(x, S), @mask M is (-1 >> S)
+static int simplify_mask_or(struct instruction *insn, unsigned long long mask, struct instruction *or)
+{
+ pseudo_t src1 = or->src1;
+ pseudo_t src2 = or->src2;
+ int rc;
+
+ if (src1->type == PSEUDO_REG) {
+ if ((rc = simplify_mask_or_and(insn, mask, src1, src2)))
+ return rc;
+ }
+ if (src2->type == PSEUDO_REG) {
+ if ((rc = simplify_mask_or_and(insn, mask, src2, src1)))
+ return rc;
+ } else if (src2->type == PSEUDO_VAL) {
+ unsigned long long oval = src2->value;
+ unsigned long long nval = oval & mask;
+ // Try to simplify:
+ // OP(OR(x, C), K)
+ if (nval == 0) {
+ // if (C & M) == 0: OR(x, C) -> x
+ return replace_pseudo(insn, &insn->src1, src1);
+ }
+ if (nval == mask) {
+ // if (C & M) == M: OR(x, C) -> M
+ return replace_pseudo(insn, &insn->src1, value_pseudo(mask));
+ }
+ if (nval != oval && !multi_users(or->target)) {
+ // if (C & M) != C: OR(x, C) -> OR(x, (C & M))
+ return replace_pseudo(or, &or->src2, value_pseudo(nval));
+ }
+ }
+ return 0;
+}
+
static long long check_shift_count(struct instruction *insn, unsigned long long uval)
{
unsigned int size = insn->size;
@@ -606,18 +695,6 @@ static long long check_shift_count(struct instruction *insn, unsigned long long
return sval;
}
-static int simplify_or_lsr(struct instruction *insn, pseudo_t src, pseudo_t other, unsigned shift)
-{
- // src->def->opcode == OP_AND
- pseudo_t src2 = src->def->src2;
-
- if (!constant(src2))
- return 0;
- if (((unsigned long long) src2->value) >> shift)
- return 0;
- return replace_pseudo(insn, &insn->src1, other);
-}
-
static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long value)
{
struct instruction *def;
@@ -625,7 +702,6 @@ static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long v
unsigned long long nval;
unsigned int size;
pseudo_t src2;
- pseudo_t src;
if (!value)
return replace_with_pseudo(insn, pseudo);
@@ -697,16 +773,8 @@ static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long v
case OP_LSR:
goto case_shift_shift;
case OP_OR:
- // replace ((A & M) | B) >> S
- // by (B >> S)
- // when (M >> S) == 0
- src = def->src1;
- if (def_opcode(src) == OP_AND)
- return simplify_or_lsr(insn, src, def->src2, value);
- src = def->src2;
- if (def_opcode(src) == OP_AND)
- return simplify_or_lsr(insn, src, def->src1, value);
- break;
+ mask = bits_mask(size - value) << value;
+ return simplify_mask_or(insn, mask, def);
case OP_SHL:
// replace ((x << S) >> S)
// by (x & (-1 >> S))
@@ -740,6 +808,9 @@ static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long v
break;
mask = bits_mask(insn->size - value) << value;
goto replace_mask;
+ case OP_OR:
+ mask = bits_mask(size - value);
+ return simplify_mask_or(insn, mask, def);
case OP_SHL:
case_shift_shift: // also for LSR - LSR
if (def == insn) // cyclic DAG!
@@ -881,24 +952,12 @@ static int simplify_seteq_setne(struct instruction *insn, long long value)
return 0;
}
-static int simplify_and_or_mask(struct instruction *insn, pseudo_t and, pseudo_t other, unsigned long long mask)
-{
- struct instruction *def = and->def;
-
- if (!constant(def->src2))
- return 0;
- if (def->src2->value & mask)
- return 0;
- return replace_pseudo(insn, &insn->src1, other);
-}
-
static int simplify_constant_mask(struct instruction *insn, unsigned long long mask)
{
pseudo_t old = insn->src1;
unsigned long long omask;
unsigned long long nmask;
struct instruction *def;
- pseudo_t src1, src2;
int osize;
switch (DEF_OPCODE(def, old)) {
@@ -906,16 +965,7 @@ static int simplify_constant_mask(struct instruction *insn, unsigned long long m
osize = 1;
goto oldsize;
case OP_OR:
- // Let's handle ((A & M') | B ) & M
- // or (B | (A & M')) & M
- // when M' & M == 0
- src1 = def->src1;
- src2 = def->src2;
- if (def_opcode(src1) == OP_AND)
- return simplify_and_or_mask(insn, src1, src2, mask);
- if (def_opcode(src2) == OP_AND)
- return simplify_and_or_mask(insn, src2, src1, mask);
- break;
+ return simplify_mask_or(insn, mask, def);
case OP_ZEXT:
osize = def->orig_type->bit_size;
/* fall through */
diff --git a/validation/optim/and-or-bf0.c b/validation/optim/and-or-bf0.c
new file mode 100644
index 00000000..cfaff4f2
--- /dev/null
+++ b/validation/optim/and-or-bf0.c
@@ -0,0 +1,24 @@
+struct s {
+ int f:3;
+};
+
+void foo(struct s *p, int a)
+{
+ p->f = 1;
+ p->f = a;
+}
+
+void bar(struct s *p, int a)
+{
+ p->f = a;
+ p->f = 1;
+}
+
+/*
+ * check-name: and-or-bf0
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(3): and\\.
+ * check-output-pattern(2): or\\.
+ */
diff --git a/validation/optim/and-or-bf1.c b/validation/optim/and-or-bf1.c
new file mode 100644
index 00000000..23477ff3
--- /dev/null
+++ b/validation/optim/and-or-bf1.c
@@ -0,0 +1,18 @@
+struct s {
+ int :2;
+ int f:3;
+};
+
+void foo(struct s *d, const struct s *s, int a)
+{
+ d->f = s->f | a;
+}
+
+/*
+ * check-name: and-or-bf1
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(2): and\\.
+ * check-output-pattern(2): or\\.
+ */
diff --git a/validation/optim/and-or-bf2.c b/validation/optim/and-or-bf2.c
new file mode 100644
index 00000000..2296da12
--- /dev/null
+++ b/validation/optim/and-or-bf2.c
@@ -0,0 +1,27 @@
+struct s {
+ char a:3;
+ char b:3;
+ char c:2;
+};
+
+void foo(struct s *p)
+{
+ p->a = 1;
+ p->b = 2;
+ p->c = 3;
+}
+
+/*
+ * check-name: and-or-bf2
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-start
+foo:
+.L0:
+ <entry-point>
+ store.8 $209 -> 0[%arg1]
+ ret
+
+
+ * check-output-end
+ */
diff --git a/validation/optim/and-or-bfs.c b/validation/optim/and-or-bfs.c
new file mode 100644
index 00000000..e08b816e
--- /dev/null
+++ b/validation/optim/and-or-bfs.c
@@ -0,0 +1,24 @@
+struct s {
+ signed int :2;
+ signed int f:3;
+};
+
+int bfs(struct s s, int a)
+{
+ s.f = a;
+ return s.f;
+}
+
+/*
+ * check-name: and-or-bfs
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-pattern(1): trunc\\.
+ * check-output-pattern(1): sext\\.
+ * check-output-excludes: and\\.
+ * check-output-excludes: or\\.
+ * check-output-excludes: shl\\.
+ * check-output-excludes: lsr\\.
+ */
diff --git a/validation/optim/and-or-bfu.c b/validation/optim/and-or-bfu.c
new file mode 100644
index 00000000..c9dcfc33
--- /dev/null
+++ b/validation/optim/and-or-bfu.c
@@ -0,0 +1,22 @@
+struct u {
+ unsigned int :2;
+ unsigned int f:3;
+};
+
+int bfu(struct u s, int a)
+{
+ s.f = a;
+ return s.f;
+}
+
+/*
+ * check-name: and-or-bfu
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-pattern(1): and\\.
+ * check-output-excludes: or\\.
+ * check-output-excludes: shl\\.
+ * check-output-excludes: lsr\\.
+ */
diff --git a/validation/optim/and-or-bfx.c b/validation/optim/and-or-bfx.c
new file mode 100644
index 00000000..57a54cf5
--- /dev/null
+++ b/validation/optim/and-or-bfx.c
@@ -0,0 +1,18 @@
+struct s {
+ int f:3;
+};
+
+void foo(struct s *p, int a, int b)
+{
+ p->f = a;
+ p->f = b;
+}
+
+/*
+ * check-name: and-or-bfx
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(2): and\\.
+ * check-output-pattern(1): or\\.
+ */
diff --git a/validation/optim/and-or-constant0.c b/validation/optim/and-or-constant0.c
new file mode 100644
index 00000000..dcf440f3
--- /dev/null
+++ b/validation/optim/and-or-constant0.c
@@ -0,0 +1,12 @@
+int foo(int x)
+{
+ return (x | 0xfffff000) & 0xfff;
+}
+
+/*
+ * check-name: and-or-constant0
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-excludes: or\\.
+ */
diff --git a/validation/optim/and-or-constant1.c b/validation/optim/and-or-constant1.c
new file mode 100644
index 00000000..49823d5c
--- /dev/null
+++ b/validation/optim/and-or-constant1.c
@@ -0,0 +1,14 @@
+int foo(int x)
+{
+ return (x | 0x000fffff) & 0xfff;
+}
+
+/*
+ * check-name: or-and-constant1
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*\\$0xfff
+ * check-output-excludes: and\\.
+ * check-output-excludes: or\\.
+ */
diff --git a/validation/optim/and-or-constant2.c b/validation/optim/and-or-constant2.c
new file mode 100644
index 00000000..d7e66f9c
--- /dev/null
+++ b/validation/optim/and-or-constant2.c
@@ -0,0 +1,13 @@
+int foo(int x)
+{
+ return (x | 0xfffffff0) & 0xfff;
+}
+
+/*
+ * check-name: and-or-constant2
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: or\\..*\\$0xff0
+ * check-output-excludes: or\\..*\\$0xfffffff0
+ */
diff --git a/validation/optim/and-or-crash.c b/validation/optim/and-or-crash.c
new file mode 100644
index 00000000..98a8a9b8
--- /dev/null
+++ b/validation/optim/and-or-crash.c
@@ -0,0 +1,5 @@
+static unsigned a(unsigned b, unsigned c) { (c << 1 | b & 1 << 1) >> 1; }
+
+/*
+ * check-name: catch crashes during AND-OR simplifications
+ */
diff --git a/validation/optim/and-or-lsr0.c b/validation/optim/and-or-lsr0.c
new file mode 100644
index 00000000..227c5aed
--- /dev/null
+++ b/validation/optim/and-or-lsr0.c
@@ -0,0 +1,13 @@
+int foo(int a, int b)
+{
+ return ((a & 0x00000fff) | b) >> 12;
+}
+
+/*
+ * check-name: and-or-lsr0
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-excludes: or\\.
+ */
diff --git a/validation/optim/and-or-lsr1.c b/validation/optim/and-or-lsr1.c
new file mode 100644
index 00000000..bd1dbc8a
--- /dev/null
+++ b/validation/optim/and-or-lsr1.c
@@ -0,0 +1,13 @@
+int foo(int a, int b)
+{
+ return ((a & 0xfffff000) | b) >> 12;
+}
+
+/*
+ * check-name: and-or-lsr1
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(0): and\\.
+ * check-output-pattern(1): or\\.
+ */
diff --git a/validation/optim/and-or-lsr2.c b/validation/optim/and-or-lsr2.c
new file mode 100644
index 00000000..d1af0135
--- /dev/null
+++ b/validation/optim/and-or-lsr2.c
@@ -0,0 +1,13 @@
+int foo(int x, int y)
+{
+ return ((x & 0xf0ffffff) | y) >> 12;
+}
+
+/*
+ * check-name: and-or-lsr2
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: and\\..*\\$0xf0fff
+ * check-output-excludes: and\\..*\\$0xf0ffffff
+ */
diff --git a/validation/optim/and-or-lsrx.c b/validation/optim/and-or-lsrx.c
new file mode 100644
index 00000000..31adca92
--- /dev/null
+++ b/validation/optim/and-or-lsrx.c
@@ -0,0 +1,13 @@
+unsigned int foo(unsigned int x, unsigned int y, unsigned int a)
+{
+ return ((x & y) | (a & 0x0fff)) >> 12;
+}
+
+/*
+ * check-name: and-or-lsrx
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(1): and\\.
+ * check-output-excludes: or\\.
+ */
diff --git a/validation/optim/and-or-mask.c b/validation/optim/and-or-mask.c
new file mode 100644
index 00000000..46803789
--- /dev/null
+++ b/validation/optim/and-or-mask.c
@@ -0,0 +1,18 @@
+int foo(int a, int b)
+{
+ return ((a & 7) | (b & 3)) & 8;
+}
+
+/*
+ * check-name: and-or-mask
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-start
+foo:
+.L0:
+ <entry-point>
+ ret.32 $0
+
+
+ * check-output-end
+ */
diff --git a/validation/optim/and-or-mask0.c b/validation/optim/and-or-mask0.c
new file mode 100644
index 00000000..2d2245ea
--- /dev/null
+++ b/validation/optim/and-or-mask0.c
@@ -0,0 +1,12 @@
+int foo(int a, int b)
+{
+ return ((a & 0xfffff000) | b) & 0xfff;
+}
+
+/*
+ * check-name: and-or-mask0
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-excludes: or\\.
+ */
diff --git a/validation/optim/and-or-mask1.c b/validation/optim/and-or-mask1.c
new file mode 100644
index 00000000..bff3a89f
--- /dev/null
+++ b/validation/optim/and-or-mask1.c
@@ -0,0 +1,13 @@
+int foo(int a, int b)
+{
+ return ((a & 0x0fffffff) | b) & 0xfff;
+}
+
+/*
+ * check-name: and-or-mask1
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(1): and\\.
+ * check-output-pattern(1): or\\.
+ */
diff --git a/validation/optim/and-or-mask2.c b/validation/optim/and-or-mask2.c
new file mode 100644
index 00000000..cab802a6
--- /dev/null
+++ b/validation/optim/and-or-mask2.c
@@ -0,0 +1,13 @@
+int foo(int x, int y)
+{
+ return ((x & 0xffffff0f) | y) & 0xfff;
+}
+
+/*
+ * check-name: and-or-mask2
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: and\\..*\\$0xf0f
+ * check-output-excludes: and\\..*\\$0xffffff0f
+ */
diff --git a/validation/optim/and-or-mask3s.c b/validation/optim/and-or-mask3s.c
new file mode 100644
index 00000000..cf264723
--- /dev/null
+++ b/validation/optim/and-or-mask3s.c
@@ -0,0 +1,25 @@
+#define W 3
+#define S 8
+#define M (W << S)
+
+static inline int fun(unsigned int x, unsigned int y)
+{
+ return ((x & M) | (y << S)) >> S;
+}
+
+short foo(unsigned int x, unsigned int y)
+{
+ return fun(x, y) & W;
+}
+
+/*
+ * check-name: and-or-mask3s
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-pattern(1): lsr\\.
+ * check-output-pattern(1): or\\.
+ * check-output-pattern(1): and\\.
+ * check-output-excludes: shl\\.
+ */
diff --git a/validation/optim/and-or-mask3u.c b/validation/optim/and-or-mask3u.c
new file mode 100644
index 00000000..c5b6c5fa
--- /dev/null
+++ b/validation/optim/and-or-mask3u.c
@@ -0,0 +1,25 @@
+#define W 3
+#define S 8
+#define M (W << S)
+
+static inline int fun(unsigned int x, unsigned int y)
+{
+ return ((x & M) | (y << S)) >> S;
+}
+
+int foo(unsigned int x, unsigned int y)
+{
+ return fun(x, y) & W;
+}
+
+/*
+ * check-name: and-or-mask3u
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-pattern(1): lsr\\.
+ * check-output-pattern(1): or\\.
+ * check-output-pattern(1): and\\.
+ * check-output-excludes: shl\\.
+ */
diff --git a/validation/optim/and-or-mask4.c b/validation/optim/and-or-mask4.c
new file mode 100644
index 00000000..1c4bc01a
--- /dev/null
+++ b/validation/optim/and-or-mask4.c
@@ -0,0 +1,25 @@
+#define W 3
+#define S 8
+#define M (W << S)
+
+static inline int fun(unsigned int x, unsigned int y)
+{
+ return ((x & W) | (y >> S)) << S;
+}
+
+int foo(unsigned int x, unsigned int y)
+{
+ return fun(x, y) & M;
+}
+
+/*
+ * check-name: and-or-mask4
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-pattern(1): shl\\.
+ * check-output-pattern(1): or\\.
+ * check-output-pattern(1): and\\.
+ * check-output-excludes: lsr\\.
+ */
diff --git a/validation/optim/and-or-maskx.c b/validation/optim/and-or-maskx.c
new file mode 100644
index 00000000..21d44e8d
--- /dev/null
+++ b/validation/optim/and-or-maskx.c
@@ -0,0 +1,13 @@
+int foo(int x, int y, int a)
+{
+ return ((x & y) | (a & 0xf000)) & 0x0fff;
+}
+
+/*
+ * check-name: and-or-maskx
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(2): and\\.
+ * check-output-excludes: or\\.
+ */
diff --git a/validation/optim/and-or-shl0.c b/validation/optim/and-or-shl0.c
new file mode 100644
index 00000000..4850b326
--- /dev/null
+++ b/validation/optim/and-or-shl0.c
@@ -0,0 +1,12 @@
+int foo(int a, int b)
+{
+ return ((a & 0xfff00000) | b) << 12;
+}
+
+/*
+ * check-name: and-or-shl0
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-excludes: or\\.
+ */
diff --git a/validation/optim/and-or-shl1.c b/validation/optim/and-or-shl1.c
new file mode 100644
index 00000000..bea22245
--- /dev/null
+++ b/validation/optim/and-or-shl1.c
@@ -0,0 +1,13 @@
+int foo(int a, int b)
+{
+ return ((a & 0x000fffff) | b) << 12;
+}
+
+/*
+ * check-name: and-or-shl1
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(0): and\\.
+ * check-output-pattern(1): or\\.
+ */
diff --git a/validation/optim/and-or-shl2.c b/validation/optim/and-or-shl2.c
new file mode 100644
index 00000000..f5f62758
--- /dev/null
+++ b/validation/optim/and-or-shl2.c
@@ -0,0 +1,13 @@
+int foo(int x, int y)
+{
+ return ((x & 0xffffff0f) | y) << 12;
+}
+
+/*
+ * check-name: and-or-shl2
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-contains: and\\..*\\$0xfff0f
+ * check-output-excludes: and\\..*\\$0xffffff0f
+ */
diff --git a/validation/optim/and-or-shlx.c b/validation/optim/and-or-shlx.c
new file mode 100644
index 00000000..ec2a2ced
--- /dev/null
+++ b/validation/optim/and-or-shlx.c
@@ -0,0 +1,13 @@
+unsigned int foo(unsigned int x, unsigned int y, unsigned int a)
+{
+ return ((x & y) | (a & 0xfff00000)) << 12;
+}
+
+/*
+ * check-name: and-or-shlx
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(1): and\\.
+ * check-output-excludes: or\\.
+ */
diff --git a/validation/optim/and-or-trunc0.c b/validation/optim/and-or-trunc0.c
new file mode 100644
index 00000000..873cb2d5
--- /dev/null
+++ b/validation/optim/and-or-trunc0.c
@@ -0,0 +1,14 @@
+char foo(int x, int y)
+{
+ return (x & 0xff00) | y;
+}
+
+/*
+ * check-name: and-or-trunc0
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-excludes: and\\.
+ * check-output-excludes: or\\.
+ */
diff --git a/validation/optim/and-or-trunc1.c b/validation/optim/and-or-trunc1.c
new file mode 100644
index 00000000..84c20317
--- /dev/null
+++ b/validation/optim/and-or-trunc1.c
@@ -0,0 +1,13 @@
+char foo(int x, int y)
+{
+ return (x & 0xffff) | y;
+}
+
+/*
+ * check-name: and-or-trunc1
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-excludes: and\\.
+ */
diff --git a/validation/optim/and-or-trunc2.c b/validation/optim/and-or-trunc2.c
new file mode 100644
index 00000000..04cb57e7
--- /dev/null
+++ b/validation/optim/and-or-trunc2.c
@@ -0,0 +1,14 @@
+char foo(int x, int y)
+{
+ return (x & 0xff07) | y;
+}
+
+/*
+ * check-name: and-or-trunc2
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-pattern(1): and\\.
+ * check-output-pattern(1): and\\..*\\$7
+ */
diff --git a/validation/optim/and-or-truncx.c b/validation/optim/and-or-truncx.c
new file mode 100644
index 00000000..47d80dae
--- /dev/null
+++ b/validation/optim/and-or-truncx.c
@@ -0,0 +1,14 @@
+char foo(int x, int y, int b)
+{
+ return (x & y) | (b & 0xff00);
+}
+
+/*
+ * check-name: and-or-truncx
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-pattern(1): and\\.
+ * check-output-excludes: or\\.
+ */
diff --git a/validation/optim/store-load-bitfield.c b/validation/optim/bitfield-store-load0.c
index f68cb600..f68cb600 100644
--- a/validation/optim/store-load-bitfield.c
+++ b/validation/optim/bitfield-store-load0.c
diff --git a/validation/optim/bitfield-store-loads.c b/validation/optim/bitfield-store-loads.c
new file mode 100644
index 00000000..99a0a03a
--- /dev/null
+++ b/validation/optim/bitfield-store-loads.c
@@ -0,0 +1,24 @@
+struct s {
+ char :2;
+ char f:3;
+};
+
+int foo(struct s s, int a)
+{
+ s.f = a;
+ return s.f;
+}
+
+/*
+ * check-name: bitfield-store-load signed
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-excludes: shl\\.
+ * check-output-excludes: lsr\\.
+ * check-output-excludes: or\\.
+ * check-output-excludes: [sz]ext\\.
+ * check-output-excludes: trunc\\.
+ * check-output-pattern(1): and\\.
+ */
diff --git a/validation/optim/bitfield-store-loadu.c b/validation/optim/bitfield-store-loadu.c
new file mode 100644
index 00000000..4c289504
--- /dev/null
+++ b/validation/optim/bitfield-store-loadu.c
@@ -0,0 +1,22 @@
+struct s {
+ unsigned int :2;
+ unsigned int f:3;
+};
+
+int foo(struct s s, int a)
+{
+ s.f = a;
+ return s.f;
+}
+
+/*
+ * check-name: bitfield-store-load unsigned
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-excludes: shl\\.
+ * check-output-excludes: lsr\\.
+ * check-output-excludes: or\\.
+ * check-output-pattern(1): and\\.
+ */
diff --git a/validation/optim/or-and-constant1.c b/validation/optim/or-and-constant1.c
new file mode 100644
index 00000000..aa673b90
--- /dev/null
+++ b/validation/optim/or-and-constant1.c
@@ -0,0 +1,29 @@
+unsigned int and_or_equ(unsigned int a)
+{
+ return (a | 3) & 3;
+}
+
+int and_or_eqs(int a)
+{
+ return (a | 3) & 3;
+}
+
+unsigned int or_and_equ(unsigned int a)
+{
+ return (a & 3) | 3;
+}
+
+int or_and_eqs(int a)
+{
+ return (a & 3) | 3;
+}
+
+/*
+ * check-name: or-and-constant1
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-pattern(4): ret\\..*\\$3
+ * check-output-excludes: or\\.
+ */
diff --git a/validation/optim/sh-or-and0.c b/validation/optim/sh-or-and0.c
new file mode 100644
index 00000000..02f0cb03
--- /dev/null
+++ b/validation/optim/sh-or-and0.c
@@ -0,0 +1,20 @@
+unsigned lsr_or_and0(unsigned x, unsigned b)
+{
+ return (((x & 0x00000fff) | b) >> 12);
+}
+
+unsigned shl_or_and0(unsigned x, unsigned b)
+{
+ return (((x & 0xfff00000) | b) << 12);
+}
+
+/*
+ * check-name: sh-or-and0
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(1): lsr\\.
+ * check-output-pattern(1): shl\\.
+ * check-output-excludes: or\\.
+ * check-output-excludes: and\\.
+ */
diff --git a/validation/optim/sh-or-and1.c b/validation/optim/sh-or-and1.c
new file mode 100644
index 00000000..7b79bbf3
--- /dev/null
+++ b/validation/optim/sh-or-and1.c
@@ -0,0 +1,20 @@
+unsigned lsr_or_and1(unsigned x, unsigned b)
+{
+ return (((x & 0xfffff000) | b) >> 12);
+}
+
+unsigned shl_or_and1(unsigned x, unsigned b)
+{
+ return (((x & 0x000fffff) | b) << 12);
+}
+
+/*
+ * check-name: sh-or-and1
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(1): lsr\\.
+ * check-output-pattern(1): shl\\.
+ * check-output-pattern(2): or\\.
+ * check-output-excludes: and\\.
+ */
diff --git a/validation/optim/sh-or-and2.c b/validation/optim/sh-or-and2.c
new file mode 100644
index 00000000..241aeaff
--- /dev/null
+++ b/validation/optim/sh-or-and2.c
@@ -0,0 +1,21 @@
+unsigned lsr_or_and2(unsigned x, unsigned b)
+{
+ return (((x & 0xf0ffffff) | b) >> 12);
+}
+
+unsigned shl_or_and2(unsigned x, unsigned b)
+{
+ return (((x & 0xffffff0f) | b) << 12);
+}
+
+/*
+ * check-name: sh-or-and2
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(1): lsr\\.
+ * check-output-pattern(1): shl\\.
+ * check-output-pattern(2): or\\.
+ * check-output-pattern(1): and\\..*\\$0xf0fff000
+ * check-output-pattern(1): and\\..*\\$0xfff0f
+ */
diff --git a/validation/optim/trunc-or-shl.c b/validation/optim/trunc-or-shl.c
new file mode 100644
index 00000000..70d8bd1d
--- /dev/null
+++ b/validation/optim/trunc-or-shl.c
@@ -0,0 +1,13 @@
+char foo(int a, int b)
+{
+ return (a << 8) | b;
+}
+
+/*
+ * check-name: trunc-or-shl
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*%arg2
+ */