I have one problem and two options for its solution:
• I can make a simple pass which will specify the subtarget instruction set (ARM or Thumb) for a particular instruction (or a basic block) LLVM intermediate representation
• I can add a special pass to arm backend which will do the same (specify subtarget instruction set (ARM or Thumb) for a particular instruction or basic block LLVM intermediate representation)
Can you tell me which way is easier and describe to me how to code it?
What are you trying to do? There's not much that really needs to switch modes in normal operation. The big one is floating point on pre-ARMv7 devices (Thumb1 mode). The typical answer for those situations is to use helper-functions in the compiler runtime library to perform those operations.
The ARM backend currently considers the sub-target to be a per-translation-unit option. There's some basic bits in place that anticipate supporting switching on a per-function basis, but that's pretty hit and miss. There's no support at all for doing it on a block by block basis, and it would likely be a very significant undertaking to implement such a feature. It would also significantly complicate the back end, so there would need to be a pretty compelling argument for doing that.
That said, if you really need something more general, there are options. Considering that a mode switch is performed by branch instructions, the code that needs a mode switch could be extracted out into a separate function. Then the call/return instructions handle the mode switch just like normal interworking. Getting something like that working would involve two steps:
1) Get per-function subtarget selection working in the ARM backend.
I suspect this will not be too horrible, as things are done on a function-by-function basis already. There will need to be some re-initialization of back end bits, but it shouldn't be too horrible. Perhaps try adding function-attributes in the front end to specify "thumb" or "arm" mode. That will give you a way to test the ability of the back end to handle switching back and forth between arm and thumb, and is a useful feature in and of itself.
2) Write a pass to factor out the bits of IR you want to in ARM mode from your functions.
How difficult this is will depend entirely on the specifics of your problem. It could be quite straightforward or rather difficult. For example, if you want to use custom calling conventions for the factored functions to reduce overhead, things get a bit tougher. I would suggest researching "Code factoring" and "procedural abstraction" for some background reading on this sort of thing.