This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] ARM - transform (X << y) - 1) into ~(~(X-1) << y) for const X

This patch adds a new define_split for ARM to transform expressions of the 

	(X << y) - 1


	~(~(X-1) << y)

for constant X.

The former always takes at least 3 insns on ARM, because a 
register-specified shift can only be done on a register, and a constant 
cannot be subtracted from a shift operation in the same insn.  The 
transformed form, however, is normally possible in 2 insns (generate the 
variant constant, and then use shift-and-invert).  Furthermore, the 
alternate form can often be further combined, for example, it's common for 
the above expression to be used either in its inverse (where the two not 
expressions now cancel out, or for it to be used directly in as a mask in 
an AND operation (where the ARM bic instruction can be used).

So we can now transform code like

	mov	r0, #1
	mov	r0, r0, lsl r2
	sub	r0, r0, #1
	and	r0, r0, r3


	mvn	r0, #0	@ r0 = -1
	bic	r0, r3, r0, lsl r2

This idiom is quite common in some C code.  For example, combine.c uses it 
about twenty times, and some parts of the jpeg library make use of it 
regularly too.

Bootstrapped and regression tested on arm-netbsdelf.


2003-12-08  Richard Earnshaw  <>

	* New split to transform ((X << y) - 1) into ~(~(X-1) << y)
	for constant X.

Attachment: shft-cst-m1.patch
Description: shft-cst-m1.patch

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]