Skip to content

Commit 95a3e54

Browse files
authored
[CIR][Lowering] Fix inconditional sign extension on vec.cmp op (#1747)
(Copied from my question on Discord) I’ve been working on the vector to bit-mask related intrinsics for X86. I’ve been stuck specifically on `X86::BI__builtin_ia32_cvtb2mask128(_mm256_movepi16_mask`) and its variations with different vector/mask sizes. In this case, we perform a vector comparison of `vector<16xi16>` and bitcast the resulting `vector<16xi1>` directly into a scalar integer mask (i16). I’m successfully able to lower to cir: ``` ... %5 = cir.vec.cmp(lt, %3, %4) : !cir.vector<!s16i x 16>, !cir.vector<!cir.int<u, 1> x 16> %6 = cir.cast(bitcast, %5 : !cir.vector<!cir.int<u, 1> x 16>), !u16i ... ``` There's an issue arises when lowering this to LLVM, the error message I'm getting is: ``` error: integer width of the output type is smaller or equal to the integer width of the input type ``` By looking at the test cases on the llvm dialect, this is related to the sext / zext instruction. This is the cir → llvm dialect lowered for the latter: ``` ... %14 = "llvm.icmp"(%12, %13) <{predicate = 2 : i64}> : (vector<16xi16>, vector<16xi16>) -> vector<16xi1> %15 = "llvm.sext"(%14) : (vector<16xi1>) -> vector<16xi1> %16 = "llvm.bitcast"(%15) : (vector<16xi1>) -> i16 ... ``` This is seems to be the cause: ``` %15 = "llvm.sext"(%14) : (vector<16xi1>) -> vector<16xi1> ``` **The fix**: Added a type check: if the result type does not differ from the expected type, we won't insert a sextOp
1 parent d45823a commit 95a3e54

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,8 +2063,14 @@ mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
20632063
} else {
20642064
return op.emitError() << "unsupported type for VecCmpOp: " << elementType;
20652065
}
2066-
rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
2067-
op, typeConverter->convertType(op.getType()), bitResult);
2066+
2067+
// Check if the types are the same before generating SExtOp
2068+
auto targetType = typeConverter->convertType(op.getType());
2069+
if (bitResult.getType() == targetType)
2070+
rewriter.replaceOp(op, bitResult);
2071+
else
2072+
rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(op, targetType, bitResult);
2073+
20682074
return mlir::success();
20692075
}
20702076

clang/test/CIR/Lowering/vec-cmp.cir

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: cir-opt %s -cir-to-llvm -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=MLIR
3+
4+
!s16i = !cir.int<s, 16>
5+
!u16i = !cir.int<u, 16>
6+
7+
cir.func @vec_cmp(%0: !cir.vector<!s16i x 16>, %1: !cir.vector<!s16i x 16>) -> () {
8+
%2 = cir.vec.cmp(lt, %0, %1) : !cir.vector<!s16i x 16>, !cir.vector<!cir.int<u, 1> x 16>
9+
%3 = cir.cast(bitcast, %2 : !cir.vector<!cir.int<u, 1> x 16>), !u16i
10+
cir.return
11+
}
12+
13+
// MLIR: llvm.func @vec_cmp
14+
// MLIR-NEXT: %{{[0-9]+}} = llvm.icmp "slt" %arg0, %arg1 : vector<16xi16>
15+
// MLIR-NEXT: %{{[0-9]+}} = llvm.bitcast %{{[0-9]+}} : vector<16xi1> to i16
16+
// MLIR-NEXT: llvm.return

0 commit comments

Comments
 (0)