https://github.com/beakthoven updated 
https://github.com/llvm/llvm-project/pull/203214

>From a5a1033523a66d68cff0c904415cd102e68d4fed Mon Sep 17 00:00:00 2001
From: Dakkshesh <[email protected]>
Date: Thu, 11 Jun 2026 11:50:55 +0530
Subject: [PATCH] [clang][AVR] Add basic AVR builtin functions

Add builtins for nop, sei, cli, sleep, wdr, swap. These builtins lower
to their llvm.avr.* intrinsics.

Remaining builtins are marked as TODO.

Signed-off-by: Dakkshesh <[email protected]>
---
 clang/include/clang/Basic/BuiltinsAVR.def  |  47 ++++
 clang/include/clang/Basic/TargetBuiltins.h |  12 +-
 clang/lib/Basic/Targets/AVR.cpp            |  35 ++-
 clang/lib/Basic/Targets/AVR.h              |   4 +-
 clang/lib/CodeGen/CGBuiltin.cpp            |   2 +
 clang/lib/CodeGen/CMakeLists.txt           |   1 +
 clang/lib/CodeGen/CodeGenFunction.h        |   1 +
 clang/lib/CodeGen/TargetBuiltins/AVR.cpp   |  42 +++
 clang/test/CodeGen/avr/avr-builtins.c      | 303 ++++++++++++++++++---
 clang/test/Preprocessor/avr-builtins.c     |   8 +
 10 files changed, 412 insertions(+), 43 deletions(-)
 create mode 100644 clang/include/clang/Basic/BuiltinsAVR.def
 create mode 100644 clang/lib/CodeGen/TargetBuiltins/AVR.cpp
 create mode 100644 clang/test/Preprocessor/avr-builtins.c

diff --git a/clang/include/clang/Basic/BuiltinsAVR.def 
b/clang/include/clang/Basic/BuiltinsAVR.def
new file mode 100644
index 0000000000000..78b8daefef934
--- /dev/null
+++ b/clang/include/clang/Basic/BuiltinsAVR.def
@@ -0,0 +1,47 @@
+//===--- BuiltinsAVR.def - AVR Builtin function database --------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AVR-specific builtin function database.  Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// Void instructions
+BUILTIN(__builtin_avr_nop, "v", "n")
+BUILTIN(__builtin_avr_sei, "v", "n")
+BUILTIN(__builtin_avr_cli, "v", "n")
+BUILTIN(__builtin_avr_sleep, "v", "n")
+BUILTIN(__builtin_avr_wdr, "v", "n")
+
+// Swap nibbles
+BUILTIN(__builtin_avr_swap, "UcUc", "nc")
+
+// TODO:
+// Fractional multiply
+// BUILTIN(__builtin_avr_fmul, "UiUcUc", "nc")
+// BUILTIN(__builtin_avr_fmuls, "SiScSc", "nc")
+// BUILTIN(__builtin_avr_fmulsu, "SiScUc", "nc")
+
+// Delay cycles
+// BUILTIN(__builtin_avr_delay_cycles, "vULi", "n")
+
+// Emit N NOP instructions
+// BUILTIN(__builtin_avr_nops, "vUi", "n")
+
+// Bit manipulation
+// BUILTIN(__builtin_avr_insert_bits, "UcULiUcUc", "nc")
+
+// Flash segment query
+// BUILTIN(__builtin_avr_flash_segment, "ScvC*", "nc")
+
+// __builtin_avr_mask1
+// __builtin_avr_strlen_flash
+// __builtin_avr_strlen_flashx
+// __builtin_avr_strlen_memx
+
+#undef BUILTIN
diff --git a/clang/include/clang/Basic/TargetBuiltins.h 
b/clang/include/clang/Basic/TargetBuiltins.h
index 9b4613c853206..2c6d007e45ead 100644
--- a/clang/include/clang/Basic/TargetBuiltins.h
+++ b/clang/include/clang/Basic/TargetBuiltins.h
@@ -476,12 +476,22 @@ namespace clang {
     };
   }
 
