@@ -501,47 +501,53 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
501501 EEO_CASE (EEOP_INNER_SYSVAR )
502502 {
503503 int attnum = op -> d .var .attnum ;
504+ Datum d ;
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 int attnum = op -> d .var .attnum ;
522+ Datum d ;
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 int attnum = op -> d .var .attnum ;
540+ Datum d ;
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 FunctionCallInfo fcinfo = op -> d .func .fcinfo_data ;
661+ Datum d ;
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 FunctionCallInfo fcinfo = op -> d .func .fcinfo_data ;
659674 bool * argnull = fcinfo -> argnull ;
660675 int argno ;
676+ Datum d ;
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 FunctionCallInfo fcinfo = op -> d .func .fcinfo_data ;
682699 PgStat_FunctionCallUsage fcusage ;
700+ Datum d ;
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_FunctionCallUsage fcusage ;
699718 bool * argnull = fcinfo -> argnull ;
700719 int argno ;
720+ Datum d ;
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 FunctionCallInfo fcinfo_in ;
1137+ Datum d ;
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 FunctionCallInfo fcinfo = op -> d .rowcompare_step .fcinfo_data ;
1294+ Datum d ;
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