Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit136ab7c

Browse files
committed
Marginal improvement for generated code in execExprInterp.c.
Avoid the coding pattern "*op->resvalue = f();", as some compilers thinkthat requires them to evaluate "op->resvalue" before the function call.Unless there are lots of free registers, this can lead to a uselessregister spill and reload across the call.I changed all the cases like this in ExecInterpExpr(), but didn't botherin the out-of-line opcode eval subroutines, since those are presumablynot as performance-critical.Discussion:https://postgr.es/m/2508.1506630094@sss.pgh.pa.us
1 parent5373bc2 commit136ab7c

File tree

1 file changed

+42
-17
lines changed

1 file changed

+42
-17
lines changed

‎src/backend/executor/execExprInterp.c

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -501,47 +501,53 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
501501
EEO_CASE(EEOP_INNER_SYSVAR)
502502
{
503503
intattnum=op->d.var.attnum;
504+
Datumd;
504505

505506
/* these asserts must match defenses in slot_getattr */
506507
Assert(innerslot->tts_tuple!=NULL);
507508
Assert(innerslot->tts_tuple!=&(innerslot->tts_minhdr));
508-
/* heap_getsysattr has sufficient defenses against bad attnums */
509509

510-
*op->resvalue=heap_getsysattr(innerslot->tts_tuple,attnum,
511-
innerslot->tts_tupleDescriptor,
512-
op->resnull);
510+
/* heap_getsysattr has sufficient defenses against bad attnums */
511+
d=heap_getsysattr(innerslot->tts_tuple,attnum,
512+
innerslot->tts_tupleDescriptor,
513+
op->resnull);
514+
*op->resvalue=d;
513515

514516
EEO_NEXT();
515517
}
516518

517519
EEO_CASE(EEOP_OUTER_SYSVAR)
518520
{
519521
intattnum=op->d.var.attnum;
522+
Datumd;
520523

521524
/* these asserts must match defenses in slot_getattr */
522525
Assert(outerslot->tts_tuple!=NULL);
523526
Assert(outerslot->tts_tuple!=&(outerslot->tts_minhdr));
524527

525528
/* heap_getsysattr has sufficient defenses against bad attnums */
526-
*op->resvalue=heap_getsysattr(outerslot->tts_tuple,attnum,
527-
outerslot->tts_tupleDescriptor,
528-
op->resnull);
529+
d=heap_getsysattr(outerslot->tts_tuple,attnum,
530+
outerslot->tts_tupleDescriptor,
531+
op->resnull);
532+
*op->resvalue=d;
529533

530534
EEO_NEXT();
531535
}
532536

533537
EEO_CASE(EEOP_SCAN_SYSVAR)
534538
{
535539
intattnum=op->d.var.attnum;
540+
Datumd;
536541

537542
/* these asserts must match defenses in slot_getattr */
538543
Assert(scanslot->tts_tuple!=NULL);
539544
Assert(scanslot->tts_tuple!=&(scanslot->tts_minhdr));
540-
/* heap_getsysattr has sufficient defenses against bad attnums */
541545

542-
*op->resvalue=heap_getsysattr(scanslot->tts_tuple,attnum,
543-
scanslot->tts_tupleDescriptor,
544-
op->resnull);
546+
/* heap_getsysattr has sufficient defenses against bad attnums */
547+
d=heap_getsysattr(scanslot->tts_tuple,attnum,
548+
scanslot->tts_tupleDescriptor,
549+
op->resnull);
550+
*op->resvalue=d;
545551

546552
EEO_NEXT();
547553
}
@@ -641,13 +647,22 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
641647
* As both STRICT checks and function-usage are noticeable performance
642648
* wise, and function calls are a very hot-path (they also back
643649
* operators!), it's worth having so many separate opcodes.
650+
*
651+
* Note: the reason for using a temporary variable "d", here and in
652+
* other places, is that some compilers think "*op->resvalue = f();"
653+
* requires them to evaluate op->resvalue into a register before
654+
* calling f(), just in case f() is able to modify op->resvalue
655+
* somehow. The extra line of code can save a useless register spill
656+
* and reload across the function call.
644657
*/
645658
EEO_CASE(EEOP_FUNCEXPR)
646659
{
647660
FunctionCallInfofcinfo=op->d.func.fcinfo_data;
661+
Datumd;
648662

649663
fcinfo->isnull= false;
650-
*op->resvalue=op->d.func.fn_addr(fcinfo);
664+
d=op->d.func.fn_addr(fcinfo);
665+
*op->resvalue=d;
651666
*op->resnull=fcinfo->isnull;
652667

653668
EEO_NEXT();
@@ -658,6 +673,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
658673
FunctionCallInfofcinfo=op->d.func.fcinfo_data;
659674
bool*argnull=fcinfo->argnull;
660675
intargno;
676+
Datumd;
661677

662678
/* strict function, so check for NULL args */
663679
for (argno=0;argno<op->d.func.nargs;argno++)
@@ -669,7 +685,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
669685
}
670686
}
671687
fcinfo->isnull= false;
672-
*op->resvalue=op->d.func.fn_addr(fcinfo);
688+
d=op->d.func.fn_addr(fcinfo);
689+
*op->resvalue=d;
673690
*op->resnull=fcinfo->isnull;
674691