+  /// AVR builtins
+  namespace AVR {
+    enum {
+      LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsAVR.def"
+      LastTSBuiltin
+    };
+  }
+
   static constexpr uint64_t LargestBuiltinID = std::max<uint64_t>(
       {ARM::LastTSBuiltin, AArch64::LastTSBuiltin, BPF::LastTSBuiltin,
        PPC::LastTSBuiltin, NVPTX::LastTSBuiltin, AMDGPU::LastTSBuiltin,
        X86::LastTSBuiltin, VE::LastTSBuiltin, RISCV::LastTSBuiltin,
        Hexagon::LastTSBuiltin, Mips::LastTSBuiltin, XCore::LastTSBuiltin,
-       SystemZ::LastTSBuiltin, WebAssembly::LastTSBuiltin});
+       SystemZ::LastTSBuiltin, WebAssembly::LastTSBuiltin, 
AVR::LastTSBuiltin});
 
 } // end namespace clang.
 
diff --git a/clang/lib/Basic/Targets/AVR.cpp b/clang/lib/Basic/Targets/AVR.cpp
index 75144099b2bdd..227651a2ab6fa 100644
--- a/clang/lib/Basic/Targets/AVR.cpp
+++ b/clang/lib/Basic/Targets/AVR.cpp
@@ -11,12 +11,28 @@
 
//===----------------------------------------------------------------------===//
 
 #include "AVR.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
 #include "llvm/ADT/StringSwitch.h"
 
 using namespace clang;
 using namespace clang::targets;
 
+static constexpr int NumBuiltins = AVR::LastTSBuiltin - 
Builtin::FirstTSBuiltin;
+
+static constexpr llvm::StringTable BuiltinStrings =
+    CLANG_BUILTIN_STR_TABLE_START
+#define BUILTIN CLANG_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsAVR.def"
+    ;
+
+static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({
+#define BUILTIN CLANG_BUILTIN_ENTRY
+#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY
+#include "clang/Basic/BuiltinsAVR.def"
+});
+
 namespace clang {
 namespace targets {
 
@@ -471,8 +487,13 @@ static bool ArchHas3BytePC(StringRef Arch) {
 }
 
 bool AVRTargetInfo::isValidCPUName(StringRef Name) const {
-  return llvm::any_of(
-      AVRMcus, [&](const MCUInfo &Info) { return Info.Name == Name; });
+  return llvm::any_of(AVRMcus,
+                      [&](const MCUInfo &Info) { return Info.Name == Name; });
+}
+
+llvm::SmallVector<Builtin::InfosShard>
+AVRTargetInfo::getTargetBuiltins() const {
+  return {{&BuiltinStrings, BuiltinInfos}};
 }
 
 void AVRTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const 
{
@@ -524,7 +545,7 @@ void AVRTargetInfo::getTargetDefines(const LangOptions 
&Opts,
     Builder.defineMacro("__AVR_TINY__", "1");
 
   if (DefineName.size() != 0)
-      Builder.defineMacro(DefineName);
+    Builder.defineMacro(DefineName);
 
   Builder.defineMacro("__AVR_ARCH__", Arch);
 
@@ -564,4 +585,12 @@ void AVRTargetInfo::getTargetDefines(const LangOptions 
&Opts,
     Builder.defineMacro("__flash4", "__attribute__((__address_space__(5)))");
   if (NumFlashBanks >= 6)
     Builder.defineMacro("__flash5", "__attribute__((__address_space__(6)))");
+
+  // Define macros for builtins
+  Builder.defineMacro("__BUILTIN_AVR_NOP", "1");
+  Builder.defineMacro("__BUILTIN_AVR_SEI", "1");
+  Builder.defineMacro("__BUILTIN_AVR_CLI", "1");
+  Builder.defineMacro("__BUILTIN_AVR_WDR", "1");
+  Builder.defineMacro("__BUILTIN_AVR_SLEEP", "1");
+  Builder.defineMacro("__BUILTIN_AVR_SWAP", "1");
 }
diff --git a/clang/lib/Basic/Targets/AVR.h b/clang/lib/Basic/Targets/AVR.h
index f6fed1d97c9ea..211cf90fe9fb2 100644
--- a/clang/lib/Basic/Targets/AVR.h
+++ b/clang/lib/Basic/Targets/AVR.h
@@ -63,9 +63,7 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public 
TargetInfo {
   void getTargetDefines(const LangOptions &Opts,
                         MacroBuilder &Builder) const override;
 
-  llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
-    return {};
-  }
+  llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
 
   bool allowsLargerPreferedTypeAlignment() const override { return false; }
 
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 682b125890fe1..509ab4245d99a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -133,6 +133,8 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction 
*CGF,
     [[fallthrough]];
   case llvm::Triple::spirv:
     return CGF->EmitSPIRVBuiltinExpr(BuiltinID, E);
+  case llvm::Triple::avr:
+    return CGF->EmitAVRBuiltinExpr(BuiltinID, E);
   default:
     return nullptr;
   }
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index 75b2f5826f863..479967ee0a230 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -122,6 +122,7 @@ add_clang_library(clangCodeGen
   SanitizerMetadata.cpp
   SwiftCallingConv.cpp
   TargetBuiltins/ARM.cpp
+  TargetBuiltins/AVR.cpp
   TargetBuiltins/AMDGPU.cpp
   TargetBuiltins/DirectX.cpp
   TargetBuiltins/Hexagon.cpp
diff --git a/clang/lib/CodeGen/CodeGenFunction.h 
b/clang/lib/CodeGen/CodeGenFunction.h
index 6bb9f285ebcfd..e1af1d281764a 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4965,6 +4965,7 @@ class CodeGenFunction : public CodeGenTypeCache {
   llvm::Value *EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
                                           const CallExpr *E);
   llvm::Value *EmitHexagonBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+  llvm::Value *EmitAVRBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
   llvm::Value *EmitRISCVBuiltinExpr(unsigned BuiltinID, const CallExpr *E,
                                     ReturnValueSlot ReturnValue);
 
diff --git a/clang/lib/CodeGen/TargetBuiltins/AVR.cpp 
b/clang/lib/CodeGen/TargetBuiltins/AVR.cpp
new file mode 100644
index 0000000000000..a9860c03a091f
--- /dev/null
+++ b/clang/lib/CodeGen/TargetBuiltins/AVR.cpp
@@ -0,0 +1,42 @@
+//===------ AVR.cpp - Emit LLVM Code for AVR builtins 
---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Builtin calls as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGBuiltin.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/IntrinsicsAVR.h"
+
+using namespace clang;
+using namespace CodeGen;
+using namespace llvm;
+
+Value *CodeGenFunction::EmitAVRBuiltinExpr(unsigned BuiltinID,
+                                           const CallExpr *E) {
+  switch (BuiltinID) {
+  default:
+    return nullptr;
+  case AVR::BI__builtin_avr_nop:
+    return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_nop));
+  case AVR::BI__builtin_avr_sei:
+    return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_sei));
+  case AVR::BI__builtin_avr_cli:
+    return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_cli));
+  case AVR::BI__builtin_avr_sleep:
+    return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_sleep));
+  case AVR::BI__builtin_avr_wdr:
+    return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_wdr));
+  case AVR::BI__builtin_avr_swap: {
+    Value *Arg0 = EmitScalarExpr(E->getArg(0));
+    return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_swap), Arg0);
+  }
+  }
+}
diff --git a/clang/test/CodeGen/avr/avr-builtins.c 
b/clang/test/CodeGen/avr/avr-builtins.c
index 7c2c424848080..cd844d85a005f 100644
--- a/clang/test/CodeGen/avr/avr-builtins.c
+++ b/clang/test/CodeGen/avr/avr-builtins.c
@@ -1,127 +1,358 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
 // RUN: %clang_cc1 -triple avr-unknown-unknown -emit-llvm -o - %s | FileCheck 
