From eabf11f9ea8d647d78e455664658b4faf8880029 Mon Sep 17 00:00:00 2001 From: Fraser Cormack Date: Wed, 20 Oct 2021 15:51:36 +0100 Subject: [PATCH] [CodeGenPrepare] Avoid a scalable-vector crash in ctlz/cttz This patch fixes a crash when despeculating ctlz/cttz intrinsics with scalable-vector types. It is not safe to speculatively get the size of the vector type in bits in case the vector type is not a fixed-length type. As it happens this isn't required as vector types are skipped anyway. Reviewed By: RKSimon Differential Revision: https://reviews.llvm.org/D112141 --- llvm/lib/CodeGen/CodeGenPrepare.cpp | 2 +- .../CodeGenPrepare/RISCV/cttz-ctlz.ll | 28 +++++++++++++++++++ .../CodeGenPrepare/RISCV/lit.local.cfg | 2 ++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/CodeGenPrepare/RISCV/cttz-ctlz.ll create mode 100644 llvm/test/Transforms/CodeGenPrepare/RISCV/lit.local.cfg diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 85def4f17f03..9fdee8f5e4ff 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -2036,7 +2036,7 @@ static bool despeculateCountZeros(IntrinsicInst *CountZeros, // Only handle legal scalar cases. Anything else requires too much work. Type *Ty = CountZeros->getType(); - unsigned SizeInBits = Ty->getPrimitiveSizeInBits(); + unsigned SizeInBits = Ty->getScalarSizeInBits(); if (Ty->isVectorTy() || SizeInBits > DL->getLargestLegalIntTypeSizeInBits()) return false; diff --git a/llvm/test/Transforms/CodeGenPrepare/RISCV/cttz-ctlz.ll b/llvm/test/Transforms/CodeGenPrepare/RISCV/cttz-ctlz.ll new file mode 100644 index 000000000000..c70112e91ebd --- /dev/null +++ b/llvm/test/Transforms/CodeGenPrepare/RISCV/cttz-ctlz.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -codegenprepare < %s | FileCheck %s + +target triple = "riscv64-unknown-unknown" + +; Check that despeculating count-zeros intrinsics doesn't crash when those +; intrinsics use scalable types. + +define @cttz_nxv4i64( %x) { +; CHECK-LABEL: @cttz_nxv4i64( +; CHECK-NEXT: [[Z:%.*]] = call @llvm.cttz.nxv4i64( [[X:%.*]], i1 false) +; CHECK-NEXT: ret [[Z]] +; + %z = call @llvm.cttz.nxv4i64( %x, i1 false) + ret %z +} + +define @ctlz_nxv4i64( %x) { +; CHECK-LABEL: @ctlz_nxv4i64( +; CHECK-NEXT: [[Z:%.*]] = call @llvm.ctlz.nxv4i64( [[X:%.*]], i1 false) +; CHECK-NEXT: ret [[Z]] +; + %z = call @llvm.ctlz.nxv4i64( %x, i1 false) + ret %z +} + +declare @llvm.cttz.nxv4i64(, i1) +declare @llvm.ctlz.nxv4i64(, i1) diff --git a/llvm/test/Transforms/CodeGenPrepare/RISCV/lit.local.cfg b/llvm/test/Transforms/CodeGenPrepare/RISCV/lit.local.cfg new file mode 100644 index 000000000000..c63820126f8c --- /dev/null +++ b/llvm/test/Transforms/CodeGenPrepare/RISCV/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'RISCV' in config.root.targets: + config.unsupported = True