Studying note of GCC-3.4.6 source (50)

4.2.11.      Update information about hard registers used by call

Back to backend_init, if the source is compiled with optimization of the size or with optimization level higher than –O2, flag_caller_saves will be true. Then init_caller_save is invoked. Here we look at all the hard registers that are used by a call and for which regclass.c has not already excluded from being used across a call.

Notice that for this evaluation, it should also be taken within the dummy function context created at section Create dummy function context.

 

111     void

112     init_caller_save (void)                                                                       in caller-save.c

113     {

114       rtx addr_reg;

115       int offset;

116       rtx address;

117       int i, j;

118       enum machine_mode mode;

119       rtx savepat, restpat;

120      rtx test_reg, test_mem;

121      rtx saveinsn, restinsn;

122   

123      /* First find all the registers that we need to deal with and all

124        the modes that they can have. If we can't find a mode to use,

125        we can't have the register live over calls.  */

126   

127      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)

128      {

129        if (call_used_regs[i] && ! call_fixed_regs[i])

130        {

131          for (j = 1; j <= MOVE_MAX_WORDS; j++)

132          {

133            regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j,

134                                                             VOIDmode);

135            if (regno_save_mode[i][j] == VOIDmode && j == 1)

136            {

137              call_fixed_regs[i] = 1;

138              SET_HARD_REG_BIT (call_fixed_reg_set, i);

139            }

140          }

141        }

142        else

143          regno_save_mode[i][1] = VOIDmode;

144    }

 

At line 131, MOVE_MAX_WORDS has definition as.

 

47      #define MOVE_MAX_WORDS (MOVE_MAX / UNITS_PER_WORD)   in caller-save.c

 

MOVE_MAX for x86 machine is defined as 16, it is max number of bytes we can move from memory to memory in one reasonably fast instruction.

 

1137   #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE)/ in i386.h

1138     (CC_REGNO_P (REGNO) ? VOIDmode                                  /

1139      : (MODE) == VOIDmode && (NREGS) != 1 ? VOIDmode                   /

1140      : (MODE) == VOIDmode ? choose_hard_reg_mode ((REGNO), (NREGS), false)/

1141      : (MODE) == HImode && !TARGET_PARTIAL_REG_STALL ? SImode             /

1142      : (MODE) == QImode && (REGNO) >= 4 && !TARGET_64BIT ? SImode        /

1143      : (MODE))

 

HARD_REGNO_CALLER_SAVE_MODE tries to find out mode that will require NREGS consecutive registers having register number of REGNO, and if no such mode, VOIDmode will be returned. The result will be saved at regno_save_mode[REGNO][NREGS]. See that at line 127, the start value of loop control variable j is 1, regno_save_mode[REGNO][0] are never used and always VOIDmode.

We have seen from init_reg_sets_1 and Table 6: register classes for x86 machine, the value at call_fixed_regs[REGNO], if is 1, means the corresponding register is that are fixed use or call used registers that cannot hold quantities across calls even with save and restore. And remember that call_fixed_regs is the subset of call_used_regs which also includes registers that will be clobbered across call. And of which we can use with the aid of save and restore.

After collecting valid modes for different data size, init_caller_save continue to check the conditions under which we can easily save and restore a register without scratching registers or other complexities.

 

init_caller_save (continue)

 

146    /* The following code tries to approximate the conditions under which

147       we can easily save and restore a register without scratch registers or

148       other complexities. It will usually work, except under conditions where

149       the validity of an insn operand is dependent on the address offset.

150       No such cases are currently known.

151   

152       We first find a typical offset from some BASE_REG_CLASS register.

153       This address is chosen by finding the first register in the class

154       and by finding the smallest power of two that is a valid offset from

155       that register in every mode we will use to save registers.  */

156   

157    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)

158       if (TEST_HARD_REG_BIT

159            (reg_class_contents

160            [(int) MODE_BASE_REG_CLASS (regno_save_mode [i][1])], i))

161         break;

162   

163    if (i == FIRST_PSEUDO_REGISTER)

164       abort ();

165   

166    addr_reg = gen_rtx_REG (Pmode, i);

167   

168    for (offset = 1 << (HOST_BITS_PER_INT / 2); offset; offset >>= 1)

169    {

170       address = gen_rtx_PLUS (Pmode, addr_reg, GEN_INT (offset));

171   

172       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)

173         if (regno_save_mode[i][1] != VOIDmode

174                && ! strict_memory_address_p (regno_save_mode[i][1], address))

175           break;

176   

177       if (i == FIRST_PSEUDO_REGISTER)

178         break;

179    }

180   

181    /* If we didn't find a valid address, we must use register indirect.  */

182    if (offset == 0)

183       address = addr_reg;

 

MODE_BASE_REG_CLASS(mode) for x86 machine is just GENERAL_REGS when used as index in reg_class_contentswill return bits representing eax, ebx, ecx, edx, esi, edi, ebp, esp, r8 ~ r15. So for FOR loop at line 157, i = 0 (eax) will exit the loop. And this register is used to hold address at line 166, then at line 170, it further creates address like following figure.

As we have seen above, regno_save_mode[REGNO][1] if isn’t VOIDmode, indicates the mode that one register of REGNO can hold. Then strict_memory_address_p checks if the mode can hold the address. In fact strict_memory_address_p invokes GO_IF_LEGITIMATE_ADDRESS, which in turn invokes legitimate_address_p.