%s
 
 // Check that the parameter types match. This verifies pr43309.
 // RUN: %clang_cc1 -triple avr-unknown-unknown -Wconversion -verify %s
 // expected-no-diagnostics
 
+// CHECK-LABEL: define dso_local i8 @bitrev8(
+// CHECK-SAME: i8 noundef zeroext [[DATA:%.*]]) addrspace(1) #[[ATTR0:[0-9]+]] 
{
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[DATA_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i8 [[DATA]], ptr [[DATA_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[DATA_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = call addrspace(1) i8 @llvm.bitreverse.i8(i8 
[[TMP0]])
+// CHECK-NEXT:    ret i8 [[TMP1]]
+//
 unsigned char bitrev8(unsigned char data) {
     return __builtin_bitreverse8(data);
 }
 
-// CHECK: define{{.*}} i8 @bitrev8
-// CHECK: i8 @llvm.bitreverse.i8(i8
 
+// CHECK-LABEL: define dso_local i16 @bitrev16(
+// CHECK-SAME: i16 noundef [[DATA:%.*]]) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[DATA_ADDR:%.*]] = alloca i16, align 1
+// CHECK-NEXT:    store i16 [[DATA]], ptr [[DATA_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[DATA_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = call addrspace(1) i16 
@llvm.bitreverse.i16(i16 [[TMP0]])
+// CHECK-NEXT:    ret i16 [[TMP1]]
+//
 unsigned int bitrev16(unsigned int data) {
     return __builtin_bitreverse16(data);
 }
 
-// CHECK: define{{.*}} i16 @bitrev16
-// CHECK: i16 @llvm.bitreverse.i16(i16
 
+// CHECK-LABEL: define dso_local i32 @bitrev32(
+// CHECK-SAME: i32 noundef [[DATA:%.*]]) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[DATA_ADDR:%.*]] = alloca i32, align 1
+// CHECK-NEXT:    store i32 [[DATA]], ptr [[DATA_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[DATA_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = call addrspace(1) i32 
@llvm.bitreverse.i32(i32 [[TMP0]])
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
 unsigned long bitrev32(unsigned long data) {
     return __builtin_bitreverse32(data);
 }
-// CHECK: define{{.*}} i32 @bitrev32
-// CHECK: i32 @llvm.bitreverse.i32(i32
 
+// CHECK-LABEL: define dso_local i64 @bitrev64(
+// CHECK-SAME: i64 noundef [[DATA:%.*]]) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[DATA_ADDR:%.*]] = alloca i64, align 1
+// CHECK-NEXT:    store i64 [[DATA]], ptr [[DATA_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr [[DATA_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = call addrspace(1) i64 
@llvm.bitreverse.i64(i64 [[TMP0]])
+// CHECK-NEXT:    ret i64 [[TMP1]]
+//
 unsigned long long bitrev64(unsigned long long data) {
     return __builtin_bitreverse64(data);
 }
 
-// CHECK: define{{.*}} i64 @bitrev64
-// CHECK: i64 @llvm.bitreverse.i64(i64
 
+// CHECK-LABEL: define dso_local i8 @rotleft8(
+// CHECK-SAME: i8 noundef zeroext [[X:%.*]], i8 noundef zeroext [[Y:%.*]]) 
addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i8 [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    store i8 [[Y]], ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = urem i8 [[TMP1]], 8
+// CHECK-NEXT:    [[TMP3:%.*]] = call addrspace(1) i8 @llvm.fshl.i8(i8 
[[TMP0]], i8 [[TMP0]], i8 [[TMP2]])
+// CHECK-NEXT:    ret i8 [[TMP3]]
+//
 unsigned char rotleft8(unsigned char x, unsigned char y) {
     return __builtin_rotateleft8(x, y);
 }
 
-// CHECK: define{{.*}} i8 @rotleft8
-// CHECK: i8 @llvm.fshl.i8(i8
 
+// CHECK-LABEL: define dso_local i16 @rotleft16(
+// CHECK-SAME: i16 noundef [[X:%.*]], i16 noundef [[Y:%.*]]) addrspace(1) 
#[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i16, align 1
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i16, align 1
+// CHECK-NEXT:    store i16 [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    store i16 [[Y]], ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = urem i16 [[TMP1]], 16
+// CHECK-NEXT:    [[TMP3:%.*]] = call addrspace(1) i16 @llvm.fshl.i16(i16 
[[TMP0]], i16 [[TMP0]], i16 [[TMP2]])
+// CHECK-NEXT:    ret i16 [[TMP3]]
+//
 unsigned int rotleft16(unsigned int x, unsigned int y) {
     return __builtin_rotateleft16(x, y);
 }
 
-// CHECK: define{{.*}} i16 @rotleft16
-// CHECK: i16 @llvm.fshl.i16(i16
 
+// CHECK-LABEL: define dso_local i32 @rotleft32(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) addrspace(1) 
#[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 1
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 1
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = urem i32 [[TMP1]], 32
+// CHECK-NEXT:    [[TMP3:%.*]] = call addrspace(1) i32 @llvm.fshl.i32(i32 
[[TMP0]], i32 [[TMP0]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
 unsigned long rotleft32(unsigned long x, unsigned long y) {
     return __builtin_rotateleft32(x, y);
 }
-// CHECK: define{{.*}} i32 @rotleft32
-// CHECK: i32 @llvm.fshl.i32(i32
 
+// CHECK-LABEL: define dso_local i64 @rotleft64(
+// CHECK-SAME: i64 noundef [[X:%.*]], i64 noundef [[Y:%.*]]) addrspace(1) 
#[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i64, align 1
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i64, align 1
+// CHECK-NEXT:    store i64 [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    store i64 [[Y]], ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i64, ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = urem i64 [[TMP1]], 64
+// CHECK-NEXT:    [[TMP3:%.*]] = call addrspace(1) i64 @llvm.fshl.i64(i64 
[[TMP0]], i64 [[TMP0]], i64 [[TMP2]])
+// CHECK-NEXT:    ret i64 [[TMP3]]
+//
 unsigned long long rotleft64(unsigned long long x, unsigned long long y) {
     return __builtin_rotateleft64(x, y);
 }
 
-// CHECK: define{{.*}} i64 @rotleft64
-// CHECK: i64 @llvm.fshl.i64(i64
 
+// CHECK-LABEL: define dso_local i8 @rotright8(
+// CHECK-SAME: i8 noundef zeroext [[X:%.*]], i8 noundef zeroext [[Y:%.*]]) 
addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i8 [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    store i8 [[Y]], ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = urem i8 [[TMP1]], 8
+// CHECK-NEXT:    [[TMP3:%.*]] = call addrspace(1) i8 @llvm.fshr.i8(i8 
[[TMP0]], i8 [[TMP0]], i8 [[TMP2]])
+// CHECK-NEXT:    ret i8 [[TMP3]]
+//
 unsigned char rotright8(unsigned char x, unsigned char y) {
     return __builtin_rotateright8(x, y);
 }
 
-// CHECK: define{{.*}} i8 @rotright8
-// CHECK: i8 @llvm.fshr.i8(i8
 
+// CHECK-LABEL: define dso_local i16 @rotright16(
+// CHECK-SAME: i16 noundef [[X:%.*]], i16 noundef [[Y:%.*]]) addrspace(1) 
#[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i16, align 1
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i16, align 1
+// CHECK-NEXT:    store i16 [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    store i16 [[Y]], ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = urem i16 [[TMP1]], 16
+// CHECK-NEXT:    [[TMP3:%.*]] = call addrspace(1) i16 @llvm.fshr.i16(i16 
[[TMP0]], i16 [[TMP0]], i16 [[TMP2]])
+// CHECK-NEXT:    ret i16 [[TMP3]]
+//
 unsigned int rotright16(unsigned int x, unsigned int y) {
     return __builtin_rotateright16(x, y);
 }
 
-// CHECK: define{{.*}} i16 @rotright16
-// CHECK: i16 @llvm.fshr.i16(i16
 
+// CHECK-LABEL: define dso_local i32 @rotright32(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) addrspace(1) 
#[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 1
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 1
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = urem i32 [[TMP1]], 32
+// CHECK-NEXT:    [[TMP3:%.*]] = call addrspace(1) i32 @llvm.fshr.i32(i32 
[[TMP0]], i32 [[TMP0]], i32 [[TMP2]])
+// CHECK-NEXT:    ret i32 [[TMP3]]
+//
 unsigned long rotright32(unsigned long x, unsigned long y) {
     return __builtin_rotateright32(x, y);
 }
-// CHECK: define{{.*}} i32 @rotright32
-// CHECK: i32 @llvm.fshr.i32(i32
 
+// CHECK-LABEL: define dso_local i64 @rotright64(
+// CHECK-SAME: i64 noundef [[X:%.*]], i64 noundef [[Y:%.*]]) addrspace(1) 
#[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i64, align 1
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i64, align 1
+// CHECK-NEXT:    store i64 [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    store i64 [[Y]], ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i64, ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = urem i64 [[TMP1]], 64
+// CHECK-NEXT:    [[TMP3:%.*]] = call addrspace(1) i64 @llvm.fshr.i64(i64 
[[TMP0]], i64 [[TMP0]], i64 [[TMP2]])
+// CHECK-NEXT:    ret i64 [[TMP3]]
+//
 unsigned long long rotright64(unsigned long long x, unsigned long long y) {
     return __builtin_rotateright64(x, y);
 }
 
-// CHECK: define{{.*}} i64 @rotright64
-// CHECK: i64 @llvm.fshr.i64(i64
 
+// CHECK-LABEL: define dso_local i16 @byteswap16(
+// CHECK-SAME: i16 noundef [[X:%.*]]) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i16, align 1
+// CHECK-NEXT:    store i16 [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = call addrspace(1) i16 @llvm.bswap.i16(i16 
[[TMP0]])
+// CHECK-NEXT:    ret i16 [[TMP1]]
+//
 unsigned int byteswap16(unsigned int x) {
     return __builtin_bswap16(x);
 }
 
