Skip to content

Commit aa12cdc

Browse files
author
Ard Biesheuvel
committed
Improve x86 inline assembler
- added cc annotation to inline asm that clobbers the condition flags - remove hardcoded constants (IS_LONG,IS_DOUBLE) - remove hardcoded offsets (zval->value, zval->type)
1 parent 5bfdf4f commit aa12cdc

File tree

2 files changed

+65
-37
lines changed

2 files changed

+65
-37
lines changed

Zend/zend_alloc.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -667,12 +667,12 @@ static inline unsigned int zend_mm_high_bit(size_t _size)
667667
#if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
668668
unsigned int n;
669669

670-
__asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm" (_size));
670+
__asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm" (_size) : "cc");
671671
return n;
672672
#elif defined(__GNUC__) && defined(__x86_64__)
673673
unsigned long n;
674674

675-
__asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm" (_size));
675+
__asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm" (_size) : "cc");
676676
return (unsigned int)n;
677677
#elif defined(_MSC_VER) && defined(_M_IX86)
678678
__asm {
@@ -693,17 +693,17 @@ static inline unsigned int zend_mm_low_bit(size_t _size)
693693
#if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
694694
unsigned int n;
695695

696-
__asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm" (_size));
696+
__asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm" (_size) : "cc");
697697
return n;
698698
#elif defined(__GNUC__) && defined(__x86_64__)
699699
unsigned long n;
700700

701-
__asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm" (_size));
701+
__asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm" (_size) : "cc");
702702
return (unsigned int)n;
703703
#elif defined(_MSC_VER) && defined(_M_IX86)
704704
__asm {
705705
bsf eax, _size
706-
}
706+
}
707707
#else
708708
static const int offset[16] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
709709
unsigned int n;

Zend/zend_operators.h

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,10 @@ ZEND_API void zend_update_current_locale(void);
477477
#define zend_update_current_locale()
478478
#endif
479479

480+
/* The offset in bytes between the value and type fields of a zval */
481+
#define ZVAL_OFFSETOF_TYPE \
482+
(__builtin_offsetof(zval,type) - __builtin_offsetof(zval,value))
483+
480484
static zend_always_inline int fast_increment_function(zval *op1)
481485
{
482486
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
@@ -486,20 +490,26 @@ static zend_always_inline int fast_increment_function(zval *op1)
486490
"jno 0f\n\t"
487491
"movl $0x0, (%0)\n\t"
488492
"movl $0x41e00000, 0x4(%0)\n\t"
489-
"movb $0x2,0xc(%0)\n"
493+
"movb %1, %c2(%0)\n"
490494
"0:"
491495
:
492-
: "r"(op1));
496+
: "r"(&op1->value),
497+
"n"(IS_DOUBLE),
498+
"n"(ZVAL_OFFSETOF_TYPE)
499+
: "cc");
493500
#elif defined(__GNUC__) && defined(__x86_64__)
494501
__asm__(
495502
"incq (%0)\n\t"
496503
"jno 0f\n\t"
497504
"movl $0x0, (%0)\n\t"
498505
"movl $0x43e00000, 0x4(%0)\n\t"
499-
"movb $0x2,0x14(%0)\n"
506+
"movb %1, %c2(%0)\n"
500507
"0:"
501508
:
502-
: "r"(op1));
509+
: "r"(&op1->value),
510+
"n"(IS_DOUBLE),
511+
"n"(ZVAL_OFFSETOF_TYPE)
512+
: "cc");
503513
#else
504514
if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MAX)) {
505515
/* switch to double */
@@ -523,20 +533,26 @@ static zend_always_inline int fast_decrement_function(zval *op1)
523533
"jno 0f\n\t"
524534
"movl $0x00200000, (%0)\n\t"
525535
"movl $0xc1e00000, 0x4(%0)\n\t"
526-
"movb $0x2,0xc(%0)\n"
536+
"movb %1,%c2(%0)\n"
527537
"0:"
528538
:
529-
: "r"(op1));
539+
: "r"(&op1->value),
540+
"n"(IS_DOUBLE),
541+
"n"(ZVAL_OFFSETOF_TYPE)
542+
: "cc");
530543
#elif defined(__GNUC__) && defined(__x86_64__)
531544
__asm__(
532545
"decq (%0)\n\t"
533546
"jno 0f\n\t"
534547
"movl $0x00000000, (%0)\n\t"
535548
"movl $0xc3e00000, 0x4(%0)\n\t"
536-
"movb $0x2,0x14(%0)\n"
549+
"movb %1,%c2(%0)\n"
537550
"0:"
538551
:
539-
: "r"(op1));
552+
: "r"(&op1->value),
553+
"n"(IS_DOUBLE),
554+
"n"(ZVAL_OFFSETOF_TYPE)
555+
: "cc");
540556
#else
541557
if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MIN)) {
542558
/* switch to double */
@@ -561,40 +577,46 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o
561577
"addl (%2), %%eax\n\t"
562578
"jo 0f\n\t"
563579
"movl %%eax, (%0)\n\t"
564-
"movb $0x1,0xc(%0)\n\t"
580+
"movb %3, %c5(%0)\n\t"
565581
"jmp 1f\n"
566582
"0:\n\t"
567583
"fildl (%1)\n\t"
568584
"fildl (%2)\n\t"
569585
"faddp %%st, %%st(1)\n\t"
570-
"movb $0x2,0xc(%0)\n\t"
586+
"movb %4, %c5(%0)\n\t"
571587
"fstpl (%0)\n"
572588
"1:"
573589
:
574-
: "r"(result),
575-
"r"(op1),
576-
"r"(op2)
577-
: "eax");
590+
: "r"(&result->value),
591+
"r"(&op1->value),
592+
"r"(&op2->value),
593+
"n"(IS_LONG),
594+
"n"(IS_DOUBLE),
595+
"n"(ZVAL_OFFSETOF_TYPE)
596+
: "eax","cc");
578597
#elif defined(__GNUC__) && defined(__x86_64__)
579598
__asm__(
580599
"movq (%1), %%rax\n\t"
581600
"addq (%2), %%rax\n\t"
582601
"jo 0f\n\t"
583602
"movq %%rax, (%0)\n\t"
584-
"movb $0x1,0x14(%0)\n\t"
603+
"movb %3, %c5(%0)\n\t"
585604
"jmp 1f\n"
586605
"0:\n\t"
587606
"fildq (%1)\n\t"
588607
"fildq (%2)\n\t"
589608
"faddp %%st, %%st(1)\n\t"
590-
"movb $0x2,0x14(%0)\n\t"
609+
"movb %4, %c5(%0)\n\t"
591610
"fstpl (%0)\n"
592611
"1:"
593612
:
594-
: "r"(result),
595-
"r"(op1),
596-
"r"(op2)
597-
: "rax");
613+
: "r"(&result->value),
614+
"r"(&op1->value),
615+
"r"(&op2->value),
616+
"n"(IS_LONG),
617+
"n"(IS_DOUBLE),
618+
"n"(ZVAL_OFFSETOF_TYPE)
619+
: "rax","cc");
598620
#else
599621
Z_LVAL_P(result) = Z_LVAL_P(op1) + Z_LVAL_P(op2);
600622

