HI to SI mode miss conversion on MIPS.

Hiroyuki Machida machida@sm.sony.co.jp
Thu Feb 10 04:04:00 GMT 2000


Hi,
I found the problem about HI to SI mode conversion on MIPS.

REPEATED BY
	gcc -O2 -g -df -dc hisi.c -o hisi
	./hisi

VERSION
	gcc version 2.95.2 19991024 (release) for MIPS
	gcc version 2.96 20000124 (experimental) for MIPS

The attached test program shows that gcc produces the incorrect 
object for swapping lower and upper byte. This test code derived 
from linux kernel linux/drivers/net/slhc.c.

The test swaps 0x0000235f twice, expceted results is 0x0000235f. But
you will get 0x005f235f on MIPSEB box. (This problem is occured even
if on MIPSEL box)

I tracked down in rough. In my observation, required "zero_extend"
or somthing was vanished on the "combination-phase".

Followings are interested portions of the test programe and
corresponding RTL codes. The problem is occured at the line 65 of
the C source code.

In the hisi.c.08.flow, RTLs look good. But #78, #86 and #99 in the
hisi.c.09.combine produce incorrect result.  
In my concern, The RTL corresspoindig to #95 in the hisi.c.08.flow,
	(set (reg:SI 111) (zero_extend:SI (reg:HI 111)))
must be put at the next of
#86 (set (subreg:SI (reg:HI 111) 0) (ior:SI (reg:SI 114) (reg:SI 117))) 
in the hisi.c.09.combine.

The attached patch is a workaround for this problem. Does anyone
have better solution or real fix ?  



=== Portion of C codes in hisi.c.
line 16:
__inline__ __const__ __u16 uswb16(__u16 x)
{
        return ((__u16)(
                  (((__u16)(  x  ) & (__u16)0x00ffU) << 8)
                | (((__u16)( x ) & (__u16)0xff00U) >> 8) ) )  ;
}
 :
 :
unsigned long result = 0 ;
 :
 :
line 65:
	result += swb16(swapped);

=== Portion of RTLs in hisi.08.flow. (produced by -df )

	Note:   Commtents begin with ";;".
		"Rxxx" denotes register xxx in comments.
		"#xx" denotes the insn number xx.

;; R108 <- (__u16) swapped
#67 (set (reg:HI 109) (mem/v/f:HI (symbol_ref:SI ("swapped")) 1))
#69 (set (reg:SI 108) (zero_extend:SI (reg:HI 109)))

;; R114 <- ( R108 & 0xff) << 8
#76 (set (reg:SI 112) (and:SI (reg:SI 108) (const_int 255 [0xff])))
#78 (set (reg:SI 114) (ashift:SI (reg:SI 112) (const_int 8 [0x8])))

;; R117 <- ((__u16)(R108 & 0xff00)) >> 8
#79 (set (reg:SI 115) (and:SI (reg:SI 108) (const_int 65280 [0xff00])))
#80 (set (reg:SI 116) (zero_extend:SI (subreg:HI (reg:SI 115) 0)))
#81 (set (reg:SI 117) (lshiftrt:SI (reg:SI 116) (const_int 8 [0x8])))

;; R121 <-  (__u16) (R114 | R117)
#84 (set (reg:SI 120) (ior:SI (reg:SI 114) (reg:SI 117)))
#85 (set (reg:SI 121) (zero_extend:SI (subreg:HI (reg:SI 120) 0))) 

;; R122 <- (__u16)R121
#86 (set (subreg:SI (reg:HI 111) 0) (reg:SI 121)) ;; paradoixcal subreg
#95 (set (reg:SI 122) (zero_extend:SI (reg:HI 111)))

;;  result <- R122+R107
#99 (set (reg:SI 124) (plus:SI (reg:SI 107) (reg:SI 122)))
#101 (set (mem/f:SI (symbol_ref:SI ("result")) 3) (reg:SI 124)) 


=== Portion of RTLs in hisi.09.combine. (produced buy -dc)

;; R108 <- (__u16) swapped
#67 (set (reg:HI 109) (mem/v/f:HI (symbol_ref:SI ("swapped")) 1))
#69 (set (reg:SI 108) (zero_extend:SI (reg:HI 109)))

;; R114 <- R108 << 8 ;; upper part of R114 is not cleard.
#76  NOTE_INSN_DELETED
#78 (set (reg:SI 114) (ashift:SI (reg:SI 108) (const_int 8 [0x8])))

;; R117 <- R108 >> 8
#79  NOTE_INSN_DELETED
#80  NOTE_INSN_DELETED
#81 (set (reg:SI 117) (lshiftrt:SI (reg:SI 108) (const_int 8 [0x8])))

#84  NOTE_INSN_DELETED
#85  NOTE_INSN_DELETED

;; R111 <- R117 | R114
#86 (set (subreg:SI (reg:HI 111) 0) (ior:SI (reg:SI 114) (reg:SI 117))) 

;; R122 <- R103 | R106
#95 (set (reg:SI 122) (ior:SI (reg:SI 103) (reg:SI 106)))

;; result <- R122 + R111
#99 (set (reg:SI 124) (plus:SI (reg:SI 122) (subreg:SI (reg:HI 111) 0)))
#101 (set (mem/f:SI (symbol_ref:SI ("result")) 3) (reg:SI 124))

=== 
---
Hiroyuki Machida
Creative Station		SCE Inc./Sony Corp.



More information about the Gcc-bugs mailing list