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

>From 332868c021c7531cb15ab3d19d3ec47e3f4e7def Mon Sep 17 00:00:00 2001
From: Dakkshesh <[email protected]>
Date: Thu, 11 Jun 2026 11:50:55 +0530
Subject: [PATCH 1/2] [clang][AVR] Add AVR-specific builtin functions

Add builtins for nop, sei, cli, sleep, wdr, swap, fmul/fmuls/fmulsu,
delay_cycles, nops, insert_bits, and flash_segment.

The builtins lower to their llvm.avr.* intrinsics, fmul variants use
inline asm, delay_cycles emits inline-asm delay loops, insert_bits
expands to bitwise shifts and masks based on a compile-time map, and
flash_segment resolves to a constant based on the pointer address space.

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            |  42 ++-
 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   | 303 +++++++++++++++++++++
 clang/lib/Sema/SemaChecking.cpp            |  23 ++
 clang/test/CodeGen/avr/avr-builtins.c      | 131 +++++++++
 clang/test/Preprocessor/avr-builtins.c     |  15 +
 clang/test/Sema/avr-builtins.c             |  32 +++
 12 files changed, 606 insertions(+), 7 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
 create mode 100644 clang/test/Sema/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..e157ebff8159a
--- /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")
+
+// 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")
+
+// TODO
+// __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..e4d174c43e775 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,19 @@ 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");
+  Builder.defineMacro("__BUILTIN_AVR_FMUL", "1");
+  Builder.defineMacro("__BUILTIN_AVR_FMULS", "1");
+  Builder.defineMacro("__BUILTIN_AVR_FMULSU", "1");
+  Builder.defineMacro("__BUILTIN_AVR_DELAY_CYCLES", "1");
+  Builder.defineMacro("__BUILTIN_AVR_NOPS", "1");
+  Builder.defineMacro("__BUILTIN_AVR_FLASH_SEGMENT", "1");
+  Builder.defineMacro("__BUILTIN_AVR_INSERT_BITS", "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..bb7b4fc459479
--- /dev/null
+++ b/clang/lib/CodeGen/TargetBuiltins/AVR.cpp
@@ -0,0 +1,303 @@
+//===------ 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;
+
+/// Emit an inline-asm-based fractional multiply (fmul/fmuls/fmulsu).
+/// All three variants share the same shape: two i8 inputs → one i16 output,
+/// with the result collected from R1:R0 via movw, then R1 cleared.
+static Value *EmitAVRFMulInlineAsm(CodeGenFunction &CGF, const CallExpr *E,
+                                   const char *AsmInsn) {
+  Value *Arg0 = CGF.EmitScalarExpr(E->getArg(0));
+  Value *Arg1 = CGF.EmitScalarExpr(E->getArg(1));
+  llvm::LLVMContext &Ctx = CGF.getLLVMContext();
+  llvm::Type *ResTy = llvm::Type::getInt16Ty(Ctx);
+  llvm::Type *ArgTy = llvm::Type::getInt8Ty(Ctx);
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(ResTy, {ArgTy, ArgTy}, false);
+
+  // Build the asm string: "<insn> $1, $2\n\tmovw $0, r0\n\tclr r1"
+  std::string Asm = std::string(AsmInsn) + " $1, $2\n\tmovw $0, r0\n\tclr r1";
+  llvm::InlineAsm *IA =
+      llvm::InlineAsm::get(FTy, Asm, "=r,a,a,~{r0},~{r1}", true);
+  return CGF.Builder.CreateCall(IA, {Arg0, Arg1});
+}
+
+/// Emit __builtin_avr_delay_cycles(N).
+///
+/// Generates an optimal sequence of inline assembly delay loops and NOPs
+/// to consume exactly N clock cycles.
+///
+/// The decomposed N into a sum of contributions from nested loops
+/// of decreasing register width, then fills the remainder with rjmp/.+0
+/// (2 cycles) and nop (1 cycle).
+///
+/// Loop types:
+///   4-byte loop: ldi×4 + (subi + sbci×3 + brne) = 9 setup + 6/iter
+///   3-byte loop: ldi×3 + (subi + sbci×2 + brne) = 7 setup + 5/iter
+///   2-byte loop: ldi×2 + (sbiw + brne)           = 5 setup + 4/iter
+///   1-byte loop: ldi   + (dec  + brne)            = 3/iter (no setup 
overhead)
+static Value *EmitAVRDelayLoops(CodeGenFunction &CGF, uint32_t Cycles) {
+  if (Cycles == 0)
+    return nullptr;
+
+  std::string Asm;
+  std::string Clobbers;
+  unsigned ClobberIdx = 0;
+  unsigned LabelIdx = 1;
+
+  auto AddClobber = [&](unsigned Reg) {
+    if (!Clobbers.empty())
+      Clobbers += ",";
+    Clobbers += "~{r" + std::to_string(Reg) + "}";
+  };
+
+  // 4-byte loop: 9 + 6*(loop_count-1) cycles
+  // ldi×4 + (subi + sbci×3 + brne) per iteration
+  if (Cycles >= 83886082u) {
+    uint32_t LoopCount = ((Cycles - 9) / 6) + 1;
+    uint32_t Used = ((LoopCount - 1) * 6) + 9;
+    unsigned Base = 16 + ClobberIdx;
+    std::string L = std::to_string(LabelIdx++);
+    Asm += "ldi r" + std::to_string(Base) + ", lo8(" +
+           std::to_string(LoopCount) + ")\n\t";
+    Asm += "ldi r" + std::to_string(Base + 1) + ", hi8(" +
+           std::to_string(LoopCount) + ")\n\t";
+    Asm += "ldi r" + std::to_string(Base + 2) + ", hlo8(" +
+           std::to_string(LoopCount) + ")\n\t";
+    Asm += "ldi r" + std::to_string(Base + 3) + ", hhi8(" +
+           std::to_string(LoopCount) + ")\n\t";
+    Asm += L + ": subi r" + std::to_string(Base) + ", 1\n\t";
+    Asm += "sbci r" + std::to_string(Base + 1) + ", 0\n\t";
+    Asm += "sbci r" + std::to_string(Base + 2) + ", 0\n\t";
+    Asm += "sbci r" + std::to_string(Base + 3) + ", 0\n\t";
+    Asm += "brne " + L + "b\n\t";
+    AddClobber(Base);
+    AddClobber(Base + 1);
+    AddClobber(Base + 2);
+    AddClobber(Base + 3);
+    ClobberIdx += 4;
+    Cycles -= Used;
+  }
+
+  // 3-byte loop: 7 + 5*(loop_count-1) cycles
+  // ldi×3 + (subi + sbci×2 + brne) per iteration
+  if (Cycles >= 262145u) {
+    uint32_t LoopCount = ((Cycles - 7) / 5) + 1;
+    if (LoopCount > 0xFFFFFFu)
+      LoopCount = 0xFFFFFFu;
+    uint32_t Used = ((LoopCount - 1) * 5) + 7;
+    unsigned Base = 16 + ClobberIdx;
+    std::string L = std::to_string(LabelIdx++);
+    Asm += "ldi r" + std::to_string(Base) + ", lo8(" +
+           std::to_string(LoopCount) + ")\n\t";
+    Asm += "ldi r" + std::to_string(Base + 1) + ", hi8(" +
+           std::to_string(LoopCount) + ")\n\t";
+    Asm += "ldi r" + std::to_string(Base + 2) + ", hlo8(" +
+           std::to_string(LoopCount) + ")\n\t";
+    Asm += L + ": subi r" + std::to_string(Base) + ", 1\n\t";
+    Asm += "sbci r" + std::to_string(Base + 1) + ", 0\n\t";
+    Asm += "sbci r" + std::to_string(Base + 2) + ", 0\n\t";
+    Asm += "brne " + L + "b\n\t";
+    AddClobber(Base);
+    AddClobber(Base + 1);
+    AddClobber(Base + 2);
+    ClobberIdx += 3;
+    Cycles -= Used;
+  }
+
+  // 2-byte loop: 5 + 4*(loop_count-1) cycles
+  // ldi×2 + (sbiw + brne) per iteration
+  // sbiw requires an even register in {r24, r26, r28, r30}.
+  if (Cycles >= 768u) {
+    uint32_t LoopCount = ((Cycles - 5) / 4) + 1;
+    if (LoopCount > 0xFFFFu)
+      LoopCount = 0xFFFFu;
+    uint32_t Used = ((LoopCount - 1) * 4) + 5;
+    std::string L = std::to_string(LabelIdx++);
+    // Use r24:r25 for sbiw (hardcoded per AVR ISA constraint).
+    Asm += "ldi r24, lo8(" + std::to_string(LoopCount) + ")\n\t";
+    Asm += "ldi r25, hi8(" + std::to_string(LoopCount) + ")\n\t";
+    Asm += L + ": sbiw r24, 1\n\t";
+    Asm += "brne " + L + "b\n\t";
+    AddClobber(24);
+    AddClobber(25);
+    Cycles -= Used;
+  }
+
+  // 1-byte loop: 3*loop_count cycles
+  // ldi + (dec + brne) per iteration
+  if (Cycles >= 6u) {
+    uint32_t LoopCount = Cycles / 3;
+    if (LoopCount > 255u)
+      LoopCount = 255u;
+    uint32_t Used = LoopCount * 3;
+    unsigned Reg = 16 + ClobberIdx;
+    if (Reg > 31)
+      Reg = 31; // safety
+    std::string L = std::to_string(LabelIdx++);
+    Asm += "ldi r" + std::to_string(Reg) + ", " + std::to_string(LoopCount) +
+           "\n\t";
+    Asm += L + ": dec r" + std::to_string(Reg) + "\n\t";
+    Asm += "brne " + L + "b\n\t";
+    AddClobber(Reg);
+    ClobberIdx++;
+    Cycles -= Used;
+  }
+
+  // Fill remaining with rjmp .+0 (2 cycles each)
+  while (Cycles >= 2) {
+    Asm += "rjmp .+0\n\t";
+    Cycles -= 2;
+  }
+
+  // Final single cycle
+  if (Cycles == 1) {
+    Asm += "nop\n\t";
+  }
+
+  if (Asm.empty())
+    return nullptr;
+
+  // Remove trailing \n\t
+  if (Asm.size() >= 3 && Asm.substr(Asm.size() - 3) == "\n\t")
+    Asm.resize(Asm.size() - 3);
+
+  llvm::LLVMContext &Ctx = CGF.getLLVMContext();
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false);
+  llvm::InlineAsm *IA = llvm::InlineAsm::get(FTy, Asm, Clobbers, true);
+  return CGF.Builder.CreateCall(IA);
+}
+
+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);
+  }
+  case AVR::BI__builtin_avr_fmul:
+    return EmitAVRFMulInlineAsm(*this, E, "fmul");
+  case AVR::BI__builtin_avr_fmuls:
+    return EmitAVRFMulInlineAsm(*this, E, "fmuls");
+  case AVR::BI__builtin_avr_fmulsu:
+    return EmitAVRFMulInlineAsm(*this, E, "fmulsu");
+
+  case AVR::BI__builtin_avr_delay_cycles: {
+    // Argument is validated as a compile time constant in Sema.
+    Expr::EvalResult Result;
+    E->getArg(0)->EvaluateAsInt(Result, getContext());
+    uint32_t Cycles = 
static_cast<uint32_t>(Result.Val.getInt().getZExtValue());
+    if (Cycles == 0) {
+      // Nothing to emit.
+      llvm::FunctionType *FTy = llvm::FunctionType::get(
+          llvm::Type::getVoidTy(getLLVMContext()), false);
+      return Builder.CreateCall(llvm::InlineAsm::get(FTy, "", "", true));
+    }
+    return EmitAVRDelayLoops(*this, Cycles);
+  }
+
+  case AVR::BI__builtin_avr_nops: {
+    // Argument is validated as a compile-time constant in Sema.
+    Expr::EvalResult Result;
+    E->getArg(0)->EvaluateAsInt(Result, getContext());
+    uint32_t N = static_cast<uint32_t>(Result.Val.getInt().getZExtValue());
+    if (N == 0) {
+      // Nothing to emit.
+      llvm::FunctionType *FTy = llvm::FunctionType::get(
+          llvm::Type::getVoidTy(getLLVMContext()), false);
+      return Builder.CreateCall(llvm::InlineAsm::get(FTy, "", "", true));
+    }
+    llvm::Function *NopFn = CGM.getIntrinsic(Intrinsic::avr_nop);
+    Value *Last = nullptr;
+    for (uint32_t I = 0; I < N; ++I)
+      Last = Builder.CreateCall(NopFn);
+    return Last;
+  }
+  case AVR::BI__builtin_avr_insert_bits: {
+    // Map is a compile-time constant (validated in Sema).
+    Expr::EvalResult MapResult;
+    E->getArg(0)->EvaluateAsInt(MapResult, getContext());
+    uint32_t Map =
+        static_cast<uint32_t>(MapResult.Val.getInt().getZExtValue());
+    Value *Bits = EmitScalarExpr(E->getArg(1));
+    Value *Val = EmitScalarExpr(E->getArg(2));
+
+    llvm::Type *I8Ty = Builder.getInt8Ty();
+    Value *Result = llvm::ConstantInt::get(I8Ty, 0);
+
+    for (unsigned I = 0; I < 8; ++I) {
+      unsigned Nibble = (Map >> (I * 4)) & 0xF;
+      Value *Bit;
+      if (Nibble < 8) {
+        // Extract bit 'Nibble' from 'Bits' and place it at position 'I'.
+        Bit = Builder.CreateAnd(
+            Builder.CreateLShr(Bits, llvm::ConstantInt::get(I8Ty, Nibble)),
+            llvm::ConstantInt::get(I8Ty, 1));
+      } else if (Nibble == 0xF) {
+        // Keep bit 'I' from 'Val'.
+        Bit = Builder.CreateAnd(
+            Builder.CreateLShr(Val, llvm::ConstantInt::get(I8Ty, I)),
+            llvm::ConstantInt::get(I8Ty, 1));
+      } else {
+        // Nibble 8-14: undefined per GCC docs, treat as 0.
+        continue;
+      }
+      Value *Shifted =
+          Builder.CreateShl(Bit, llvm::ConstantInt::get(I8Ty, I));
+      Result = Builder.CreateOr(Result, Shifted);
+    }
+    return Result;
+  }
+
+  case AVR::BI__builtin_avr_flash_segment: {
+    // Extract the address space from the pointer argument's type.
+    // __flash = addrspace(1) -> segment 0
+    // __flash1 = addrspace(2) -> segment 1
+    // ...
+    // __flash5 = addrspace(6) -> segment 5
+    // Non-flash (addrspace 0 or >6) -> -1
+    QualType ArgTy = E->getArg(0)->getType();
+    int8_t Segment = -1;
+    if (ArgTy->isPointerType()) {
+      LangAS AS = ArgTy->getPointeeType().getAddressSpace();
+      if (isTargetAddressSpace(AS)) {
+        unsigned TargetAS = toTargetAddressSpace(AS);
+        if (TargetAS >= 1 && TargetAS <= 6)
+          Segment = static_cast<int8_t>(TargetAS - 1);
+      }
+    }
+    return llvm::ConstantInt::get(Builder.getInt8Ty(), Segment,
+                                  /*IsSigned=*/true);
+  }
+  }
+}
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index b8a3f48a32f24..c467f7165b723 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -53,6 +53,7 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/Specifiers.h"
 #include "clang/Basic/SyncScope.h"
