Addressing Modes#
This is about addressing modes.
-
HAVE_PRE_INCREMENT#
-
HAVE_PRE_DECREMENT#
-
HAVE_POST_INCREMENT#
-
HAVE_POST_DECREMENT#
A C expression that is nonzero if the machine supports pre-increment, pre-decrement, post-increment, or post-decrement addressing respectively.
-
HAVE_PRE_MODIFY_DISP#
-
HAVE_POST_MODIFY_DISP#
A C expression that is nonzero if the machine supports pre- or post-address side-effect generation involving constants other than the size of the memory operand.
-
HAVE_PRE_MODIFY_REG#
-
HAVE_POST_MODIFY_REG#
A C expression that is nonzero if the machine supports pre- or post-address side-effect generation involving a register displacement.
-
CONSTANT_ADDRESS_P(x)#
A C expression that is 1 if the RTX
x
is a constant which is a valid address. On most machines the default definition of(CONSTANT_P (x) && GET_CODE (x) != CONST_DOUBLE)
is acceptable, but a few machines are more restrictive as to which constant addresses are supported.
-
CONSTANT_P(x)#
CONSTANT_P
, which is defined by target-independent code, accepts integer-values expressions whose values are not explicitly known, such assymbol_ref
,label_ref
, andhigh
expressions andconst
arithmetic expressions, in addition toconst_int
andconst_double
expressions.
-
MAX_REGS_PER_ADDRESS#
A number, the maximum number of registers that can appear in a valid memory address. Note that it is up to you to specify a value equal to the maximum number that
TARGET_LEGITIMATE_ADDRESS_P
would ever accept.
-
bool TARGET_LEGITIMATE_ADDRESS_P(machine_mode mode, rtx x, bool strict)#
A function that returns whether
x
(an RTX) is a legitimate memory address on the target machine for a memory operand of modemode
.Legitimate addresses are defined in two variants: a strict variant and a non-strict one. The
strict
parameter chooses which variant is desired by the caller.The strict variant is used in the reload pass. It must be defined so that any pseudo-register that has not been allocated a hard register is considered a memory reference. This is because in contexts where some kind of register is required, a pseudo-register with no hard register must be rejected. For non-hard registers, the strict variant should look up the
reg_renumber
array; it should then proceed using the hard register number in the array, or treat the pseudo as a memory reference if the array holds-1
.The non-strict variant is used in other passes. It must be defined to accept all pseudo-registers in every context where some kind of register is required.
Normally, constant addresses which are the sum of a
symbol_ref
and an integer are stored inside aconst
RTX to mark them as constant. Therefore, there is no need to recognize such sums specifically as legitimate addresses. Normally you would simply recognize anyconst
as legitimate.Usually
PRINT_OPERAND_ADDRESS
is not prepared to handle constant sums that are not marked withconst
. It assumes that a nakedplus
indicates indexing. If so, then you must reject such naked constant sums as illegitimate addresses, so that none of them will be given toPRINT_OPERAND_ADDRESS
.On some machines, whether a symbolic address is legitimate depends on the section that the address refers to. On these machines, define the target hook
TARGET_ENCODE_SECTION_INFO
to store the information into thesymbol_ref
, and then check for it here. When you see aconst
, you will have to look inside it to find thesymbol_ref
in order to determine the section. See Defining the Output Assembler Language.Some ports are still using a deprecated legacy substitute for this hook, the
GO_IF_LEGITIMATE_ADDRESS
macro. This macro has this syntax:#define GO_IF_LEGITIMATE_ADDRESS (mode, x, label)
and should
goto label
if the addressx
is a valid address on the target machine for a memory operand of modemode
.Compiler source files that want to use the strict variant of this macro define the macro
REG_OK_STRICT
. You should use an#ifdef REG_OK_STRICT
conditional to define the strict variant in that case and the non-strict variant otherwise.Using the hook is usually simpler because it limits the number of files that are recompiled when changes are made.
-
TARGET_MEM_CONSTRAINT#
A single character to be used instead of the default
'm'
character for general memory addresses. This defines the constraint letter which matches the memory addresses accepted byTARGET_LEGITIMATE_ADDRESS_P
. Define this macro if you want to support new address formats in your back end without changing the semantics of the'm'
constraint. This is necessary in order to preserve functionality of inline assembly constructs using the'm'
constraint.
-
FIND_BASE_TERM(x)#
A C expression to determine the base term of address
x
, or to provide a simplified version ofx
from whichalias.cc
can easily find the base term. This macro is used in only two places:find_base_value
andfind_base_term
inalias.cc
.It is always safe for this macro to not be defined. It exists so that alias analysis can understand machine-dependent addresses.
The typical use of this macro is to handle addresses containing a label_ref or symbol_ref within an UNSPEC.
-
rtx TARGET_LEGITIMIZE_ADDRESS(rtx x, rtx oldx, machine_mode mode)#
This hook is given an invalid memory address
x
for an operand of modemode
and should try to return a valid memory address.x
will always be the result of a call tobreak_out_memory_refs
, andoldx
will be the operand that was given to that function to producex
.The code of the hook should not alter the substructure of
x
. If it transformsx
into a more legitimate form, it should return the newx
.It is not necessary for this hook to come up with a legitimate address, with the exception of native TLS addresses (see Emulating TLS). The compiler has standard ways of doing so in all cases. In fact, if the target supports only emulated TLS, it is safe to omit this hook or make it return
x
if it cannot find a valid way to legitimize the address. But often a machine-dependent strategy can generate better code.
-
LEGITIMIZE_RELOAD_ADDRESS(x, mode, opnum, type, ind_levels, win)#
A C compound statement that attempts to replace
x
, which is an address that needs reloading, with a valid memory address for an operand of modemode
.win
will be a C statement label elsewhere in the code. It is not necessary to define this macro, but it might be useful for performance reasons.For example, on the i386, it is sometimes possible to use a single reload register instead of two by reloading a sum of two pseudo registers into a register. On the other hand, for number of RISC processors offsets are limited so that often an intermediate address needs to be generated in order to address a stack slot. By defining
LEGITIMIZE_RELOAD_ADDRESS
appropriately, the intermediate addresses generated for adjacent some stack slots can be made identical, and thus be shared.Note
This macro should be used with caution. It is necessary to know something of how reload works in order to effectively use this, and it is quite easy to produce macros that build in too much knowledge of reload internals.
Note
This macro must be able to reload an address created by a previous invocation of this macro. If it fails to handle such addresses then the compiler may generate incorrect code or abort.
The macro definition should use
push_reload
to indicate parts that need reloading;opnum
,type
andind_levels
are usually suitable to be passed unaltered topush_reload
.The code generated by this macro must not alter the substructure of
x
. If it transformsx
into a more legitimate form, it should assignx
(which will always be a C variable) a new value. This also applies to parts that you change indirectly by callingpush_reload
.The macro definition may use
strict_memory_address_p
to test if the address has become legitimate.If you want to change only a part of
x
, one standard way of doing this is to usecopy_rtx
. Note, however, that it unshares only a single level of rtl. Thus, if the part to be changed is not at the top level, you’ll need to replace first the top level. It is not necessary for this macro to come up with a legitimate address; but often a machine-dependent strategy can generate better code.
-
bool TARGET_MODE_DEPENDENT_ADDRESS_P(const_rtx addr, addr_space_t addrspace)#
This hook returns
true
if memory addressaddr
in address spaceaddrspace
can have different meanings depending on the machine mode of the memory reference it is used for or if the address is valid for some modes but not others.Autoincrement and autodecrement addresses typically have mode-dependent effects because the amount of the increment or decrement is the size of the operand being addressed. Some machines have other mode-dependent addresses. Many RISC machines have no mode-dependent addresses.
You may assume that
addr
is a valid address for the machine.The default version of this hook returns
false
.
-
bool TARGET_LEGITIMATE_CONSTANT_P(machine_mode mode, rtx x)#
This hook returns true if
x
is a legitimate constant for amode
-mode immediate operand on the target machine. You can assume thatx
satisfiesCONSTANT_P
, so you need not check this.The default definition returns true.
-
bool TARGET_PRECOMPUTE_TLS_P(machine_mode mode, rtx x)#
This hook returns true if
x
is a TLS operand on the target machine that should be pre-computed when used as the argument in a call. You can assume thatx
satisfiesCONSTANT_P
, so you need not check this.The default definition returns false.
-
rtx TARGET_DELEGITIMIZE_ADDRESS(rtx x)#
This hook is used to undo the possibly obfuscating effects of the
LEGITIMIZE_ADDRESS
andLEGITIMIZE_RELOAD_ADDRESS
target macros. Some backend implementations of these macros wrap symbol references inside anUNSPEC
rtx to represent PIC or similar addressing modes. This target hook allows GCC’s optimizers to understand the semantics of these opaqueUNSPEC
s by converting them back into their original form.
-
bool TARGET_CONST_NOT_OK_FOR_DEBUG_P(rtx x)#
This hook should return true if
x
should not be emitted into debug sections.
-
bool TARGET_CANNOT_FORCE_CONST_MEM(machine_mode mode, rtx x)#
This hook should return true if
x
is of a form that cannot (or should not) be spilled to the constant pool.mode
is the mode ofx
.The default version of this hook returns false.
The primary reason to define this hook is to prevent reload from deciding that a non-legitimate constant would be better reloaded from the constant pool instead of spilling and reloading a register holding the constant. This restriction is often true of addresses of TLS symbols for various targets.
-
bool TARGET_USE_BLOCKS_FOR_CONSTANT_P(machine_mode mode, const_rtx x)#
This hook should return true if pool entries for constant
x
can be placed in anobject_block
structure.mode
is the mode ofx
.The default version returns false for all constants.
-
bool TARGET_USE_BLOCKS_FOR_DECL_P(const_tree decl)#
This hook should return true if pool entries for
decl
should be placed in anobject_block
structure.The default version returns true for all decls.
-
tree TARGET_BUILTIN_RECIPROCAL(tree fndecl)#
This hook should return the DECL of a function that implements the reciprocal of the machine-specific builtin function
fndecl
, orNULL_TREE
if such a function is not available.
-
tree TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD(void)#
This hook should return the DECL of a function
f
that given an addressaddr
as an argument returns a maskm
that can be used to extract from two vectors the relevant data that resides inaddr
in caseaddr
is not properly aligned.The autovectorizer, when vectorizing a load operation from an address
addr
that may be unaligned, will generate two vector loads from the two aligned addresses aroundaddr
. It then generates aREALIGN_LOAD
operation to extract the relevant data from the two loaded vectors. The first two arguments toREALIGN_LOAD
,v1
andv2
, are the two vectors, each of sizeVS
, and the third argument,OFF
, defines how the data will be extracted from these two vectors: ifOFF
is 0, then the returned vector isv2
; otherwise, the returned vector is composed from the lastVS
-OFF
elements ofv1
concatenated to the firstOFF
elements ofv2
.If this hook is defined, the autovectorizer will generate a call to
f
(using the DECL tree that this hook returns) and will use the return value off
as the argumentOFF
toREALIGN_LOAD
. Therefore, the maskm
returned byf
should comply with the semantics expected byREALIGN_LOAD
described above. If this hook is not defined, thenaddr
will be used as the argumentOFF
toREALIGN_LOAD
, in which case the low log2(VS
) - 1 bits ofaddr
will be considered.
-
int TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST(enum vect_cost_for_stmt type_of_cost, tree vectype, int misalign)#
Returns cost of different scalar or vector statements for vectorization cost model. For vector memory operations the cost may depend on type (
vectype
) and misalignment value (misalign
).
-
poly_uint64 TARGET_VECTORIZE_PREFERRED_VECTOR_ALIGNMENT(const_tree type)#
This hook returns the preferred alignment in bits for accesses to vectors of type
type
in vectorized code. This might be less than or greater than the ABI-defined value returned byTARGET_VECTOR_ALIGNMENT
. It can be equal to the alignment of a single element, in which case the vectorizer will not try to optimize for alignment.The default hook returns
TYPE_ALIGN (type)
, which is correct for most targets.
-
bool TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE(const_tree type, bool is_packed)#
Return true if vector alignment is reachable (by peeling N iterations) for the given scalar type
type
.is_packed
is false if the scalar access usingtype
is known to be naturally aligned.
-
bool TARGET_VECTORIZE_VEC_PERM_CONST(machine_mode mode, machine_mode op_mode, rtx output, rtx in0, rtx in1, const vec_perm_indices &sel)#
This hook is used to test whether the target can permute up to two vectors of mode
op_mode
using the permutation vectorsel
, producing a vector of modemode
. The hook is also used to emit such a permutation.When the hook is being used to test whether the target supports a permutation,
in0
,in1
, andout
are all null. When the hook is being used to emit a permutation,in0
andin1
are the source vectors of modeop_mode
andout
is the destination vector of modemode
.in1
is the same asin0
ifsel
describes a permutation on one vector instead of two.Return true if the operation is possible, emitting instructions for it if rtxes are provided.
If the hook returns false for a mode with multibyte elements, GCC will try the equivalent byte operation. If that also fails, it will try forcing the selector into a register and using the
vec_perm {mode }
instruction pattern. There is no need for the hook to handle these two implementation approaches itself.
-
tree TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION(unsigned code, tree vec_type_out, tree vec_type_in)#
This hook should return the decl of a function that implements the vectorized variant of the function with the
combined_fn
codecode
orNULL_TREE
if such a function is not available. The return type of the vectorized function shall be of vector typevec_type_out
and the argument types should bevec_type_in
.
-
tree TARGET_VECTORIZE_BUILTIN_MD_VECTORIZED_FUNCTION(tree fndecl, tree vec_type_out, tree vec_type_in)#
This hook should return the decl of a function that implements the vectorized variant of target built-in function
fndecl
. The return type of the vectorized function shall be of vector typevec_type_out
and the argument types should bevec_type_in
.
-
bool TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT(machine_mode mode, const_tree type, int misalignment, bool is_packed)#
This hook should return true if the target supports misaligned vector store/load of a specific factor denoted in the
misalignment
parameter. The vector store/load should be of machine modemode
and the elements in the vectors should be of typetype
.is_packed
parameter is true if the memory access is defined in a packed struct.
-
machine_mode TARGET_VECTORIZE_PREFERRED_SIMD_MODE(scalar_mode mode)#
This hook should return the preferred mode for vectorizing scalar mode
mode
. The default is equal toword_mode
, because the vectorizer can do some transformations even in absence of specialized SIMD hardware.
-
machine_mode TARGET_VECTORIZE_SPLIT_REDUCTION(machine_mode)#
This hook should return the preferred mode to split the final reduction step on
mode
to. The reduction is then carried out reducing upper against lower halves of vectors recursively until the specified mode is reached. The default ismode
which means no splitting.
-
unsigned int TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES(vector_modes *modes, bool all)#
If using the mode returned by
TARGET_VECTORIZE_PREFERRED_SIMD_MODE
is not the only approach worth considering, this hook should add one mode tomodes
for each useful alternative approach. These modes are then passed toTARGET_VECTORIZE_RELATED_MODE
to obtain the vector mode for a given element mode.The modes returned in
modes
should use the smallest element mode possible for the vectorization approach that they represent, preferring integer modes over floating-poing modes in the event of a tie. The first mode should be theTARGET_VECTORIZE_PREFERRED_SIMD_MODE
for its element mode.If
all
is true, add suitable vector modes even when they are generally not expected to be worthwhile.The hook returns a bitmask of flags that control how the modes in
modes
are used. The flags are:- VECT_COMPARE_COSTS#
Tells the loop vectorizer to try all the provided modes and pick the one with the lowest cost. By default the vectorizer will choose the first mode that works.
The hook does not need to do anything if the vector returned by
TARGET_VECTORIZE_PREFERRED_SIMD_MODE
is the only one relevant for autovectorization. The default implementation adds no modes and returns 0.
-
opt_machine_mode TARGET_VECTORIZE_RELATED_MODE(machine_mode vector_mode, scalar_mode element_mode, poly_uint64 nunits)#
If a piece of code is using vector mode
vector_mode
and also wants to operate on elements of modeelement_mode
, return the vector mode it should use for those elements. Ifnunits
is nonzero, ensure that the mode has exactlynunits
elements, otherwise pick whichever vector size pairs the most naturally withvector_mode
. Return an emptyopt_machine_mode
if there is no supported vector mode with the required properties.There is no prescribed way of handling the case in which
nunits
is zero. One common choice is to pick a vector mode with the same size asvector_mode
; this is the natural choice if the target has a fixed vector size. Another option is to choose a vector mode with the same number of elements asvector_mode
; this is the natural choice if the target has a fixed number of elements. Alternatively, the hook might choose a middle ground, such as trying to keep the number of elements as similar as possible while applying maximum and minimum vector sizes.The default implementation uses
mode_for_vector
to find the requested mode, returning a mode with the same size asvector_mode
whennunits
is zero. This is the correct behavior for most targets.
-
opt_machine_mode TARGET_VECTORIZE_GET_MASK_MODE(machine_mode mode)#
Return the mode to use for a vector mask that holds one boolean result for each element of vector mode
mode
. The returned mask mode can be a vector of integers (classMODE_VECTOR_INT
), a vector of booleans (classMODE_VECTOR_BOOL
) or a scalar integer (classMODE_INT
). Return an emptyopt_machine_mode
if no such mask mode exists.The default implementation returns a
MODE_VECTOR_INT
with the same size and number of elements asmode
, if such a mode exists.
-
bool TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE(unsigned ifn)#
This hook returns true if masked internal function
ifn
(really of typeinternal_fn
) should be considered expensive when the mask is all zeros. GCC can then try to branch around the instruction instead.
-
class vector_costs *TARGET_VECTORIZE_CREATE_COSTS(vec_info *vinfo, bool costing_for_scalar)#
This hook should initialize target-specific data structures in preparation for modeling the costs of vectorizing a loop or basic block. The default allocates three unsigned integers for accumulating costs for the prologue, body, and epilogue of the loop or basic block. If
loop_info
is non-NULL, it identifies the loop being vectorized; otherwise a single block is being vectorized. Ifcosting_for_scalar
is true, it indicates the current cost model is for the scalar version of a loop or block; otherwise it is for the vector version.
-
tree TARGET_VECTORIZE_BUILTIN_GATHER(const_tree mem_vectype, const_tree index_type, int scale)#
Target builtin that implements vector gather operation.
mem_vectype
is the vector type of the load andindex_type
is scalar type of the index, scaled byscale
. The default isNULL_TREE
which means to not vectorize gather loads.
-
tree TARGET_VECTORIZE_BUILTIN_SCATTER(const_tree vectype, const_tree index_type, int scale)#
Target builtin that implements vector scatter operation.
vectype
is the vector type of the store andindex_type
is scalar type of the index, scaled byscale
. The default isNULL_TREE
which means to not vectorize scatter stores.
-
int TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN(struct cgraph_node*, struct cgraph_simd_clone*, tree, int)#
This hook should set
vecsize_mangle
,vecsize_int
,vecsize_float
fields insimd_clone
structure pointed byclone_info
argument and alsosimdlen
field if it was previously 0.vecsize_mangle
is a marker for the backend only.vecsize_int
andvecsize_float
should be left zero on targets where the number of lanes is not determined by the bitsize (in which casesimdlen
is always used). The hook should return 0 if SIMD clones shouldn’t be emitted, or number ofvecsize_mangle
variants that should be emitted.
-
void TARGET_SIMD_CLONE_ADJUST(struct cgraph_node*)#
This hook should add implicit
attribute(target("..."))
attribute to SIMD clonenode
if needed.
-
int TARGET_SIMD_CLONE_USABLE(struct cgraph_node*)#
This hook should return -1 if SIMD clone
node
shouldn’t be used in vectorized loops in current function, or non-negative number if it is usable. In that case, the smaller the number is, the more desirable it is to use it.
-
int TARGET_SIMT_VF(void)#
Return number of threads in SIMT thread group on the target.
-
int TARGET_OMP_DEVICE_KIND_ARCH_ISA(enum omp_device_kind_arch_isa trait, const char *name)#
Return 1 if
trait
name
is present in the OpenMP context’s device trait set, return 0 if not present in any OpenMP context in the whole translation unit, or -1 if not present in the current OpenMP context but might be present in another OpenMP context in the same TU.
-
bool TARGET_GOACC_VALIDATE_DIMS(tree decl, int *dims, int fn_level, unsigned used)#
This hook should check the launch dimensions provided for an OpenACC compute region, or routine. Defaulted values are represented as -1 and non-constant values as 0. The
fn_level
is negative for the function corresponding to the compute region. For a routine it is the outermost level at which partitioned execution may be spawned. The hook should verify non-default values. If DECL is NULL, global defaults are being validated and unspecified defaults should be filled in. Diagnostics should be issued as appropriate. Return true, if changes have been made. You must override this hook to provide dimensions larger than 1.
-
int TARGET_GOACC_DIM_LIMIT(int axis)#
This hook should return the maximum size of a particular dimension, or zero if unbounded.
-
bool TARGET_GOACC_FORK_JOIN(gcall *call, const int *dims, bool is_fork)#
This hook can be used to convert IFN_GOACC_FORK and IFN_GOACC_JOIN function calls to target-specific gimple, or indicate whether they should be retained. It is executed during the oacc_device_lower pass. It should return true, if the call should be retained. It should return false, if it is to be deleted (either because target-specific gimple has been inserted before it, or there is no need for it). The default hook returns false, if there are no RTL expanders for them.
-
void TARGET_GOACC_REDUCTION(gcall *call)#
This hook is used by the oacc_transform pass to expand calls to the
GOACC_REDUCTION
internal function, into a sequence of gimple instructions.call
is gimple statement containing the call to the function. This hook removes statementcall
after the expanded sequence has been inserted. This hook is also responsible for allocating any storage for reductions when necessary.
-
tree TARGET_PREFERRED_ELSE_VALUE(unsigned ifn, tree type, unsigned nops, tree *ops)#
This hook returns the target’s preferred final argument for a call to conditional internal function
ifn
(really of typeinternal_fn
).type
specifies the return type of the function andops
are the operands to the conditional operation, of which there arenops
.For example, if
ifn
isIFN_COND_ADD
, the hook returns a value of typetype
that should be used whenops[0]
andops[1]
are conditionally added together.This hook is only relevant if the target supports conditional patterns like
cond_addm
. The default implementation returns a zero constant of typetype
.
-
tree TARGET_GOACC_ADJUST_PRIVATE_DECL(location_t loc, tree var, int level)#
This hook, if defined, is used by accelerator target back-ends to adjust OpenACC variable declarations that should be made private to the given parallelism level (i.e.
GOMP_DIM_GANG
,GOMP_DIM_WORKER
orGOMP_DIM_VECTOR
). A typical use for this hook is to force variable declarations at thegang
level to reside in GPU shared memory.loc
may be used for diagnostic purposes.You may also use the
TARGET_GOACC_EXPAND_VAR_DECL
hook if the adjusted variable declaration needs to be expanded to RTL in a non-standard way.
-
rtx TARGET_GOACC_EXPAND_VAR_DECL(tree var)#
This hook, if defined, is used by accelerator target back-ends to expand specially handled kinds of
VAR_DECL
expressions. A particular use is to place variables with specific attributes inside special accelarator memories. A return value ofNULL
indicates that the target does not handle thisVAR_DECL
, and normal RTL expanding is resumed.Only define this hook if your accelerator target needs to expand certain
VAR_DECL
nodes in a way that differs from the default. You can also adjust private variables at OpenACC device-lowering time using theTARGET_GOACC_ADJUST_PRIVATE_DECL
target hook.
-
tree TARGET_GOACC_CREATE_WORKER_BROADCAST_RECORD(tree rec, bool sender, const char *name, unsigned HOST_WIDE_INT offset)#
Create a record used to propagate local-variable state from an active worker to other workers. A possible implementation might adjust the type of REC to place the new variable in shared GPU memory.
Presence of this target hook indicates that middle end neutering/broadcasting be used.
-
void TARGET_GOACC_SHARED_MEM_LAYOUT(unsigned HOST_WIDE_INT*, unsigned HOST_WIDE_INT*, int[], unsigned HOST_WIDE_INT[], unsigned HOST_WIDE_INT[])#
Lay out a fixed shared-memory region on the target. The LO and HI arguments should be set to a range of addresses that can be used for worker broadcasting. The dimensions, reduction size and gang-private size arguments are for the current offload region.