675692
strictfail:
@@ -680,11 +697,13 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
680697
{
681698
FunctionCallInfofcinfo=op->d.func.fcinfo_data;
682699
PgStat_FunctionCallUsagefcusage;
700+
Datumd;
683701

684702
pgstat_init_function_usage(fcinfo,&fcusage);
685703

686704
fcinfo->isnull= false;
687-
*op->resvalue=op->d.func.fn_addr(fcinfo);
705+
d=op->d.func.fn_addr(fcinfo);
706+
*op->resvalue=d;
688707
*op->resnull=fcinfo->isnull;
689708

690709
pgstat_end_function_usage(&fcusage, true);
@@ -698,6 +717,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
698717
PgStat_FunctionCallUsagefcusage;
699718
bool*argnull=fcinfo->argnull;
700719
intargno;
720+
Datumd;
701721

702722
/* strict function, so check for NULL args */
703723
for (argno=0;argno<op->d.func.nargs;argno++)
@@ -712,7 +732,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
712732
pgstat_init_function_usage(fcinfo,&fcusage);
713733

714734
fcinfo->isnull= false;
715-
*op->resvalue=op->d.func.fn_addr(fcinfo);
735+
d=op->d.func.fn_addr(fcinfo);
736+
*op->resvalue=d;
716737
*op->resnull=fcinfo->isnull;
717738

718739
pgstat_end_function_usage(&fcusage, true);
@@ -1113,14 +1134,16 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
11131134
if (!op->d.iocoerce.finfo_in->fn_strict||str!=NULL)
11141135
{
11151136
FunctionCallInfofcinfo_in;
1137+
Datumd;
11161138

11171139
fcinfo_in=op->d.iocoerce.fcinfo_data_in;
11181140
fcinfo_in->arg[0]=PointerGetDatum(str);
11191141
fcinfo_in->argnull[0]=*op->resnull;
11201142
/* second and third arguments are already set up */
11211143

11221144
fcinfo_in->isnull= false;
1123-
*op->resvalue=FunctionCallInvoke(fcinfo_in);
1145+
d=FunctionCallInvoke(fcinfo_in);
1146+
*op->resvalue=d;
11241147

11251148
/* Should get null result if and only if str is NULL */
11261149
if (str==NULL)
@@ -1268,6 +1291,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
12681291
EEO_CASE(EEOP_ROWCOMPARE_STEP)
12691292
{
12701293
FunctionCallInfofcinfo=op->d.rowcompare_step.fcinfo_data;
1294+
Datumd;
12711295

12721296
/* force NULL result if strict fn and NULL input */
12731297
if (op->d.rowcompare_step.finfo->fn_strict&&
@@ -1279,7 +1303,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
12791303

12801304
/* Apply comparison function */
12811305
fcinfo->isnull= false;
1282-
*op->resvalue=op->d.rowcompare_step.fn_addr(fcinfo);
1306+
d=op->d.rowcompare_step.fn_addr(fcinfo);
1307+
*op->resvalue=d;
12831308

12841309
/* force NULL result if NULL function result */
12851310
if (fcinfo->isnull)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp