SystemZ intrinsics definitions / memory flags

Hi,

I would like some help on how to change some SystemZ intrinsics (memory) flags that are wrong. Currently MIs are forced to have known wrong flags because they have an intrinsic in their pattern that demands the instruction to also have the same flag. The problem is that I couldn't figure out how to change the intrinsic flags...

* This intrinsic only stores and does not load:

def int_s390_tbegin : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty],
[IntrNoDuplicate]>;

 let mayLoad = 1 in  // WRONG: does not load
   def TBEGINC : SideEffectBinarySIL&lt;&quot;tbeginc&quot;, 0xE561,
                                     int\_s390\_tbeginc, imm32zx16&gt;;

I tried doing [IntrNoDuplicate, WriteOnly<0>], but found that for some reason that didn't work as I had hoped for.

* Similarly,

def int_s390_ntstg : Intrinsic<, [llvm_i64_ty, llvm_ptr64_ty],
[IntrArgMemOnly]>;

does not load, but the using instruction must have the mayLoad flag set. Again, WriteOnly<1> does not work.

* This intrinsic:

def int_s390_tabort : Intrinsic<, [llvm_i64_ty],
[IntrNoReturn, Throws]>;

should have just the hasSideEffects=1 on the instruction, but per the above intrinsic definition, both mayLoad and mayStore flags are required on the MI.

* These two set/read the FP control register, and both have reg-reg/mem-reg variants. So EFPC and SFPC actually do not touch memory at all:

def int_s390_sfpc : GCCBuiltin<"__builtin_s390_sfpc">,
Intrinsic<, [llvm_i32_ty], >;
def int_s390_efpc : GCCBuiltin<"__builtin_s390_efpc">,
Intrinsic<[llvm_i32_ty], , >;

let mayLoad = 1, mayStore = 1 in {
def EFPC : InherentRRE<"efpc", 0xB38C, GR32, int_s390_efpc>; // no-mem
def STFPC : StoreInherentS<"stfpc", 0xB29C, storei<int_s390_efpc>, 4>; // stores

def SFPC : SideEffectUnaryRRE&lt;&quot;sfpc&quot;, 0xB384, GR32, int\_s390\_sfpc&gt;;      // no\-mem
def LFPC : SideEffectUnaryS&lt;&quot;lfpc&quot;, 0xB29D, loadu&lt;int\_s390\_sfpc&gt;, 4&gt;;&gt;;  // loads

}

Is the proper solution in this case to make a duplicate version for each intrinsic that does not touch memory?

Any suggestions welcome,

/Jonas

>
> def int_s390_tbegin : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty,
> llvm_i32_ty],
> [IntrNoDuplicate]>;
>
> let mayLoad = 1 in // WRONG: does not load
> def TBEGINC : SideEffectBinarySIL<"tbeginc", 0xE561,
> int_s390_tbeginc, imm32zx16>;
>
> I tried doing [IntrNoDuplicate, WriteOnly<0>], but found that for some
> reason that didn't work as I had hoped for.

Hmm. While there is a comment by Richard further down in the file:

// In fact write-only but there's no property
// for that.

it seems this may no longer be true. Looking at Intrinsics.td, I now see:

// IntrWriteMem - This intrinsic only writes to memory, but does not read from
// memory, and has no other side effects. This means dead stores before calls
// to this intrinsics may be removed.
def IntrWriteMem : IntrinsicProperty;

``
> * Similarly,
>
> def int_s390_ntstg : Intrinsic<[], [llvm_i64_ty, llvm_ptr64_ty],
> [IntrArgMemOnly]>;
>
> does not load, but the using instruction must have the mayLoad flag set.
> Again, WriteOnly<1> does not work.
>
> * This intrinsic:
>
> def int_s390_tabort : Intrinsic<[], [llvm_i64_ty],
> [IntrNoReturn, Throws]>;
>
> should have just the hasSideEffects=1 on the instruction, but per the
> above intrinsic definition, both mayLoad and mayStore flags are required
> on the MI.

What about using IntrNoMem plus IntrHasSideEffects ?

``
> * These two set/read the FP control register, and both have
> reg-reg/mem-reg variants. So EFPC and SFPC actually do not touch memory
> at all:
>
> def int_s390_sfpc : GCCBuiltin<"__builtin_s390_sfpc">,
> Intrinsic<[], [llvm_i32_ty], []>;
> def int_s390_efpc : GCCBuiltin<"__builtin_s390_efpc">,
> Intrinsic<[llvm_i32_ty], [], []>;
>
> let mayLoad = 1, mayStore = 1 in {
> def EFPC : InherentRRE<"efpc", 0xB38C, GR32,
> int_s390_efpc>; // no-mem
> def STFPC : StoreInherentS<"stfpc", 0xB29C, storei<int_s390_efpc>,
> 4>; // stores
>
> def SFPC : SideEffectUnaryRRE<"sfpc", 0xB384, GR32,
> int_s390_sfpc>; // no-mem
> def LFPC : SideEffectUnaryS<"lfpc", 0xB29D, loadu<int_s390_sfpc>,
> 4>;>; // loads
> }
>
> Is the proper solution in this case to make a duplicate version for each
> intrinsic that does not touch memory?

I'd just use IntrNoMem here. The variants that match the mem-reg cases
will have both the intrinsic and a load/store node in the DAG, and will
inherit the mayLoad / mayStore property from the latter node.

Bye,
Ulrich