This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TI MSPGCC 5.3.0 bug report (loop initialization incorrectly optimized out with -Os)

The enclosed program (extract.c) is an extract from my larger code. When compiled this way:

msp430-elf-gcc -Os -g -c extract.c

the resulting object code ends up incorrect. See the enclosed object dump file (dump.txt) with my annotations.

Description:

The program (function qfree) amounts to two loops. When the second loop is entered, variable chunk (held in r14) is not initialized properly, but its value as left by the previous loop is incorrectly assumed. The problem disappears when chunk is declared as volatile.

extract.c
typedef	unsigned int	word;
typedef	word		*address;

static 	address *mpools;

#define	m_nextp(c)	((address)(*(c)))
#define m_setnextp(c,p)	(*(c) = (word)(p))
#define m_size(c)	(*((c)-1))
#define	m_magic(c) 	(*((c)+1))
#define	m_hdrlen	1
#define	MA_NP		0
#define	NULL		0


static void qfree (address ch) {

#if	0
	// Trying to circumvent a bug in TI MSPGCC
	volatile
#endif
	address chunk, cc;

	cc = (address)(mpools + MA_NP);

	for (chunk = mpools [MA_NP]; chunk != NULL; chunk = m_nextp (chunk)) {
		if (chunk + m_size (chunk) + m_hdrlen == ch) {
			/* Merge at the front */
			m_setnextp (cc, m_nextp (chunk));
			m_size (chunk) += m_hdrlen + m_size (ch);
			ch = chunk;
		} else if (ch + m_size (ch) + m_hdrlen == chunk) {
			/* Merge at the back */
			m_setnextp (cc, m_nextp (chunk));
			m_size (ch) += m_hdrlen + m_size (chunk);
		} else {
			/* Skip */
			cc = chunk;
		}
	}

	/* Insert */
	cc = (address)(mpools + MA_NP);
	for (chunk = mpools [MA_NP]; chunk != NULL; cc = chunk,
		chunk = m_nextp (chunk))
			if (m_size (chunk) >= m_size (ch))
				break;

	m_setnextp (ch, chunk);
	m_setnextp (cc, ch);
	m_magic (ch) = 0xdeaf;

}

void initializer (address *a) {
	mpools = a;
}

void freeer (address a) {
	qfree (a);
}

void secondfreer (address a) {
	// To prevent inline compilation (for clarity)
	qfree (a + 2);
}

dump.txt
extract.o:     file format elf32-msp430


Disassembly of section .text:

00000000 <qfree>:
qfree():
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:15
   0:	1a 15       	pushm	#2,	r10	;16-bit words

00000002 <.LCFI0>:
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:23
   2:	1b 42 00 00 	mov	&0x0000,r11	;0x0000

00000006 <.LVL1>:
// ===============================================
// PG: initializing chunk for the first loop (r14)
// ===============================================
   6:	2e 4b       	mov	@r11,	r14	;

00000008 <.LVL2>:
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25
   8:	0a 4b       	mov	r11,	r10	;
   a:	0d 4e       	mov	r14,	r13	;

0000000c <.L2>:
   c:	0d 93       	cmp	#0,	r13	;r3 As==00
// ==============================================================
// PG: this exits the first loop and enters the second one at .L6
// ==============================================================
   e:	00 24       	jz	$+2      	;abs 0x10


00000010 <.Loc.26.1>:
  10:	1f 4d fe ff 	mov	-2(r13),r15	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25 (discriminator 1)
  14:	1f 53       	inc	r15		;
  16:	0f 5f       	rla	r15		;
  18:	0f 5d       	add	r13,	r15	;
  1a:	29 4d       	mov	@r13,	r9	;
// =============
// PG: r12 is ch
// =============
  1c:	0c 9f       	cmp	r15,	r12	;
  1e:	00 20       	jnz	$+2      	;abs 0x20

00000020 <.Loc.28.1>:
  20:	8a 49 00 00 	mov	r9,	0(r10)	;

00000024 <.Loc.29.1>:
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:26
  24:	1c 4c fe ff 	mov	-2(r12),r12	;

00000028 <.LVL4>:
  28:	1c 5d fe ff 	add	-2(r13),r12	;
  2c:	1c 53       	inc	r12		;
  2e:	8d 4c fe ff 	mov	r12,	-2(r13)	; 0xfffe

00000032 <.LVL5>:
  32:	0c 4d       	mov	r13,	r12	;
  34:	30 40 00 00 	br	#0x0000		;

00000038 <.L3>:
  38:	1f 4c fe ff 	mov	-2(r12),r15	;
  3c:	1f 53       	inc	r15		;
  3e:	0f 5f       	rla	r15		;
  40:	0f 5c       	add	r12,	r15	;
  42:	0d 9f       	cmp	r15,	r13	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:28
  44:	00 20       	jnz	$+2      	;abs 0x46

00000046 <.Loc.33.1>:
  46:	8a 49 00 00 	mov	r9,	0(r10)	;

0000004a <.Loc.34.1>:
  4a:	1f 4c fe ff 	mov	-2(r12),r15	;
  4e:	1f 5d fe ff 	add	-2(r13),r15	;
  52:	1f 53       	inc	r15		;
  54:	8c 4f fe ff 	mov	r15,	-2(r12)	; 0xfffe
  58:	30 40 00 00 	br	#0x0000		;

0000005c <.L9>:
  5c:	0a 4d       	mov	r13,	r10	;

0000005e <.L4>:
  5e:	2d 4d       	mov	@r13,	r13	;
  60:	30 40 00 00 	br	#0x0000		;