-// CHECK: define{{.*}} i16 @byteswap16
-// CHECK: i16 @llvm.bswap.i16(i16
 
+// CHECK-LABEL: define dso_local i32 @byteswap32(
+// CHECK-SAME: i32 noundef [[X:%.*]]) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 1
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = call addrspace(1) i32 @llvm.bswap.i32(i32 
[[TMP0]])
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
 unsigned long byteswap32(unsigned long x) {
     return __builtin_bswap32(x);
 }
-// CHECK: define{{.*}} i32 @byteswap32
-// CHECK: i32 @llvm.bswap.i32(i32
 
+// CHECK-LABEL: define dso_local i64 @byteswap64(
+// CHECK-SAME: i64 noundef [[X:%.*]]) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i64, align 1
+// CHECK-NEXT:    store i64 [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = call addrspace(1) i64 @llvm.bswap.i64(i64 
[[TMP0]])
+// CHECK-NEXT:    ret i64 [[TMP1]]
+//
 unsigned long long byteswap64(unsigned long long x) {
     return __builtin_bswap64(x);
 }
 
-// CHECK: define{{.*}} i64 @byteswap64
-// CHECK: i64 @llvm.bswap.i64(i64
 
+// CHECK-LABEL: define dso_local float @powi(
+// CHECK-SAME: float noundef [[X:%.*]], i16 noundef [[Y:%.*]]) addrspace(1) 
#[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca float, align 1
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i16, align 1
+// CHECK-NEXT:    store float [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    store i16 [[Y]], ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = call addrspace(1) float 
@llvm.powi.f32.i16(float [[TMP0]], i16 [[TMP1]])
+// CHECK-NEXT:    ret float [[TMP2]]
+//
 double powi(double x, int y) {
   return __builtin_powi(x, y);
 }
 
