================
@@ -369,12 +369,96 @@ static mlir::Value emitCommonNeonSISDBuiltinExpr(
   case NEON::BI__builtin_neon_vmaxv_f32:
   case NEON::BI__builtin_neon_vmaxvq_f32:
   case NEON::BI__builtin_neon_vmaxvq_f64:
-    return emitNeonCall(cgf.cgm, cgf.getBuilder(),
-                        {cgf.convertType(expr->getArg(0)->getType())}, ops,
-                        llvmIntrName, cgf.convertType(expr->getType()), loc);
+  case NEON::BI__builtin_neon_vsrid_n_s64:
+  case NEON::BI__builtin_neon_vsrid_n_u64:
+    break;
   }
 
-  return nullptr;
+  // Generic handling based on TypeModifier flags, mirroring
+  // EmitCommonNeonSISDBuiltinExpr + LookupNeonLLVMIntrinsic in ARM.cpp.
+  //
+  // The TypeModifier encodes how the intrinsic's argument and return types
+  // relate to the builtin's scalar types. For SISD builtins the key flags
+  // are:
+  //   - VectorizeArgTypes: wrap each arg type into a fixed-width vector
+  //   - Use64BitVectors / Use128BitVectors: choose the vector width
+  //     (when neither is set the vector has 1 element)
+  //   - AddRetType / VectorizeRetType: analogous flags for the return type
+  //
+  // ARM.cpp doesn't need to know about specific builtins like
+  // `vsrid_n_{s,u}64` because it lets LLVM resolve the intrinsic's
+  // signature (via `CGM.getIntrinsic`) and then walks the resolved
+  // Function* formal parameter types. CIR has no LLVMContext here, so
+  // we derive the same argument/result types directly from the Clang
+  // operand types.
+
+  unsigned modifier = info.TypeModifier;
+  CIRGenBuilderTy &builder = cgf.getBuilder();
+  mlir::Type argTy = cgf.convertType(expr->getArg(0)->getType());
+  mlir::Type resultTy = cgf.convertType(expr->getType());
+
+  int vectorSize = 0;
+  if (modifier & Use64BitVectors)
+    vectorSize = 64;
+  else if (modifier & Use128BitVectors)
+    vectorSize = 128;
+
+  auto wrapAsVector = [&](mlir::Type ty) -> cir::VectorType {
+    unsigned bits = cgf.cgm.getDataLayout().getTypeSizeInBits(ty);
+    unsigned elts = vectorSize ? vectorSize / bits : 1;
+    return cir::VectorType::get(ty, elts);
+  };
+
+  // Determine the vectorized data type.
+  cir::VectorType vecArgTy;
+  if (modifier & VectorizeArgTypes)
+    vecArgTy = wrapAsVector(argTy);
+
+  // Determine the intrinsic result type: `VectorizeRetType` returns a
+  // vector; otherwise, if data args are vectorized and `AddRetType` is
+  // unset, use a vector return with the same shape as those args.
+  mlir::Type funcResTy = resultTy;
+  if (modifier & VectorizeRetType)
+    funcResTy = wrapAsVector(resultTy);
+  else if (vecArgTy && !(modifier & AddRetType))
+    funcResTy = wrapAsVector(resultTy);
+
+  // Build the arg types for `emitNeonCall`.
+  llvm::SmallVector<mlir::Type> argTypes;
+  argTypes.reserve(ops.size());
+  for (mlir::Value op : ops) {
+    if (vecArgTy && op.getType() == argTy)
+      argTypes.push_back(vecArgTy);
+    else
+      argTypes.push_back(op.getType());
+  }
----------------
iamvickynguyen wrote:

You're right to question this! It isn't obvious at first glance :smile:

So far, in this PR, only `vsri*` need bitcast. For those, we need to loop 
through all the operands to check the types. `vsri*` has 1 overload knob but 2 
operands of that type, and  both need bitcast.
https://github.com/llvm/llvm-project/blob/e7887d5470e080c55fd69de83786fbf060d3955a/llvm/include/llvm/IR/IntrinsicsAArch64.td#L433-L433

https://github.com/llvm/llvm-project/blob/e7887d5470e080c55fd69de83786fbf060d3955a/llvm/include/llvm/IR/IntrinsicsAArch64.td#L200-L203

If we use `Add1ArgType` / `Add2ArgTypes` like in `ARM.cpp`, only the first 
operand would be bitcast and the second would stay as i64. In `ARM.cpp`, when 
`Add1ArgType` is set, they push `ArgType` once into the overload-type list for 
`getIntrinsic`.
https://github.com/llvm/llvm-project/blob/e7887d5470e080c55fd69de83786fbf060d3955a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp?plain=1#L1103-L1110

In `ARM.cpp`, the per-operand bitcasts happen later in `EmitNeonCall`
https://github.com/llvm/llvm-project/blob/e7887d5470e080c55fd69de83786fbf060d3955a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp?plain=1#L427-L440

The CIR loop does the same thing.

If we used `Add1ArgType` / `Add2ArgTypes` for this, `test_vsrid_n_s64` and 
`test_vsrid_n_u64` would fail.


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

Reply via email to