+#include "clang/Basic/TargetBuiltins.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TypeTraits.h"
 #include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
@@ -2124,6 +2125,28 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo 
&TI, unsigned BuiltinID,
     // Some builtins don't require additional checking, so just consider these
     // acceptable.
     return false;
+  case llvm::Triple::avr: {
+    switch (BuiltinID) {
+    default:
+      return false;
+    case AVR::BI__builtin_avr_delay_cycles: {
+      llvm::APSInt Result;
+      if (BuiltinConstantArg(TheCall, 0, Result))
+        return true;
+      if (Result.isNegative())
+        return Diag(TheCall->getArg(0)->getBeginLoc(),
+                    diag::err_argument_invalid_range)
+               << toString(Result, 10) << (unsigned)0 << (unsigned)UINT32_MAX
+               << TheCall->getArg(0)->getSourceRange();
+      return false;
+    }
+    case AVR::BI__builtin_avr_insert_bits:
+    case AVR::BI__builtin_avr_nops: {
+      llvm::APSInt Result;
+      return BuiltinConstantArg(TheCall, 0, Result);
+    }
+    }
+  }
   case llvm::Triple::arm:
   case llvm::Triple::armeb:
   case llvm::Triple::thumb:
diff --git a/clang/test/CodeGen/avr/avr-builtins.c 
b/clang/test/CodeGen/avr/avr-builtins.c
index 7c2c424848080..3af77f1cae7d0 100644
--- a/clang/test/CodeGen/avr/avr-builtins.c
+++ b/clang/test/CodeGen/avr/avr-builtins.c
@@ -125,3 +125,134 @@ long double powil(long double x, int y) {
 
 // CHECK: define{{.*}} float @powil
 // CHECK: float @llvm.powi.f32.i16(float %0, i16 %1)
+
+// CHECK-LABEL: define{{.*}} void @test_nop()
+void test_nop(void) {
+  // CHECK: call{{.*}} void @llvm.avr.nop()
+  __builtin_avr_nop();
+}
+
+// CHECK-LABEL: define{{.*}} void @test_sei()
+void test_sei(void) {
+  // CHECK: call{{.*}} void @llvm.avr.sei()
+  __builtin_avr_sei();
+}
+
+// CHECK-LABEL: define{{.*}} void @test_cli()
+void test_cli(void) {
+  // CHECK: call{{.*}} void @llvm.avr.cli()
+  __builtin_avr_cli();
+}
+
+// CHECK-LABEL: define{{.*}} void @test_sleep()
+void test_sleep(void) {
+  // CHECK: call{{.*}} void @llvm.avr.sleep()
+  __builtin_avr_sleep();
+}
+
+// CHECK-LABEL: define{{.*}} void @test_wdr()
+void test_wdr(void) {
+  // CHECK: call{{.*}} void @llvm.avr.wdr()
+  __builtin_avr_wdr();
+}
+
+// CHECK-LABEL: define{{.*}} i8 @test_swap
+unsigned char test_swap(unsigned char a) {
+  // CHECK: call{{.*}} i8 @llvm.avr.swap(i8
+  return __builtin_avr_swap(a);
+}
+
+// CHECK-LABEL: define{{.*}} i16 @test_fmul
+unsigned int test_fmul(unsigned char a, unsigned char b) {
+  // CHECK: call{{.*}} i16 asm sideeffect "fmul $1, $2
+  return __builtin_avr_fmul(a, b);
+}
+
+// CHECK-LABEL: define{{.*}} i16 @test_fmuls
+int test_fmuls(signed char a, signed char b) {
+  // CHECK: call{{.*}} i16 asm sideeffect "fmuls $1, $2
+  return __builtin_avr_fmuls(a, b);
+}
+
+// CHECK-LABEL: define{{.*}} i16 @test_fmulsu
+int test_fmulsu(signed char a, unsigned char b) {
+  // CHECK: call{{.*}} i16 asm sideeffect "fmulsu $1, $2
+  return __builtin_avr_fmulsu(a, b);
+}
+
+// CHECK-LABEL: define{{.*}} void @test_nops()
+void test_nops(void) {
+  // CHECK: call{{.*}} void @llvm.avr.nop()
+  // CHECK-NEXT: call{{.*}} void @llvm.avr.nop()
+  // CHECK-NEXT: call{{.*}} void @llvm.avr.nop()
+  __builtin_avr_nops(3);
+}
+
+// CHECK-LABEL: define{{.*}} void @test_delay_cycles_small()
+void test_delay_cycles_small(void) {
+  // 1 cycle = 1 nop
+  // CHECK: call{{.*}} void asm sideeffect "nop
+  __builtin_avr_delay_cycles(1);
+}
+
+// CHECK-LABEL: define{{.*}} void @test_delay_cycles_two()
+void test_delay_cycles_two(void) {
+  // 2 cycles = rjmp .+0
+  // CHECK: call{{.*}} void asm sideeffect "rjmp .+0
+  __builtin_avr_delay_cycles(2);
+}
+
+// CHECK-LABEL: define{{.*}} void @test_delay_cycles_loop()
+void test_delay_cycles_loop(void) {
+  // 12 cycles: 1-byte loop (4 iters = 12 cycles)
+  // CHECK: call{{.*}} void asm sideeffect "ldi{{.*}}dec{{.*}}brne
+  __builtin_avr_delay_cycles(12);
+}
+
+// CHECK-LABEL: define{{.*}} void @test_delay_cycles_zero()
+void test_delay_cycles_zero(void) {
+  // 0 cycles = empty inline asm
+  // CHECK: call{{.*}} void asm sideeffect "", ""()
+  __builtin_avr_delay_cycles(0);
+}
+
+// CHECK-LABEL: define{{.*}} i8 @test_insert_bits_identity
+unsigned char test_insert_bits_identity(unsigned char bits, unsigned char val) 
{
+  // Identity map: 0x76543210 — each nibble N maps bit N from 'bits'
+  // CHECK: lshr
+  // CHECK: and
+  // CHECK: or
+  return __builtin_avr_insert_bits(0x76543210UL, bits, val);
+}
+
+// CHECK-LABEL: define{{.*}} i8 @test_insert_bits_reverse
+unsigned char test_insert_bits_reverse(unsigned char bits) {
+  // Reverse map: 0x01234567 — reverses the bit order
+  // CHECK: lshr
+  // CHECK: and
+  return __builtin_avr_insert_bits(0x01234567UL, bits, 0);
+}
+
+// CHECK-LABEL: define{{.*}} i8 @test_insert_bits_keep_val
+unsigned char test_insert_bits_keep_val(unsigned char val) {
+  // 0xFFFFFFFF — all nibbles are 0xF, keep all bits from 'val'
+  // CHECK: lshr
+  // CHECK: and
+  return __builtin_avr_insert_bits(0xFFFFFFFFUL, 0, val);
+}
+
+// CHECK-LABEL: define{{.*}} i8 @test_flash_segment_flash
+signed char test_flash_segment_flash(void) {
+  const __attribute__((address_space(1))) unsigned char *p = 0;
+  // __flash = addrspace(1), segment 0
+  // CHECK: ret i8 0
+  return __builtin_avr_flash_segment(p);
+}
+
+// CHECK-LABEL: define{{.*}} i8 @test_flash_segment_ram
+signed char test_flash_segment_ram(void) {
+  const unsigned char *p = 0;
+  // RAM = addrspace(0), segment -1
+  // CHECK: ret i8 -1
+  return __builtin_avr_flash_segment(p);
+}
diff --git a/clang/test/Preprocessor/avr-builtins.c 
b/clang/test/Preprocessor/avr-builtins.c
new file mode 100644
index 0000000000000..6b82a30401716
--- /dev/null
+++ b/clang/test/Preprocessor/avr-builtins.c
@@ -0,0 +1,15 @@
+// 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_DELAY_CYCLES 1
+// CHECK: #define __BUILTIN_AVR_FLASH_SEGMENT 1
+// CHECK: #define __BUILTIN_AVR_FMUL 1
+// CHECK: #define __BUILTIN_AVR_FMULS 1
+// CHECK: #define __BUILTIN_AVR_FMULSU 1
+// CHECK: #define __BUILTIN_AVR_INSERT_BITS 1
+// CHECK: #define __BUILTIN_AVR_NOP 1
+// CHECK: #define __BUILTIN_AVR_NOPS 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
diff --git a/clang/test/Sema/avr-builtins.c b/clang/test/Sema/avr-builtins.c
new file mode 100644
index 0000000000000..e389a03a38f96
--- /dev/null
+++ b/clang/test/Sema/avr-builtins.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple avr-unknown-unknown -fsyntax-only -verify %s
+
+void test_delay_cycles_variable(unsigned long n) {
+  __builtin_avr_delay_cycles(n); // expected-error {{argument to 
'__builtin_avr_delay_cycles' must be a constant integer}}
+}
+
+void test_delay_cycles_ok(void) {
+  __builtin_avr_delay_cycles(100); // ok
+  __builtin_avr_delay_cycles(0);   // ok
+}
+
+void test_nops_variable(unsigned int n) {
+  __builtin_avr_nops(n); // expected-error {{argument to '__builtin_avr_nops' 
must be a constant integer}}
+}
+
+void test_nops_ok(void) {
+  __builtin_avr_nops(5); // ok
+  __builtin_avr_nops(0); // ok
+}
+
+void test_insert_bits_variable(unsigned long map, unsigned char bits,
+                               unsigned char val) {
+  __builtin_avr_insert_bits(map, bits, val); // expected-error {{argument to 
'__builtin_avr_insert_bits' must be a constant integer}}
+}
+
+unsigned char test_insert_bits_ok(unsigned char bits, unsigned char val) {
+  unsigned char r;
+  r = __builtin_avr_insert_bits(0x76543210UL, bits, val); // ok
+  r = __builtin_avr_insert_bits(0xFFFFFFFFUL, 0, val);    // ok
+  r = __builtin_avr_insert_bits(0x01234567UL, bits, 0);   // ok
+  return r;
+}

