================
@@ -159,6 +159,119 @@ Value *EmitAMDGPUGridSize(CodeGenFunction &CGF, unsigned 
Index) {
                   llvm::MDNode::get(CGF.getLLVMContext(), {}));
   return LD;
 }
+// Lowers __builtin_amdgcn_ds_bpermute to the corresponding LLVM intrinsic with
+// careful bit-level coercions of operands and result to match Clang types.
+llvm::Value *emitAMDGCNDsBpermute(clang::CodeGen::CodeGenFunction &CGF,
+                                  const clang::CallExpr *Call) {
+  auto &Builder = CGF.Builder;
+  auto &CGM = CGF.CGM;
+  const llvm::DataLayout &DL = CGM.getDataLayout();
+
+  llvm::Type *I32Ty = Builder.getInt32Ty();
+
+  auto GetBitWidth = [&](llvm::Type *Ty) -> unsigned {
+    return DL.getTypeSizeInBits(Ty).getFixedValue();
+  };
+
+  // Coerces arbitrary scalar/vector/pointer to i32 by preserving value/bit
+  // semantics where applicable.
+  auto ToI32Bits = [&](llvm::Value *Val, clang::QualType Qt) -> llvm::Value * {
+    llvm::Type *Ty = Val->getType();
+
+    if (Ty->isIntegerTy()) {
+      unsigned BitWidth = Ty->getIntegerBitWidth();
+      if (BitWidth < 32) {
+        if (Qt->isSignedIntegerType())
+          return Builder.CreateSExt(Val, I32Ty);
+        else
+          return Builder.CreateZExt(Val, I32Ty);
+      } else
+        return Builder.CreateZExtOrTrunc(Val, I32Ty);
+    }
+
+    if (Ty->isPointerTy()) {
+      unsigned PtrBits = DL.getPointerSizeInBits(Ty->getPointerAddressSpace());
+      llvm::Type *IntPtrTy = Builder.getIntNTy(PtrBits);
+      llvm::Value *AsInt = Builder.CreatePtrToInt(Val, IntPtrTy);
+      return Builder.CreateZExtOrTrunc(AsInt, I32Ty);
+    }
+
+    unsigned Bits = GetBitWidth(Ty);
+    llvm::Type *IntN = Builder.getIntNTy(Bits);
+    llvm::Value *AsInt = Builder.CreateBitCast(Val, IntN);
+    return Builder.CreateZExtOrTrunc(AsInt, I32Ty);
+  };
+
+  // Bit-preserving resize/cast between arbitrary source and destination LLVM
+  // types.
+  auto BitCoerceTo = [&](llvm::Value *Val, llvm::Type *DstTy) -> llvm::Value * 
{
+    llvm::Type *SrcTy = Val->getType();
+    if (SrcTy == DstTy)
+      return Val;
+
+    unsigned SrcBits = DL.getTypeSizeInBits(SrcTy).getFixedValue();
+    unsigned DstBits = DL.getTypeSizeInBits(DstTy).getFixedValue();
+
+    if (SrcTy->isIntegerTy() && DstTy->isIntegerTy())
+      return Builder.CreateZExtOrTrunc(Val, DstTy);
+
+    if (SrcBits == DstBits)
+      return Builder.CreateBitCast(Val, DstTy);
+
+    llvm::Type *IntSrcTy = Builder.getIntNTy(SrcBits);
+    llvm::Value *AsInt = Val;
+    if (SrcTy->isPointerTy())
+      AsInt = Builder.CreatePtrToInt(Val, IntSrcTy);
+    else if (!SrcTy->isIntegerTy())
+      AsInt = Builder.CreateBitCast(Val, IntSrcTy);
+
+    llvm::Type *IntDstTy = Builder.getIntNTy(DstBits);
+    llvm::Value *Resized = Builder.CreateZExtOrTrunc(AsInt, IntDstTy);
+
+    if (DstTy->isPointerTy())
+      return Builder.CreateIntToPtr(Resized, DstTy);
+
+    return Builder.CreateBitCast(Resized, DstTy);
+  };
+
+  llvm::Value *Index = CGF.EmitScalarExpr(Call->getArg(0));
+  llvm::Value *Source = CGF.EmitScalarExpr(Call->getArg(1));
+
+  llvm::Type *ReturnTy = CGF.ConvertType(Call->getType());
+
+  llvm::Value *IndexI32 = ToI32Bits(Index, Call->getArg(0)->getType());
+
+  llvm::Value *SourceForIntrinsic;
+  llvm::Type *SourceTy = Source->getType();
+
+  if (SourceTy->isDoubleTy()) {
+    llvm::Value *AsFloat = Builder.CreateFPTrunc(Source, Builder.getFloatTy());
----------------
shiltian wrote:

Do we really want to do this? Why is double handed here but other types are not?

https://github.com/llvm/llvm-project/pull/153501
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to