打印
[开发工具]

STM32 IAR 编译优化问题,奇哉,怪哉!

[复制链接]
1973|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xfiori|  楼主 | 2014-5-5 15:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 xfiori 于 2014-5-5 15:08 编辑

近日开发一个项目,调试的时候好好的,发布的软件确死活不正常,后来一步步看,终于发现是编译器优化造成的,不过为何会优化成这种结果,却百思不得其解啊,望高手指点。

wTemp = MAKEWORD(a,b);
   \   000000B6   ........           LDR.W    R0,??DataTable39_9
   \   000000BA   617B               LDRB     R1,[R4, #+13]
   \   000000BC   227B               LDRB     R2,[R4, #+12]
   \   000000BE   02EB0121           ADD      R1,R2,R1, LSL #+8
   
wTemp = (wTemp>>4) & 0x1FF;
   \   000000C2   CA05               LSLS     R2,R1,#+23
   \   000000C4   D20E               LSRS     R2,R2,#+27
   
c = (uint8_t)(wTemp*50/0x150);
   \   000000C6   3221               MOVS     R1,#+50
   \   000000C8   5143               MULS     R1,R1,R2
   \   000000CA   4FF4A872           MOV      R2,#+336
   \   000000CE   91FBF2F1           SDIV     R1,R1,R2

其中最关键的问题出在第二步,我明明需要先右移4位,然后与0x1FF,这样可以得到高位的内容
而优化后的代码,给我先左移23位,再右移27位,虽然也达到了右移4位的目的,可是我的高位却丢失了,造成结果总是不正确
它实际上已经变成了 wTemp = (wTemp&0x1FF) >> 4;

而我明明是有括号的,甚至于我就算这样写
wTemp = (wTemp&0x1FFF) >> 4;
或者这样写
wTemp = wTemp >> 4;
wTemp &= 0x1FFF;

最后的优化结果也是一样的。。。。。

不知道哪位高人对此有所了解,可以解答我的疑惑呢?
沙发
戈卫东| | 2014-5-5 16:44 | 只看该作者
c = (uint8_t)(wTemp*50/0x150);
问题会不会是出在这里?

使用特权

评论回复
板凳
戈卫东| | 2014-5-5 16:59 | 只看该作者
    tt1 = (tt1>>4) & 0x1FF;
   0x20000458: 0xf3c0 0x1008  UBFX      R0, R0, #4, #9
我这里只有一条指令。。。。。。。

使用特权

评论回复
地板
guet_new_man| | 2014-5-6 01:54 | 只看该作者
wTemp是32位的数据?

使用特权

评论回复
5
liyang121316| | 2014-5-6 07:42 | 只看该作者
优化级别调第一点试试呢

使用特权

评论回复
6
nametony| | 2014-5-6 11:20 | 只看该作者
的确IAR COMPILER有问题! 楼主获得捉虫能手奖.
我把它改为方便测试的形式:
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
uint8_t TestIar1(uint8_t a,uint8_t b)
{
  uint8_t bt;
  unsigned short int w=a*256+b;        //改为uint8_t 或 uint32_t 都OK
  w=(w>>4) & 0x1FF;
  bt=(uint8_t)(w*50/0x150);
  return bt;
}
看LIST:
      1          typedef unsigned char uint8_t;
      2          typedef unsigned int uint32_t;

   \                                 In section .text, align 2, keep-with-next
      3          uint8_t TestIar1(uint8_t a,uint8_t b)
      4          {
      5            uint8_t bt;
      6            unsigned short int w=a*256+b;
      7            w=(w>>4) & 0x1FF;
      8            bt=(uint8_t)(w*50/0x150);
      9            return bt;
   \                     TestIar1:
   \   00000000   01EB0020           ADD      R0,R1,R0, LSL #+8
   \   00000004   C105               LSLS     R1,R0,#+23
   \   00000006   C90E               LSRS     R1,R1,#+27
   \   00000008   3220               MOVS     R0,#+50
   \   0000000A   4843               MULS     R0,R0,R1
   \   0000000C   4FF4A871           MOV      R1,#+336
   \   00000010   90FBF1F0           SDIV     R0,R0,R1
   \   00000014   C0B2               UXTB     R0,R0
   \   00000016   7047               BX       LR               ;; return
     10          }

使用特权

评论回复
7
xfiori|  楼主 | 2014-5-6 12:37 | 只看该作者
guet_new_man 发表于 2014-5-6 01:54
wTemp是32位的数据?

16位的

使用特权

评论回复
8
xfiori|  楼主 | 2014-5-6 12:40 | 只看该作者
nametony 发表于 2014-5-6 11:20
的确IAR COMPILER有问题! 楼主获得捉虫能手奖.
我把它改为方便测试的形式:
unsigned short int w=a*256+b;        //改为uint8_t 或 uint32_t 都OK
; ...


确实,把wTemp更改为32位的可以解决此问题,8位不符合我对变量的需求,不予考虑

问题是,为啥用16位就不正确呢?
我的IAR是6.10的,不知道新的版本是否已经修正了这个BUG呢?

使用特权

评论回复
9
xfiori|  楼主 | 2014-5-6 12:42 | 只看该作者
liyang121316 发表于 2014-5-6 07:42
优化级别调第一点试试呢

调低优化或者不优化肯定是好的,但是没意义啊,我必须要优化,因为代码空间有限

因此必须在优化的情况下解决这个问题

使用特权

评论回复
10
icecut| | 2014-5-6 13:34 | 只看该作者
赞....中奖了.
arm 是32bit处理器.使用32bit类型会达到更好的效果.

使用特权

评论回复
11
guet_new_man| | 2014-5-7 22:04 | 只看该作者
感觉编译器把wTemp当作32位对待了,否则不可能出现左移23位、右移27位的现象,  至于为什么,就不清楚了,我想应该需要了解IAR编译器的优化原理吧。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

13

帖子

0

粉丝