Skip to content

Commit f1697e0

Browse files
hunhoffeclaude
andauthored
[VectorToAIEVec] Match arith.subi vector legality to arith.addi (CPP-only) (Xilinx#3065)
Co-authored-by: Claude Opus 4 (1M context) <noreply@anthropic.com>
1 parent dae0ead commit f1697e0

2 files changed

Lines changed: 99 additions & 13 deletions

File tree

lib/Dialect/AIEVec/Transforms/VectorToAIEVecConversions.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5227,11 +5227,11 @@ static void configureAIEVecCommonLegalizations(ConversionTarget &target,
52275227
if (backend == TargetBackend::CPP) {
52285228
target.addDynamicallyLegalOp<arith::AddIOp>(
52295229
[](arith::AddIOp op) { return !isa<VectorType>(op.getType()); });
5230+
target.addDynamicallyLegalOp<arith::SubIOp>(
5231+
[](arith::SubIOp op) { return !isa<VectorType>(op.getType()); });
52305232
}
52315233
target.addDynamicallyLegalOp<arith::AddFOp>(
52325234
[](arith::AddFOp op) { return !isa<VectorType>(op.getType()); });
5233-
target.addDynamicallyLegalOp<arith::SubIOp>(
5234-
[](arith::SubIOp op) { return !isa<VectorType>(op.getType()); });
52355235
target.addDynamicallyLegalOp<arith::SubFOp>(
52365236
[](arith::SubFOp op) { return !isa<VectorType>(op.getType()); });
52375237

@@ -5549,18 +5549,17 @@ static void configureAIEVecV2Legalizations(ConversionTarget &target,
55495549
return !laneSizeElWidthPairSet.count(
55505550
std::make_pair(laneSize, resultElWidth));
55515551
});
5552-
}
5553-
5554-
target.addDynamicallyLegalOp<arith::SubIOp>([=](arith::SubIOp op) {
5555-
auto resultType = dyn_cast<VectorType>(op.getType());
5556-
if (!resultType)
5557-
return true;
5558-
auto resultElWidth = resultType.getElementType().getIntOrFloatBitWidth();
5559-
unsigned laneSize = getVectorLaneSize(resultType);
5552+
target.addDynamicallyLegalOp<arith::SubIOp>([=](arith::SubIOp op) {
5553+
auto resultType = dyn_cast<VectorType>(op.getType());
5554+
if (!resultType)
5555+
return true;
5556+
auto resultElWidth = resultType.getElementType().getIntOrFloatBitWidth();
5557+
unsigned laneSize = getVectorLaneSize(resultType);
55605558

5561-
return !laneSizeElWidthPairSet.count(
5562-
std::make_pair(laneSize, resultElWidth));
5563-
});
5559+
return !laneSizeElWidthPairSet.count(
5560+
std::make_pair(laneSize, resultElWidth));
5561+
});
5562+
}
55645563

