Patchwork [PR43814] Assume function arguments of pointer type are aligned.

login
register
mail settings
Submitter Tom de Vries
Date Oct. 25, 2011, 12:22 p.m.
Message ID <4EA6AA02.6010301@mentor.com>
Download mbox | patch
Permalink /patch/121642/
State New
Headers show

Comments

Tom de Vries - Oct. 25, 2011, 12:22 p.m.
On 09/24/2011 01:42 PM, Richard Guenther wrote:
> On Sat, Sep 24, 2011 at 11:40 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Sat, Sep 24, 2011 at 11:31:25AM +0200, Richard Guenther wrote:
>>> In the end I'd probably say the patch is ok without the option (thus
>>> turned on by default), but if LC_GLOBAL_LOCALE is part of the
>>> glibc ABI then we clearly can't do this.
>>
>> Yes, LC_GLOBAL_LOCALE is part of glibc ABI.  I guess we could only assume
>> the alignment if the pointer is actually dereferenced on the statement
>> that checks the ABI or in some stmt that dominates the spot where you want
>> to check the alignment.  It is IMHO quite common to pass arbitrary values
>> in pointer types, then cast them back or just compare.
> 
> Yeah (even if technically invoking undefined behavior in C).  Checking if
> there is a dereference post-dominating function entry with sth like
> 
>   FOR_EACH_IMM_USE_STMT (... ptr ...)
>      if (stmt_post_dominates_entry && contains derefrence of ptr)
>        alignment = TYPE_ALIGN (...);
> 
> and otherwise not assuming anything about parameter alignment might work.
> Be careful to check the alignment of the dereference though,
> 
> typedef int int_unaligned __attribute__((aligned(1)));
> int foo (int *p)
> {
>   int_unaligned *q = p;
>   return *q;
> }
> 
> will be MEM[p] but with (well, hopefully ;)) TYPE_ALIGN of TREE_TYPE (MEM[p])
> being 1.  And yes, you'd have to look into handled-components as well.  I guess
> you'll face similar problems as we do with tree-sra.c
> tree_non_mode_aligned_mem_p
> (you need to assume eventually misaligned accesses the same way expansion
> does for the dereference, otherwise you'll run into issues on
> strict-align targets).
> 
> As that de-refrence thing doesn't really fit the CCP propagation you
> won't be able
> to handle
> 
> int foo (int *p)
> {
>   int *q = (char *)p + 3;
>   return *q;
> }
> 
> and assume q is aligned (and p is misaligned by 1).
> 
> That is, if the definition of a pointer is post-dominated by a derefrence
> we could assume proper alignment for that pointer (as opposed to just
> special-casing its default definition).  Would be certainly interesting to
> see what kind of fallout we would get from that ;)
> 

I gave this a try in deduce_alignment_from_dereferences.

