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_contents,will 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.
figure 32: orignal Rtx object of register to memory
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].
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.