55655564
target.addDynamicallyLegalOp<arith::AddFOp>([](arith::AddFOp op) {
55665565
auto resultType = dyn_cast<VectorType>(op.getType());
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//===- test-int-add-sub-backend.mlir - int add/sub legality per backend -*- MLIR -*-===//
2+
//
3+
// This file is licensed 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+
// Copyright (C) 2026, Advanced Micro Devices, Inc.
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
// Integer vector arith.{addi,subi} → aievec.{add_elem,sub_elem} only on the
12+
// CPP (chess) backend; on the LLVMIR (Peano) backend the arith ops must pass
13+
// through unchanged so the standard arith→LLVM lowering can handle them.
14+
//
15+
// Regression for issue #3027: prior to the fix, arith.subi on vectors was
16+
// marked illegal under both backends but had a conversion pattern only under
17+
// CPP, hard-failing aiecc on AIE2P with target-backend=llvmir for vector
18+
// sizes the rewrite would otherwise have matched (e.g. vector<32xi16>).
19+
20+
// RUN: aie-opt %s --convert-vector-to-aievec="aie-target=aie2 target-backend=cpp" \
21+
// RUN: | FileCheck %s --check-prefix=CPP
22+
// RUN: aie-opt %s --convert-vector-to-aievec="aie-target=aie2 target-backend=llvmir" \
23+
// RUN: | FileCheck %s --check-prefix=LLVM
24+
// RUN: aie-opt %s --convert-vector-to-aievec="aie-target=aie2p target-backend=llvmir" \
25+
// RUN: | FileCheck %s --check-prefix=LLVM
26+
// RUN: aie-opt %s --convert-vector-to-aievec="aie-target=aie2p target-backend=llvmir" \
27+
// RUN: | FileCheck %s --check-prefix=NO-INT-ADD-SUB-AIEVEC
28+
29+
// CPP-LABEL: func @vec_addi_i16_512(
30+
// LLVM-LABEL: func @vec_addi_i16_512(
31+
func.func @vec_addi_i16_512(%a: vector<32xi16>, %b: vector<32xi16>) -> vector<32xi16> {
32+
// CPP: aievec.add_elem %{{.*}}, %{{.*}} : vector<32xi16>
33+
// LLVM-NOT: aievec.add_elem
34+
// LLVM: arith.addi %{{.*}}, %{{.*}} : vector<32xi16>
35+
%r = arith.addi %a, %b : vector<32xi16>
36+
return %r : vector<32xi16>
37+
}
38+
39+
// CPP-LABEL: func @vec_subi_i16_512(
40+
// LLVM-LABEL: func @vec_subi_i16_512(
41+
func.func @vec_subi_i16_512(%a: vector<32xi16>, %b: vector<32xi16>) -> vector<32xi16> {
42+
// CPP: aievec.sub_elem %{{.*}}, %{{.*}} : vector<32xi16>
43+
// LLVM-NOT: aievec.sub_elem
44+
// LLVM: arith.subi %{{.*}}, %{{.*}} : vector<32xi16>
45+
%r = arith.subi %a, %b : vector<32xi16>
46+
return %r : vector<32xi16>
47+
}
48+
49+
// CPP-LABEL: func @vec_subi_i8_512(
50+
// LLVM-LABEL: func @vec_subi_i8_512(
51+
func.func @vec_subi_i8_512(%a: vector<64xi8>, %b: vector<64xi8>) -> vector<64xi8> {
52+
// CPP: aievec.sub_elem %{{.*}}, %{{.*}} : vector<64xi8>
53+
// LLVM-NOT: aievec.sub_elem
54+
// LLVM: arith.subi %{{.*}}, %{{.*}} : vector<64xi8>
55+
%r = arith.subi %a, %b : vector<64xi8>
56+
return %r : vector<64xi8>
57+
}
58+
59+
// 256-bit i8 vectors stay legal on both backends (no rewrite, no failure).
60+
61+
// CPP-LABEL: func @vec_subi_i8_256(
62+
// LLVM-LABEL: func @vec_subi_i8_256(
63+
func.func @vec_subi_i8_256(%a: vector<32xi8>, %b: vector<32xi8>) -> vector<32xi8> {
64+
// CPP-NOT: aievec.sub_elem
65+
// LLVM-NOT: aievec.sub_elem
66+
// CPP: arith.subi %{{.*}}, %{{.*}} : vector<32xi8>
67+
// LLVM: arith.subi %{{.*}}, %{{.*}} : vector<32xi8>
68+
%r = arith.subi %a, %b : vector<32xi8>
69+
return %r : vector<32xi8>
70+
}
71+
72+
// Scalars stay legal on both backends.
73+
74+
// CPP-LABEL: func @scalar_subi(
75+
// LLVM-LABEL: func @scalar_subi(
76+
func.func @scalar_subi(%a: i32, %b: i32) -> i32 {
77+
// CPP-NOT: aievec.sub_elem
78+
// LLVM-NOT: aievec.sub_elem
79+
// CPP: arith.subi %{{.*}}, %{{.*}} : i32
80+
// LLVM: arith.subi %{{.*}}, %{{.*}} : i32
81+
%r = arith.subi %a, %b : i32
82+
return %r : i32
83+
}
84+
85+
// NO-INT-ADD-SUB-AIEVEC: module
86+
// NO-INT-ADD-SUB-AIEVEC-NOT: aievec.add_elem
87+
// NO-INT-ADD-SUB-AIEVEC-NOT: aievec.sub_elem

0 commit comments

Comments
 (0)