>From f603008ce9c91ea552c72d8e2d487a7272c7dba8 Mon Sep 17 00:00:00 2001
From: Dakkshesh <[email protected]>
Date: Fri, 12 Jun 2026 11:37:13 +0530
Subject: [PATCH 2/2] [clang][AVR] Format test files

Signed-off-by: Dakkshesh <[email protected]>
---
 clang/test/CodeGen/avr/avr-builtins.c | 528 ++++++++++++++++++++++----
 clang/test/Sema/avr-builtins.c        |   1 +
 2 files changed, 449 insertions(+), 80 deletions(-)

diff --git a/clang/test/CodeGen/avr/avr-builtins.c 
b/clang/test/CodeGen/avr/avr-builtins.c
index 3af77f1cae7d0..d393c4f81ac6c 100644
--- a/clang/test/CodeGen/avr/avr-builtins.c
+++ b/clang/test/CodeGen/avr/avr-builtins.c
@@ -1,258 +1,626 @@
+// 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{{.*}} void @test_nop()
+// 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) {
-  // CHECK: call{{.*}} void @llvm.avr.nop()
   __builtin_avr_nop();
 }
 
-// CHECK-LABEL: define{{.*}} void @test_sei()
+// 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) {
-  // CHECK: call{{.*}} void @llvm.avr.sei()
   __builtin_avr_sei();
 }
 