The fall-out I got from this were unaligned dereferenced pointers in
gcc.c-torture/unsorted/*{cmp,set}.c.

Bootstrapped and reg-tested on x86_64. Build and reg-tested on MIPS and ARM.

Ok for trunk?

Thanks,
- Tom

> Richard.
> 
>>        Jakub
>>

2011-10-25  Tom de Vries <tom@codesourcery.com>

	PR target/43814
	* tree-ssa-ccp.c (get_align_value): New function, factored out of
	get_value_from_alignment.
	(get_value_from_alignment): Use get_align_value.
	(get_value_for_expr): Use get_align_value to handle alignment of
	pointers with ptr_info->align set.
	(deduce_alignment_from_dereferences): New function.
	(do_ssa_ccp): Calculate post-dominance info and call
	deduce_alignment_from_dereferences.

	* gcc/testsuite/gcc.target/arm/pr43814-2.c: New test.
	* gcc.c-torture/unsorted/HIcmp.c: Fix unaligned pointer.
	* gcc.c-torture/unsorted/HIset.c: Same.
	* gcc.c-torture/unsorted/SIcmp.c: Same.
	* gcc.c-torture/unsorted/SIset.c: Same.
	* gcc.c-torture/unsorted/SFset.c: Same.
	* gcc.c-torture/unsorted/UHIcmp.c: Same.
	* gcc.c-torture/unsorted/USIcmp.c: Same.
	* gcc.c-torture/unsorted/DFcmp.c: Same.
Richard Guenther - Oct. 26, 2011, 10:19 a.m.
On Tue, Oct 25, 2011 at 2:22 PM, Tom de Vries <Tom_deVries@mentor.com> wrote:
> On 09/24/2011 01:42 PM, Richard Guenther wrote:
>> On Sat, Sep 24, 2011 at 11:40 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>>> On Sat, Sep 24, 2011 at 11:31:25AM +0200, Richard Guenther wrote:
>>>> In the end I'd probably say the patch is ok without the option (thus
>>>> turned on by default), but if LC_GLOBAL_LOCALE is part of the
>>>> glibc ABI then we clearly can't do this.
>>>
>>> Yes, LC_GLOBAL_LOCALE is part of glibc ABI.  I guess we could only assume
>>> the alignment if the pointer is actually dereferenced on the statement
>>> that checks the ABI or in some stmt that dominates the spot where you want
>>> to check the alignment.  It is IMHO quite common to pass arbitrary values
>>> in pointer types, then cast them back or just compare.
>>
>> Yeah (even if technically invoking undefined behavior in C).  Checking if
>> there is a dereference post-dominating function entry with sth like
>>
>>   FOR_EACH_IMM_USE_STMT (... ptr ...)
>>      if (stmt_post_dominates_entry && contains derefrence of ptr)
>>        alignment = TYPE_ALIGN (...);
>>
>> and otherwise not assuming anything about parameter alignment might work.
>> Be careful to check the alignment of the dereference though,
>>
>> typedef int int_unaligned __attribute__((aligned(1)));
>> int foo (int *p)
>> {
>>   int_unaligned *q = p;
>>   return *q;
>> }
>>
>> will be MEM[p] but with (well, hopefully ;)) TYPE_ALIGN of TREE_TYPE (MEM[p])
>> being 1.  And yes, you'd have to look into handled-components as well.  I guess
>> you'll face similar problems as we do with tree-sra.c
>> tree_non_mode_aligned_mem_p
>> (you need to assume eventually misaligned accesses the same way expansion
>> does for the dereference, otherwise you'll run into issues on
>> strict-align targets).
>>
>> As that de-refrence thing doesn't really fit the CCP propagation you
>> won't be able
>> to handle
>>
>> int foo (int *p)
>> {
>>   int *q = (char *)p + 3;
>>   return *q;
>> }
>>
>> and assume q is aligned (and p is misaligned by 1).
>>
>> That is, if the definition of a pointer is post-dominated by a derefrence
>> we could assume proper alignment for that pointer (as opposed to just
>> special-casing its default definition).  Would be certainly interesting to
>> see what kind of fallout we would get from that ;)
>>
>
> I gave this a try in deduce_alignment_from_dereferences.
>
> The fall-out I got from this were unaligned dereferenced pointers in
> gcc.c-torture/unsorted/*{cmp,set}.c.
>
> Bootstrapped and reg-tested on x86_64. Build and reg-tested on MIPS and ARM.
>
> Ok for trunk?

Can you not do the get_value_from_alignment split (it doesn't look
necessary to me) and drop the

@@ -541,10 +550,18 @@ get_value_for_expr (tree expr, bool for_
   if (TREE_CODE (expr) == SSA_NAME)
     {
       val = *get_value (expr);
-      if (for_bits_p
-         && val.lattice_val == CONSTANT
+      if (!for_bits_p)
+       return val;
+
+      if (val.lattice_val == CONSTANT
          && TREE_CODE (val.value) == ADDR_EXPR)
        val = get_value_from_alignment (val.value);
+      else if (val.lattice_val == VARYING
+              && SSA_NAME_PTR_INFO (expr) != NULL
+              && SSA_NAME_PTR_INFO (expr)->align > 1
+              && SSA_NAME_PTR_INFO (expr)->misalign == 0)
+       val = get_align_value (SSA_NAME_PTR_INFO (expr)->align * BITS_PER_UNIT,
+                              TREE_TYPE (expr), 0);
     }

hunk?  I'm not sure why it is necessary at all - CCP is the only pass
computing alignment, so it should simply re-compute the info?

Anyway, it looks unrelated to the purpose of the patch in general.

The error reporting in deduce_alignment_from_dereferences is bogus,
the programs are undefined only at runtime, so you can at most
issue a warning.

+  /* Needs to be the successor of entry, for CDI_POST_DOMINATORS.  */
+  entry = single_succ (ENTRY_BLOCK_PTR);
+
+  FOR_EACH_BB (bb)
+    {
+      gimple_stmt_iterator i;
+
+      if (!dominated_by_p (CDI_POST_DOMINATORS, entry, bb))
+       continue;

if you only consider post-dominators of the entry block then just walk
them directly (first_dom_son / next_dom_son).

+             align = TYPE_ALIGN (TREE_TYPE (memref)) / BITS_PER_UNIT;
+             if (align == 1)
+               continue;

I think you want to match what expand thinks of the alignment of this
memory reference, not just what TYPE_ALIGN says (and yes, that
needs to be split out somehow, SRA would need this as well).

+         while (TREE_CODE (ptr) == SSA_NAME)
+           {
+             pi = get_ptr_info (ptr);
+             if (pi->misalign != 0)
+               {
+                 error ("misaligned pointer dereferenced");
+                 break;
+               }

simply looking at pi->misalign is wrong.  pi->align may be bigger
than the align that you computed above, so pi->misalign % align != 0
would be the right check.

+             if (pi->align >= align)
+               break;
+             pi->align = align;

and then set pi->misalign to zero here.  But I would initialize the
CCP lattice with this, not set SSA_NAME_PTR_INFO, from
ccp_initialize, that already walks over all blocks and statements.

+             if (gimple_assign_rhs_code (def) == POINTER_PLUS_EXPR)
+               {
+                 offset = gimple_assign_rhs2 (def);
+                 if (!host_integerp (offset, 0)
+                     || tree_low_cst (offset, 0) % align != 0)
+                   break;
+
+                 ptr = gimple_assign_rhs1 (def);

properly tracking explicit misalignment would be useful here, but I
see you are posting a proof-of-concept?

 /* Main entry point for SSA Conditional Constant Propagation.  */

 static unsigned int
 do_ssa_ccp (void)
 {
+  calculate_dominance_info (CDI_POST_DOMINATORS);
+  deduce_alignment_from_dereferences ();

you need to free post-dom info again.

The

       * gcc.c-torture/unsorted/HIcmp.c: Fix unaligned pointer.
       * gcc.c-torture/unsorted/HIset.c: Same.
       * gcc.c-torture/unsorted/SIcmp.c: Same.
       * gcc.c-torture/unsorted/SIset.c: Same.
       * gcc.c-torture/unsorted/SFset.c: Same.
       * gcc.c-torture/unsorted/UHIcmp.c: Same.
       * gcc.c-torture/unsorted/USIcmp.c: Same.
       * gcc.c-torture/unsorted/DFcmp.c: Same.

changes are ok with s/sizeof/alignof/

Thanks,
Richard.

> Thanks,
> - Tom
>
>> Richard.
>>
>>>        Jakub
>>>
>
> 2011-10-25  Tom de Vries <tom@codesourcery.com>
>
>        PR target/43814
>        * tree-ssa-ccp.c (get_align_value): New function, factored out of
>        get_value_from_alignment.
>        (get_value_from_alignment): Use get_align_value.
>        (get_value_for_expr): Use get_align_value to handle alignment of
>        pointers with ptr_info->align set.
>        (deduce_alignment_from_dereferences): New function.
>        (do_ssa_ccp): Calculate post-dominance info and call
>        deduce_alignment_from_dereferences.
>
>        * gcc/testsuite/gcc.target/arm/pr43814-2.c: New test.
>        * gcc.c-torture/unsorted/HIcmp.c: Fix unaligned pointer.
>        * gcc.c-torture/unsorted/HIset.c: Same.
>        * gcc.c-torture/unsorted/SIcmp.c: Same.
>        * gcc.c-torture/unsorted/SIset.c: Same.
>        * gcc.c-torture/unsorted/SFset.c: Same.
>        * gcc.c-torture/unsorted/UHIcmp.c: Same.
>        * gcc.c-torture/unsorted/USIcmp.c: Same.
>        * gcc.c-torture/unsorted/DFcmp.c: Same.
>

Patch

Index: gcc/tree-ssa-ccp.c
===================================================================
--- gcc/tree-ssa-ccp.c (revision 180237)
+++ gcc/tree-ssa-ccp.c (working copy)
@@ -500,20 +500,14 @@  value_to_double_int (prop_value_t val)
     return double_int_zero;
 }
 
-/* Return the value for the address expression EXPR based on alignment
-   information.  */
+/* Return the value for an expr of type TYPE with alignment ALIGN and offset
+   BITPOS relative to the alignment.  */
 
 static prop_value_t
-get_value_from_alignment (tree expr)
+get_align_value (unsigned int align, tree type, unsigned HOST_WIDE_INT bitpos)
 {
-  tree type = TREE_TYPE (expr);
   prop_value_t val;
-  unsigned HOST_WIDE_INT bitpos;
-  unsigned int align;
-
-  gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
 
-  align = get_object_alignment_1 (TREE_OPERAND (expr, 0), &bitpos);
   val.mask
     = double_int_and_not (POINTER_TYPE_P (type) || TYPE_UNSIGNED (type)
 			  ? double_int_mask (TYPE_PRECISION (type))
@@ -529,6 +523,21 @@  get_value_from_alignment (tree expr)
   return val;
 }
 
+/* Return the value for the address expression EXPR based on alignment
+   information.  */
+
+static prop_value_t
+get_value_from_alignment (tree expr)
+{
+  unsigned int align;
+  unsigned HOST_WIDE_INT bitpos;
+
+  gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
+
+  align = get_object_alignment_1 (TREE_OPERAND (expr, 0), &bitpos);
+  return get_align_value (align, TREE_TYPE (expr), bitpos);
+}
+
 /* Return the value for the tree operand EXPR.  If FOR_BITS_P is true
    return constant bits extracted from alignment information for
    invariant addresses.  */
@@ -541,10 +550,18 @@  get_value_for_expr (tree expr, bool for_
   if (TREE_CODE (expr) == SSA_NAME)
     {
       val = *get_value (expr);
-      if (for_bits_p
-	  && val.lattice_val == CONSTANT
+      if (!for_bits_p)
+	return val;
+
+      if (val.lattice_val == CONSTANT
 	  && TREE_CODE (val.value) == ADDR_EXPR)
 	val = get_value_from_alignment (val.value);
+      else if (val.lattice_val == VARYING
+	       && SSA_NAME_PTR_INFO (expr) != NULL
+	       && SSA_NAME_PTR_INFO (expr)->align > 1
+	       && SSA_NAME_PTR_INFO (expr)->misalign == 0)
+	val = get_align_value (SSA_NAME_PTR_INFO (expr)->align * BITS_PER_UNIT,
+			       TREE_TYPE (expr), 0);
     }
   else if (is_gimple_min_invariant (expr)
 	   && (!for_bits_p || TREE_CODE (expr) != ADDR_EXPR))
@@ -2018,12 +2035,105 @@  ccp_visit_stmt (gimple stmt, edge *taken
   return SSA_PROP_VARYING;
 }
 
+/* Find pointer dereferences that post-dominate function entry and set
+   ptr_info->align for those pointers, and propagate backward through pointer
+   arithmetic.  */
+
+static void
+deduce_alignment_from_dereferences (void)
+{
+  basic_block bb, entry;
+  gimple stmt, def;
+  unsigned int align;
+  tree memref, ptr, offset;
+  struct ptr_info_def *pi;
+
+  /* Needs to be the successor of entry, for CDI_POST_DOMINATORS.  */
+  entry = single_succ (ENTRY_BLOCK_PTR);
+
+  FOR_EACH_BB (bb)
+    {
+      gimple_stmt_iterator i;
+
+      if (!dominated_by_p (CDI_POST_DOMINATORS, entry, bb))
+	continue;
+
+      for (i = gsi_start_nondebug_bb (bb); !gsi_end_p (i);
+	   gsi_next_nondebug (&i))
+        {
+	  stmt = gsi_stmt (i);
+	  if (!is_gimple_assign (stmt))
+	    continue;
+
+	  if (gimple_assign_rhs_code (stmt) == MEM_REF)
+	    {
+	      memref = gimple_assign_rhs1 (stmt);
+
+	      align = TYPE_ALIGN (TREE_TYPE (memref)) / BITS_PER_UNIT;
+	      if (align == 1)
+		continue;
+
+	      offset = TREE_OPERAND (memref, 1);
+	      if (!host_integerp (offset, 0)
+		  || tree_low_cst (offset, 0) % align != 0)
+		continue;
+
+	      ptr = TREE_OPERAND (memref, 0);
+	    }
+	  else
+	    /* Todo: handle more cases.  */
+	    continue;
+
+	  if (TREE_CODE (ptr) == INTEGER_CST
+	      && host_integerp (ptr, 0)
+	      && tree_low_cst (ptr, 0) % align != 0)
+	    error ("misaligned pointer dereferenced");
+
+	  while (TREE_CODE (ptr) == SSA_NAME)
+	    {
+	      pi = get_ptr_info (ptr);
+	      if (pi->misalign != 0)
+		{
+		  error ("misaligned pointer dereferenced");
+		  break;
+		}
+
+	      if (pi->align >= align)
+		break;
+	      pi->align = align;
+
+	      if (SSA_NAME_IS_DEFAULT_DEF (ptr))
+		break;
+
+	      /* Propagate backwards over pointer arithmetic.  */
+	      def = SSA_NAME_DEF_STMT (ptr);
+	      if (!is_gimple_assign (def))
+		break;
+
+	      if (gimple_assign_rhs_code (def) == POINTER_PLUS_EXPR)
+		{
+		  offset = gimple_assign_rhs2 (def);
+		  if (!host_integerp (offset, 0)
+		      || tree_low_cst (offset, 0) % align != 0)
+		    break;
+
+		  ptr = gimple_assign_rhs1 (def);
+		}
+	      else
+		/* Todo: handle more cases.  */
+		break;
+	    }
+	}
+    }
+}
 
 /* Main entry point for SSA Conditional Constant Propagation.  */
 
 static unsigned int
 do_ssa_ccp (void)
 {
+  calculate_dominance_info (CDI_POST_DOMINATORS);
+  deduce_alignment_from_dereferences ();
   ccp_initialize ();
   ssa_propagate (ccp_visit_stmt, ccp_visit_phi_node);
   if (ccp_finalize ())
Index: gcc/testsuite/gcc.target/arm/pr43814-2.c
===================================================================
--- /dev/null (new file)
+++ gcc/testsuite/gcc.target/arm/pr43814-2.c (revision 0)
@@ -0,0 +1,33 @@ 
+/* { dg-do compile } */
+/* { dg-options "-Os -finline-functions -mno-unaligned-access -fdump-rtl-expand" } */
+
+typedef unsigned int size_t;
+extern void* memcpy (void *, const void *, size_t);
+
+typedef union JValue {
+  void* l;
+} JValue;
+typedef struct Object {
+  int x;
+} Object;
+
+extern __inline__ long long
+dvmGetArgLong (const unsigned int* args, int elem)
+{
+  long long val;
+  memcpy (&val, &args[elem], 8);
+  return val;
+}
+
+void
+Dalvik_sun_misc_Unsafe_getObject (const unsigned int* args, JValue* pResult)
+{
+  Object* obj = (Object*) args[1];
+  long long offset = dvmGetArgLong (args, 2);
+  Object** address = (Object**) (((unsigned char*) obj) + offset);
+  pResult->l = ((void*) *address);
+}
+
+/* { dg-final { scan-rtl-dump-times "memcpy" 0 "expand"} } */
+/* { dg-final { cleanup-tree-dump "expand" } } */
+
Index: gcc/testsuite/gcc.c-torture/unsorted/HIcmp.c
===================================================================
--- gcc/testsuite/gcc.c-torture/unsorted/HIcmp.c (revision 180237)
+++ gcc/testsuite/gcc.c-torture/unsorted/HIcmp.c (working copy)
@@ -12,7 +12,7 @@  type glob0, glob1;
 #define adrx0 (E0[x0])
 #define regx0 (p0[x0])
 
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(sizeof (type) - 1)))
 #define reg1 r1
 #define indreg1 (*p1)
 #define imm1 33
Index: gcc/testsuite/gcc.c-torture/unsorted/HIset.c
===================================================================
--- gcc/testsuite/gcc.c-torture/unsorted/HIset.c (revision 180237)
+++ gcc/testsuite/gcc.c-torture/unsorted/HIset.c (working copy)
@@ -8,7 +8,7 @@ 
 #define adrx0 (E0[x0])
 #define regx0 (p0[x0])
 
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(sizeof (type) - 1)))
 #define reg1 r1
 #define indreg1 (*p1)
 #define imm1 33
Index: gcc/testsuite/gcc.c-torture/unsorted/SIcmp.c
===================================================================
--- gcc/testsuite/gcc.c-torture/unsorted/SIcmp.c (revision 180237)
+++ gcc/testsuite/gcc.c-torture/unsorted/SIcmp.c (working copy)
@@ -12,7 +12,7 @@  type glob0, glob1;
 #define adrx0 (E0[x0])
 #define regx0 (p0[x0])
 
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(sizeof (type) - 1)))
 #define reg1 r1
 #define indreg1 (*p1)
 #define imm1 33
Index: gcc/testsuite/gcc.c-torture/unsorted/SIset.c
===================================================================
--- gcc/testsuite/gcc.c-torture/unsorted/SIset.c (revision 180237)
+++ gcc/testsuite/gcc.c-torture/unsorted/SIset.c (working copy)
@@ -8,7 +8,7 @@ 
 #define adrx0 (E0[x0])
 #define regx0 (p0[x0])
 
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(sizeof (type) - 1)))
 #define reg1 r1
 #define indreg1 (*p1)
 #define imm1 33
