LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 16572 - thumb generates mov lr,pc
Summary: thumb generates mov lr,pc
Status: RESOLVED INVALID
Alias: None
Product: new-bugs
Classification: Unclassified
Component: new bugs (show other bugs)
Version: unspecified
Hardware: PC Linux
: P normal
Assignee: Unassigned LLVM Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-07-09 09:49 PDT by dwelch
Modified: 2013-07-09 10:27 PDT (History)
2 users (show)

See Also:
Fixed By Commit(s):


Attachments
picojpeg.c code generates this backend problem. (62.94 KB, text/x-csrc)
2013-07-09 09:49 PDT, dwelch
Details

Note You need to log in before you can comment on or make changes to this bug.
Description dwelch 2013-07-09 09:49:10 PDT
Created attachment 10841 [details]
picojpeg.c code generates this backend problem.

While compiling the open source picojpeg code with llvm 3.3 it generates code like this

	mov	lr, pc
	bx	r6

In thumb mode, and the code it is calling with the bx has code that uses this

push {...,lr}
pop {...,pc}

Which is just bad form, a bx should be used (pop {rn}; bx rn) not pop {pc}, in either case the lr does not have the lsbit set, because mov lr,pc does not set the lsbit (the pc does not have the lsbit set in thumb mode it is stripped by bl,bx,blx) so when it returns after this combination

	mov	lr, pc
	bx	r6
        ;returns here ideally

which is thumb code, if the processor is a cortex-m then it is game over because you tried to switch to arm mode (in that case I would hope to see an exception, but didnt test it there), if it is not a cortex-m then it returns in arm mode and tries to execute the thumb instructions as arm instructions and unpredictable results will occur.

Naturally with more code in the project, and llvm-linking the project and optimizing the whole thing the problem can move around but the attached code with this makefile generates the mov lr,pc with clang+llvm 3.3


OOPS = -std-compile-opts -strip-debug -disable-simplify-libcalls
LOPS = -Wall -m32 -emit-llvm 
LLCOPS = -march=thumb -disable-simplify-libcalls 

picojpeg.s : picojpeg.c
	clang $(LOPS) -c picojpeg.c -o picojpeg.bc
	opt $(OOPS) picojpeg.bc -o picojpeg.opt.bc
	llc $(LLCOPS) picojpeg.opt.bc -o picojpeg.s
Comment 1 dwelch 2013-07-09 10:06:50 PDT
From the ARM ARM

The general-purpose registers loaded can include the PC. If they do, the word  loaded for the PC is treated as an address and a branch occurs to that address. In ARMv5 and above, bit[0] of the loaded value determines whether execution continues after this branch in ARM state or in Thumb state, as though the following instruction had been executed:

BX (loaded_value)

In T variants of ARMv4, bit[0] of the loaded value is ignored and execution continues in Thumb state, as though the following instruction had been executed:

MOV PC,(loaded_value)


So replacing pop {pc} with a bx is only needed on ARMv4T I guess.  I was using my instruction set simulator when I detected this and then verified the problem on an ARMv6
Comment 2 dwelch 2013-07-09 10:27:22 PDT
Okay, I see this is valid armv4t code.  adding mcpu=something changes the code generation.