-// CHECK-LABEL: define{{.*}} void @test_cli()
+// 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) {
-  // CHECK: call{{.*}} void @llvm.avr.cli()
   __builtin_avr_cli();
 }
 
-// CHECK-LABEL: define{{.*}} void @test_sleep()
+// 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) {
-  // CHECK: call{{.*}} void @llvm.avr.sleep()
   __builtin_avr_sleep();
 }
 
-// CHECK-LABEL: define{{.*}} void @test_wdr()
+// 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) {
-  // CHECK: call{{.*}} void @llvm.avr.wdr()
   __builtin_avr_wdr();
 }
 
-// CHECK-LABEL: define{{.*}} i8 @test_swap
+// 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) {
-  // CHECK: call{{.*}} i8 @llvm.avr.swap(i8
   return __builtin_avr_swap(a);
 }
 
-// CHECK-LABEL: define{{.*}} i16 @test_fmul
+// CHECK-LABEL: define dso_local i16 @test_fmul(
+// CHECK-SAME: i8 noundef zeroext [[A:%.*]], i8 noundef zeroext [[B:%.*]]) 
addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i8 [[A]], ptr [[A_ADDR]], align 1
+// CHECK-NEXT:    store i8 [[B]], ptr [[B_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[A_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[B_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = call addrspace(0) i16 asm sideeffect "fmul 
$1, $2\0A\09movw $0, r0\0A\09clr r1", "=r,a,a,~{r0},~{r1}"(i8 [[TMP0]], i8 
[[TMP1]])
+// CHECK-NEXT:    ret i16 [[TMP2]]
+//
 unsigned int test_fmul(unsigned char a, unsigned char b) {
-  // CHECK: call{{.*}} i16 asm sideeffect "fmul $1, $2
   return __builtin_avr_fmul(a, b);
 }
 