00000064 <.L8>:
// ==========================================
// PG: if (m_size (chunk) >= m_size (ch)) ...
// ==========================================
  64:	9e 9c fe ff 	cmp	-2(r12),-2(r14)	; 0xfffe
  68:	fe ff 
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:29
  6a:	00 2c       	jc	$+2      	;abs 0x6c

0000006c <.LVL10>:
// ===================================================================
// PG: What is in r14 now??? It is used here as chunk, but it is never
// initialized for the second loop!!!
// ===================================================================
  6c:	0b 4e       	mov	r14,	r11	;
  6e:	2e 4e       	mov	@r14,	r14	;

00000070 <.L6>:
// ======================================================================
// PG: Here is actually where the second loop is entered with r14 left as
// it was at the end of the first loop!
// ======================================================================
  70:	0e 93       	cmp	#0,	r14	;r3 As==00
  72:	00 20       	jnz	$+2      	;abs 0x74

00000074 <.L7>:
  74:	8c 4e 00 00 	mov	r14,	0(r12)	;

00000078 <.Loc.49.1>:
  78:	8b 4c 00 00 	mov	r12,	0(r11)	;

0000007c <.Loc.50.1>:
  7c:	bc 40 af de 	mov	#57007,	2(r12)	;#0xdeaf
  80:	02 00 

00000082 <.Loc.52.1>:
  82:	19 17       	popm	#2,	r10	;16-bit words
  84:	30 41       	ret			


// ============================================================================
// ============================================================================
// ============================================================================

00000086 <initializer>:
initializer():
  86:	82 4c 00 00 	mov	r12,	&0x0000	;

0000008a <.Loc.56.1>:
  8a:	30 41       	ret			

0000008c <freeer>:
  8c:	b0 12 00 00 	call	#0		;

00000090 <.LVL14>:
  90:	30 41       	ret			

00000092 <secondfreer>:
  92:	2c 52       	add	#4,	r12	;r2 As==10

00000094 <.LVL16>:
  94:	b0 12 00 00 	call	#0		;

00000098 <.LVL17>:
  98:	30 41       	ret			

Disassembly of section .bss:

00000000 <mpools>:
	...

Disassembly of section .debug_frame:

00000000 <.debug_frame>:
qfree():
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:15
   0:	10 00       	bra	@r0+		;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:23
   2:	00 00       	beq			
   4:	ff ff       	.word	0xffff;	????
   6:	ff ff       	.word	0xffff;	????
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25
   8:	03 00       	mova	@r0,	r3	;
   a:	01 7e       	subc	r14,	r1	;
   c:	00 0c       	bra	@r12		;
   e:	01 02       	mova	@r2,	r1	;
  10:	80 01 00 00 	mova	#65536,	r0	;0x10000
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25 (discriminator 1)
  14:	18 00       	mova	@r0+,	r8	;
	...
  22:	00 00       	beq			
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:26
  24:	04 00       	mova	@r0,	r4	;
  26:	00 00       	beq			
  28:	00 0e       	bra	@r14		;
  2a:	06 8a       	sub	r10,	r6	;
  2c:	02 89       	sub	r9,	r2	;
  2e:	03 00       	mova	@r0,	r3	;
  30:	0c 00       	mova	@r0,	r12	;
	...
  3e:	00 00       	beq			
  40:	0c 00       	mova	@r0,	r12	;
	...
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:28
  4e:	00 00       	beq			
  50:	0c 00       	mova	@r0,	r12	;
	...

Disassembly of section .debug_info:

00000000 <.debug_info>:
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:15
   0:	28 01 00 00 	mova	&65536,	r8	;0x10000
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:23
   4:	04 00       	mova	@r0,	r4	;
   6:	00 00       	beq			
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25
   8:	00 00       	beq			
   a:	04 01       	mova	@r1,	r4	;
   c:	00 00       	beq			
   e:	00 00       	beq			
  10:	0c 00       	mova	@r0,	r12	;
	...
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25 (discriminator 1)
  22:	00 00       	beq			
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:26
  24:	00 02       	bra	@r2		;
  26:	00 00       	beq			
  28:	00 00       	beq			
  2a:	01 01       	mova	@r1,	r1	;
  2c:	30 00 00 00 	bra	0(r0)		;
  30:	03 02       	mova	@r2,	r3	;
  32:	07 00       	mova	@r0,	r7	;
  34:	00 00       	beq			
  36:	00 02       	bra	@r2		;
  38:	00 00       	beq			
  3a:	00 00       	beq			
  3c:	01 02       	mova	@r2,	r1	;
  3e:	42 00       	rrcm.a	#1,	r2	;
  40:	00 00       	beq			
  42:	04 02       	mova	@r2,	r4	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:28
  44:	25 00 00 00 	mova	&0,	r5	;
  48:	05 00       	mova	@r0,	r5	;
  4a:	00 00       	beq			
  4c:	00 01       	bra	@r1		;
  4e:	0f 00       	mova	@r0,	r15	;
  50:	00 00       	beq			
  52:	00 00       	beq			
  54:	00 00       	beq			
  56:	00 01       	bra	@r1		;
  58:	9c 89 00 00 	sub	0(r9),	1536(r12); 0x0600
  5c:	00 06 
  5e:	63 68       	.word	0x6863;	????
  60:	00 01       	bra	@r1		;
  62:	0f 37       	jge	$-480    	;abs 0xfffffe82
  64:	00 00       	beq			
  66:	00 00       	beq			
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:29
  68:	00 00       	beq			
  6a:	00 07       	bra	@r7		;
  6c:	00 00       	beq			
  6e:	00 00       	beq			
  70:	01 15       	pushm	#1,	r1	;16-bit words
  72:	37 00 00 00 	mova	0(r0),	r7	;
  76:	00 00       	beq			
  78:	00 00       	beq			
  7a:	08 63       	adc	r8		;
  7c:	63 00 01 15 	mova	r0,	&201985	; 0x31501
  80:	37 00 00 00 	mova	0(r0),	r7	;
  84:	00 00       	beq			
