Skip to content

Commit dfac521

Browse files
committed
[ARM] Fix vector saddsat costs.
It turns out the vectorizer calls the getIntrinsicInstrCost functions with a scalar return type and vector VF. This updates the costmodel to handle that, still producing the correct vector costs. A vectorizer test is added to show it vectorizing at the correct factor again.
1 parent 0eeb157 commit dfac521

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -1531,8 +1531,13 @@ int ARMTTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,
15311531
case Intrinsic::usub_sat: {
15321532
if (!ST->hasMVEIntegerOps())
15331533
break;
1534+
// Get the Return type, either directly of from ICA.ReturnType and ICA.VF.
1535+
Type *VT = ICA.getReturnType();
1536+
if (!VT->isVectorTy() && !ICA.getVectorFactor().isScalar())
1537+
VT = VectorType::get(VT, ICA.getVectorFactor());
1538+
15341539
std::pair<int, MVT> LT =
1535-
TLI->getTypeLegalizationCost(DL, ICA.getReturnType());
1540+
TLI->getTypeLegalizationCost(DL, VT);
15361541
if (LT.second == MVT::v4i32 || LT.second == MVT::v8i16 ||
15371542
LT.second == MVT::v16i8) {
15381543
// This is a base cost of 1 for the vadd, plus 3 extract shifts if we
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -loop-vectorize -instcombine -simplifycfg < %s -S -o - | FileCheck %s --check-prefix=CHECK
3+
4+
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
5+
target triple = "thumbv8.1m.main-arm-none-eabi"
6+
7+
define void @arm_offset_q15(i16* nocapture readonly %pSrc, i16 signext %offset, i16* nocapture noalias %pDst, i32 %blockSize) #0 {
8+
; CHECK-LABEL: @arm_offset_q15(
9+
; CHECK-NEXT: entry:
10+
; CHECK-NEXT: [[CMP_NOT6:%.*]] = icmp eq i32 [[BLOCKSIZE:%.*]], 0
11+
; CHECK-NEXT: br i1 [[CMP_NOT6]], label [[WHILE_END:%.*]], label [[VECTOR_PH:%.*]]
12+
; CHECK: vector.ph:
13+
; CHECK-NEXT: [[N_RND_UP:%.*]] = add i32 [[BLOCKSIZE]], 7
14+
; CHECK-NEXT: [[N_VEC:%.*]] = and i32 [[N_RND_UP]], -8
15+
; CHECK-NEXT: [[BROADCAST_SPLATINSERT8:%.*]] = insertelement <8 x i16> poison, i16 [[OFFSET:%.*]], i32 0
16+
; CHECK-NEXT: [[BROADCAST_SPLAT9:%.*]] = shufflevector <8 x i16> [[BROADCAST_SPLATINSERT8]], <8 x i16> poison, <8 x i32> zeroinitializer
17+
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
18+
; CHECK: vector.body:
19+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
20+
; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i16, i16* [[PSRC:%.*]], i32 [[INDEX]]
21+
; CHECK-NEXT: [[NEXT_GEP5:%.*]] = getelementptr i16, i16* [[PDST:%.*]], i32 [[INDEX]]
22+
; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = call <8 x i1> @llvm.get.active.lane.mask.v8i1.i32(i32 [[INDEX]], i32 [[BLOCKSIZE]])
23+
; CHECK-NEXT: [[TMP0:%.*]] = bitcast i16* [[NEXT_GEP]] to <8 x i16>*
24+
; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <8 x i16> @llvm.masked.load.v8i16.p0v8i16(<8 x i16>* [[TMP0]], i32 2, <8 x i1> [[ACTIVE_LANE_MASK]], <8 x i16> poison)
25+
; CHECK-NEXT: [[TMP1:%.*]] = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> [[WIDE_MASKED_LOAD]], <8 x i16> [[BROADCAST_SPLAT9]])
26+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i16* [[NEXT_GEP5]] to <8 x i16>*
27+
; CHECK-NEXT: call void @llvm.masked.store.v8i16.p0v8i16(<8 x i16> [[TMP1]], <8 x i16>* [[TMP2]], i32 2, <8 x i1> [[ACTIVE_LANE_MASK]])
28+
; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 8
29+
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
30+
; CHECK-NEXT: br i1 [[TMP3]], label [[WHILE_END]], label [[VECTOR_BODY]], [[LOOP0:!llvm.loop !.*]]
31+
; CHECK: while.end:
32+
; CHECK-NEXT: ret void
33+
;
34+
entry:
35+
%cmp.not6 = icmp eq i32 %blockSize, 0
36+
br i1 %cmp.not6, label %while.end, label %while.body
37+
38+
while.body: ; preds = %entry, %while.body
39+
%blkCnt.09 = phi i32 [ %dec, %while.body ], [ %blockSize, %entry ]
40+
%pSrc.addr.08 = phi i16* [ %incdec.ptr, %while.body ], [ %pSrc, %entry ]
41+
%pDst.addr.07 = phi i16* [ %incdec.ptr3, %while.body ], [ %pDst, %entry ]
42+
%incdec.ptr = getelementptr inbounds i16, i16* %pSrc.addr.08, i32 1
43+
%0 = load i16, i16* %pSrc.addr.08, align 2
44+
%1 = tail call i16 @llvm.sadd.sat.i16(i16 %0, i16 %offset)
45+
%incdec.ptr3 = getelementptr inbounds i16, i16* %pDst.addr.07, i32 1
46+
store i16 %1, i16* %pDst.addr.07, align 2
47+
%dec = add i32 %blkCnt.09, -1
48+
%cmp.not = icmp eq i32 %dec, 0
49+
br i1 %cmp.not, label %while.end, label %while.body
50+
51+
while.end: ; preds = %while.body, %entry
52+
ret void
53+
}
54+
55+
declare i16 @llvm.sadd.sat.i16(i16, i16)
56+
57+
attributes #0 = { "target-features"="+mve" }

0 commit comments

Comments
 (0)