GVN-PRE sucks -- well, for SPECCFP2000 mgrid anyway

Steven Bosscher stevenb@suse.de
Sun Aug 15 11:42:00 GMT 2004


Hi,

SPEC2000's mgrid benchmark has typical code fortran that looks
like this:

      DO I3=2,N-1
        DO I2=2,N-1
          DO I1=2,N-1
            R(I1,I2,I3) = V(I1,I2,I3)
     >      -A(0)*( U(I1,  I2,  I3  ) )
     >      -A(1)*( U(I1-1,I2,  I3  ) + U(I1+1,I2,  I3  )
     >                 +  U(I1,  I2-1,I3  ) + U(I1,  I2+1,I3  )
     >                 +  U(I1,  I2,  I3-1) + U(I1,  I2,  I3+1) )
     >      -A(2)*( U(I1-1,I2-1,I3  ) + U(I1+1,I2-1,I3  )
     >                 +  U(I1-1,I2+1,I3  ) + U(I1+1,I2+1,I3  )
     >                 +  U(I1,  I2-1,I3-1) + U(I1,  I2+1,I3-1)
     >                 +  U(I1,  I2-1,I3+1) + U(I1,  I2+1,I3+1)
     >                 +  U(I1-1,I2,  I3-1) + U(I1-1,I2,  I3+1)
     >                 +  U(I1+1,I2,  I3-1) + U(I1+1,I2,  I3+1) )
     >      -A(3)*( U(I1-1,I2-1,I3-1) + U(I1+1,I2-1,I3-1)
     >                 +  U(I1-1,I2+1,I3-1) + U(I1+1,I2+1,I3-1)
     >                 +  U(I1-1,I2-1,I3+1) + U(I1+1,I2-1,I3+1)
     >                 +  U(I1-1,I2+1,I3+1) + U(I1+1,I2+1,I3+1) )
          END DO
        END DO
      END DO

where R,V,A, and U are function arguments and I[123] are loop
counters.

When gfortran flattens the arrays it exposes a lot of redundancies
for address arithmetic, most of which is loop invariant.  So PRE
gets to work, moves everything it can out of the loop, and we get:

  # BLOCK 14
  # PRED: 0 [79.0%]  (false,exec)
<L28>:;
  pretmp.202<D919>_117 = (int8<D8>)2;
  pretmp.204<D921>_475 = stride.10<D458>_28 * pretmp.202<D919>_117;
  # SUCC: 1 [100.0%]  (fallthru)

  # BLOCK 1
  # PRED: 17 [100.0%]  (fallthru) 14 [100.0%]  (fallthru)
  # prephitmp.205<D922>_466 = PHI <T.95<D560>_214(17), pretmp.204<D921>_475(14)>;
  # prephitmp.203<D920>_122 = PHI <T.94<D559>_213(17), pretmp.202<D919>_117(14)>;
  # TMT.201<D892>_425 = PHI <TMT.201<D892>_502(14), TMT.201<D892>_532(17)>;
  # TMT.200<D891>_357 = PHI <TMT.200<D891>_503(14), TMT.200<D891>_531(17)>;
  # i3<D445>_262 = PHI <2(14), T.93<D558>_212(17)>;
  # count.18<D466>_261 = PHI <count.18<D466>_60(14), count.18<D466>_118(17)>;
