================ @@ -19445,6 +19445,70 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; switch (BuiltinID) { + case Builtin::BI__builtin_hlsl_adduint64: { + Value *OpA = EmitScalarExpr(E->getArg(0)); + Value *OpB = EmitScalarExpr(E->getArg(1)); + assert(E->getArg(0)->getType()->hasIntegerRepresentation() && + E->getArg(1)->getType()->hasIntegerRepresentation() && + "AddUint64 operands must have an integer representation"); + assert(((E->getArg(0)->getType()->castAs<VectorType>()->getNumElements() == + 2 && + E->getArg(1)->getType()->castAs<VectorType>()->getNumElements() == + 2) || + (E->getArg(0)->getType()->castAs<VectorType>()->getNumElements() == + 4 && + E->getArg(1)->getType()->castAs<VectorType>()->getNumElements() == + 4)) && + "input vectors must have 2 or 4 elements each"); + + uint64_t NumElements = + E->getArg(0)->getType()->castAs<VectorType>()->getNumElements(); + + llvm::Value *Result = PoisonValue::get(OpA->getType()); + llvm::Value *LowA; + llvm::Value *HighA; + llvm::Value *LowB; + llvm::Value *HighB; + + // Obtain low and high words of inputs A and B + if (NumElements == 2) { + LowA = Builder.CreateExtractElement(OpA, (uint64_t)0, "LowA"); + HighA = Builder.CreateExtractElement(OpA, (uint64_t)1, "HighA"); + LowB = Builder.CreateExtractElement(OpB, (uint64_t)0, "LowB"); + HighB = Builder.CreateExtractElement(OpB, (uint64_t)1, "HighB"); + } else { + LowA = Builder.CreateShuffleVector(OpA, ArrayRef<int>{0, 2}, "LowA"); + HighA = Builder.CreateShuffleVector(OpA, ArrayRef<int>{1, 3}, "HighA"); + LowB = Builder.CreateShuffleVector(OpB, ArrayRef<int>{0, 2}, "LowB"); + HighB = Builder.CreateShuffleVector(OpB, ArrayRef<int>{1, 3}, "HighB"); + } + + // Use an uadd_with_overflow to compute the sum of low words and obtain a + // carry value + llvm::Value *Carry; + llvm::Value *LowSum = EmitOverflowIntrinsic( + *this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry); + llvm::Value *ZExtCarry = + Builder.CreateZExt(Carry, HighA->getType(), "CarryZExt"); + + // Sum the high words and the carry + llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB, "HighSum"); + llvm::Value *HighSumPlusCarry = + Builder.CreateAdd(HighSum, ZExtCarry, "HighSumPlusCarry"); + + // Insert the low and high word sums into the result vector + if (NumElements == 2) { + Result = Builder.CreateInsertElement(Result, LowSum, (uint64_t)0, + "hlsl.AddUint64.upto0"); + Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, + (uint64_t)1, "hlsl.AddUint64"); + } else { /* NumElements == 4 */ + Result = Builder.CreateShuffleVector(LowSum, HighSumPlusCarry, + ArrayRef<int>{0, 2, 1, 3}, + "hlsl.AddUint64"); + } + return Result; ---------------- bogner wrote:
Better to return early in one of these cases. This also makes it clearer that the initial `poison` value for `Result` is only used in one branch. ```c++ if (NumElements == 4) return Builder.CreateShuffleVector(...) llvm::Value *Result = PoisonValue::get(OpA->getType()); // ... return Result; ``` https://github.com/llvm/llvm-project/pull/127137 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits