[llvm] Verifier: forbid non-i32/i64 lrint, and non-i64 llrint (PR #70839)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 31 10:49:28 PDT 2023
https://github.com/artagnon created https://github.com/llvm/llvm-project/pull/70839
The LangRef clearly specifies that the return type of llvm.lrint must be i32, i64, or a vector thereof, and that the return type of llvm.llrint must be i64, or a vector thereof. Check this in the IR Verifier, and bail out early if this is not the case. Furthermore, update a couple of tests that were mistakenly using a non-existent i32-variant of llvm.llrint.
>From 9f194936d7021a5ce9bb49f8f8ec28a9bc6c5f2b Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <Ramkumar.Ramachandra at imgtec.com>
Date: Tue, 31 Oct 2023 16:46:33 +0000
Subject: [PATCH] Verifier: forbid non-i32/i64 lrint, and non-i64 llrint
The LangRef clearly specifies that the return type of llvm.lrint must be
i32, i64, or a vector thereof, and that the return type of llvm.llrint
must be i64, or a vector thereof. Check this in the IR Verifier, and
bail out early if this is not the case. Furthermore, update a couple of
tests that were mistakenly using a non-existent i32-variant of
llvm.llrint.
---
llvm/lib/IR/Verifier.cpp | 10 +++++++
.../Transforms/InstCombine/freeze-fp-ops.ll | 26 +++++++++----------
llvm/test/Transforms/Scalarizer/intrinsics.ll | 12 ++++-----
3 files changed, 29 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 396af600b8dab29..81384befef5b947 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5673,11 +5673,21 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
case Intrinsic::llrint: {
Type *ValTy = Call.getArgOperand(0)->getType();
Type *ResultTy = Call.getType();
+ unsigned ResultSz = ResultTy->getScalarSizeInBits();
Check(
ValTy->isFPOrFPVectorTy() && ResultTy->isIntOrIntVectorTy(),
"llvm.lrint, llvm.llrint: argument must be floating-point or vector "
"of floating-points, and result must be integer or vector of integers",
&Call);
+
+ if (ID == Intrinsic::lrint)
+ Check(ResultSz == 32 || ResultSz == 64,
+ "llvm.lrint: result type must be i32, i64, or a vector thereof",
+ &Call);
+ else
+ Check(ResultSz == 64,
+ "llvm.llrint: result type must be i64 or a vector thereof", &Call);
+
Check(ValTy->isVectorTy() == ResultTy->isVectorTy(),
"llvm.lrint, llvm.llrint: argument and result disagree on vector use",
&Call);
diff --git a/llvm/test/Transforms/InstCombine/freeze-fp-ops.ll b/llvm/test/Transforms/InstCombine/freeze-fp-ops.ll
index 9fb69015a8f7dca..3f147539e110cf3 100644
--- a/llvm/test/Transforms/InstCombine/freeze-fp-ops.ll
+++ b/llvm/test/Transforms/InstCombine/freeze-fp-ops.ll
@@ -411,15 +411,15 @@ define i32 @freeze_lrint(float %arg) {
ret i32 %freeze
}
-define i32 @freeze_llrint(float %arg) {
+define i64 @freeze_llrint(float %arg) {
; CHECK-LABEL: @freeze_llrint(
; CHECK-NEXT: [[ARG_FR:%.*]] = freeze float [[ARG:%.*]]
-; CHECK-NEXT: [[OP:%.*]] = call i32 @llvm.llrint.i32.f32(float [[ARG_FR]])
-; CHECK-NEXT: ret i32 [[OP]]
+; CHECK-NEXT: [[OP:%.*]] = call i64 @llvm.llrint.i64.f32(float [[ARG_FR]])
+; CHECK-NEXT: ret i64 [[OP]]
;
- %op = call i32 @llvm.llrint.i32.f32(float %arg)
- %freeze = freeze i32 %op
- ret i32 %freeze
+ %op = call i64 @llvm.llrint.i64.f32(float %arg)
+ %freeze = freeze i64 %op
+ ret i64 %freeze
}
define i32 @freeze_noundef_lround(float %arg) {
@@ -452,14 +452,14 @@ define i32 @freeze_noundef_lrint(float %arg) {
ret i32 %freeze
}
-define i32 @freeze_noundef_llrint(float %arg) {
+define i64 @freeze_noundef_llrint(float %arg) {
; CHECK-LABEL: @freeze_noundef_llrint(
-; CHECK-NEXT: [[OP:%.*]] = call noundef i32 @llvm.llrint.i32.f32(float [[ARG:%.*]])
-; CHECK-NEXT: ret i32 [[OP]]
+; CHECK-NEXT: [[OP:%.*]] = call noundef i64 @llvm.llrint.i64.f32(float [[ARG:%.*]])
+; CHECK-NEXT: ret i64 [[OP]]
;
- %op = call noundef i32 @llvm.llrint.i32.f32(float %arg)
- %freeze = freeze i32 %op
- ret i32 %freeze
+ %op = call noundef i64 @llvm.llrint.i64.f32(float %arg)
+ %freeze = freeze i64 %op
+ ret i64 %freeze
}
define float @freeze_minnum(float %arg0, float noundef %arg1) {
@@ -603,7 +603,7 @@ declare float @llvm.arithmetic.fence.f32(float)
declare i32 @llvm.lround.i32.f32(float)
declare i32 @llvm.llround.i32.f32(float)
declare i32 @llvm.lrint.i32.f32(float)
-declare i32 @llvm.llrint.i32.f32(float)
+declare i64 @llvm.llrint.i64.f32(float)
declare float @llvm.minnum.f32(float, float)
declare float @llvm.maxnum.f32(float, float)
declare float @llvm.minimum.f32(float, float)
diff --git a/llvm/test/Transforms/Scalarizer/intrinsics.ll b/llvm/test/Transforms/Scalarizer/intrinsics.ll
index f5e5be1f5998e00..2037ea4a2e794d3 100644
--- a/llvm/test/Transforms/Scalarizer/intrinsics.ll
+++ b/llvm/test/Transforms/Scalarizer/intrinsics.ll
@@ -31,7 +31,7 @@ declare <2 x i32> @llvm.fptoui.sat.v2i32.v2f32(<2 x float>)
; Unary fp operand, int return type
declare <2 x i32> @llvm.lrint.v2i32.v2f32(<2 x float>)
-declare <2 x i32> @llvm.llrint.v2i32.v2f32(<2 x float>)
+declare <2 x i64> @llvm.llrint.v2i64.v2f32(<2 x float>)
; Bool return type, overloaded on fp operand type
declare <2 x i1> @llvm.is.fpclass(<2 x float>, i32)
@@ -224,13 +224,13 @@ define <2 x i32> @scalarize_lrint(<2 x float> %x) #0 {
ret <2 x i32> %rnd
}
-define <2 x i32> @scalarize_llrint(<2 x float> %x) #0 {
+define <2 x i64> @scalarize_llrint(<2 x float> %x) #0 {
; CHECK-LABEL: @scalarize_llrint(
-; CHECK-NEXT: [[RND:%.*]] = call <2 x i32> @llvm.llrint.v2i32.v2f32(<2 x float> [[X:%.*]])
-; CHECK-NEXT: ret <2 x i32> [[RND]]
+; CHECK-NEXT: [[RND:%.*]] = call <2 x i64> @llvm.llrint.v2i64.v2f32(<2 x float> [[X:%.*]])
+; CHECK-NEXT: ret <2 x i64> [[RND]]
;
- %rnd = call <2 x i32> @llvm.llrint.v2i32.v2f32(<2 x float> %x)
- ret <2 x i32> %rnd
+ %rnd = call <2 x i64> @llvm.llrint.v2i64.v2f32(<2 x float> %x)
+ ret <2 x i64> %rnd
}
define <2 x i1> @scalarize_is_fpclass(<2 x float> %x) #0 {
More information about the llvm-commits
mailing list