================
@@ -469,8 +465,28 @@ static mlir::Value emitCommonNeonSISDBuiltinExpr(
   auto [funcResTy, argTypes] = deriveNeonSISDIntrinsicOperandTypes(
       cgf, info.TypeModifier, arg0Ty, resultTy, ops);
 
-  return emitNeonCall(cgf.cgm, builder, std::move(argTypes), ops, llvmIntrName,
-                      funcResTy, loc);
+  // Scalar operands feeding a vector `argType` (e.g. vqsubb_s8, which has no
+  // scalar overload) are splatted into lane 0 of a poison vector.
+  for (unsigned i = 0, e = ops.size(); i != e; ++i) {
+    auto vecArgTy = mlir::dyn_cast<cir::VectorType>(argTypes[i]);
+    if (vecArgTy && !mlir::isa<cir::VectorType>(ops[i].getType()) &&
+        cgf.cgm.getDataLayout().getTypeSizeInBits(ops[i].getType()) !=
+            cgf.cgm.getDataLayout().getTypeSizeInBits(vecArgTy)) {
+      mlir::Value poison =
+          builder.getConstant(loc, cir::PoisonAttr::get(vecArgTy));
+      ops[i] = builder.createInsertElement(loc, poison, ops[i], /*idx=*/0);
+    }
+  }
+
+  mlir::Value result = emitNeonCall(cgf.cgm, builder, std::move(argTypes), ops,
+                                    llvmIntrName, funcResTy, loc);
+
+  // Recover a scalar result from a wider vector intrinsic result via lane 0.
+  if (auto resVecTy = mlir::dyn_cast<cir::VectorType>(result.getType());
+      resVecTy && cgf.cgm.getDataLayout().getTypeSizeInBits(resultTy) <
+                      cgf.cgm.getDataLayout().getTypeSizeInBits(resVecTy))
+    return builder.createExtractElement(loc, result, /*idx=*/0);
+  return result;
----------------
banach-space wrote:

While these changes make sense to me, I find them rather counter-intuitive - 
_why_ do we need `cir.vec.insert` and `cir.vec.extract`? I know that you are 
following ARM.cpp, but that code is also a bit non-intuitive :)

I would add a few more comments. My understanding of what is happening here is 
that:
* An SISD intrinsic is lowered to (and modelled with) a vector builtin, hence 
`cir.vec.insert` and `cir.vec.extract`.

Is this consistent with your understanding? 

Also, an equivalent of the following assert would be helpful: 
https://github.com/llvm/llvm-project/blob/bb6868abb8dd6f8ef7130ed2c81cf538793547c6/clang/lib/CodeGen/TargetBuiltins/ARM.cpp?plain=1#L1099-L1101

[nit] "splat" to me means "broadcast" (i.e. make all vector elements equal). In 
this case, from what I can tell, there is no "splatting" :)

Thank you :)

https://github.com/llvm/llvm-project/pull/207189
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to