Index: gcc/testsuite/gcc.c-torture/unsorted/SFset.c
===================================================================
--- gcc/testsuite/gcc.c-torture/unsorted/SFset.c (revision 180237)
+++ gcc/testsuite/gcc.c-torture/unsorted/SFset.c (working copy)
@@ -8,7 +8,7 @@ 
 #define adrx0 (E0[x0])
 #define regx0 (p0[x0])
 
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(sizeof (type) - 1)))
 #define reg1 r1
 #define indreg1 (*p1)
 #define imm1 33
Index: gcc/testsuite/gcc.c-torture/unsorted/UHIcmp.c
===================================================================
--- gcc/testsuite/gcc.c-torture/unsorted/UHIcmp.c (revision 180237)
+++ gcc/testsuite/gcc.c-torture/unsorted/UHIcmp.c (working copy)
@@ -12,7 +12,7 @@  type glob0, glob1;
 #define adrx0 (E0[x0])
 #define regx0 (p0[x0])
 
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(sizeof (type) - 1)))
 #define reg1 r1
 #define indreg1 (*p1)
 #define imm1 33
Index: gcc/testsuite/gcc.c-torture/unsorted/USIcmp.c
===================================================================
--- gcc/testsuite/gcc.c-torture/unsorted/USIcmp.c (revision 180237)
+++ gcc/testsuite/gcc.c-torture/unsorted/USIcmp.c (working copy)
@@ -12,7 +12,7 @@  type glob0, glob1;
 #define adrx0 (E0[x0])
 #define regx0 (p0[x0])
 
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(sizeof (type) - 1)))
 #define reg1 r1
 #define indreg1 (*p1)
 #define imm1 33
Index: gcc/testsuite/gcc.c-torture/unsorted/DFcmp.c
===================================================================
--- gcc/testsuite/gcc.c-torture/unsorted/DFcmp.c (revision 180237)
+++ gcc/testsuite/gcc.c-torture/unsorted/DFcmp.c (working copy)
@@ -12,7 +12,7 @@  type glob0, glob1;
 #define adrx0 (E0[x0])
 #define regx0 (p0[x0])
 
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(sizeof (type) - 1)))
 #define reg1 r1
 #define indreg1 (*p1)
 #define imm1 33