-// CHECK-LABEL: define{{.*}} i16 @test_fmuls
+// CHECK-LABEL: define dso_local i16 @test_fmuls(
+// CHECK-SAME: i8 noundef signext [[A:%.*]], i8 noundef signext [[B:%.*]]) 
addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i8 [[A]], ptr [[A_ADDR]], align 1
+// CHECK-NEXT:    store i8 [[B]], ptr [[B_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[A_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[B_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = call addrspace(0) i16 asm sideeffect "fmuls 
$1, $2\0A\09movw $0, r0\0A\09clr r1", "=r,a,a,~{r0},~{r1}"(i8 [[TMP0]], i8 
[[TMP1]])
+// CHECK-NEXT:    ret i16 [[TMP2]]
+//
 int test_fmuls(signed char a, signed char b) {
-  // CHECK: call{{.*}} i16 asm sideeffect "fmuls $1, $2
   return __builtin_avr_fmuls(a, b);
 }
 
-// CHECK-LABEL: define{{.*}} i16 @test_fmulsu
+// CHECK-LABEL: define dso_local i16 @test_fmulsu(
+// CHECK-SAME: i8 noundef signext [[A:%.*]], i8 noundef zeroext [[B:%.*]]) 
addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i8 [[A]], ptr [[A_ADDR]], align 1
+// CHECK-NEXT:    store i8 [[B]], ptr [[B_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[A_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[B_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = call addrspace(0) i16 asm sideeffect "fmulsu 
$1, $2\0A\09movw $0, r0\0A\09clr r1", "=r,a,a,~{r0},~{r1}"(i8 [[TMP0]], i8 
[[TMP1]])
+// CHECK-NEXT:    ret i16 [[TMP2]]
+//
 int test_fmulsu(signed char a, unsigned char b) {
-  // CHECK: call{{.*}} i16 asm sideeffect "fmulsu $1, $2
   return __builtin_avr_fmulsu(a, b);
 }
 