figure 31: Rtx object of Addressing Expression

Go through the legitimate_address_p, we can see base points to REG, disp points to const_int in above figure, the function will check if the register (eax) holding base is valid or not, and if disp is valid. For the address presented in above figure, strict_memory_address_p will return true. Notice that in strict_memory_address_p, modes in regno_save_mode[REGNO][1] is not used in the processing, but only the addressing expression will be evaluated, so in FOR loop at line 172 strict_memory_address_p will run through 0 ~ FIRST_PSEUDO_REGISTER successfully.

 

init_caller_save (continue)

 

185    /* Next we try to form an insn to save and restore the register. We

186       see if such an insn is recognized and meets its constraints.

187   

188       To avoid lots of unnecessary RTL allocation, we construct all the RTL

189       once, then modify the memory and register operands in-place.  */

190   

191    test_reg = gen_rtx_REG (VOIDmode, 0);

192    test_mem = gen_rtx_MEM (VOIDmode, address);

193    savepat = gen_rtx_SET (VOIDmode, test_mem, test_reg);

194    restpat = gen_rtx_SET (VOIDmode, test_reg, test_mem);

195   

196    saveinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, 0, 0, savepat, -1, 0, 0);

197    restinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, 0, 0, restpat, -1, 0, 0);

198   

199    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)

200       for (mode = 0 ; mode < MAX_MACHINE_MODE; mode++)

201         if (HARD_REGNO_MODE_OK (i, mode))

202         {

203           int ok;

204   

205           /* Update the register number and modes of the register

206             and memory operand.  */

207           REGNO (test_reg) = i;

208           PUT_MODE (test_reg, mode);

209           PUT_MODE (test_mem, mode);

210   

211            /* Force re-recognition of the modified insns.  */

212           INSN_CODE (saveinsn) = -1;

213           INSN_CODE (restinsn) = -1;

214   

215           reg_save_code[i][mode] = recog_memoized (saveinsn);

216           reg_restore_code[i][mode] = recog_memoized (restinsn);

217   

218           /* Now extract both insns and see if we can meet their

219             constraints.  */

220           ok = (reg_save_code[i][mode] != -1

221               && reg_restore_code[i][mode] != -1);

222           if (ok)

223           {

224             extract_insn (saveinsn);

225             ok = constrain_operands (1);

226             extract_insn (restinsn);

227             ok &= constrain_operands (1);

228           }

229   

230           if (! ok)

231           {

232             reg_save_code[i][mode] = -1;

233             reg_restore_code[i][mode] = -1;

234           }

235         }

236         else

237         {

238           reg_save_code[i][mode] = -1;

239           reg_restore_code[i][mode] = -1;

240         }

241   

242    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)

243       for (j = 1; j <= MOVE_MAX_WORDS; j++)

244         if (reg_save_code [i][regno_save_mode[i][j]] == -1)

245         {

246           regno_save_mode[i][j] = VOIDmode;

247           if (j == 1)

248           {

249             call_fixed_regs[i] = 1;

250             SET_HARD_REG_BIT (call_fixed_reg_set, i);

251           }

252         }

253    }

 

Next we will only make a register eligible for caller-save if it can be saved in its widest mode with a simple back-end instruction - SET (refer to line 193 & 194) as long as the memory address is valid. INSN_CODE of the instruction is recorded at reg_save_code[REGNO][mode] (if recog_memoized recognizes an instruction, it will return its INSN_CODE), and reg_restore_code[REGNO][mode] since when we emit them, the addresses might not be valid, so they might not be recognized.

To do that, we need create certain rtx object for evaluation. Then, above, at line 196 and 197, gen_rtx_INSN creates two INSN objects as following.

Studying note of GCC-3.4.6 source (50)_第1张图片

 

figure 32: orignal Rtx object of register to memory

Studying note of GCC-3.4.6 source (50)_第2张图片

figure 33: orignal Rtx object of memory to register

The FOR loop at line 199, iterates all available registers and modes to check if saving the content into memory and restoring back from memory is possible or not. Line from 207 to 213, reset register number, mode, and instruction code. Note at line 212 and 213, instruction code is set as -1, which will trigger recog_memoized at line 215 and 216 to invoke recog. This function will return instruction code if it can recognize the INSN object, otherwise -1.

If the specified register and mode is recognized by recog, it then goes to check the validatity of the INSN object from line 224 ~ 227 by extract_insn and constrain_operands. Then at line 242, it updates call_fixed_regs further by reg_save_code[REGNO][1].

 

 

4.2.12.      Clean up dummy function context

Now we finish the initialization of back-end, we need clean up the dummy function context.

 

6861 void

6862 expand_dummy_function_end (void)                                                          in function.c

6863 {

6864   /* End any sequences that failed to be closed due to syntax errors.  */

6865   while (in_sequence_p ())

6866     end_sequence ();

6867

6868   /* Outside function body, can't compute type's actual size

6869     until next function's body starts.  */

6870  

6871     free_after_parsing (cfun);

6872     free_after_compilation (cfun);

6873     cfun = 0;

6874   }

 

free_after_parsing here does nothing, free_after_compilation will reset most fields of cfun.

 

你可能感兴趣的:(function,object,Class,optimization,Parsing,compilation)