-// CHECK: define{{.*}} float @powi
-// CHECK: float @llvm.powi.f32.i16(float %0, i16 %1)
 
+// CHECK-LABEL: define dso_local float @powif(
+// CHECK-SAME: float noundef [[X:%.*]], i16 noundef [[Y:%.*]]) addrspace(1) 
#[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca float, align 1
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i16, align 1
+// CHECK-NEXT:    store float [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    store i16 [[Y]], ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = call addrspace(1) float 
@llvm.powi.f32.i16(float [[TMP0]], i16 [[TMP1]])
+// CHECK-NEXT:    ret float [[TMP2]]
+//
 float powif(float x, int y) {
     return __builtin_powif(x, y);
 }
 
-// CHECK: define{{.*}} float @powif
-// CHECK: float @llvm.powi.f32.i16(float %0, i16 %1)
 
+// CHECK-LABEL: define dso_local float @powil(
+// CHECK-SAME: float noundef [[X:%.*]], i16 noundef [[Y:%.*]]) addrspace(1) 
#[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca float, align 1
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i16, align 1
+// CHECK-NEXT:    store float [[X]], ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    store i16 [[Y]], ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[X_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[Y_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = call addrspace(1) float 
@llvm.powi.f32.i16(float [[TMP0]], i16 [[TMP1]])
+// CHECK-NEXT:    ret float [[TMP2]]
+//
 long double powil(long double x, int y) {
     return __builtin_powil(x, y);
 }
 