-// CHECK-LABEL: define{{.*}} void @test_nops()
+// CHECK-LABEL: define dso_local void @test_nops(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call addrspace(1) void @llvm.avr.nop()
+// CHECK-NEXT:    call addrspace(1) void @llvm.avr.nop()
+// CHECK-NEXT:    call addrspace(1) void @llvm.avr.nop()
+// CHECK-NEXT:    ret void
+//
 void test_nops(void) {
-  // CHECK: call{{.*}} void @llvm.avr.nop()
-  // CHECK-NEXT: call{{.*}} void @llvm.avr.nop()
-  // CHECK-NEXT: call{{.*}} void @llvm.avr.nop()
   __builtin_avr_nops(3);
 }
 
-// CHECK-LABEL: define{{.*}} void @test_delay_cycles_small()
+// CHECK-LABEL: define dso_local void @test_delay_cycles_small(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call addrspace(0) void asm sideeffect "nop\0A\09", ""()
+// CHECK-NEXT:    ret void
+//
 void test_delay_cycles_small(void) {
   // 1 cycle = 1 nop
-  // CHECK: call{{.*}} void asm sideeffect "nop
   __builtin_avr_delay_cycles(1);
 }
 
-// CHECK-LABEL: define{{.*}} void @test_delay_cycles_two()
+// CHECK-LABEL: define dso_local void @test_delay_cycles_two(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call addrspace(0) void asm sideeffect "rjmp .+0\0A\09", ""()
+// CHECK-NEXT:    ret void
+//
 void test_delay_cycles_two(void) {
   // 2 cycles = rjmp .+0
-  // CHECK: call{{.*}} void asm sideeffect "rjmp .+0
   __builtin_avr_delay_cycles(2);
 }
 
-// CHECK-LABEL: define{{.*}} void @test_delay_cycles_loop()
+// CHECK-LABEL: define dso_local void @test_delay_cycles_loop(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call addrspace(0) void asm sideeffect "ldi r16, 4\0A\091: 
dec r16\0A\09brne 1b\0A\09", "~{r16}"()
+// CHECK-NEXT:    ret void
+//
 void test_delay_cycles_loop(void) {
   // 12 cycles: 1-byte loop (4 iters = 12 cycles)
-  // CHECK: call{{.*}} void asm sideeffect "ldi{{.*}}dec{{.*}}brne
   __builtin_avr_delay_cycles(12);
 }
 
-// CHECK-LABEL: define{{.*}} void @test_delay_cycles_zero()
+// CHECK-LABEL: define dso_local void @test_delay_cycles_zero(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call addrspace(0) void asm sideeffect "", ""()
+// CHECK-NEXT:    ret void
+//
 void test_delay_cycles_zero(void) {
   // 0 cycles = empty inline asm
-  // CHECK: call{{.*}} void asm sideeffect "", ""()
   __builtin_avr_delay_cycles(0);
 }
 
