eine gerade oder ungerade Zahl unterscheiden


  • Mod

    Interessant wäre noch, ob Compiler hinreichend intelligent sind, um

    int x = ...;
    int y = ( x % 2 + 2 ) % 2;
    

    zu optimieren.



  • camper schrieb:

    Interessant wäre noch, ob Compiler hinreichend intelligent sind, um

    int x = ...;
    int y = ( x % 2 + 2 ) % 2;
    

    zu optimieren.

    Hoffentlich hab ich alles richtig entziffert.

    movl	$_ZSt3cin, %edi    //&cin laden nach edi
    	leaq	12(%rsp), %rsi     //&x laden nach rsi
    	call	_ZNSirsERi         //op<< aufrufen
    	movl	12(%rsp), %esi     //y=x //also erstmal in ein register tun
    	movl	$_ZSt4cout, %edi   //&cout laden nach edi
    	andl	$1, %esi           //y = ( y % 2 + 2 ) % 2; //optimiert
    	call	_ZNSolsEi          //op>> aufrufen
    

    Da guckstu. Wiedermal der magische gcc.



  • Die Frage ist bei solchen Sachen immer (zumindest für mich), ob da einer aus Langeweile ein spezielles Pattern implementiert hat oder ob das ein allgemeiner Mechanismus ist.



  • Du kannst dich ja in den GCC-Sourcen auf die Suche machen. 😉



  • Bashar schrieb:

    Die Frage ist bei solchen Sachen immer (zumindest für mich), ob da einer aus Langeweile ein spezielles Pattern implementiert hat oder ob das ein allgemeiner Mechanismus ist.

    Da alles konstant ist, kriegt der Compiler das locker mit den allgemeinen Regeln hin. Was für ein spezielles Pattern soll das denn sein?



  • nurf schrieb:

    Da alles konstant ist, kriegt der Compiler das locker mit den allgemeinen Regeln hin.

    x ist nicht konstant. Und so locker kann das nicht sein, der MSVC kann das z.B. nicht.


  • Mod

    Ist leider tatsächlich nur eine spezielle Behandlung für gewisse Zahlen.

    cin >> x;
        int y = ( x % 1000 + 1000 ) % 1000;
        cout << y << '\n';
        int z = (unsigned)x % 1000;
        cout << z << '\n';
    

    führt zu

    call    _ZNSirsERi
            movl    8(%rsp), %esi
            movl    $_ZSt4cout, %edi
            movl    %esi, %eax
            imull   %ebx                   // (1)
            movl    %esi, %eax
            sarl    $31, %eax
            sarl    $6, %edx
            subl    %eax, %edx
            imull   $1000, %edx, %edx
            subl    %edx, %esi
            addl    $1000, %esi
            movl    %esi, %eax
            imull   %ebx                   // (2)
            movl    %esi, %eax
            sarl    $31, %eax
            sarl    $6, %edx
            subl    %eax, %edx
            imull   $1000, %edx, %edx
            subl    %edx, %esi
            call    _ZNSolsEi
            movq    %rbp, %rsi
            movl    $1, %edx
            movq    %rax, %rdi
            movb    $10, 15(%rsp)
            call    _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
            movl    8(%rsp), %esi
            movl    $_ZSt4cout, %edi
            movl    %esi, %eax
            mull    %ebx
            shrl    $6, %edx
            imull   $1000, %edx, %edx
            subl    %edx, %esi
            call    _ZNSolsEi
            movq    %rbp, %rsi
            movl    $1, %edx
            movq    %rax, %rdi
            movb    $10, 15(%rsp)
            call    _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
    

    also 2 Divisionen (durch Multiplikation ersetzt) im ersten Fall.


Anmelden zum Antworten