Skip to content

Commit 97f0ff0

Browse files
authored
[AVR] Fix Avr indvar detection and strength reduction (missed optimization) (llvm#152028)
Fix llvm#151080
1 parent 6f53f1c commit 97f0ff0

File tree

9 files changed

+209
-13
lines changed

9 files changed

+209
-13
lines changed

clang/lib/Basic/Targets/AVR.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
5757
Int16Type = SignedInt;
5858
Char32Type = UnsignedLong;
5959
SigAtomicType = SignedChar;
60-
resetDataLayout("e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8");
60+
resetDataLayout(
61+
"e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-n16:8-a:8");
6162
}
6263

6364
void getTargetDefines(const LangOptions &Opts,

llvm/lib/Target/AVR/AVRTargetMachine.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "AVR.h"
2121
#include "AVRMachineFunctionInfo.h"
2222
#include "AVRTargetObjectFile.h"
23+
#include "AVRTargetTransformInfo.h"
2324
#include "MCTargetDesc/AVRMCTargetDesc.h"
2425
#include "TargetInfo/AVRTargetInfo.h"
2526

@@ -28,7 +29,7 @@
2829
namespace llvm {
2930

3031
static const char *AVRDataLayout =
31-
"e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8";
32+
"e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-n16:8-a:8";
3233

3334
/// Processes a CPU name.
3435
static StringRef getCPU(StringRef CPU) {
@@ -62,7 +63,9 @@ namespace {
6263
class AVRPassConfig : public TargetPassConfig {
6364
public:
6465
AVRPassConfig(AVRTargetMachine &TM, PassManagerBase &PM)
65-
: TargetPassConfig(TM, PM) {}
66+
: TargetPassConfig(TM, PM) {
67+
EnableLoopTermFold = true;
68+
}
6669

6770
AVRTargetMachine &getAVRTargetMachine() const {
6871
return getTM<AVRTargetMachine>();
@@ -107,6 +110,11 @@ const AVRSubtarget *AVRTargetMachine::getSubtargetImpl(const Function &) const {
107110
return &SubTarget;
108111
}
109112

113+
TargetTransformInfo
114+
AVRTargetMachine::getTargetTransformInfo(const Function &F) const {
115+
return TargetTransformInfo(std::make_unique<AVRTTIImpl>(this, F));
116+
}
117+
110118
MachineFunctionInfo *AVRTargetMachine::createMachineFunctionInfo(
111119
BumpPtrAllocator &Allocator, const Function &F,
112120
const TargetSubtargetInfo *STI) const {

llvm/lib/Target/AVR/AVRTargetMachine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class AVRTargetMachine : public CodeGenTargetMachineImpl {
4848
createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
4949
const TargetSubtargetInfo *STI) const override;
5050

51+
TargetTransformInfo getTargetTransformInfo(const Function &F) const override;
52+
5153
bool isNoopAddrSpaceCast(unsigned SrcAs, unsigned DestAs) const override {
5254
// While AVR has different address spaces, they are all represented by
5355
// 16-bit pointers that can be freely casted between (of course, a pointer
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//===- AVRTargetTransformInfo.h - AVR specific TTI --------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
/// \file
9+
/// This file defines a TargetTransformInfoImplBase conforming object specific
10+
/// to the AVR target machine. It uses the target's detailed information to
11+
/// provide more precise answers to certain TTI queries, while letting the
12+
/// target independent and default TTI implementations handle the rest.
13+
///
14+
//===----------------------------------------------------------------------===//
15+
16+
#ifndef LLVM_LIB_TARGET_AVR_AVRTARGETTRANSFORMINFO_H
17+
#define LLVM_LIB_TARGET_AVR_AVRTARGETTRANSFORMINFO_H
18+
19+
#include "AVRSubtarget.h"
20+
#include "AVRTargetMachine.h"
21+
#include "llvm/Analysis/TargetTransformInfo.h"
22+
#include "llvm/CodeGen/BasicTTIImpl.h"
23+
#include "llvm/IR/Function.h"
24+
#include <optional>
25+
26+
namespace llvm {
27+
28+
class AVRTTIImpl final : public BasicTTIImplBase<AVRTTIImpl> {
29+
using BaseT = BasicTTIImplBase<AVRTTIImpl>;
30+
using TTI = TargetTransformInfo;
31+
32+
friend BaseT;
33+
34+
const AVRSubtarget *ST;
35+
const AVRTargetLowering *TLI;
36+
37+
const AVRSubtarget *getST() const { return ST; }
38+
const AVRTargetLowering *getTLI() const { return TLI; }
39+
40+
public:
41+
explicit AVRTTIImpl(const AVRTargetMachine *TM, const Function &F)
42+
: BaseT(TM, F.getDataLayout()), ST(TM->getSubtargetImpl(F)),
43+
TLI(ST->getTargetLowering()) {}
44+
45+
bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1,
46+
const TargetTransformInfo::LSRCost &C2) const override {
47+
if (C2.Insns == ~0u)
48+
return true;
49+
return 2 * C1.Insns + C1.AddRecCost + C1.SetupCost + C1.NumRegs <
50+
2 * C2.Insns + C2.AddRecCost + C2.SetupCost + C2.NumRegs;
51+
}
52+
};
53+
54+
} // end namespace llvm
55+
56+
#endif // LLVM_LIB_TARGET_AVR_AVRTARGETTRANSFORMINFO_H

llvm/test/CodeGen/AVR/bug-143247.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ define void @complex_sbi() {
88
; CHECK: ; %bb.0: ; %entry
99
; CHECK-NEXT: push r16
1010
; CHECK-NEXT: push r17
11-
; CHECK-NEXT: ldi r24, 0
11+
; CHECK-NEXT: ldi r24, 1
1212
; CHECK-NEXT: ldi r25, 0
1313
; CHECK-NEXT: .LBB0_1: ; %while.cond
1414
; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1
1515
; CHECK-NEXT: sbi 1, 7
16-
; CHECK-NEXT: adiw r24, 1
1716
; CHECK-NEXT: movw r16, r24
1817
; CHECK-NEXT: andi r24, 15
1918
; CHECK-NEXT: andi r25, 0
2019
; CHECK-NEXT: adiw r24, 1
2120
; CHECK-NEXT: call nil
2221
; CHECK-NEXT: movw r24, r16
22+
; CHECK-NEXT: adiw r24, 1
2323
; CHECK-NEXT: rjmp .LBB0_1
2424
entry:
2525
br label %while.cond

llvm/test/CodeGen/AVR/issue-151080.ll

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -O=3 -mtriple=avr-none -mcpu=attiny85 -verify-machineinstrs | FileCheck %s
3+
4+
declare dso_local void @foo(i16 noundef) addrspace(1)
5+
@ci = dso_local global [30 x i16] zeroinitializer, align 1
6+
define void @loopreduce() {
7+
; CHECK-LABEL: loopreduce:
8+
; CHECK: ; %bb.0: ; %entry
9+
; CHECK-NEXT: push r14
10+
; CHECK-NEXT: push r15
11+
; CHECK-NEXT: push r16
12+
; CHECK-NEXT: push r17
13+
; CHECK-NEXT: ldi r26, lo8(ci)
14+
; CHECK-NEXT: ldi r27, hi8(ci)
15+
; CHECK-NEXT: ldi r16, lo8(ci+60)
16+
; CHECK-NEXT: ldi r17, hi8(ci+60)
17+
; CHECK-NEXT: .LBB0_1: ; %for.body
18+
; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1
19+
; CHECK-NEXT: ld r24, X+
20+
; CHECK-NEXT: ld r25, X+
21+
; CHECK-NEXT: movw r14, r26
22+
; CHECK-NEXT: rcall foo
23+
; CHECK-NEXT: movw r26, r14
24+
; CHECK-NEXT: cp r26, r16
25+
; CHECK-NEXT: cpc r27, r17
26+
; CHECK-NEXT: brne .LBB0_1
27+
; CHECK-NEXT: ; %bb.2: ; %for.cond.cleanup
28+
; CHECK-NEXT: pop r17
29+
; CHECK-NEXT: pop r16
30+
; CHECK-NEXT: pop r15
31+
; CHECK-NEXT: pop r14
32+
; CHECK-NEXT: ret
33+
entry:
34+
br label %for.body
35+
for.body: ; preds = %entry, %for.body
36+
%i.03 = phi i16 [ 0, %entry ], [ %inc, %for.body ]
37+
%arrayidx = getelementptr inbounds nuw [30 x i16], ptr @ci, i16 0, i16 %i.03
38+
%0 = load i16, ptr %arrayidx, align 1
39+
tail call addrspace(1) void @foo(i16 noundef %0)
40+
%inc = add nuw nsw i16 %i.03, 1
41+
%exitcond.not = icmp eq i16 %inc, 30
42+
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
43+
; Exit blocks
44+
for.cond.cleanup: ; preds = %for.body
45+
ret void
46+
}
47+
48+
define void @indvar() {
49+
; CHECK-LABEL: indvar:
50+
; CHECK: ; %bb.0: ; %entry
51+
; CHECK-NEXT: push r12
52+
; CHECK-NEXT: push r13
53+
; CHECK-NEXT: push r14
54+
; CHECK-NEXT: push r15
55+
; CHECK-NEXT: push r17
56+
; CHECK-NEXT: ldi r24, 8
57+
; CHECK-NEXT: ldi r25, 0
58+
; CHECK-NEXT: movw r14, r24
59+
; CHECK-NEXT: ldi r24, 1
60+
; CHECK-NEXT: ldi r25, 0
61+
; CHECK-NEXT: movw r12, r24
62+
; CHECK-NEXT: ldi r17, 3
63+
; CHECK-NEXT: .LBB1_1: ; %for.body
64+
; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1
65+
; CHECK-NEXT: movw r24, r12
66+
; CHECK-NEXT: rcall foo
67+
; CHECK-NEXT: movw r22, r14
68+
; CHECK-NEXT: movw r24, r22
69+
; CHECK-NEXT: rcall __mulhi3
70+
; CHECK-NEXT: movw r30, r14
71+
; CHECK-NEXT: adiw r30, 1
72+
; CHECK-NEXT: movw r14, r30
73+
; CHECK-NEXT: cpi r24, -24
74+
; CHECK-NEXT: cpc r25, r17
75+
; CHECK-NEXT: brlo .LBB1_1
76+
; CHECK-NEXT: ; %bb.2: ; %for.cond.cleanup
77+
; CHECK-NEXT: pop r17
78+
; CHECK-NEXT: pop r15
79+
; CHECK-NEXT: pop r14
80+
; CHECK-NEXT: pop r13
81+
; CHECK-NEXT: pop r12
82+
; CHECK-NEXT: ret
83+
entry:
84+
br label %for.body
85+
for.body: ; preds = %entry, %for.body
86+
%i.03 = phi i16 [ 7, %entry ], [ %inc, %for.body ]
87+
tail call addrspace(1) void @foo(i16 noundef 1)
88+
%inc = add nuw nsw i16 %i.03, 1
89+
%mul = mul nuw nsw i16 %inc, %inc
90+
%cmp = icmp samesign ult i16 %mul, 1000
91+
br i1 %cmp, label %for.body, label %for.cond.cleanup
92+
for.cond.cleanup: ; preds = %for.body
93+
ret void
94+
}
95+

llvm/test/CodeGen/AVR/load.ll

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: llc -mattr=avr6,sram < %s -mtriple=avr -verify-machineinstrs | FileCheck %s
1+
; RUN: llc -mattr=avr6,sram < %s -mtriple=avr-none -verify-machineinstrs | FileCheck %s
22

33
define i8 @load8(ptr %x) {
44
; CHECK-LABEL: load8:
@@ -98,9 +98,33 @@ while.end: ; preds = %while.body, %entry
9898
ret i16 %r.0.lcssa
9999
}
100100

101+
define i16 @load16postincloopreduce(ptr %p, i16 %cnt) {
102+
; CHECK-LABEL: load16postincloopreduce:
103+
; CHECK: ld {{.*}}, {{[XYZ]}}+
104+
; CHECK: ld {{.*}}, {{[XYZ]}}+
105+
entry:
106+
%cmp3 = icmp sgt i16 %cnt, 0
107+
br i1 %cmp3, label %for.body, label %for.cond.cleanup
108+
for.cond.cleanup: ; preds = %for.body, %entry
109+
%sum.0.lcssa = phi i16 [ 0, %entry ], [ %add, %for.body ]
110+
ret i16 %sum.0.lcssa
111+
for.body: ; preds = %entry, %for.body
112+
%i.06 = phi i16 [ %inc, %for.body ], [ 0, %entry ]
113+
%sum.05 = phi i16 [ %add, %for.body ], [ 0, %entry ]
114+
%p.addr.04 = phi ptr [ %incdec.ptr, %for.body ], [ %p, %entry ]
115+
%incdec.ptr = getelementptr inbounds nuw i8, ptr %p.addr.04, i16 2
116+
%0 = load i16, ptr %p.addr.04, align 1
117+
%add = add nsw i16 %0, %sum.05
118+
%inc = add nuw nsw i16 %i.06, 1
119+
%exitcond.not = icmp eq i16 %inc, %cnt
120+
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
121+
}
122+
101123
define i8 @load8predec(ptr %x, i8 %y) {
102124
; CHECK-LABEL: load8predec:
103-
; CHECK: ld {{.*}}, -{{[XYZ]}}
125+
; TODO: ld {{.*}}, -{{[XYZ]}}
126+
; CHECK: sbiw r26, 1
127+
; CHECK: ld {{.*}}, X
104128
entry:
105129
%tobool6 = icmp eq i8 %y, 0
106130
br i1 %tobool6, label %while.end, label %while.body
@@ -121,8 +145,12 @@ while.end: ; preds = %while.body, %entry
121145

122146
define i16 @load16predec(ptr %x, i16 %y) {
123147
; CHECK-LABEL: load16predec:
124-
; CHECK: ld {{.*}}, -{{[XYZ]}}
125-
; CHECK: ld {{.*}}, -{{[XYZ]}}
148+
; TODO: ld {{.*}}, -{{[XYZ]}}
149+
; TODO: ld {{.*}}, -{{[XYZ]}}
150+
; CHECK: sbiw r24, 2
151+
; CHECK: movw r30, r24
152+
; CHECK: ld {{.*}}, Z
153+
; CHECK: ldd {{.*}}, Z+1
126154
entry:
127155
%tobool2 = icmp eq i16 %y, 0
128156
br i1 %tobool2, label %while.end, label %while.body

llvm/test/CodeGen/AVR/shift.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2-
; RUN: llc < %s -mtriple=avr -mtriple=avr -verify-machineinstrs | FileCheck %s
2+
; RUN: llc < %s -mtriple=avr-none -verify-machineinstrs | FileCheck %s
33

44
; Optimize for speed.
55
define i8 @shift_i8_i8_speed(i8 %a, i8 %b) {

llvm/test/CodeGen/AVR/store.ll

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ while.end: ; preds = %while.body, %entry
9494

9595
define void @store8predec(ptr %x, i8 %y) {
9696
; CHECK-LABEL: store8predec:
97-
; CHECK: st -{{[XYZ]}}, {{.*}}
97+
; TODO: st -{{[XYZ]}}, {{.*}}
98+
; CHECK: sbiw r26, 1
99+
; CHECK: st X, {{.*}}
98100
entry:
99101
%tobool3 = icmp eq i8 %y, 0
100102
br i1 %tobool3, label %while.end, label %while.body
@@ -112,8 +114,12 @@ while.end: ; preds = %while.body, %entry
112114

113115
define void @store16predec(ptr %x, i16 %y) {
114116
; CHECK-LABEL: store16predec:
115-
; CHECK: st -{{[XYZ]}}, {{.*}}
116-
; CHECK: st -{{[XYZ]}}, {{.*}}
117+
; TODO: st -{{[XYZ]}}, {{.*}}
118+
; TODO: st -{{[XYZ]}}, {{.*}}
119+
; CHECK: sbiw r24, 2
120+
; CHECK: movw r30, r24
121+
; CHECK: std Z+1, {{.*}}
122+
; CHECK: st Z, {{.*}}
117123
entry:
118124
%tobool3 = icmp eq i16 %y, 0
119125
br i1 %tobool3, label %while.end, label %while.body

0 commit comments

Comments
 (0)