Qing Zhao <qing.z...@oracle.com> writes: >> On Sep 23, 2020, at 6:05 AM, Richard Sandiford <richard.sandif...@arm.com> >> wrote: >> >> Qing Zhao <qing.z...@oracle.com <mailto:qing.z...@oracle.com>> writes: >>>> On Sep 22, 2020, at 12:06 PM, Richard Sandiford >>>> <richard.sandif...@arm.com> wrote: >>>>>>> >>>>>>> The following is what I see from i386.md: (I didn’t look at how >>>>>>> “UNSPEC_volatile” is used in data flow analysis in GCC yet) >>>>>>> >>>>>>> ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers >>>>>>> and >>>>>>> ;; all of memory. This blocks insns from being moved across this point. >>>>>> >>>>>> Heh, it looks like that comment dates back to 1994. :-) >>>>>> >>>>>> The comment is no longer correct though. I wasn't around at the time, >>>>>> but I assume the comment was only locally true even then. >>>>>> >>>>>> If what the comment said was true, then something like: >>>>>> >>>>>> (define_insn "cld" >>>>>> [(unspec_volatile [(const_int 0)] UNSPECV_CLD)] >>>>>> "" >>>>>> "cld" >>>>>> [(set_attr "length" "1") >>>>>> (set_attr "length_immediate" "0") >>>>>> (set_attr "modrm" "0")]) >>>>>> >>>>>> would invalidate the entire register file and so would require all values >>>>>> to be spilt to the stack around the CLD. >>>>> >>>>> Okay, thanks for the info. >>>>> then, what’s the current definition of UNSPEC_VOLATILE? >>>> >>>> I'm not sure it's written down anywhere TBH. rtl.texi just says: >>>> >>>> @code{unspec_volatile} is used for volatile operations and operations >>>> that may trap; @code{unspec} is used for other operations. >>>> >>>> which seems like a cyclic definition: volatile expressions are defined >>>> to be expressions that are volatile. >>>> >>>> But IMO the semantics are that unspec_volatile patterns with a given >>>> set of inputs and outputs act for dataflow purposes like volatile asms >>>> with the same inputs and outputs. The semantics of asm volatile are >>>> at least slightly more well-defined (if only by example); see extend.texi >>>> for details. In particular: >>>> >>>> Note that the compiler can move even @code{volatile asm} instructions >>>> relative >>>> to other code, including across jump instructions. For example, on many >>>> targets there is a system register that controls the rounding mode of >>>> floating-point operations. Setting it with a @code{volatile asm} statement, >>>> as in the following PowerPC example, does not work reliably. >>>> >>>> @example >>>> asm volatile("mtfsf 255, %0" : : "f" (fpenv)); >>>> sum = x + y; >>>> @end example >>>> >>>> The compiler may move the addition back before the @code{volatile asm} >>>> statement. To make it work as expected, add an artificial dependency to >>>> the @code{asm} by referencing a variable in the subsequent code, for >>>> example: >>>> >>>> @example >>>> asm volatile ("mtfsf 255,%1" : "=X" (sum) : "f" (fpenv)); >>>> sum = x + y; >>>> @end example >>>> >>>> which is very similar to the unspec_volatile case we're talking about. >>>> >>>> To take an x86 example: >>>> >>>> void >>>> f (char *x) >>>> { >>>> asm volatile (""); >>>> x[0] = 0; >>>> asm volatile (""); >>>> x[1] = 0; >>>> asm volatile (""); >>>> } >>> >>> If we change the above as the following: (but it might not correct on the >>> asm format): >>> >>> Void >>> F (char *x) >>> { >>> asm volatile (“x[0]”); >>> x[0] = 0; >>> asm volatile (“x[1]"); >>> x[1] = 0; >>> asm volatile ("”); >>> } >>> >>> Will the moving and merging be blocked? >> >> That would stop assignments moving up, but it wouldn't stop x[0] moving >> down across the x[1] asm. Using: >> >> asm volatile ("" ::: "memory"); >> >> would prevent moves in both directions, which was what I meant in my >> later comment about memory clobbers. >> >> In each case, the same would be true for unspec_volatile. > > So, is the following good enough: > > asm volatile (reg1, reg2, … regN, memory) > mov reg1, 0 > mov reg2, 0 > ... > mov regN,0 > asm volatile (reg1, reg2,… regN, memory) > return > > > I.e, just add one “asm volatile” insn whose operands include all registers > and memory BEFORE and AFTER the whole zeroing sequence.
It isn't clear from your syntax whether the asm volatile arguments are uses or clobbers. The idea was: - There would be an asm volatile before the moves that clobbers (but does not use) (mem:BLK (scratch)) and the zeroed registers. - EPILOGUE_USES would make the zeroed registers live after the return. > Or, we have to add one “asm volatile” insn before and after each “mov” insn? No, the idea with the multiple clobber thing was to have a single asm. >>> If we use “ASM_OPERANDS” instead of “UNSPEXC_VOLATILE” as you suggested, >>> the data flow analysis should automatically pick up the operands of >>> “ASM_OPERANDS”, and fix the data flow, right? >> >> Using a volatile asm or an unspec_volatile would be equally correct. >> The reason for preferring a volatile asm is that it doesn't require >> target-specific .md patterns. > Okay. > > Then is there any benefit to use “UNSPEC_volatile” over “volatile asm”? In general, yes: you can use the full .md functionality with unspec_volatiles, such as splitting insns, adding match_scratches with different clobber requirements, writing custom output code, setting attributes, etc. But there isn't an advantage to using unspec_volatile in this case, where the instruction doesn't actually do anything. >> Of course, as mentioned before, “correct” in this case is: make a good >> but not foolproof attempt at trying to prevent later passes from moving >> the zeroing instructions further away from the return instruction >> (or, equivalently, moving other instructions closer to the return >> instruction). Remember that we arrived here from a discussion about >> whether the volatile insns would be enough to prevent machine_reorg and >> other passes from moving instructions around (modulo bugs in those passes). >> My position was that the volatile insns would help, but that we might >> still find cases where a machine_reorg makes a behaviourally-correct >> transformation that we don't want. > So, you mean after adding “volatile asm” or “UNSPEC_volatile”, although > most of the insn movement can be prevented, there might still be small > possibitly > Some unwanted transformation might happen? I wouldn't want to quantify the possibility. The point is just that the possibility exists. The unspec_volatile does not prevent movement of unrelated non-volatile operations. Thanks, Richard