-// CHECK: define{{.*}} float @powil
-// CHECK: float @llvm.powi.f32.i16(float %0, i16 %1)
+
+// CHECK-LABEL: define dso_local void @test_nop(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call addrspace(1) void @llvm.avr.nop()
+// CHECK-NEXT:    ret void
+//
+void test_nop(void) {
+  __builtin_avr_nop();
+}
+
+// CHECK-LABEL: define dso_local void @test_sei(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call addrspace(1) void @llvm.avr.sei()
+// CHECK-NEXT:    ret void
+//
+void test_sei(void) {
+  __builtin_avr_sei();
+}
+
+// CHECK-LABEL: define dso_local void @test_cli(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call addrspace(1) void @llvm.avr.cli()
+// CHECK-NEXT:    ret void
+//
+void test_cli(void) {
+  __builtin_avr_cli();
+}
+
+// CHECK-LABEL: define dso_local void @test_sleep(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call addrspace(1) void @llvm.avr.sleep()
+// CHECK-NEXT:    ret void
+//
+void test_sleep(void) {
+  __builtin_avr_sleep();
+}
+
+// CHECK-LABEL: define dso_local void @test_wdr(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call addrspace(1) void @llvm.avr.wdr()
+// CHECK-NEXT:    ret void
+//
+void test_wdr(void) {
+  __builtin_avr_wdr();
+}
+
+// CHECK-LABEL: define dso_local i8 @test_swap(
+// CHECK-SAME: i8 noundef zeroext [[A:%.*]]) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i8 [[A]], ptr [[A_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[A_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = call addrspace(1) i8 @llvm.avr.swap(i8 
[[TMP0]])
+// CHECK-NEXT:    ret i8 [[TMP1]]
+//
+unsigned char test_swap(unsigned char a) {
+  return __builtin_avr_swap(a);
+}
\ No newline at end of file
diff --git a/clang/test/Preprocessor/avr-builtins.c 
b/clang/test/Preprocessor/avr-builtins.c
new file mode 100644
index 0000000000000..8a0190bde08b3
--- /dev/null
+++ b/clang/test/Preprocessor/avr-builtins.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -E -dM -triple avr-unknown-unknown -target-cpu atmega328p 
%s | FileCheck %s
+
+// CHECK: #define __BUILTIN_AVR_CLI 1
+// CHECK: #define __BUILTIN_AVR_NOP 1
+// CHECK: #define __BUILTIN_AVR_SEI 1
+// CHECK: #define __BUILTIN_AVR_SLEEP 1
+// CHECK: #define __BUILTIN_AVR_SWAP 1
+// CHECK: #define __BUILTIN_AVR_WDR 1

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

Reply via email to