<L2>:;
  pretmp.206<D923>_465 = pretmp.202<D919>_117;
  pretmp.208<D925>_463 = stride.8<D456>_24 * pretmp.206<D923>_465;
  pretmp.210<D927>_461 = (int8<D8>)i3<D445>_262;
  pretmp.212<D929>_453 = stride.10<D458>_28 * pretmp.210<D927>_461;
  pretmp.214<D931>_451 = pretmp.208<D925>_463 + pretmp.212<D929>_453;
  pretmp.216<D933>_449 = i3<D445>_262 - 1;
  pretmp.218<D935>_447 = (int8<D8>)pretmp.216<D933>_449;
  pretmp.220<D937>_441 = stride.10<D458>_28 * pretmp.218<D935>_447;
  pretmp.222<D939>_411 = pretmp.208<D925>_463 + pretmp.220<D937>_441;
  pretmp.224<D941>_409 = i3<D445>_262 + 1;
  pretmp.226<D943>_403 = (int8<D8>)pretmp.224<D941>_409;
  pretmp.228<D945>_401 = stride.10<D458>_28 * pretmp.226<D943>_403;
  pretmp.230<D947>_399 = pretmp.208<D925>_463 + pretmp.228<D945>_401;
  # SUCC: 2 [100.0%]  (fallthru,exec)

  # BLOCK 2
  # PRED: 16 [100.0%]  (fallthru) 1 [100.0%]  (fallthru,exec)
  # prephitmp.231<D948>_398 = PHI <T.134<D599>_313(16), pretmp.230<D947>_399(1)>;
  # prephitmp.229<D946>_400 = PHI <T.95<D560>_214(16), pretmp.228<D945>_401(1)>;
  # prephitmp.227<D944>_402 = PHI <T.94<D559>_213(16), pretmp.226<D943>_403(1)>;
  # prephitmp.225<D942>_408 = PHI <T.93<D558>_212(16), pretmp.224<D941>_409(1)>;
  # prephitmp.223<D940>_410 = PHI <T.124<D589>_289(16), pretmp.222<D939>_411(1)>;
  # prephitmp.221<D938>_440 = PHI <T.87<D552>_203(16), pretmp.220<D937>_441(1)>;
  # prephitmp.219<D936>_442 = PHI <T.86<D551>_202(16), pretmp.218<D935>_447(1)>;
  # prephitmp.217<D934>_448 = PHI <T.85<D550>_201(16), pretmp.216<D933>_449(1)>;
  # prephitmp.215<D932>_450 = PHI <T.80<D545>_193(16), pretmp.214<D931>_451(1)>;
  # prephitmp.213<D930>_452 = PHI <T.37<D502>_127(16), pretmp.212<D929>_453(1)>;
  # prephitmp.211<D928>_454 = PHI <T.36<D501>_126(16), pretmp.210<D927>_461(1)>;
  # prephitmp.209<D926>_462 = PHI <T.79<D544>_190(16), pretmp.208<D925>_463(1)>;
  # prephitmp.207<D924>_464 = PHI <T.78<D543>_189(16), pretmp.206<D923>_465(1)>;
  # TMT.201<D892>_426 = PHI <TMT.201<D892>_425(1), TMT.201<D892>_532(16)>;
  # TMT.200<D891>_358 = PHI <TMT.200<D891>_357(1), TMT.200<D891>_531(16)>;
  # i2<D447>_242 = PHI <2(1), T.77<D542>_188(16)>;
  # count.18<D466>_241 = PHI <count.18<D466>_60(1), count.18<D466>_123(16)>;
