%%% section \section{\kcode{ref}, \kcode{val}, \kcode{uval} Modifiers for \kcode{linear} Clause} \label{sec:linear_modifier} \index{modifiers, linear@modifiers, \kcode{linear}!ref@\kcode{ref}} \index{modifiers, linear@modifiers, \kcode{linear}!val@\kcode{val}} \index{modifiers, linear@modifiers, \kcode{linear}!uval@\kcode{uval}} \index{clauses!linear@\kcode{linear}} \index{linear clause@\kcode{linear} clause} When generating vector functions from \kcode{declare simd} directives, it is important for a compiler to know the proper types of function arguments in order to generate efficient codes. This is especially true for C++ reference types and Fortran arguments. In the following example, the function \ucode{add_one2} has a C++ reference parameter (or Fortran argument) \ucode{p}. Variable \ucode{p} gets incremented by 1 in the function. The caller loop \ucode{i} in the main program passes a variable \ucode{k} as a reference to the function \ucode{add_one2} call. The \kcode{ref} modifier for the \kcode{linear} clause on the \kcode{declare simd} directive specifies that the reference-type parameter \ucode{p} is to match the property of the variable \ucode{k} in the loop. This use of reference type is equivalent to the second call to \ucode{add_one2} with a direct passing of the array element \ucode{a[i]}. In the example, the preferred vector length 8 is specified for both the caller loop and the callee function. When \kcode{linear(\ucode{p}: ref)} is applied to an argument passed by reference, it tells the compiler that the addresses in its vector argument are consecutive, and so the compiler can generate a single vector load or store instead of a gather or scatter. This allows more efficient SIMD code to be generated with less source changes. \cppexample[5.2]{linear_modifier}{1} \ffreeexample[5.2]{linear_modifier}{1} %\clearpage The following example is a variant of the above example. The function \ucode{add_one2} in the C++ code includes an additional C++ reference parameter \ucode{i}. The loop index \ucode{i} of the caller loop \ucode{i} in the main program is passed as a reference to the function \ucode{add_one2} call. The loop index \ucode{i} has a uniform address with linear value of step 1 across SIMD lanes. Thus, the \kcode{uval} modifier is used for the \kcode{linear} clause to specify that the C++ reference-type parameter \ucode{i} is to match the property of loop index \ucode{i}. In the corresponding Fortran code the arguments \ucode{p} and \ucode{i} in the routine \ucode{add_on2} are passed by references. Similar modifiers are used for these variables in the \kcode{linear} clauses to match with the property at the caller loop in the main program. When \kcode{linear(\ucode{i}: uval)} is applied to an argument passed by reference, it tells the compiler that its addresses in the vector argument are uniform so that the compiler can generate a scalar load or scalar store and create linear values. This allows more efficient SIMD code to be generated with less source changes. \cppexample[5.2]{linear_modifier}{2} \ffreeexample[5.2]{linear_modifier}{2} In the following example, the function \ucode{func} takes arrays \ucode{x} and \ucode{y} as arguments, and accesses the array elements referenced by the index \ucode{i}. The caller loop \ucode{i} in the main program passes a linear copy of the variable \ucode{k} to the function \ucode{func}. The \kcode{val} modifier is used for the \kcode{linear} clause in the \kcode{declare simd} directive for the function \ucode{func} to specify that the argument \ucode{i} is to match the property of the actual argument \ucode{k} passed in the SIMD loop. Arrays \ucode{x} and \ucode{y} have uniform addresses across SIMD lanes. When \kcode{linear(\ucode{i}: val,step(\ucode{1}))} is applied to an argument, it tells the compiler that its addresses in the vector argument may not be consecutive, however, their values are linear (with stride 1 here). When the value of \ucode{i} is used in subscript of array references (e.g., \ucode{x[i]}), the compiler can generate a vector load or store instead of a gather or scatter. This allows more efficient SIMD code to be generated with less source changes. \cexample[5.2]{linear_modifier}{3} \ffreeexample[5.2]{linear_modifier}{3}