From 8202a3da3c897fc663f55ae5c638ae56f11543c1 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Thu, 19 Jan 2023 14:49:43 +0100 Subject: [PATCH] [AVR] Support most address space casts All hardware address spaces on AVR can be freely cast between (they keep the same bit pattern). They just aren't dereferenceable when they're in a different address space as they really do point to a separate address space. This is supported in avr-gcc: https://godbolt.org/z/9Gfvhnhv9 avr-gcc also supports the `__memx` address space which is 24 bits. We don't support this address space yet but I've added a safeguard just in case. Differential Revison: https://reviews.llvm.org/D142107 --- llvm/lib/Target/AVR/AVRTargetMachine.h | 9 +++++ llvm/test/CodeGen/AVR/addrspacecast.ll | 65 ++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 llvm/test/CodeGen/AVR/addrspacecast.ll diff --git a/llvm/lib/Target/AVR/AVRTargetMachine.h b/llvm/lib/Target/AVR/AVRTargetMachine.h index ea29c8e..0fee27d 100644 --- a/llvm/lib/Target/AVR/AVRTargetMachine.h +++ b/llvm/lib/Target/AVR/AVRTargetMachine.h @@ -48,6 +48,15 @@ public: createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F, const TargetSubtargetInfo *STI) const override; + bool isNoopAddrSpaceCast(unsigned SrcAs, unsigned DestAs) const override { + // While AVR has different address spaces, they are all represented by + // 16-bit pointers that can be freely casted between (of course, a pointer + // must be cast back to its original address space to be dereferenceable). + // To be safe, also check the pointer size in case we implement __memx + // pointers. + return getPointerSize(SrcAs) == getPointerSize(DestAs); + } + private: std::unique_ptr TLOF; AVRSubtarget SubTarget; diff --git a/llvm/test/CodeGen/AVR/addrspacecast.ll b/llvm/test/CodeGen/AVR/addrspacecast.ll new file mode 100644 index 0000000..eb582e1 --- /dev/null +++ b/llvm/test/CodeGen/AVR/addrspacecast.ll @@ -0,0 +1,65 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=avr | FileCheck %s + +@global = external global i8 +@progmem = external addrspace(1) global i8 + +declare void @func() addrspace(1) +declare void @doCallback(ptr) addrspace(1) + +define ptr @casttodata(ptr addrspace(1) %funcptr) addrspace(1) { +; CHECK-LABEL: casttodata: +; CHECK: ; %bb.0: +; CHECK-NEXT: ret + %result = addrspacecast ptr addrspace(1) %funcptr to ptr + ret ptr %result +} + +define ptr addrspace(1) @casttofuncptr(ptr %data) addrspace(1) { +; CHECK-LABEL: casttofuncptr: +; CHECK: ; %bb.0: +; CHECK-NEXT: ret + %result = addrspacecast ptr %data to ptr addrspace(1) + ret ptr addrspace(1) %result +} + +define ptr addrspace(1) @castglobal() addrspace(1) { +; CHECK-LABEL: castglobal: +; CHECK: ; %bb.0: +; CHECK-NEXT: ldi r24, lo8(global) +; CHECK-NEXT: ldi r25, hi8(global) +; CHECK-NEXT: ret + %result = addrspacecast ptr @global to ptr addrspace(1) + ret ptr addrspace(1) %result +} + +define ptr @castprogmem() addrspace(1) { +; CHECK-LABEL: castprogmem: +; CHECK: ; %bb.0: +; CHECK-NEXT: ldi r24, lo8(progmem) +; CHECK-NEXT: ldi r25, hi8(progmem) +; CHECK-NEXT: ret + %result = addrspacecast ptr addrspace(1) @progmem to ptr + ret ptr %result +} + +define ptr @castfunc() addrspace(1) { +; CHECK-LABEL: castfunc: +; CHECK: ; %bb.0: +; CHECK-NEXT: ldi r24, pm_lo8(func) +; CHECK-NEXT: ldi r25, pm_hi8(func) +; CHECK-NEXT: ret + %result = addrspacecast ptr addrspace(1) @func to ptr + ret ptr %result +} + +define void @callCallback() addrspace(1) { +; CHECK-LABEL: callCallback: +; CHECK: ; %bb.0: +; CHECK-NEXT: ldi r24, pm_lo8(func) +; CHECK-NEXT: ldi r25, pm_hi8(func) +; CHECK-NEXT: rcall doCallback +; CHECK-NEXT: ret + call addrspace(1) void @doCallback(ptr addrspacecast (ptr addrspace(1) @func to ptr)) + ret void +} -- 2.7.4