다음은 어셈블러에서 내 컴파일러의 일부 출력입니다. GCC v3.23을 기반으로하는 MPLAB C30 C 컴파일러는 dsPIC33FJ128GP802 (16 비트 중간 정도의 고속 DSP/MCU 용)입니다.최적화 버그입니까?
212: inline uint16_t ror_16(uint16_t word, int num)
213: {
078C4 608270 and.w w1,#16,w4
078C6 DE0204 lsr w0,w4,w4
078C8 780101 mov.w w1,w2
078CA EA8102 com.w w2,w2
078CC EA8183 com.w w3,w3
078CE 610170 and.w w2,#16,w2
078D0 DD0002 sl w0,w2,w0
078D2 700004 ior.w w0,w4,w0
214: num &= 16; // limit to 16 shifts
215: return (word >> num) | (word << (16 - num));
216: }
078D4 060000 return
특히 I는 다음의 관심 :
and.w w1,#16,w4 AND W1 with 16, storing result in W4
lsr w0,w4,w4 Logical shift right W0 by W4 times storing result in W4
mov.w w1,w2 Move W1 to W2
com.w w2,w2 Logical complement of W2 stored in W2
com.w w3,w3 Logical complement of W3 stored in W3 <-- This line is confusing me
and.w w2,#16,w2 AND W2 with 16, storing result in W2
sl w0,w2,w0 (Logical) shift left W0 left by W2 times storing result in W0
ior.w w0,w4,w0 Inclusive OR of W0 and W4 stored in W0
return Return from function
W0..W15 칩 16 비트 레지스터에 여섯 배열이다.
효과적으로이 (원시적 RTL에서)로 단순화
W4 := W1 & 16
W4 := W0 LSR W4
W1 := W2
W2 := COM W2
W3 := COM W3
W2 := W2 & 16
W0 := W0 SL W2
W0 := W0 | W4
return
가 지금은 두 전달 된 인수 (W0 및 W1있을 때 왜 W3의 보수를 계산되어에서 혼란 스러워요 -이 사용 더 작은 인수를 갖는 함수에 인수를 함수에 전달하기위한 W 배열.) W3은 계산에 사용되지 않으며 반환되지 않습니다. 실제로 함수에 데이터가 저장되지는 않습니다. 함수에 의해 저장되는 데이터는 없습니다. 함수가 W0..W7을 유지해야 할 필요는 없지만 호출 수신자 만 데이터를 가질 것입니다. 그것에 의존하고 있어야합니다.) 왜 코드에 포함되어 있습니까? 그냥 컴파일러 결함이나 오류, 아니면 내가 뭔가를 놓친거야?
그리고이 코드 만이 아닙니다. 코드의 다른 부분에서 매우 똑같은 이상함을보고 있습니다. 16 비트 변수의 보수와 같은 것을 계산하도록 고안된 코드조차도 항상 두 개의 레지스터를 사용하는 것처럼 보입니다. 그것은 내가 잃어버린있다!
이로이 코드 수 있습니다. 아마도 파이프 라인은 이전 COM의 결과를 사용하기 전에 항상 다른 COM 명령을 실행해야하는 방식으로 작동합니다. –
@Pascal Cuoq이 프로세서에는 이러한 파이프 라인이 없습니다. 어쩌면 2 단계 파이프 라인을 가지고 있기 때문에 (fetch-decode-execute-write RISC주기를 작동시킬 수는 있지만) 이전 지침에 의존하지는 않습니다. 유일한 지연 시간은 분기와 명령어 건너 뛰기에서 비롯됩니다. –
함수의 원래 C 코드를 게시 할 수 있습니까? 16 비트 레지스터 중 16 개가 시프트되면 정말 이상하게 보입니다. – ruslik