@@ -636,7 +658,7 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
636658
"subl (%2), %%eax\n\t"
637659
"jo 0f\n\t"
638660
"movl %%eax, (%0)\n\t"
639-
"movb $0x1,0xc(%0)\n\t"
661+
"movb %3, %c5(%0)\n\t"
640662
"jmp 1f\n"
641663
"0:\n\t"
642664
"fildl (%2)\n\t"
@@ -646,21 +668,24 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
646668
#else
647669
"fsubp %%st, %%st(1)\n\t"
648670
#endif
649-
"movb $0x2,0xc(%0)\n\t"
671+
"movb %4, %c5(%0)\n\t"
650672
"fstpl (%0)\n"
651673
"1:"
652674
:
653-
: "r"(result),
654-
"r"(op1),
655-
"r"(op2)
656-
: "eax");
675+
: "r"(&result->value),
676+
"r"(&op1->value),
677+
"r"(&op2->value),
678+
"n"(IS_LONG),
679+
"n"(IS_DOUBLE),
680+
"n"(ZVAL_OFFSETOF_TYPE)
681+
: "eax","cc");
657682
#elif defined(__GNUC__) && defined(__x86_64__)
658683
__asm__(
659684
"movq (%1), %%rax\n\t"
660685
"subq (%2), %%rax\n\t"
661686
"jo 0f\n\t"
662687
"movq %%rax, (%0)\n\t"
663-
"movb $0x1,0x14(%0)\n\t"
688+
"movb %3, %c5(%0)\n\t"
664689
"jmp 1f\n"
665690
"0:\n\t"
666691
"fildq (%2)\n\t"
@@ -670,14 +695,17 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
670695
#else
671696
"fsubp %%st, %%st(1)\n\t"
672697
#endif
673-
"movb $0x2,0x14(%0)\n\t"
698+
"movb %4, %c5(%0)\n\t"
674699
"fstpl (%0)\n"
675700
"1:"
676701
:
677-
: "r"(result),
678-
"r"(op1),
679-
"r"(op2)
680-
: "rax");
702+
: "r"(&result->value),
703+
"r"(&op1->value),
704+
"r"(&op2->value),
705+
"n"(IS_LONG),
706+
"n"(IS_DOUBLE),
707+
"n"(ZVAL_OFFSETOF_TYPE)
708+
: "rax","cc");
681709
#else
682710
Z_LVAL_P(result) = Z_LVAL_P(op1) - Z_LVAL_P(op2);
683711

0 commit comments

Comments
 (0)