From edbbc3985a485c508cc842c46afc84b9e9b90e49 Mon Sep 17 00:00:00 2001 From: pavani karveti Date: Mon, 21 Apr 2025 01:14:10 -0700 Subject: [PATCH] [Hexagon] Handle Call Operand vxi1 in Hexagon without HVX Enabled This commit updates the Hexagon backend to handle vxi1 call operands Without HVX enabled. It ensures compatibility for vector types of sizes 4, 8, 16, 32, 64, and 128 x i1 when HVX is not enabled. Change-Id: Iddecb58b7e2884cc7b3b35569c0768e203979e95 --- .../Target/Hexagon/HexagonISelLowering.cpp | 77 +++++++++++++++++++ llvm/lib/Target/Hexagon/HexagonISelLowering.h | 12 +++ .../CodeGen/Hexagon/calloperand-v128i1.ll | 30 +++++--- .../test/CodeGen/Hexagon/calloperand-v16i1.ll | 23 ++++-- .../test/CodeGen/Hexagon/calloperand-v32i1.ll | 6 ++ .../test/CodeGen/Hexagon/calloperand-v64i1.ll | 7 ++ 6 files changed, 138 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index 4c479ac41be12..dca8aaaf66422 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -155,7 +155,84 @@ static bool CC_SkipOdd(unsigned &ValNo, MVT &ValVT, MVT &LocVT, } #include "HexagonGenCallingConv.inc" +unsigned HexagonTargetLowering::getVectorTypeBreakdownForCallingConv( + LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, + unsigned &NumIntermediates, MVT &RegisterVT) const { + + RegisterVT = MVT::v8i8; + IntermediateVT = MVT::v8i1; + // Split vectors of type vXi1 into (X/8) vectors of type v8i1, + // where X is divisible by 8. + if (!Subtarget.useHVXOps()) { + switch (VT.getSimpleVT().SimpleTy) { + case MVT::v16i1: + NumIntermediates = 2; + return 2; + case MVT::v32i1: + NumIntermediates = 4; + return 4; + case MVT::v64i1: + NumIntermediates = 8; + return 8; + case MVT::v128i1: + NumIntermediates = 16; + return 16; + default: + break; + } + } + // Split v128i1 vectors into 2 v64i1 vectors in HVX 64-byte mode. + if (VT == MVT::v128i1 && Subtarget.useHVX64BOps()) { + RegisterVT = MVT::v64i8; + IntermediateVT = MVT::v64i1; + NumIntermediates = 2; + return 2; + } + return TargetLowering::getVectorTypeBreakdownForCallingConv( + Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT); +} +std::pair +HexagonTargetLowering::handleMaskRegisterForCallingConv( + unsigned NumElts, CallingConv::ID CC, const HexagonSubtarget &Subtarget, + EVT VT) const { + + unsigned NumIntermediates = 1; + ElementCount EC = VT.getVectorElementCount(); + // For vectors of type vXi1, where X is divisible by 8, + // use Double registers when HVX is not enabled. + if (VT.getVectorNumElements() >= 16 && !Subtarget.useHVXOps() && + isPowerOf2_32(EC.getKnownMinValue())) { + while (EC.getKnownMinValue() > 8) { + EC = EC.divideCoefficientBy(2); + + NumIntermediates <<= 1; + } + return {MVT::v8i8, NumIntermediates}; + } + // Split v128i1 vectors into 2 v64i1 vectors in HVX 64-byte mode. + if (VT == MVT::v128i1 && Subtarget.useHVX64BOps()) { + return {MVT::v64i8, 2}; + } + return {MVT::INVALID_SIMPLE_VALUE_TYPE, 0}; +} + +MVT HexagonTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context, + CallingConv::ID CC, + EVT VT) const { + if (VT.isVector()) { + if (VT.getVectorElementType() == MVT::i1) { + unsigned NumElts = VT.getVectorNumElements(); + MVT RegisterVT; + unsigned NumRegisters; + std::tie(RegisterVT, NumRegisters) = + handleMaskRegisterForCallingConv(NumElts, CC, Subtarget, VT); + if (RegisterVT != MVT::INVALID_SIMPLE_VALUE_TYPE) + return RegisterVT; + } + } + return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT); +} SDValue HexagonTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h index 4df88b3a8abd7..8270498b70061 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h @@ -183,6 +183,10 @@ class HexagonTargetLowering : public TargetLowering { SelectionDAG &DAG) const override; const char *getTargetNodeName(unsigned Opcode) const override; + std::pair + handleMaskRegisterForCallingConv(unsigned NumElts, CallingConv::ID CC, + const HexagonSubtarget &Subtarget, + EVT VT) const; SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const; @@ -263,6 +267,14 @@ class HexagonTargetLowering : public TargetLowering { Register getRegisterByName(const char* RegName, LLT VT, const MachineFunction &MF) const override; + unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, + CallingConv::ID CC, EVT VT, + EVT &IntermediateVT, + unsigned &NumIntermediates, + MVT &RegisterVT) const override; + + MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, + EVT VT) const override; /// If a physical register, this returns the register that receives the /// exception address on entry to an EH pad. Register diff --git a/llvm/test/CodeGen/Hexagon/calloperand-v128i1.ll b/llvm/test/CodeGen/Hexagon/calloperand-v128i1.ll index ddac8c1cd8279..9d323b455449e 100644 --- a/llvm/test/CodeGen/Hexagon/calloperand-v128i1.ll +++ b/llvm/test/CodeGen/Hexagon/calloperand-v128i1.ll @@ -1,10 +1,20 @@ -;RUN: llc -mtriple=hexagon -mattr=+hvxv79,+hvx-length128b < %s -o - | FileCheck %s +;RUN: llc -mtriple=hexagon < %s -o - | FileCheck %s --check-prefix=CHECK +;RUN: llc -mtriple=hexagon -mattr=+hvxv79,+hvx-length64b < %s -o - | FileCheck %s --check-prefixes=CHECK-64,CHECK-64-128 +;RUN: llc -mtriple=hexagon -mattr=+hvxv79,+hvx-length128b < %s -o - | FileCheck %s --check-prefixes=CHECK-128,CHECK-64-128 ; CHECK-LABEL: compare_vectors -; CHECK: [[REG1:(q[0-9]+)]] = vcmp.eq(v{{[0-9]+}}.b,v{{[0-9]+}}.b) -; CHECK: [[REG2:(r[0-9]+)]] = #-1 -; CHECK: v0 = vand([[REG1]],[[REG2]]) - +; CHECK: [[REG8:(r[0-9]+):[0-9]]] = CONST64(#72340172838076673) +; CHECK: r{{[0-9]+}}:{{[0-9]+}} = and(r{{[0-9]+}}:{{[0-9]+}},[[REG8]]) +; CHECK: r{{[0-9]+}}:{{[0-9]+}} = and(r{{[0-9]+}}:{{[0-9]+}},[[REG8]]) +; CHECK: r{{[0-9]+}}:{{[0-9]+}} = and(r{{[0-9]+}}:{{[0-9]+}},[[REG8]]) +; CHECK-128: [[REG1:(q[0-9]+)]] = vcmp.eq(v{{[0-9]+}}.b,v{{[0-9]+}}.b) +; CHECK-128: [[REG2:(r[0-9]+)]] = #-1 +; CHECK-128: v0 = vand([[REG1]],[[REG2]]) +; CHECK-64: [[REG5:(q[0-9]+)]] = vcmp.eq(v{{[0-9]+}}.b,v{{[0-9]+}}.b) +; CHECK-64: [[REG6:(q[0-9]+)]] = vcmp.eq(v{{[0-9]+}}.b,v{{[0-9]+}}.b) +; CHECK-64: [[REG7:(r[0-9]+)]] = #-1 +; CHECK-64: v0 = vand([[REG5]],[[REG7]]) +; CHECK-64: v1 = vand([[REG6]],[[REG7]]) define void @compare_vectors(<128 x i8> %a, <128 x i8> %b) { entry: %result = icmp eq <128 x i8> %a, %b @@ -13,11 +23,13 @@ entry: } ; CHECK-LABEL: f.1: -; CHECK: [[REG3:(q[0-9]+)]] = vand(v0,r{{[0-9]+}}) -; CHECK: [[REG4:(v[0-9]+)]] = vand([[REG3]],r{{[0-9]+}}) -; CHECK: r{{[0-9]+}} = vextract([[REG4]],r{{[0-9]+}}) +; CHECK: [[REG9:(r[0-9]+)]] = and([[REG9]],##16843009) +; CHECK: [[REG10:(r[0-9]+)]] = and([[REG10]],##16843009) +; CHECK-64-128: [[REG3:(q[0-9]+)]] = vand(v0,r{{[0-9]+}}) +; CHECK-64-128: [[REG4:(v[0-9]+)]] = vand([[REG3]],r{{[0-9]+}}) +; CHECK-64-128: r{{[0-9]+}} = vextract([[REG4]],r{{[0-9]+}}) -define i32 @f.1(<128 x i1> %vec) { +define i32 @f.1(<128 x i1> %vec){ %element = extractelement <128 x i1> %vec, i32 6 %is_true = icmp eq i1 %element, true br i1 %is_true, label %if_true, label %if_false diff --git a/llvm/test/CodeGen/Hexagon/calloperand-v16i1.ll b/llvm/test/CodeGen/Hexagon/calloperand-v16i1.ll index bbb2697246df1..6cf1a3fca70b7 100644 --- a/llvm/test/CodeGen/Hexagon/calloperand-v16i1.ll +++ b/llvm/test/CodeGen/Hexagon/calloperand-v16i1.ll @@ -1,10 +1,15 @@ -;RUN: llc -mtriple=hexagon -mattr=+hvxv79,+hvx-length64b < %s -o - | FileCheck %s --check-prefix=CHECK -;RUN: llc -mtriple=hexagon -mattr=+hvxv79,+hvx-length128b < %s -o - | FileCheck %s --check-prefix=CHECK +;RUN: llc -mtriple=hexagon < %s -o - | FileCheck %s --check-prefix=CHECK +;RUN: llc -mtriple=hexagon -mattr=+hvxv79,+hvx-length64b < %s -o - | FileCheck %s --check-prefix=CHECK-HVX +;RUN: llc -mtriple=hexagon -mattr=+hvxv79,+hvx-length128b < %s -o - | FileCheck %s --check-prefix=CHECK-HVX ; CHECK-LABEL: compare_vectors -; CHECK: [[REG1:(q[0-9]+)]] = vcmp.eq(v{{[0-9]+}}.w,v{{[0-9]+}}.w) -; CHECK: [[REG2:(r[0-9]+)]] = #-1 -; CHECK: v0 = vand([[REG1]],[[REG2]]) +; CHECK: [[REG5:(r[0-9]+):[0-9]]] = CONST64(#72340172838076673) +; CHECK: r{{[0-9]+}}:{{[0-9]+}} = and(r{{[0-9]+}}:{{[0-9]+}},[[REG5]]) +; CHECK: r{{[0-9]+}}:{{[0-9]+}} = and(r{{[0-9]+}}:{{[0-9]+}},[[REG5]]) + +; CHECK-HVX: [[REG1:(q[0-9]+)]] = vcmp.eq(v{{[0-9]+}}.w,v{{[0-9]+}}.w) +; CHECK-HVX: [[REG2:(r[0-9]+)]] = #-1 +; CHECK-HVX: v0 = vand([[REG1]],[[REG2]]) define void @compare_vectors(<16 x i32> %a, <16 x i32> %b) { entry: @@ -14,9 +19,11 @@ entry: } ; CHECK-LABEL: f.1: -; CHECK: [[REG3:(q[0-9]+)]] = vand(v0,r{{[0-9]+}}) -; CHECK: [[REG4:(v[0-9]+)]] = vand([[REG3]],r{{[0-9]+}}) -; CHECK: r{{[0-9]+}} = vextract([[REG4]],r{{[0-9]+}}) +; CHECK: [[REG3:(r[0-9]+)]] = and([[REG3]],##16843009) +; CHECK: [[REG4:(r[0-9]+)]] = and([[REG4]],##16843009) +; CHECK-HVX: [[REG3:(q[0-9]+)]] = vand(v0,r{{[0-9]+}}) +; CHECK-HVX: [[REG4:(v[0-9]+)]] = vand([[REG3]],r{{[0-9]+}}) +; CHECK-HVX: r{{[0-9]+}} = vextract([[REG4]],r{{[0-9]+}}) define i32 @f.1(<16 x i1> %vec) { %element = extractelement <16 x i1> %vec, i32 6 diff --git a/llvm/test/CodeGen/Hexagon/calloperand-v32i1.ll b/llvm/test/CodeGen/Hexagon/calloperand-v32i1.ll index a73478728d910..c43ad70b94100 100644 --- a/llvm/test/CodeGen/Hexagon/calloperand-v32i1.ll +++ b/llvm/test/CodeGen/Hexagon/calloperand-v32i1.ll @@ -1,7 +1,11 @@ +; RUN: llc -mtriple=hexagon < %s -o - | FileCheck %s --check-prefix=CHECK ; RUN: llc -mtriple=hexagon -mattr=+hvxv79,+hvx-length64b < %s -o - | FileCheck %s --check-prefix=CHECK-64 ; RUN: llc -mtriple=hexagon -mattr=+hvxv79,+hvx-length128b < %s -o - | FileCheck %s --check-prefix=CHECK-128 ; CHECK-LABEL: compare_vectors +; CHECK: [[REG8:(r[0-9]+):[0-9]]] = CONST64(#72340172838076673) +; CHECK: r{{[0-9]+}}:{{[0-9]+}} = and(r{{[0-9]+}}:{{[0-9]+}},[[REG8]]) +; CHECK: r{{[0-9]+}}:{{[0-9]+}} = and(r{{[0-9]+}}:{{[0-9]+}},[[REG8]]) ; CHECK-64: [[REG1:(q[0-9]+)]] = vcmp.eq(v{{[0-9]+}}.h,v{{[0-9]+}}.h) ; CHECK-64: [[REG2:(r[0-9]+)]] = #-1 ; CHECK-64: v0 = vand([[REG1]],[[REG2]]) @@ -21,6 +25,8 @@ entry: } ; CHECK-LABEL: f.1: +; CHECK: [[REG9:(r[0-9]+)]] = and([[REG9]],##16843009) +; CHECK: [[REG10:(r[0-9]+)]] = and([[REG10]],##16843009) ; CHECK-64: [[REG3:(q[0-9]+)]] = vand(v0,r{{[0-9]+}}) ; CHECK-64: [[REG4:(v[0-9]+)]] = vand([[REG3]],r{{[0-9]+}}) ; CHECK-64: r{{[0-9]+}} = vextract([[REG4]],r{{[0-9]+}}) diff --git a/llvm/test/CodeGen/Hexagon/calloperand-v64i1.ll b/llvm/test/CodeGen/Hexagon/calloperand-v64i1.ll index 7cc562085a7e6..90a2da14f1971 100644 --- a/llvm/test/CodeGen/Hexagon/calloperand-v64i1.ll +++ b/llvm/test/CodeGen/Hexagon/calloperand-v64i1.ll @@ -1,7 +1,12 @@ +; RUN: llc -mtriple=hexagon < %s -o - | FileCheck %s --check-prefix=CHECK ; RUN: llc -mtriple=hexagon -mattr=+hvxv79,+hvx-length64b < %s -o - | FileCheck %s --check-prefix=CHECK-64 ; RUN: llc -mtriple=hexagon -mattr=+hvxv79,+hvx-length128b < %s -o - | FileCheck %s --check-prefix=CHECK-128 ; CHECK-LABEL: compare_vectors +; CHECK: [[REG8:(r[0-9]+):[0-9]]] = CONST64(#72340172838076673) +; CHECK: r{{[0-9]+}}:{{[0-9]+}} = and(r{{[0-9]+}}:{{[0-9]+}},[[REG8]]) +; CHECK: r{{[0-9]+}}:{{[0-9]+}} = and(r{{[0-9]+}}:{{[0-9]+}},[[REG8]]) +; CHECK: r{{[0-9]+}}:{{[0-9]+}} = and(r{{[0-9]+}}:{{[0-9]+}},[[REG8]]) ; CHECK-64: [[REG1:(q[0-9]+)]] = vcmp.eq(v{{[0-9]+}}.b,v{{[0-9]+}}.b) ; CHECK-64: [[REG2:(r[0-9]+)]] = #-1 ; CHECK-64: v0 = vand([[REG1]],[[REG2]]) @@ -21,6 +26,8 @@ entry: } ; CHECK-LABEL: f.1: +; CHECK: [[REG9:(r[0-9]+)]] = and([[REG9]],##16843009) +; CHECK: [[REG10:(r[0-9]+)]] = and([[REG10]],##16843009) ; CHECK-64: [[REG3:(q[0-9]+)]] = vand(v0,r{{[0-9]+}}) ; CHECK-64: [[REG4:(v[0-9]+)]] = vand([[REG3]],r{{[0-9]+}}) ; CHECK-64: r{{[0-9]+}} = vextract([[REG4]],r{{[0-9]+}})