initializer():
  86:	00 00       	beq			
  88:	00 09       	bra	@r9		;
  8a:	00 00       	beq			
  8c:	00 00       	beq			
  8e:	01 36       	jge	$-1020   	;abs 0xfffffc92
	...
  98:	01 9c       	cmp	r12,	r1	;
  9a:	aa 00 00 00 	adda	#0,	r10	;
  9e:	0a 61       	addc	r1,	r10	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:31
  a0:	00 01       	bra	@r1		;
  a2:	36 aa       	dadd	@r10+,	r6	;
  a4:	00 00       	beq			
  a6:	00 01       	bra	@r1		;
  a8:	5c 00       	rrcm	#1,	r12	;
  aa:	04 02       	mova	@r2,	r4	;
  ac:	37 00 00 00 	mova	0(r0),	r7	;
  b0:	09 00       	mova	@r0,	r9	;
  b2:	00 00       	beq			
  b4:	00 01       	bra	@r1		;
  b6:	3a 00 00 00 	mova	0(r0),	r10	;
  ba:	00 00       	beq			
  bc:	00 00       	beq			
  be:	00 01       	bra	@r1		;
  c0:	9c e4 00 00 	xor	0(r4),	1536(r12); 0x0600
  c4:	00 06 
  c6:	61 00 01 3a 	mova	r0,	&80385	; 0x13a01
  ca:	37 00 00 00 	mova	0(r0),	r7	;
  ce:	00 00       	beq			
  d0:	00 00       	beq			
  d2:	0b 00       	mova	@r0,	r11	;
  d4:	00 00       	beq			
  d6:	00 48       	br	r8		;
  d8:	00 00       	beq			
  da:	00 0c       	bra	@r12		;
  dc:	01 5c       	add	r12,	r1	;
  de:	03 f3       	.word	0xf303;	????
  e0:	01 5c       	add	r12,	r1	;
  e2:	00 00       	beq			
  e4:	09 00       	mova	@r0,	r9	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:33
  e6:	00 00       	beq			
  e8:	00 01       	bra	@r1		;
  ea:	3e 00 00 00 	mova	0(r0),	r14	;
  ee:	00 00       	beq			
  f0:	00 00       	beq			
  f2:	00 01       	bra	@r1		;
  f4:	9c 1a 01 00 	rpt r12 { movax	@r0,	r1	;
  f8:	00 06       	bra	@r6		;
  fa:	61 00 01 3e 	mova	r0,	&81409	; 0x13e01
  fe:	37 00 00 00 	mova	0(r0),	r7	;
 102:	00 00       	beq			
 104:	00 00       	beq			
 106:	0b 00       	mova	@r0,	r11	;
 108:	00 00       	beq			
 10a:	00 48       	br	r8		;
 10c:	00 00       	beq			
 10e:	00 0c       	bra	@r12		;
 110:	01 5c       	add	r12,	r1	;
 112:	05 f3       	and	#0,	r5	;r3 As==00
 114:	01 5c       	add	r12,	r1	;
 116:	23 04 00 00 	mova	&262144,r3	;0x40000
 11a:	0d 00       	mova	@r0,	r13	;
 11c:	00 00       	beq			
 11e:	00 01       	bra	@r1		;
 120:	04 aa       	dadd	r10,	r4	;
 122:	00 00       	beq			
 124:	00 05       	bra	@r5		;
 126:	03 00       	mova	@r0,	r3	;
 128:	00 00       	beq			
	...

Disassembly of section .debug_abbrev:

00000000 <.debug_abbrev>:
qfree():
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:15
   0:	01 11       	rra	r1		;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:23
   2:	01 25       	jz	$+516    	;abs 0x206
   4:	0e 13       	reti			;return from interupt
   6:	0b 03       	mova	@r3,	r11	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25
   8:	0e 1b 0e 11 	rpt #15 { rrax.?	r14		; Reserved use of A/L and B/W bits detected
   c:	01 12       	push	r1		;
   e:	06 10       	rrc	r6		;
  10:	17 00       	mova	@r0+,	r7	;
  12:	00 02       	bra	@r2		;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25 (discriminator 1)
  14:	16 00       	mova	@r0+,	r6	;
  16:	03 0e       	mova	@r14,	r3	;
  18:	3a 0b 3b 0b 	mova	2875(r11),r10	;0x00b3b
  1c:	49 13       	calla	r9		;
  1e:	00 00       	beq			
  20:	03 24       	jz	$+8      	;abs 0x28
  22:	00 0b       	bra	@r11		;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:26
  24:	0b 3e       	jmp	$-1000   	;abs 0xfffffc3c
  26:	0b 03       	mova	@r3,	r11	;
  28:	0e 00       	mova	@r0,	r14	;
  2a:	00 04       	bra	@r4		;
  2c:	0f 00       	mova	@r0,	r15	;
  2e:	0b 0b       	mova	@r11,	r11	;
  30:	49 13       	calla	r9		;
  32:	00 00       	beq			
  34:	05 2e       	jc	$-1012   	;abs 0xfffffc40
  36:	01 03       	mova	@r3,	r1	;
  38:	0e 3a       	jl	$-994    	;abs 0xfffffc56
  3a:	0b 3b       	jl	$-488    	;abs 0xfffffe52
  3c:	0b 27       	jz	$-488    	;abs 0xfffffe54
  3e:	19 11 01 12 	rra	4609(r9)	;01201
  42:	06 40       	mov	r0,	r6	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:28
  44:	18 97 42 19 	cmp	6466(r7),r8	;0x01942
  48:	01 13       	reti			;return from interupt
  4a:	00 00       	beq			
  4c:	06 05       	mova	@r5,	r6	;
  4e:	00 03       	bra	@r3		;
  50:	08 3a       	jl	$-1006   	;abs 0xfffffc62
  52:	0b 3b       	jl	$-488    	;abs 0xfffffe6a
  54:	0b 49       	mov	r9,	r11	;
  56:	13 02       	mova	@r2+,	r3	;
  58:	17 00       	mova	@r0+,	r7	;
  5a:	00 07       	bra	@r7		;
  5c:	34 00 03 0e 	mova	3587(r0),r4	;PC rel. 0x00e61
  60:	3a 0b 3b 0b 	mova	2875(r11),r10	;0x00b3b
  64:	49 13       	calla	r9		;
  66:	02 17       	popm	#1,	r2	;16-bit words
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:29
  68:	00 00       	beq			
  6a:	08 34       	jge	$+18     	;abs 0x7c
  6c:	00 03       	bra	@r3		;
  6e:	08 3a       	jl	$-1006   	;abs 0xfffffc80
  70:	0b 3b       	jl	$-488    	;abs 0xfffffe88
  72:	0b 49       	mov	r9,	r11	;
  74:	13 02       	mova	@r2+,	r3	;
  76:	17 00       	mova	@r0+,	r7	;
  78:	00 09       	bra	@r9		;
  7a:	2e 01 3f 19 	mova	&71999,	r14	;0x1193f
  7e:	03 0e       	mova	@r14,	r3	;
  80:	3a 0b 3b 0b 	mova	2875(r11),r10	;0x00b3b
  84:	27 19 11 01 	rpt #8 { movax	@r1+,	r1	;
initializer():
  88:	12 06       	mova	@r6+,	r2	;
  8a:	40 18 97 42 	movx.w	&0x00119,19(r7)	; 0x00013
  8e:	19 01 13 00 
  92:	00 0a       	bra	@r10		;
  94:	05 00       	mova	@r0,	r5	;
  96:	03 08       	mova	@r8,	r3	;
  98:	3a 0b 3b 0b 	mova	2875(r11),r10	;0x00b3b
  9c:	49 13       	calla	r9		;
  9e:	02 18 00 00 	rpt #3 { beqx			
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:31
  a2:	0b 89       	sub	r9,	r11	;
  a4:	82 01 01 11 	mova	#69889,	r2	;0x11101
  a8:	01 31       	jn	$+516    	;abs 0x2ac
  aa:	13 00       	mova	@r0+,	r3	;
  ac:	00 0c       	bra	@r12		;
  ae:	8a 82 01 00 	sub	r2,	1(r10)	;
  b2:	02 18 91 42 	movx.?	&0x00018,134400(r1); Reserved use of A/L and B/W bits detected
  b6:	18 00 00 0d 
  ba:	34 00 03 0e 	mova	3587(r0),r4	;PC rel. 0x00ebf
  be:	3a 0b 3b 0b 	mova	2875(r11),r10	;0x00b3b
  c2:	49 13       	calla	r9		;
  c4:	02 18 00 00 	rpt #3 { beqx			
	...

Disassembly of section .debug_loc:

00000000 <.debug_loc>:
	...
qfree():
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25
   8:	01 00       	mova	@r0,	r1	;
   a:	5c 00       	rrcm	#1,	r12	;
   c:	00 00       	beq			
   e:	00 00       	beq			
  10:	00 00       	beq			
  12:	00 01       	bra	@r1		;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25 (discriminator 1)
  14:	00 5d       	add	r13,	r0	;
	...
  1e:	01 00       	mova	@r0,	r1	;
  20:	5c 00       	rrcm	#1,	r12	;
	...
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:26
  2e:	00 00       	beq			
  30:	00 01       	bra	@r1		;
  32:	00 5e       	add	r14,	r0	;
	...
  3c:	01 00       	mova	@r0,	r1	;
  3e:	5d 00       	rrcm	#1,	r13	;
  40:	00 00       	beq			
  42:	00 00       	beq			
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:28
  44:	00 00       	beq			
  46:	00 01       	bra	@r1		;
  48:	00 5e       	add	r14,	r0	;
	...
  52:	02 00       	mova	@r0,	r2	;
  54:	7e 00 00 00 	mova	r0,	0(r14)	;
  58:	00 00       	beq			
  5a:	00 00       	beq			
  5c:	00 00       	beq			
  5e:	01 00       	mova	@r0,	r1	;
  60:	5e 00       	rrcm	#1,	r14	;
	...
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:29
  6e:	00 00       	beq			
  70:	00 01       	bra	@r1		;
  72:	00 5b       	add	r11,	r0	;
	...
  7c:	01 00       	mova	@r0,	r1	;
  7e:	5a 00       	rrcm	#1,	r10	;
  80:	00 00       	beq			
  82:	00 00       	beq			
  84:	00 00       	beq			
initializer():
  86:	00 01       	bra	@r1		;
  88:	00 5b       	add	r11,	r0	;
	...
  92:	01 00       	mova	@r0,	r1	;
  94:	5e 00       	rrcm	#1,	r14	;
  96:	00 00       	beq			
  98:	00 00       	beq			
  9a:	00 00       	beq			
  9c:	00 01       	bra	@r1		;
  9e:	00 5b       	add	r11,	r0	;
	...
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:31
  b0:	01 00       	mova	@r0,	r1	;
  b2:	5c 00       	rrcm	#1,	r12	;
  b4:	00 00       	beq			
  b6:	00 00       	beq			
  b8:	00 00       	beq			
  ba:	00 04       	bra	@r4		;
  bc:	00 f3       	and	#0,	r0	;r3 As==00
  be:	01 5c       	add	r12,	r1	;
  c0:	9f 00 00 00 	cmpa	#0,	r15	;
	...
  d0:	00 01       	bra	@r1		;
  d2:	00 5c       	add	r12,	r0	;
	...
  dc:	03 00       	mova	@r0,	r3	;
  de:	7c 7c       	subc.b	@r12+,	r12	;
  e0:	9f 00 00 00 	cmpa	#0,	r15	;
  e4:	00 00       	beq			
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:33
  e6:	00 00       	beq			
  e8:	00 04       	bra	@r4		;
  ea:	00 f3       	and	#0,	r0	;r3 As==00
  ec:	01 5c       	add	r12,	r1	;
  ee:	9f 00 00 00 	cmpa	#0,	r15	;
  f2:	00 00       	beq			
  f4:	00 00       	beq			
	...

Disassembly of section .debug_aranges:

00000000 <.debug_aranges>:
qfree():
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:15
   0:	1c 00       	mova	@r0+,	r12	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:23
   2:	00 00       	beq			
   4:	02 00       	mova	@r0,	r2	;
   6:	00 00       	beq			
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25
   8:	00 00       	beq			
   a:	04 00       	mova	@r0,	r4	;
	...

Disassembly of section .debug_line:

00000000 <L0>:
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:15
   0:	e0 00       	adda	r0,	r0	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:23
   2:	00 00       	beq			
   4:	02 00       	mova	@r0,	r2	;
   6:	20 00 00 00 	bra	&0		;

0000000a <L0>:
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25
   a:	01 01       	mova	@r1,	r1	;
   c:	fb 0e       	suba	r14,	r11	;
   e:	0d 00       	mova	@r0,	r13	;
  10:	01 01       	mova	@r1,	r1	;
  12:	01 01       	mova	@r1,	r1	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25 (discriminator 1)
  14:	00 00       	beq			
  16:	00 01       	bra	@r1		;
  18:	00 00       	beq			
  1a:	01 00       	mova	@r0,	r1	;
  1c:	65 78       	subc.b	@r8,	r5	;
  1e:	74 72       	subc.b	#8,	r4	;r2 As==11
  20:	61 63       	addc.b	#2,	r1	;r3 As==10
  22:	74 2e       	jc	$-790    	;abs 0xfffffd0c
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:26
  24:	63 00 00 00 	mova	r0,	&196608	; 0x30000
  28:	00 00       	beq			
  2a:	00 05       	bra	@r5		;
  2c:	02 00       	mova	@r0,	r2	;
  2e:	00 00       	beq			
  30:	00 03       	bra	@r3		;
  32:	0e 01       	mova	@r1,	r14	;
  34:	03 08       	mova	@r8,	r3	;
  36:	09 00       	mova	@r0,	r9	;
  38:	00 01       	bra	@r1		;
  3a:	03 02       	mova	@r2,	r3	;
  3c:	09 00       	mova	@r0,	r9	;
  3e:	00 01       	bra	@r1		;
  40:	00 02       	bra	@r2		;
  42:	04 01       	mova	@r1,	r4	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:28
  44:	06 03       	mova	@r3,	r6	;
  46:	00 09       	bra	@r9		;
  48:	00 00       	beq			
  4a:	01 06       	mova	@r6,	r1	;
  4c:	03 01       	mova	@r1,	r3	;
  4e:	09 00       	mova	@r0,	r9	;
  50:	00 01       	bra	@r1		;
  52:	03 02       	mova	@r2,	r3	;
  54:	09 00       	mova	@r0,	r9	;
  56:	00 01       	bra	@r1		;
  58:	03 01       	mova	@r1,	r3	;
  5a:	09 00       	mova	@r0,	r9	;
  5c:	00 01       	bra	@r1		;
  5e:	03 02       	mova	@r2,	r3	;
  60:	09 00       	mova	@r0,	r9	;
  62:	00 01       	bra	@r1		;
  64:	03 02       	mova	@r2,	r3	;
  66:	09 00       	mova	@r0,	r9	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:29
  68:	00 01       	bra	@r1		;
  6a:	03 01       	mova	@r1,	r3	;
  6c:	09 00       	mova	@r0,	r9	;
  6e:	00 01       	bra	@r1		;
  70:	00 02       	bra	@r2		;
  72:	04 02       	mova	@r2,	r4	;
  74:	03 77       	.word	0x7703;	????
  76:	09 00       	mova	@r0,	r9	;
  78:	00 01       	bra	@r1		;
  7a:	03 14       	pushm.a	#1,	r3	;20-bit words
  7c:	09 00       	mova	@r0,	r9	;
  7e:	00 01       	bra	@r1		;
  80:	03 7f       	.word	0x7f03;	????
  82:	09 00       	mova	@r0,	r9	;
  84:	00 01       	bra	@r1		;
initializer():
  86:	00 02       	bra	@r2		;
  88:	04 01       	mova	@r1,	r4	;
  8a:	03 7f       	.word	0x7f03;	????
  8c:	09 00       	mova	@r0,	r9	;
  8e:	00 01       	bra	@r1		;
  90:	03 05       	mova	@r5,	r3	;
  92:	09 00       	mova	@r0,	r9	;
  94:	00 01       	bra	@r1		;
  96:	03 01       	mova	@r1,	r3	;
  98:	09 00       	mova	@r0,	r9	;
  9a:	00 01       	bra	@r1		;
  9c:	03 01       	mova	@r1,	r3	;
  9e:	09 00       	mova	@r0,	r9	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:31
  a0:	00 01       	bra	@r1		;
  a2:	03 02       	mova	@r2,	r3	;
  a4:	09 00       	mova	@r0,	r9	;
  a6:	00 01       	bra	@r1		;
  a8:	03 02       	mova	@r2,	r3	;
  aa:	09 00       	mova	@r0,	r9	;
  ac:	00 01       	bra	@r1		;
  ae:	03 01       	mova	@r1,	r3	;
  b0:	09 00       	mova	@r0,	r9	;
  b2:	00 01       	bra	@r1		;
  b4:	03 01       	mova	@r1,	r3	;
  b6:	09 00       	mova	@r0,	r9	;
  b8:	00 01       	bra	@r1		;
  ba:	03 02       	mova	@r2,	r3	;
  bc:	09 00       	mova	@r0,	r9	;
  be:	00 01       	bra	@r1		;
  c0:	03 01       	mova	@r1,	r3	;
  c2:	09 00       	mova	@r0,	r9	;
  c4:	00 01       	bra	@r1		;
  c6:	03 01       	mova	@r1,	r3	;
  c8:	09 00       	mova	@r0,	r9	;
  ca:	00 01       	bra	@r1		;
  cc:	03 02       	mova	@r2,	r3	;
  ce:	09 00       	mova	@r0,	r9	;
  d0:	00 01       	bra	@r1		;
  d2:	03 02       	mova	@r2,	r3	;
  d4:	09 00       	mova	@r0,	r9	;
  d6:	00 01       	bra	@r1		;
  d8:	03 01       	mova	@r1,	r3	;
  da:	09 00       	mova	@r0,	r9	;
  dc:	00 01       	bra	@r1		;
  de:	09 02       	mova	@r2,	r9	;
  e0:	00 00       	beq			
  e2:	01 01       	mova	@r1,	r1	;

Disassembly of section .debug_str:

00000000 <.debug_str>:
qfree():
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:15
   0:	65 78       	subc.b	@r8,	r5	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:23
   2:	74 72       	subc.b	#8,	r4	;r2 As==11
   4:	61 63       	addc.b	#2,	r1	;r3 As==10
   6:	74 2e       	jc	$-790    	;abs 0xfffffcf0
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25
   8:	63 00 75 6e 	mova	r0,	&224885	; 0x36e75
   c:	73 69       	.word	0x6973;	????
   e:	67 6e       	addc.b	@r14,	r7	;
  10:	65 64       	addc.b	@r4,	r5	;
  12:	20 69       	addc	@r9,	r0	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25 (discriminator 1)
  14:	6e 74       	subc.b	@r4,	r14	;
  16:	00 63       	adc	r0		;
  18:	68 75       	subc.b	@r5,	r8	;
  1a:	6e 6b       	addc.b	@r11,	r14	;
  1c:	00 47       	br	r7		;
  1e:	4e 55       	add.b	r5,	r14	;
  20:	20 43       	br	#2		;r3 As==10
  22:	31 31       	jn	$+612    	;abs 0x286
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:26
  24:	20 35       	jge	$+578    	;abs 0x266
  26:	2e 33       	jn	$-418    	;abs 0xfffffe84
  28:	2e 30       	jn	$+94     	;abs 0x86
  2a:	20 2d       	jc	$+578    	;abs 0x26c
  2c:	67 20       	jnz	$+208    	;abs 0xfc
  2e:	2d 4f       	mov	@r15,	r13	;
  30:	73 00 71 66 	mova	r0,	26225(r3); 0x06671
  34:	72 65       	addc.b	@r5+,	r2	;
  36:	65 00 77 6f 	mova	r0,	&356215	; 0x56f77
  3a:	72 64       	addc.b	@r4+,	r2	;
  3c:	00 69       	addc	r9,	r0	;
  3e:	6e 69       	addc.b	@r9,	r14	;
  40:	74 69       	addc.b	@r9+,	r4	;
  42:	61 6c       	addc.b	@r12,	r1	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:28
  44:	69 7a       	subc.b	@r10,	r9	;
  46:	65 72       	subc.b	#4,	r5	;r2 As==10
  48:	00 6d       	addc	r13,	r0	;
  4a:	70 6f       	addc.b	@r15+,	r0	;
  4c:	6f 6c       	addc.b	@r12,	r15	;
  4e:	73 00 61 64 	mova	r0,	25697(r3); 0x06461
  52:	64 72       	subc.b	#4,	r4	;r2 As==10
  54:	65 73       	subc.b	#2,	r5	;r3 As==10
  56:	73 00 73 65 	mova	r0,	25971(r3); 0x06573
  5a:	63 6f       	.word	0x6f63;	????
  5c:	6e 64       	addc.b	@r4,	r14	;
  5e:	66 72       	subc.b	#4,	r6	;r2 As==10
  60:	65 65       	addc.b	@r5,	r5	;
  62:	72 00 66 72 	mova	r0,	29286(r2); 0x07266
  66:	65 65       	addc.b	@r5,	r5	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:29
  68:	65 72       	subc.b	#4,	r5	;r2 As==10
  6a:	00 43       	clr	r0		;
  6c:	3a 5c       	add	@r12+,	r10	;
  6e:	63 79       	.word	0x7963;	????
  70:	67 77       	subc.b	@r7,	r7	;
  72:	69 6e       	addc.b	@r14,	r9	;
  74:	36 34       	jge	$+110    	;abs 0xe2
  76:	5c 68 6f 6d 	addc.b	28015(r8),r12	;0x06d6f
  7a:	65 5c       	add.b	@r12,	r5	;
  7c:	6e 72       	subc.b	#4,	r14	;r2 As==10
  7e:	69 70       	subc.b	@r0,	r9	;
  80:	67 5c       	add.b	@r12,	r7	;
  82:	53 4f       	.word	0x4f53;	????
  84:	46 54       	add.b	r4,	r6	;
initializer():
  86:	57 41 52 45 	mov.b	17746(r1),r7	;0x04552
  8a:	5c 57 4f 52 	add.b	21071(r7),r12	;0x0524f
  8e:	4b 49       	mov.b	r9,	r11	;
  90:	4e 47       	mov.b	r7,	r14	;
	...

Disassembly of section .comment:

00000000 <.comment>:
qfree():
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:15
   0:	00 47       	br	r7		;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:23
   2:	43 43       	clr.b	r3		;
   4:	3a 20       	jnz	$+118    	;abs 0x7a
   6:	28 53       	incd	r8		;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25
   8:	4f 4d       	mov.b	r13,	r15	;
   a:	4e 49       	mov.b	r9,	r14	;
   c:	55 4d 20 54 	mov.b	21536(r13),r5	;0x05420
  10:	65 63       	addc.b	#2,	r5	;r3 As==10
  12:	68 6e       	addc.b	@r14,	r8	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25 (discriminator 1)
  14:	6f 6c       	addc.b	@r12,	r15	;
  16:	6f 67       	addc.b	@r7,	r15	;
  18:	69 65       	addc.b	@r5,	r9	;
  1a:	73 20       	jnz	$+232    	;abs 0x102
  1c:	4c 69       	addc.b	r9,	r12	;
  1e:	6d 69       	addc.b	@r9,	r13	;
  20:	74 65       	addc.b	@r5+,	r4	;
  22:	64 20       	jnz	$+202    	;abs 0xec
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:26
  24:	2d 20       	jnz	$+92     	;abs 0x80
  26:	6d 73       	subc.b	#2,	r13	;r3 As==10
  28:	70 34       	jge	$+226    	;abs 0x10a
  2a:	33 30       	jn	$+104    	;abs 0x92
  2c:	2d 67       	addc	@r7,	r13	;
  2e:	63 63       	.word	0x6363;	????
  30:	20 35       	jge	$+578    	;abs 0x272
  32:	2e 33       	jn	$-418    	;abs 0xfffffe90
  34:	2e 30       	jn	$+94     	;abs 0x92
  36:	2e 32       	jn	$-930    	;abs 0xfffffc94
  38:	31 39       	jl	$+612    	;abs 0x29c
  3a:	29 20       	jnz	$+84     	;abs 0x8e
  3c:	35 2e       	jc	$-916    	;abs 0xfffffca8
  3e:	33 2e       	jc	$-920    	;abs 0xfffffca6
  40:	30 00 00 00 	Address 0x00000042 is out of bounds.
bra	-1(r0)		;PC rel. 0x00041

Disassembly of section .MSP430.attributes:

00000000 <.MSP430.attributes>:
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:15
   0:	41 16       	popm.a	#5,	r5	;20-bit words
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:23
   2:	00 00       	beq			
   4:	00 6d       	addc	r13,	r0	;
   6:	73 70       	.word	0x7073;	????
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25
   8:	61 62       	addc.b	#4,	r1	;r2 As==10
   a:	69 00 01 0b 	mova	r0,	&592641	; 0x90b01
   e:	00 00       	beq			
  10:	00 04       	bra	@r4		;
  12:	02 06       	mova	@r6,	r2	;
C:\cygwin64\home\nripg\SOFTWARE\WORKING/extract.c:25 (discriminator 1)
  14:	01 08       	mova	@r8,	r1	;
  16:	01 00       	Address 0x00000016 is out of bounds.
.word	0xffff;	????

  • Thank you for notifying us of this problem.  I put in a request to the MSP430 GCC experts.

    Thanks and regards,

    -George

  • Hi Pawel,

    Thanks for providing a simplified test case!

    If I understand correctly, you have a function named  qfree that iterates over a data structure twice (I refer to that data structure as  data herein).  data is accessed via  mpools.  mpools is a pointer, its value is the address of  data. The value of  mpools is fixed within  qfree(): The only place that changes the value of mpools is  initializer(), nothing else has a statement like  mpools = foo.

    You've asserted that R14 holds the value of chunk, but it looks to me like R13 is generally being used to represent chunk in the first loop:

    .L2: /* First Loop */
            CMP.W   #0, R13 { JEQ   .L6 /* Check if chunk != NULL */
            MOV.W   -2(R13), R15        /* Put m_size (chunk) in R15 */
            ADD.W   #1, R15             /* R15 is now m_size (chunk) + m_hdrlen */
            ADD.W   R15, R15            /* R15 is now 2 * (m_size (chunk) + m_hdrlen), because chunk is an (int *); sizeof(int) == 2. */
            ADD.W   R13, R15            /* Add chunk to what's in R15 */
            MOV.W   @R13, R9            /* Put m_nextp(chunk) in R9 */
            CMP.W   R15, R12 { JNE  .L3 /* Compare R15 to ch */
            ...
    

    In your annotated disassembly you ask about the value of R14. At the start of  qfree, we see R14 being initialized with the value of  mpools (the address of  data)first part of data:

      MOV.W  &mpools, R11
      MOV.W  @R11, R14
    

    You asked "What is in r14 now??? It is used here as chunk, but it is never initialized for the second loop!!!". After its initialization at the start of the function, R14 isn't modified until the body of the second loop is executed, so after your question R14 still contains the address first part of  data.

    You went on to say, "Here is actually where the second loop is entered with r14 left as it was at the end of the first loop!", but as R14 isn't modified by the first loop: it's value at the end of the first loop is the same as its value at the start of the first loop (the address of  data).

    Based on the above, I don't see anything wrong with the compiler output. Have I missed something?

    As an aside, and for the benefit of others reading this, I find the assembly file produced by  gcc -S ..., easier to read that the  msp430-elf-objdump output.

    Hope this helps,

    Joe

    EDIT: corrected based on Pawel's response. Changes in bold.

  • gcc -S -fverbose-asm is even more useful - it includes useful comments denoting the mapping between variables, temporary variables etc, and also shows the .loc information so you can relate instructions back to source line numbers. I'd strongly recommend using it to understand the source/asm correlation.

  • Hello Joe,

    Sorry, I have been away for a while. Yes, you are right that R13 is used in the loop for chunk, but R14 is where the value in R13 is initialized from (mpools [MA_NP]). When you get to the second loop, at .L6, R14 is assumed to still hold exactly the same value of mpools [MA_NP] (thus assumed to represent chunk). Apparently, it hasn't changed when you just look at the code. But it did! It changed implicitly in the first loop, because it was pointed to by one of the links processed in there. This is why the program executes incorrectly. You cannot assume at the entrance to the second loop that mpools [MA_NP] is exactly as it was in front of the first loop, and this is what the compiler does.

    Cheers!

    Pawel
  • Hello Joe,

    This is me again. Thank you so much for looking at it for me. Yesterday I only had a minute, so let me elaborate a bit more on this today. First of all, even if I am seeing things, the program executes differently with the volatile keyword included (correctly in the latter case). The problem can be explained most succinctly as follows. Following Dave's advice, I have compiled this with

    msp430-elf-gcc -Os -g -S -fverbose-asm extract.c

    so my references are to that output.

    The two loops have identical envelopes. R14 is set before the first loop (at .LVL1) to keep the contents of the memory word at mpools [MA_NP] (R11 contains the address of that location, representing cc). Forget what happens inside the loops. Look immediately at the front of the second loop (at .L6), At this point R14 hasn't been re-assigned since its first assignment at..LVL1  (it only ever changes inside the body of the second loop at .LVL10, and never in the first loop). But the memory location at mpools [MA_NP] may have changed inside the first loop (m_setnextp (cc, m_nextp (chunk) does exactly that on occasion). The code comes from the memory allocator in my OS (where it has remained untouched for ca. 14 years) and handles a rather straightforward linked list where a link may point to the head forcing its overwrite.

    So the second loop is not initialized correctly (from where I am standing).

    Cheers!

    Pawel

  • Ah... that explains it. Your code is to blame, using "cc" the way you do results in undefined behavior. The compiler may ignore any assignment through type-punned pointers. Here's a good explanation: blog.qt.io/.../

  • Thanks Markus!

    Yeah, -fno-strict-aliasing does take care of it. Had I seen a warning, I would have stopped to think about it. There is no warning, though, when you compile the piece. I do agree that the code (with its intended semantics) is not too friendly from the viewpoint of optimization (or maybe the other way around), and I can understand an option to do unsafe optimization that assumes strict aliasing, but having strict aliasing by default did catch me by surprise (haven't been reading the news in this area for a longish while).

    Incidentally, the problem (probably) would not occur, if I stuck to char* as my "address" type (which, of course, should be the case), but the code is an old port from one eCOG1 (which probably nobody here ever heard about), where char* was longer than word* and alias-incompatible at the hardware level ;-).

    A bit less incidentally, I was afraid that when I compile the whole thing with -fno-strict-aliasing -Os, I would get larger code. Well, it is basically the same size, slightly shorter in fact:

    strict-aliasing:
    .text 0x49fe 0x44b0

    no-strict-aliasing:
    .text 0x49f2 0x44b0

    (no change in other sections). So much for unsafe optimization. BTW: version 5.3.0 of the GCC compiler (by TI) generates significantly longer code than the last community edition (4.6.3) (by about 25%).

    Thanks again!

    Pawel
  • Just curious: Did you use the -Wstrict-aliasing or -Wall flag? GCC will usually catch these aliasing problems.
  • > Yes, you are right that R13 is used in the loop for chunk, but R14 is where
    > the value in R13 is initialized from (mpools [MA_NP]).

    Sorry, you're right. I'll annotate my original response with that correction.

    > The program executes differently with the volatile keyword included
    > (correctly in the latter case).

    The volatile qualifier indicates that an object "may be modified in ways
    unknown to the implementation or have other unknown side effects". The standard
    offers "a memory-mapped input/output port or an object accessed by an
    asynchronously interrupting function", as examples. As a result, "Actions on
    objects so declared shall not be 'optimized out'".

    As Markus points out, your code is modifying an object in a manner that is
    unexpected by the compiler, violating assumptions the compiler makes about
    whether or not that object has changed. Marking that object as volatile tells
    the compiler that it cannot make these assumptions, although it would usually
    be preferable to adjust the code to avoid the undefined behavior.
  • Neither of them produces a smidge of a warning.