[clang] [clang][bytecode] Implement __builtin_ai32_addcarryx* (PR #111671)

via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 9 05:57:01 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/111671.diff


2 Files Affected:

- (modified) clang/lib/AST/ByteCode/Function.h (+4) 
- (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+50) 


``````````diff
diff --git a/clang/lib/AST/ByteCode/Function.h b/clang/lib/AST/ByteCode/Function.h
index 640bfa65644f0f..7fe9aeb1101204 100644
--- a/clang/lib/AST/ByteCode/Function.h
+++ b/clang/lib/AST/ByteCode/Function.h
@@ -222,6 +222,10 @@ class Function final {
     return ParamOffsets[ParamIndex];
   }
 
+  PrimType getParamType(unsigned ParamIndex) const {
+    return ParamTypes[ParamIndex];
+  }
+
 private:
   /// Construct a function representing an actual function.
   Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 98381254886e29..7d811b7baea7ce 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -38,6 +38,15 @@ static T getParam(const InterpFrame *Frame, unsigned Index) {
   return Frame->getParam<T>(Offset);
 }
 
+// static APSInt getAPSIntParam(InterpStack &Stk, size_t Offset = 0) {
+static APSInt getAPSIntParam(const InterpFrame *Frame, unsigned Index) {
+  APSInt R;
+  unsigned Offset = Frame->getFunction()->getParamOffset(Index);
+  INT_TYPE_SWITCH(Frame->getFunction()->getParamType(Index),
+                  R = Frame->getParam<T>(Offset).toAPSInt());
+  return R;
+}
+
 PrimType getIntPrimType(const InterpState &S) {
   const TargetInfo &TI = S.getASTContext().getTargetInfo();
   unsigned IntWidth = TI.getIntWidth();
@@ -1273,6 +1282,39 @@ static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,
   return true;
 }
 
+static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S,
+                                                    CodePtr OpPC,
+                                                    const InterpFrame *Frame,
+                                                    const Function *Func,
+                                                    const CallExpr *Call) {
+  unsigned BuiltinOp = Func->getBuiltinID();
+  APSInt CarryIn = getAPSIntParam(Frame, 0);
+  APSInt LHS = getAPSIntParam(Frame, 1);
+  APSInt RHS = getAPSIntParam(Frame, 2);
+
+  bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 ||
+               BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64;
+
+  unsigned BitWidth = LHS.getBitWidth();
+  unsigned CarryInBit = CarryIn.ugt(0) ? 1 : 0;
+  APInt ExResult =
+      IsAdd ? (LHS.zext(BitWidth + 1) + (RHS.zext(BitWidth + 1) + CarryInBit))
+            : (LHS.zext(BitWidth + 1) - (RHS.zext(BitWidth + 1) + CarryInBit));
+
+  APInt Result = ExResult.extractBits(BitWidth, 0);
+  APSInt CarryOut =
+      APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true);
+
+  Pointer &CarryOutPtr = S.Stk.peek<Pointer>();
+  QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
+  PrimType CarryOutT = *S.getContext().classify(CarryOutType);
+  assignInteger(CarryOutPtr, CarryOutT, APSInt(Result, true));
+
+  pushInteger(S, CarryOut, Call->getType());
+
+  return true;
+}
+
 static bool interp__builtin_os_log_format_buffer_size(InterpState &S,
                                                       CodePtr OpPC,
                                                       const InterpFrame *Frame,
@@ -1898,6 +1940,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
       return false;
     break;
 
+  case clang::X86::BI__builtin_ia32_addcarryx_u32:
+  case clang::X86::BI__builtin_ia32_addcarryx_u64:
+  case clang::X86::BI__builtin_ia32_subborrow_u32:
+  case clang::X86::BI__builtin_ia32_subborrow_u64:
+    if (!interp__builtin_ia32_addcarry_subborrow(S, OpPC, Frame, F, Call))
+      return false;
+    break;
+
   case Builtin::BI__builtin_os_log_format_buffer_size:
     if (!interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, F, Call))
       return false;

``````````

</details>


https://github.com/llvm/llvm-project/pull/111671


More information about the cfe-commits mailing list