I'm compiling a program using the sqlite3 libary in Linux(centos7_64). As the user has an old CPU, I set the -march=nehalem flag in GCC (-march=nehalem -mtune=nehalem -m64 -O3). I find I can't limit the assembly instructions to nehalem, some BMI operations still exist in the final binary.
Follow the output step by step, I find the problem comes from the linker (ld).
libsqlite3.a:
632c2: 66 41 83 4f 26 01 orw $0x1,0x26(%r15)
632c8: 0f b6 84 24 80 00 00 movzbl 0x80(%rsp),%eax
632cf: 00
632d0: c1 e0 08 shl $0x8,%eax
632d3: 89 c2 mov %eax,%edx
632d5: 0f b6 84 24 81 00 00 movzbl 0x81(%rsp),%eax
632dc: 00
632dd: c1 e0 10 shl $0x10,%eax
632e0: 09 d0 or %edx,%eax
632e2: 8d 90 00 fe ff ff lea -0x200(%rax),%edx
632e8: 41 89 47 30 mov %eax,0x30(%r15)
632ec: 81 fa 00 fe 00 00 cmp $0xfe00,%edx
632f2: 0f 87 d1 05 00 00 ja 638c9 <sqlite3BtreeOpen+0xb29>
632f8: 8d 50 ff lea -0x1(%rax),%edx
632fb: 85 c2 test %eax,%edx
632fd: 0f 85 c6 05 00 00 jne 638c9 <sqlite3BtreeOpen+0xb29>
However, in the final binary:
9499f2: 66 41 83 4f 26 01 orw $0x1,0x26(%r15)
9499f8: 0f b6 84 24 80 00 00 movzbl 0x80(%rsp),%eax
9499ff: 00
949a00: 0f b6 94 24 81 00 00 movzbl 0x81(%rsp),%edx
949a07: 00
949a08: c1 e0 08 shl $0x8,%eax
949a0b: 89 c1 mov %eax,%ecx
949a0d: 89 d0 mov %edx,%eax
949a0f: c1 e0 10 shl $0x10,%eax
949a12: 09 c8 or %ecx,%eax
949a14: 8d 90 00 fe ff ff lea -0x200(%rax),%edx
949a1a: 41 89 47 30 mov %eax,0x30(%r15)
949a1e: 81 fa 00 fe 00 00 cmp $0xfe00,%edx
949a24: 0f 87 cf 05 00 00 ja 949ff9 <sqlite3BtreeOpen+0xb09>
949a2a: c4 e2 78 f3 c8 blsr %eax,%eax
949a2f: 85 c0 test %eax,%eax
949a31: 0f 85 c2 05 00 00 jne 949ff9 <sqlite3BtreeOpen+0xb09>
Notice the last few lines, the linker changed the lea to blsr, which is unexpected.
Thus, why will this happen. Will the linker (ld) optimize the code further? How to limit the instrutions for the linker to use?