-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[Hexagon] Handle Call Operand vxi1 in Hexagon without HVX Enabled #136546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
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
@llvm/pr-subscribers-backend-hexagon Author: None (pkarveti) ChangesThis commit updates the Hexagon backend to handle Full diff: https://github.com/llvm/llvm-project/pull/136546.diff 6 Files Affected:
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<MVT, unsigned>
+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<MVT, unsigned>
+ 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]+}})
|
if (VT.getVectorNumElements() >= 16 && !Subtarget.useHVXOps() && | ||
isPowerOf2_32(EC.getKnownMinValue())) { | ||
while (EC.getKnownMinValue() > 8) { | ||
EC = EC.divideCoefficientBy(2); | ||
|
||
NumIntermediates <<= 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we don't need the loop here. Simplify to:
std::pair<MVT, unsigned>
HexagonTargetLowering::handleMaskRegisterForCallingConv(
const HexagonSubtarget &Subtarget, EVT VT) const {
assert(VT.getVectorElementType() == MVT::i1)
// For vectors of type vXi1, where X is power of 2 greater than 8,
// use Double registers when HVX is not enabled.
if (!Subtarget.useHVXOps() && VT.isPow2VectorType() && VT.getVectorNumElements() >= 16)
return {MVT::v8i8, VT.getVectorNumElements() / 8};
// 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};
}
} | ||
std::pair<MVT, unsigned> | ||
HexagonTargetLowering::handleMaskRegisterForCallingConv( | ||
unsigned NumElts, CallingConv::ID CC, const HexagonSubtarget &Subtarget, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can get rid of unsigned NumElts, CallingConv::ID CC
. I don't see them being used within the function
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; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can avoid the switch here and divide the element count by 8 here
return TargetLowering::getVectorTypeBreakdownForCallingConv( | ||
Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT); | ||
} | ||
std::pair<MVT, unsigned> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty line before the start of the function
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.