-// CHECK-LABEL: define{{.*}} i8 @test_insert_bits_identity
+// CHECK-LABEL: define dso_local i8 @test_insert_bits_identity(
+// CHECK-SAME: i8 noundef zeroext [[BITS:%.*]], i8 noundef zeroext 
[[VAL:%.*]]) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[BITS_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[VAL_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i8 [[BITS]], ptr [[BITS_ADDR]], align 1
+// CHECK-NEXT:    store i8 [[VAL]], ptr [[VAL_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[BITS_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[VAL_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = lshr i8 [[TMP0]], 0
+// CHECK-NEXT:    [[TMP3:%.*]] = and i8 [[TMP2]], 1
+// CHECK-NEXT:    [[TMP4:%.*]] = shl i8 [[TMP3]], 0
+// CHECK-NEXT:    [[TMP5:%.*]] = or i8 0, [[TMP4]]
+// CHECK-NEXT:    [[TMP6:%.*]] = lshr i8 [[TMP0]], 1
+// CHECK-NEXT:    [[TMP7:%.*]] = and i8 [[TMP6]], 1
+// CHECK-NEXT:    [[TMP8:%.*]] = shl i8 [[TMP7]], 1
+// CHECK-NEXT:    [[TMP9:%.*]] = or i8 [[TMP5]], [[TMP8]]
+// CHECK-NEXT:    [[TMP10:%.*]] = lshr i8 [[TMP0]], 2
+// CHECK-NEXT:    [[TMP11:%.*]] = and i8 [[TMP10]], 1
+// CHECK-NEXT:    [[TMP12:%.*]] = shl i8 [[TMP11]], 2
+// CHECK-NEXT:    [[TMP13:%.*]] = or i8 [[TMP9]], [[TMP12]]
+// CHECK-NEXT:    [[TMP14:%.*]] = lshr i8 [[TMP0]], 3
+// CHECK-NEXT:    [[TMP15:%.*]] = and i8 [[TMP14]], 1
+// CHECK-NEXT:    [[TMP16:%.*]] = shl i8 [[TMP15]], 3
+// CHECK-NEXT:    [[TMP17:%.*]] = or i8 [[TMP13]], [[TMP16]]
+// CHECK-NEXT:    [[TMP18:%.*]] = lshr i8 [[TMP0]], 4
+// CHECK-NEXT:    [[TMP19:%.*]] = and i8 [[TMP18]], 1
+// CHECK-NEXT:    [[TMP20:%.*]] = shl i8 [[TMP19]], 4
+// CHECK-NEXT:    [[TMP21:%.*]] = or i8 [[TMP17]], [[TMP20]]
+// CHECK-NEXT:    [[TMP22:%.*]] = lshr i8 [[TMP0]], 5
+// CHECK-NEXT:    [[TMP23:%.*]] = and i8 [[TMP22]], 1
+// CHECK-NEXT:    [[TMP24:%.*]] = shl i8 [[TMP23]], 5
+// CHECK-NEXT:    [[TMP25:%.*]] = or i8 [[TMP21]], [[TMP24]]
+// CHECK-NEXT:    [[TMP26:%.*]] = lshr i8 [[TMP0]], 6
+// CHECK-NEXT:    [[TMP27:%.*]] = and i8 [[TMP26]], 1
+// CHECK-NEXT:    [[TMP28:%.*]] = shl i8 [[TMP27]], 6
+// CHECK-NEXT:    [[TMP29:%.*]] = or i8 [[TMP25]], [[TMP28]]
+// CHECK-NEXT:    [[TMP30:%.*]] = lshr i8 [[TMP0]], 7
+// CHECK-NEXT:    [[TMP31:%.*]] = and i8 [[TMP30]], 1
+// CHECK-NEXT:    [[TMP32:%.*]] = shl i8 [[TMP31]], 7
+// CHECK-NEXT:    [[TMP33:%.*]] = or i8 [[TMP29]], [[TMP32]]
+// CHECK-NEXT:    ret i8 [[TMP33]]
+//
 unsigned char test_insert_bits_identity(unsigned char bits, unsigned char val) 
{
   // Identity map: 0x76543210 — each nibble N maps bit N from 'bits'
-  // CHECK: lshr
-  // CHECK: and
-  // CHECK: or
   return __builtin_avr_insert_bits(0x76543210UL, bits, val);
 }
 
-// CHECK-LABEL: define{{.*}} i8 @test_insert_bits_reverse
+// CHECK-LABEL: define dso_local i8 @test_insert_bits_reverse(
+// CHECK-SAME: i8 noundef zeroext [[BITS:%.*]]) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[BITS_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i8 [[BITS]], ptr [[BITS_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[BITS_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = lshr i8 [[TMP0]], 7
+// CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[TMP1]], 1
+// CHECK-NEXT:    [[TMP3:%.*]] = shl i8 [[TMP2]], 0
+// CHECK-NEXT:    [[TMP4:%.*]] = or i8 0, [[TMP3]]
+// CHECK-NEXT:    [[TMP5:%.*]] = lshr i8 [[TMP0]], 6
+// CHECK-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], 1
+// CHECK-NEXT:    [[TMP7:%.*]] = shl i8 [[TMP6]], 1
+// CHECK-NEXT:    [[TMP8:%.*]] = or i8 [[TMP4]], [[TMP7]]
+// CHECK-NEXT:    [[TMP9:%.*]] = lshr i8 [[TMP0]], 5
+// CHECK-NEXT:    [[TMP10:%.*]] = and i8 [[TMP9]], 1
+// CHECK-NEXT:    [[TMP11:%.*]] = shl i8 [[TMP10]], 2
+// CHECK-NEXT:    [[TMP12:%.*]] = or i8 [[TMP8]], [[TMP11]]
+// CHECK-NEXT:    [[TMP13:%.*]] = lshr i8 [[TMP0]], 4
+// CHECK-NEXT:    [[TMP14:%.*]] = and i8 [[TMP13]], 1
+// CHECK-NEXT:    [[TMP15:%.*]] = shl i8 [[TMP14]], 3
+// CHECK-NEXT:    [[TMP16:%.*]] = or i8 [[TMP12]], [[TMP15]]
+// CHECK-NEXT:    [[TMP17:%.*]] = lshr i8 [[TMP0]], 3
+// CHECK-NEXT:    [[TMP18:%.*]] = and i8 [[TMP17]], 1
+// CHECK-NEXT:    [[TMP19:%.*]] = shl i8 [[TMP18]], 4
+// CHECK-NEXT:    [[TMP20:%.*]] = or i8 [[TMP16]], [[TMP19]]
+// CHECK-NEXT:    [[TMP21:%.*]] = lshr i8 [[TMP0]], 2
+// CHECK-NEXT:    [[TMP22:%.*]] = and i8 [[TMP21]], 1
+// CHECK-NEXT:    [[TMP23:%.*]] = shl i8 [[TMP22]], 5
+// CHECK-NEXT:    [[TMP24:%.*]] = or i8 [[TMP20]], [[TMP23]]
+// CHECK-NEXT:    [[TMP25:%.*]] = lshr i8 [[TMP0]], 1
+// CHECK-NEXT:    [[TMP26:%.*]] = and i8 [[TMP25]], 1
+// CHECK-NEXT:    [[TMP27:%.*]] = shl i8 [[TMP26]], 6
+// CHECK-NEXT:    [[TMP28:%.*]] = or i8 [[TMP24]], [[TMP27]]
+// CHECK-NEXT:    [[TMP29:%.*]] = lshr i8 [[TMP0]], 0
+// CHECK-NEXT:    [[TMP30:%.*]] = and i8 [[TMP29]], 1
+// CHECK-NEXT:    [[TMP31:%.*]] = shl i8 [[TMP30]], 7
+// CHECK-NEXT:    [[TMP32:%.*]] = or i8 [[TMP28]], [[TMP31]]
+// CHECK-NEXT:    ret i8 [[TMP32]]
+//
 unsigned char test_insert_bits_reverse(unsigned char bits) {
   // Reverse map: 0x01234567 — reverses the bit order
-  // CHECK: lshr
-  // CHECK: and
   return __builtin_avr_insert_bits(0x01234567UL, bits, 0);
 }
 
-// CHECK-LABEL: define{{.*}} i8 @test_insert_bits_keep_val
+// CHECK-LABEL: define dso_local i8 @test_insert_bits_keep_val(
+// CHECK-SAME: i8 noundef zeroext [[VAL:%.*]]) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[VAL_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i8 [[VAL]], ptr [[VAL_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[VAL_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = lshr i8 [[TMP0]], 0
+// CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[TMP1]], 1
+// CHECK-NEXT:    [[TMP3:%.*]] = shl i8 [[TMP2]], 0
+// CHECK-NEXT:    [[TMP4:%.*]] = or i8 0, [[TMP3]]
+// CHECK-NEXT:    [[TMP5:%.*]] = lshr i8 [[TMP0]], 1
+// CHECK-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], 1
+// CHECK-NEXT:    [[TMP7:%.*]] = shl i8 [[TMP6]], 1
+// CHECK-NEXT:    [[TMP8:%.*]] = or i8 [[TMP4]], [[TMP7]]
+// CHECK-NEXT:    [[TMP9:%.*]] = lshr i8 [[TMP0]], 2
+// CHECK-NEXT:    [[TMP10:%.*]] = and i8 [[TMP9]], 1
+// CHECK-NEXT:    [[TMP11:%.*]] = shl i8 [[TMP10]], 2
+// CHECK-NEXT:    [[TMP12:%.*]] = or i8 [[TMP8]], [[TMP11]]
+// CHECK-NEXT:    [[TMP13:%.*]] = lshr i8 [[TMP0]], 3
+// CHECK-NEXT:    [[TMP14:%.*]] = and i8 [[TMP13]], 1
+// CHECK-NEXT:    [[TMP15:%.*]] = shl i8 [[TMP14]], 3
+// CHECK-NEXT:    [[TMP16:%.*]] = or i8 [[TMP12]], [[TMP15]]
+// CHECK-NEXT:    [[TMP17:%.*]] = lshr i8 [[TMP0]], 4
+// CHECK-NEXT:    [[TMP18:%.*]] = and i8 [[TMP17]], 1
+// CHECK-NEXT:    [[TMP19:%.*]] = shl i8 [[TMP18]], 4
+// CHECK-NEXT:    [[TMP20:%.*]] = or i8 [[TMP16]], [[TMP19]]
+// CHECK-NEXT:    [[TMP21:%.*]] = lshr i8 [[TMP0]], 5
+// CHECK-NEXT:    [[TMP22:%.*]] = and i8 [[TMP21]], 1
+// CHECK-NEXT:    [[TMP23:%.*]] = shl i8 [[TMP22]], 5
+// CHECK-NEXT:    [[TMP24:%.*]] = or i8 [[TMP20]], [[TMP23]]
+// CHECK-NEXT:    [[TMP25:%.*]] = lshr i8 [[TMP0]], 6
+// CHECK-NEXT:    [[TMP26:%.*]] = and i8 [[TMP25]], 1
+// CHECK-NEXT:    [[TMP27:%.*]] = shl i8 [[TMP26]], 6
+// CHECK-NEXT:    [[TMP28:%.*]] = or i8 [[TMP24]], [[TMP27]]
+// CHECK-NEXT:    [[TMP29:%.*]] = lshr i8 [[TMP0]], 7
+// CHECK-NEXT:    [[TMP30:%.*]] = and i8 [[TMP29]], 1
+// CHECK-NEXT:    [[TMP31:%.*]] = shl i8 [[TMP30]], 7
+// CHECK-NEXT:    [[TMP32:%.*]] = or i8 [[TMP28]], [[TMP31]]
+// CHECK-NEXT:    ret i8 [[TMP32]]
+//
 unsigned char test_insert_bits_keep_val(unsigned char val) {
   // 0xFFFFFFFF — all nibbles are 0xF, keep all bits from 'val'
-  // CHECK: lshr
-  // CHECK: and
   return __builtin_avr_insert_bits(0xFFFFFFFFUL, 0, val);
 }
 
-// CHECK-LABEL: define{{.*}} i8 @test_flash_segment_flash
+// CHECK-LABEL: define dso_local i8 @test_flash_segment_flash(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[P:%.*]] = alloca ptr addrspace(1), align 1
+// CHECK-NEXT:    store ptr addrspace(1) null, ptr [[P]], align 1
+// CHECK-NEXT:    ret i8 0
+//
 signed char test_flash_segment_flash(void) {
   const __attribute__((address_space(1))) unsigned char *p = 0;
   // __flash = addrspace(1), segment 0
-  // CHECK: ret i8 0
   return __builtin_avr_flash_segment(p);
 }
 
-// CHECK-LABEL: define{{.*}} i8 @test_flash_segment_ram
+// CHECK-LABEL: define dso_local i8 @test_flash_segment_ram(
+// CHECK-SAME: ) addrspace(1) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[P:%.*]] = alloca ptr, align 1
+// CHECK-NEXT:    store ptr null, ptr [[P]], align 1
+// CHECK-NEXT:    ret i8 -1
+//
 signed char test_flash_segment_ram(void) {
   const unsigned char *p = 0;
   // RAM = addrspace(0), segment -1
-  // CHECK: ret i8 -1
   return __builtin_avr_flash_segment(p);
 }
diff --git a/clang/test/Sema/avr-builtins.c b/clang/test/Sema/avr-builtins.c
index e389a03a38f96..f501354e951cf 100644
--- a/clang/test/Sema/avr-builtins.c
+++ b/clang/test/Sema/avr-builtins.c
@@ -1,3 +1,4 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
 // RUN: %clang_cc1 -triple avr-unknown-unknown -fsyntax-only -verify %s
 
 void test_delay_cycles_variable(unsigned long n) {

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

Reply via email to