diff --git a/clang/lib/Basic/Targets/AVR.h b/clang/lib/Basic/Targets/AVR.h index 75c969fd59dc9..11aa844f2ce55 100644 --- a/clang/lib/Basic/Targets/AVR.h +++ b/clang/lib/Basic/Targets/AVR.h @@ -57,7 +57,8 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo { Int16Type = SignedInt; Char32Type = UnsignedLong; SigAtomicType = SignedChar; - resetDataLayout("e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8"); + resetDataLayout( + "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-n16:8-a:8"); } void getTargetDefines(const LangOptions &Opts, diff --git a/llvm/lib/Target/AVR/AVRTargetMachine.cpp b/llvm/lib/Target/AVR/AVRTargetMachine.cpp index b75417a0896a5..02212d2151f4c 100644 --- a/llvm/lib/Target/AVR/AVRTargetMachine.cpp +++ b/llvm/lib/Target/AVR/AVRTargetMachine.cpp @@ -20,6 +20,7 @@ #include "AVR.h" #include "AVRMachineFunctionInfo.h" #include "AVRTargetObjectFile.h" +#include "AVRTargetTransformInfo.h" #include "MCTargetDesc/AVRMCTargetDesc.h" #include "TargetInfo/AVRTargetInfo.h" @@ -28,7 +29,7 @@ namespace llvm { static const char *AVRDataLayout = - "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8"; + "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-n16:8-a:8"; /// Processes a CPU name. static StringRef getCPU(StringRef CPU) { @@ -62,7 +63,9 @@ namespace { class AVRPassConfig : public TargetPassConfig { public: AVRPassConfig(AVRTargetMachine &TM, PassManagerBase &PM) - : TargetPassConfig(TM, PM) {} + : TargetPassConfig(TM, PM) { + EnableLoopTermFold = true; + } AVRTargetMachine &getAVRTargetMachine() const { return getTM(); @@ -107,6 +110,11 @@ const AVRSubtarget *AVRTargetMachine::getSubtargetImpl(const Function &) const { return &SubTarget; } +TargetTransformInfo +AVRTargetMachine::getTargetTransformInfo(const Function &F) const { + return TargetTransformInfo(std::make_unique(this, F)); +} + MachineFunctionInfo *AVRTargetMachine::createMachineFunctionInfo( BumpPtrAllocator &Allocator, const Function &F, const TargetSubtargetInfo *STI) const { diff --git a/llvm/lib/Target/AVR/AVRTargetMachine.h b/llvm/lib/Target/AVR/AVRTargetMachine.h index 167d0076e9581..9452b3d8cd8a5 100644 --- a/llvm/lib/Target/AVR/AVRTargetMachine.h +++ b/llvm/lib/Target/AVR/AVRTargetMachine.h @@ -48,6 +48,8 @@ class AVRTargetMachine : public CodeGenTargetMachineImpl { createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F, const TargetSubtargetInfo *STI) const override; + TargetTransformInfo getTargetTransformInfo(const Function &F) 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 diff --git a/llvm/lib/Target/AVR/AVRTargetTransformInfo.h b/llvm/lib/Target/AVR/AVRTargetTransformInfo.h new file mode 100644 index 0000000000000..77c2a6153f7d5 --- /dev/null +++ b/llvm/lib/Target/AVR/AVRTargetTransformInfo.h @@ -0,0 +1,56 @@ +//===- AVRTargetTransformInfo.h - AVR specific TTI ---------*- 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// This file defines a TargetTransformInfoImplBase conforming object specific +/// to the AVR target machine. It uses the target's detailed information to +/// provide more precise answers to certain TTI queries, while letting the +/// target independent and default TTI implementations handle the rest. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AVR_AVRTARGETTRANSFORMINFO_H +#define LLVM_LIB_TARGET_AVR_AVRTARGETTRANSFORMINFO_H + +#include "AVRSubtarget.h" +#include "AVRTargetMachine.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/CodeGen/BasicTTIImpl.h" +#include "llvm/IR/Function.h" +#include + +namespace llvm { + +class AVRTTIImpl final : public BasicTTIImplBase { + using BaseT = BasicTTIImplBase; + using TTI = TargetTransformInfo; + + friend BaseT; + + const AVRSubtarget *ST; + const AVRTargetLowering *TLI; + + const AVRSubtarget *getST() const { return ST; } + const AVRTargetLowering *getTLI() const { return TLI; } + +public: + explicit AVRTTIImpl(const AVRTargetMachine *TM, const Function &F) + : BaseT(TM, F.getDataLayout()), ST(TM->getSubtargetImpl(F)), + TLI(ST->getTargetLowering()) {} + + bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, + const TargetTransformInfo::LSRCost &C2) const override { + if (C2.Insns == ~0u) + return true; + return 2 * C1.Insns + C1.AddRecCost + C1.SetupCost + C1.NumRegs < + 2 * C2.Insns + C2.AddRecCost + C2.SetupCost + C2.NumRegs; + } +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_AVR_AVRTARGETTRANSFORMINFO_H diff --git a/llvm/test/CodeGen/AVR/bug-143247.ll b/llvm/test/CodeGen/AVR/bug-143247.ll index 07c4c6562c950..d4493272af76d 100644 --- a/llvm/test/CodeGen/AVR/bug-143247.ll +++ b/llvm/test/CodeGen/AVR/bug-143247.ll @@ -8,18 +8,18 @@ define void @complex_sbi() { ; CHECK: ; %bb.0: ; %entry ; CHECK-NEXT: push r16 ; CHECK-NEXT: push r17 -; CHECK-NEXT: ldi r24, 0 +; CHECK-NEXT: ldi r24, 1 ; CHECK-NEXT: ldi r25, 0 ; CHECK-NEXT: .LBB0_1: ; %while.cond ; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: sbi 1, 7 -; CHECK-NEXT: adiw r24, 1 ; CHECK-NEXT: movw r16, r24 ; CHECK-NEXT: andi r24, 15 ; CHECK-NEXT: andi r25, 0 ; CHECK-NEXT: adiw r24, 1 ; CHECK-NEXT: call nil ; CHECK-NEXT: movw r24, r16 +; CHECK-NEXT: adiw r24, 1 ; CHECK-NEXT: rjmp .LBB0_1 entry: br label %while.cond diff --git a/llvm/test/CodeGen/AVR/issue-151080.ll b/llvm/test/CodeGen/AVR/issue-151080.ll new file mode 100644 index 0000000000000..f0afc47a24458 --- /dev/null +++ b/llvm/test/CodeGen/AVR/issue-151080.ll @@ -0,0 +1,105 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=avr-none -verify-machineinstrs | FileCheck %s + +declare dso_local void @foo(i16 noundef) addrspace(1) +@ci = dso_local global [30 x i16] zeroinitializer, align 1 +define void @loopreduce() { +; CHECK-LABEL: loopreduce: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: push r14 +; CHECK-NEXT: push r15 +; CHECK-NEXT: push r16 +; CHECK-NEXT: push r17 +; CHECK-NEXT: ldi r26, lo8(ci) +; CHECK-NEXT: ldi r27, hi8(ci) +; CHECK-NEXT: ldi r16, lo8(ci+60) +; CHECK-NEXT: ldi r17, hi8(ci+60) +; CHECK-NEXT: .LBB0_1: ; %for.body +; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: ld r24, X+ +; CHECK-NEXT: ld r25, X+ +; CHECK-NEXT: mov r14, r26 +; CHECK-NEXT: mov r15, r27 +; CHECK-NEXT: rcall foo +; CHECK-NEXT: mov r26, r14 +; CHECK-NEXT: mov r27, r15 +; CHECK-NEXT: cp r26, r16 +; CHECK-NEXT: cpc r27, r17 +; CHECK-NEXT: brne .LBB0_1 +; CHECK-NEXT: ; %bb.2: ; %for.cond.cleanup +; CHECK-NEXT: pop r17 +; CHECK-NEXT: pop r16 +; CHECK-NEXT: pop r15 +; CHECK-NEXT: pop r14 +; CHECK-NEXT: ret +entry: + br label %for.body +for.body: ; preds = %entry, %for.body + %i.03 = phi i16 [ 0, %entry ], [ %inc, %for.body ] + %arrayidx = getelementptr inbounds nuw [30 x i16], ptr @ci, i16 0, i16 %i.03 + %0 = load i16, ptr %arrayidx, align 1 + tail call addrspace(1) void @foo(i16 noundef %0) #3 + %inc = add nuw nsw i16 %i.03, 1 + %exitcond.not = icmp eq i16 %inc, 30 + br i1 %exitcond.not, label %for.cond.cleanup, label %for.body +; Exit blocks +for.cond.cleanup: ; preds = %for.body + ret void +} + + +define void @induction() { +; CHECK-LABEL: induction: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: push r12 +; CHECK-NEXT: push r13 +; CHECK-NEXT: push r14 +; CHECK-NEXT: push r15 +; CHECK-NEXT: push r17 +; CHECK-NEXT: ldi r24, 8 +; CHECK-NEXT: ldi r25, 0 +; CHECK-NEXT: mov r14, r24 +; CHECK-NEXT: mov r15, r25 +; CHECK-NEXT: ldi r24, 1 +; CHECK-NEXT: ldi r25, 0 +; CHECK-NEXT: mov r12, r24 +; CHECK-NEXT: mov r13, r25 +; CHECK-NEXT: ldi r17, 3 +; CHECK-NEXT: .LBB1_1: ; %for.body +; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: mov r24, r12 +; CHECK-NEXT: mov r25, r13 +; CHECK-NEXT: rcall foo +; CHECK-NEXT: mov r22, r14 +; CHECK-NEXT: mov r23, r15 +; CHECK-NEXT: mov r24, r22 +; CHECK-NEXT: mov r25, r23 +; CHECK-NEXT: rcall __mulhi3 +; CHECK-NEXT: mov r30, r14 +; CHECK-NEXT: mov r31, r15 +; CHECK-NEXT: adiw r30, 1 +; CHECK-NEXT: mov r14, r30 +; CHECK-NEXT: mov r15, r31 +; CHECK-NEXT: cpi r24, -24 +; CHECK-NEXT: cpc r25, r17 +; CHECK-NEXT: brlo .LBB1_1 +; CHECK-NEXT: ; %bb.2: ; %for.cond.cleanup +; CHECK-NEXT: pop r17 +; CHECK-NEXT: pop r15 +; CHECK-NEXT: pop r14 +; CHECK-NEXT: pop r13 +; CHECK-NEXT: pop r12 +; CHECK-NEXT: ret +entry: + br label %for.body +for.body: ; preds = %entry, %for.body + %i.03 = phi i16 [ 7, %entry ], [ %inc, %for.body ] + tail call addrspace(1) void @foo(i16 noundef 1) #2 + %inc = add nuw nsw i16 %i.03, 1 + %mul = mul nuw nsw i16 %inc, %inc + %cmp = icmp samesign ult i16 %mul, 1000 + br i1 %cmp, label %for.body, label %for.cond.cleanup +for.cond.cleanup: ; preds = %for.body + ret void +} + diff --git a/llvm/test/CodeGen/AVR/load.ll b/llvm/test/CodeGen/AVR/load.ll index 5de6b48652914..070a888e69fa9 100644 --- a/llvm/test/CodeGen/AVR/load.ll +++ b/llvm/test/CodeGen/AVR/load.ll @@ -1,4 +1,4 @@ -; RUN: llc -mattr=avr6,sram < %s -mtriple=avr -verify-machineinstrs | FileCheck %s +; RUN: llc -mattr=avr6,sram < %s -mtriple=avr-none -verify-machineinstrs | FileCheck %s define i8 @load8(ptr %x) { ; CHECK-LABEL: load8: @@ -98,9 +98,34 @@ while.end: ; preds = %while.body, %entry ret i16 %r.0.lcssa } +define i16 @load16postincloopreduce(ptr %p, i16 %cnt) { +; CHECK-LABEL: load16postincloopreduce: +; CHECK: ld {{.*}}, {{[XYZ]}}+ +; CHECK: ld {{.*}}, {{[XYZ]}}+ +entry: + %cmp3 = icmp sgt i16 %cnt, 0 + br i1 %cmp3, label %for.body, label %for.cond.cleanup +for.cond.cleanup: ; preds = %for.body, %entry + %sum.0.lcssa = phi i16 [ 0, %entry ], [ %add, %for.body ] + ret i16 %sum.0.lcssa +for.body: ; preds = %entry, %for.body + %i.06 = phi i16 [ %inc, %for.body ], [ 0, %entry ] + %sum.05 = phi i16 [ %add, %for.body ], [ 0, %entry ] + %p.addr.04 = phi ptr [ %incdec.ptr, %for.body ], [ %p, %entry ] + %incdec.ptr = getelementptr inbounds nuw i8, ptr %p.addr.04, i16 2 + %0 = load i16, ptr %p.addr.04, align 1 + %add = add nsw i16 %0, %sum.05 + %inc = add nuw nsw i16 %i.06, 1 + %exitcond.not = icmp eq i16 %inc, %cnt + br i1 %exitcond.not, label %for.cond.cleanup, label %for.body +} + define i8 @load8predec(ptr %x, i8 %y) { ; CHECK-LABEL: load8predec: -; CHECK: ld {{.*}}, -{{[XYZ]}} +; TODO: ld {{.*}}, -{{[XYZ]}} +; TODO: ld {{.*}}, -{{[XYZ]}} +; CHECK: sbiw {{.*}}, 1 +; CHECK: ld {{.*}}, {{[XYZ]}} entry: %tobool6 = icmp eq i8 %y, 0 br i1 %tobool6, label %while.end, label %while.body @@ -121,8 +146,11 @@ while.end: ; preds = %while.body, %entry define i16 @load16predec(ptr %x, i16 %y) { ; CHECK-LABEL: load16predec: -; CHECK: ld {{.*}}, -{{[XYZ]}} -; CHECK: ld {{.*}}, -{{[XYZ]}} +; TODO: ld {{.*}}, -{{[XYZ]}} +; TODO: ld {{.*}}, -{{[XYZ]}} +; CHECK: sbiw {{.*}}, 2 +; CHECK: ld {{.*}}, {{[XZ]}} +; CHECK: ldd {{.*}}, {{[XZ]}}+1 entry: %tobool2 = icmp eq i16 %y, 0 br i1 %tobool2, label %while.end, label %while.body diff --git a/llvm/test/CodeGen/AVR/shift.ll b/llvm/test/CodeGen/AVR/shift.ll index 9836f93527b3c..1bd9b45999d7b 100644 --- a/llvm/test/CodeGen/AVR/shift.ll +++ b/llvm/test/CodeGen/AVR/shift.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=avr -mtriple=avr -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -mtriple=avr-none -verify-machineinstrs | FileCheck %s ; Optimize for speed. define i8 @shift_i8_i8_speed(i8 %a, i8 %b) { diff --git a/llvm/test/CodeGen/AVR/store.ll b/llvm/test/CodeGen/AVR/store.ll index aab02709de7a6..a1eca5d862805 100644 --- a/llvm/test/CodeGen/AVR/store.ll +++ b/llvm/test/CodeGen/AVR/store.ll @@ -94,7 +94,9 @@ while.end: ; preds = %while.body, %entry define void @store8predec(ptr %x, i8 %y) { ; CHECK-LABEL: store8predec: -; CHECK: st -{{[XYZ]}}, {{.*}} +; TODO: st -{{[XYZ]}}, {{.*}} +; CHECK: sbiw {{..*}}, 1 +; CHECK: st {{[XYZ]}}, {{.*}} entry: %tobool3 = icmp eq i8 %y, 0 br i1 %tobool3, label %while.end, label %while.body @@ -112,8 +114,11 @@ while.end: ; preds = %while.body, %entry define void @store16predec(ptr %x, i16 %y) { ; CHECK-LABEL: store16predec: -; CHECK: st -{{[XYZ]}}, {{.*}} -; CHECK: st -{{[XYZ]}}, {{.*}} +; TODO: st -{{[XYZ]}}, {{.*}} +; TODO: st -{{[XYZ]}}, {{.*}} +; CHECK: sbiw {{..*}}, 2 +; CHECK: std {{[XYZ]}}+1, {{.*}} +; CHECK: st {{[XYZ]}}, {{.*}} entry: %tobool3 = icmp eq i16 %y, 0 br i1 %tobool3, label %while.end, label %while.body