<L4>:;
  pretmp.232<D949>_397 = (int8<D8>)i2<D447>_242;
  pretmp.234<D951>_382 = stride.8<D456>_24 * pretmp.232<D949>_397;
  pretmp.236<D953>_377 = pretmp.210<D927>_461;
  pretmp.238<D955>_375 = prephitmp.205<D922>_466;
  pretmp.240<D957>_373 = pretmp.234<D951>_382 + pretmp.238<D955>_375;
  pretmp.242<D959>_371 = pretmp.206<D923>_465;
  pretmp.244<D961>_347 = pretmp.240<D957>_373 + pretmp.242<D959>_371;
  pretmp.246<D963>_345 = offset.11<D459>_34 + pretmp.244<D961>_347;
  pretmp.248<D965>_343 = i2<D447>_242 - 1;
  pretmp.250<D967>_337 = (int8<D8>)pretmp.248<D965>_343;
  pretmp.252<D969>_335 = stride.8<D456>_24 * pretmp.250<D967>_337;
  pretmp.254<D971>_333 = pretmp.238<D955>_375 + pretmp.252<D969>_335;
  pretmp.256<D973>_314 = pretmp.242<D959>_371 + pretmp.254<D971>_333;
  pretmp.258<D975>_311 = offset.11<D459>_34 + pretmp.256<D973>_314;
  pretmp.260<D977>_309 = i2<D447>_242 + 1;
  pretmp.262<D979>_307 = (int8<D8>)pretmp.260<D977>_309;
  pretmp.264<D981>_300 = stride.8<D456>_24 * pretmp.262<D979>_307;
  pretmp.266<D983>_278 = pretmp.238<D955>_375 + pretmp.264<D981>_300;
  pretmp.268<D985>_275 = pretmp.242<D959>_371 + pretmp.266<D983>_278;
  pretmp.270<D987>_273 = offset.11<D459>_34 + pretmp.268<D985>_275;
  pretmp.272<D989>_271 = pretmp.216<D933>_449;
  pretmp.274<D991>_265 = pretmp.218<D935>_447;
  pretmp.276<D993>_263 = pretmp.220<D937>_441;
  pretmp.278<D995>_259 = pretmp.234<D951>_382 + pretmp.276<D993>_263;
  pretmp.280<D997>_253 = pretmp.242<D959>_371 + pretmp.278<D995>_259;
  pretmp.282<D999>_251 = offset.11<D459>_34 + pretmp.280<D997>_253;
  pretmp.284<D1001>_249 = pretmp.224<D941>_409;
  pretmp.286<D1003>_247 = pretmp.226<D943>_403;
  pretmp.288<D1005>_239 = pretmp.228<D945>_401;
  pretmp.290<D1007>_237 = pretmp.234<D951>_382 + pretmp.288<D1005>_239;
  pretmp.292<D1009>_235 = pretmp.242<D959>_371 + pretmp.290<D1007>_237;
  pretmp.294<D1011>_230 = offset.11<D459>_34 + pretmp.292<D1009>_235;
  pretmp.296<D1013>_228 = pretmp.252<D969>_335 + pretmp.276<D993>_263;
  pretmp.298<D1015>_211 = pretmp.242<D959>_371 + pretmp.296<D1013>_228;
  pretmp.300<D1017>_205 = offset.11<D459>_34 + pretmp.298<D1015>_211;
  pretmp.302<D1019>_500 = pretmp.264<D981>_300 + pretmp.276<D993>_263;
  pretmp.304<D1021>_498 = pretmp.242<D959>_371 + pretmp.302<D1019>_500;
  pretmp.306<D1023>_496 = offset.11<D459>_34 + pretmp.304<D1021>_498;
  pretmp.308<D1025>_494 = pretmp.252<D969>_335 + pretmp.288<D1005>_239;
  pretmp.310<D1027>_492 = pretmp.242<D959>_371 + pretmp.308<D1025>_494;
  pretmp.312<D1029>_490 = offset.11<D459>_34 + pretmp.310<D1027>_492;
  pretmp.314<D1031>_488 = pretmp.264<D981>_300 + pretmp.288<D1005>_239;
  pretmp.316<D1033>_486 = pretmp.242<D959>_371 + pretmp.314<D1031>_488;
  pretmp.318<D1035>_484 = offset.11<D459>_34 + pretmp.316<D1033>_486;
  # SUCC: 3 [100.0%]  (fallthru,exec)

  # BLOCK 3
  # PRED: 15 [100.0%]  (fallthru) 2 [100.0%]  (fallthru,exec)

[ Notice how all this stuff is hoisted even out of the
  outermost loop! ]

Needless to say that on almost any architecture this will cause so
much spilling that PRE severely pessimizes the generated code.  And
indeed, on AMD64, mgrid compiled with -fno-tree-pre is almost twice
as fast as mgrid with PRE enabled.

I guess this is convincing evidence that we need to teach tree PRE
about register pressure, just like tree loop invariant code motion.

Gr.
Steven




More information about the Gcc mailing list