diff --git a/llvm/lib/Target/AVR/AVRTargetMachine.h b/llvm/lib/Target/AVR/AVRTargetMachine.h --- a/llvm/lib/Target/AVR/AVRTargetMachine.h +++ b/llvm/lib/Target/AVR/AVRTargetMachine.h @@ -48,6 +48,15 @@ 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 --- /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 +}