[PATCH] D78494: [AMDGPU][CODEGEN] Added 'A' constraint for inline assembler

Dmitry Preobrazhensky via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 20 10:22:54 PDT 2020


dp marked 6 inline comments as done.
dp added inline comments.


================
Comment at: llvm/lib/Target/AMDGPU/SIISelLowering.cpp:10735
+    } else if (BuildVectorSDNode *V = dyn_cast<BuildVectorSDNode>(Op)) {
+      if (Size != 16 || Op.getNumOperands() != 2)
+        return;
----------------
arsenm wrote:
> dp wrote:
> > Should we enforce this limitation? GCC seems to allow arbitrary vector size and type provided that all elements are equal and may be inlined.
> You mean it also accepts <4 x i8> because it's a 32-bit type?
I was wrong about GCC 'vectors'. Looks like they are not regular types and used only for auto-vectorization.

Here is the GCC implementation:


```
(define_constraint "A"
  "Inline immediate parameter"
  (and (match_code "const_int,const_double,const_vector")
       (match_test "gcn_inline_constant_p (op)")))

...

bool
gcn_inline_constant_p (rtx x)
{
  if (GET_CODE (x) == CONST_INT)
    return INTVAL (x) >= -16 && INTVAL (x) <= 64;
  if (GET_CODE (x) == CONST_DOUBLE)
    return gcn_inline_fp_constant_p (x, false);
  if (GET_CODE (x) == CONST_VECTOR)
    {
      int n;
      if (!vgpr_vector_mode_p (GET_MODE (x)))
	return false;
      n = gcn_inline_constant_p (CONST_VECTOR_ELT (x, 0));
      if (!n)
	return false;
      for (int i = 1; i < 64; i++)
	if (CONST_VECTOR_ELT (x, i) != CONST_VECTOR_ELT (x, 0))
	  return false;
      return 1;
    }
  return false;
}

...

inline bool
vgpr_vector_mode_p (machine_mode mode)
{
  return (mode == V64QImode || mode == V64HImode
	  || mode == V64SImode || mode == V64DImode
	  || mode == V64HFmode || mode == V64SFmode || mode == V64DFmode);
}

```


================
Comment at: llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp:1429-1431
+  if ((Size == 16 && Val == 0x3118) ||
+      (Size == 32 && Val == 0x3e22f983))
+    return 0x3fc45f306dc9c882;
----------------
arsenm wrote:
> Logic doesn't make sense here? Returns the 64-bit value if it's 16 or 32?
When working on this fix I was under an impression that types of values passed to inline assembler are not required to match instruction operand types. In other words, I assumed that the following code is legal:


```
"v_mov_b32 $0, $1", "=v,A"(half 0xH3C00) // 1.0h
```

Also I assumed that this code required a type conversion to end up as "v_mov_b32 ..., 1.0" and not "v_mov_b32 ..., 0x3C00" because in the latter case the constant cannot be encoded as inline value.

That assumption complicated implementation. Was the assumption incorrect?

If types of values passed to inline assembler are required to match types of corresponding assembler operands, the implementation would be much simpler.



================
Comment at: llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp:1434-1443
+  if (Size < 64) {
+    bool Lost;
+    const fltSemantics *FltSemantics =
+      (Size == 16) ? &APFloat::IEEEhalf() : &APFloat::IEEEsingle();
+    APFloat FPLiteral(*FltSemantics, APInt(Size, Val));
+    FPLiteral.convert(APFloat::IEEEdouble(),
+                      APFloat::rmNearestTiesToEven,
----------------
arsenm wrote:
> I wouldn't expect any FP rounding in the assembler
See my comments above.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78494/new/

https://reviews.llvm.org/D78494





More information about the llvm-commits mailing list