Finding an efficient shift/add/LEA instruction sequence to multiply by a given constant (avoiding MUL/IMUL)

假装没事ソ 提交于 2020-02-24 09:59:45

问题


I'm trying to write a C program mult.c that has a main function that receives 1 int argument (parsed with atoi(argv[1])), that is some constant k we want to multiply by.

This program will generate an assembly file mult.s that implements

int mult(int x) {
   return x * k;
}

for that constant k. (This is a followup to Efficient Assembly multiplication)

For example: if main() in mult.c gets 14 as argument it may generate (though it is not minimal as later emphasized):

.section .text
.globl mult
mult:              # by 14
    movl %edi,%eax         # arg passed in EDI
    shl $3,%eax
    movl %edi,%ecx
    shl $2,%ecx
    addl %ecx,%eax
    movl %edi,%ecx
    shl $1,%ecx
    addl %ecx,%eax
    ret

The assembly function recieves its argument in the %rdi register and returns its result in the %rax register.

I need to consider these following rules:

0) The assembly program should be minimal in terms of lines of code. (Dynamic instruction count). I'll worry about critical path latency later.

  1. if k is 0,1,-1 no need to multiply (obviously) - xor %eax,%eax, mov %edi, %eax, or neg
  2. if k is 3,5,9 I then need to replace the multiplication command in LEA.
  3. if k is 3*2^n, 5*2^n, 9*2^n then I need to replace the multiplication command in LEA and shifting.
  4. all other cases suppose to work also of course.

I'm having trouble with cases 3 and 4.

  1. how can I identify a number is of this structure in my c program?
  2. what do I do with negative numbers?

And a general cases that relates to both, Am I just suppose to mask, add and shift my constant 32 times (the number of bits in an integer)? Is there anything better?

来源:https://stackoverflow.com/questions/59286585/finding-an-efficient-shift-add-lea-instruction-sequence-to-multiply-by-a-given-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!