[llvm] 41ebbed - [AArch64][GlobalISel] Legalize vector boolean bitcasts to scalars by lowering via stack.
via llvm-commits
llvm-commits at lists.llvm.org
Sun Jan 5 21:32:30 PST 2025
Author: Amara Emerson
Date: 2025-01-05T21:32:27-08:00
New Revision: 41ebbed280e9e4e8fa3b394486fad70d1af4c797
URL: https://github.com/llvm/llvm-project/commit/41ebbed280e9e4e8fa3b394486fad70d1af4c797
DIFF: https://github.com/llvm/llvm-project/commit/41ebbed280e9e4e8fa3b394486fad70d1af4c797.diff
LOG: [AArch64][GlobalISel] Legalize vector boolean bitcasts to scalars by lowering via stack.
Reviewers: davemgreen, topperc, arsenm
Reviewed By: arsenm
Pull Request: https://github.com/llvm/llvm-project/pull/121171
Added:
Modified:
llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h
llvm/test/CodeGen/AArch64/GlobalISel/legalize-bitcast.mir
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 2384b22c052662..fac059803b9489 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -22,6 +22,7 @@
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/RuntimeLibcallUtil.h"
#include "llvm/CodeGen/TargetOpcodes.h"
@@ -297,6 +298,10 @@ class LegalizerHelper {
MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment,
MachinePointerInfo &PtrInfo);
+ /// Create a store of \p Val to a stack temporary and return a load as the
+ /// same type as \p Res.
+ MachineInstrBuilder createStackStoreLoad(const DstOp &Res, const SrcOp &Val);
+
/// Get a pointer to vector element \p Index located in memory for a vector of
/// type \p VecTy starting at a base address of \p VecPtr. If \p Index is out
/// of bounds the returned pointer is unspecified, but will be within the
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 7af074a37e13c3..7dece931e8e0eb 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -22,6 +22,7 @@
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
+#include "llvm/CodeGen/LowLevelTypeUtils.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
@@ -4664,6 +4665,20 @@ LegalizerHelper::createStackTemporary(TypeSize Bytes, Align Alignment,
return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
}
+MachineInstrBuilder LegalizerHelper::createStackStoreLoad(const DstOp &Res,
+ const SrcOp &Val) {
+ LLT SrcTy = Val.getLLTTy(MRI);
+ Align StackTypeAlign =
+ std::max(getStackTemporaryAlignment(SrcTy),
+ getStackTemporaryAlignment(Res.getLLTTy(MRI)));
+ MachinePointerInfo PtrInfo;
+ auto StackTemp =
+ createStackTemporary(SrcTy.getSizeInBytes(), StackTypeAlign, PtrInfo);
+
+ MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
+ return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
+}
+
static Register clampVectorIndex(MachineIRBuilder &B, Register IdxReg,
LLT VecTy) {
LLT IdxTy = B.getMRI()->getType(IdxReg);
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index c8c5e6c70b3689..09c2825ac1b8cc 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -862,6 +862,13 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
.legalForCartesianProduct({s32, v2s16, v4s8})
.legalForCartesianProduct({s64, v8s8, v4s16, v2s32})
.legalForCartesianProduct({s128, v16s8, v8s16, v4s32, v2s64, v2p0})
+ .customIf([=](const LegalityQuery &Query) {
+ // Handle casts from i1 vectors to scalars.
+ LLT DstTy = Query.Types[0];
+ LLT SrcTy = Query.Types[1];
+ return DstTy.isScalar() && SrcTy.isVector() &&
+ SrcTy.getScalarSizeInBits() == 1;
+ })
.lowerIf([=](const LegalityQuery &Query) {
return Query.Types[0].isVector() != Query.Types[1].isVector();
})
@@ -1406,11 +1413,28 @@ bool AArch64LegalizerInfo::legalizeCustom(
return Helper.lowerAbsToCNeg(MI);
case TargetOpcode::G_ICMP:
return legalizeICMP(MI, MRI, MIRBuilder);
+ case TargetOpcode::G_BITCAST:
+ return legalizeBitcast(MI, Helper);
}
llvm_unreachable("expected switch to return");
}
+bool AArch64LegalizerInfo::legalizeBitcast(MachineInstr &MI,
+ LegalizerHelper &Helper) const {
+ assert(MI.getOpcode() == TargetOpcode::G_BITCAST && "Unexpected opcode");
+ auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
+ // We're trying to handle casts from i1 vectors to scalars but reloading from
+ // stack.
+ if (!DstTy.isScalar() || !SrcTy.isVector() ||
+ SrcTy.getElementType() != LLT::scalar(1))
+ return false;
+
+ Helper.createStackStoreLoad(DstReg, SrcReg);
+ MI.eraseFromParent();
+ return true;
+}
+
bool AArch64LegalizerInfo::legalizeFunnelShift(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder,
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h
index 00d85a36e4b2ca..bcb294326fa92a 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h
@@ -66,6 +66,7 @@ class AArch64LegalizerInfo : public LegalizerInfo {
LegalizerHelper &Helper) const;
bool legalizeDynStackAlloc(MachineInstr &MI, LegalizerHelper &Helper) const;
bool legalizePrefetch(MachineInstr &MI, LegalizerHelper &Helper) const;
+ bool legalizeBitcast(MachineInstr &MI, LegalizerHelper &Helper) const;
const AArch64Subtarget *ST;
};
} // End llvm namespace.
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-bitcast.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-bitcast.mir
index e3a633c9e035d0..7b24bb1227fa26 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-bitcast.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-bitcast.mir
@@ -1,5 +1,5 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
-# RUN: llc -mtriple=aarch64 -run-pass=legalizer -global-isel-abort=1 %s -o - | FileCheck %s
+# RUN: llc -mtriple=aarch64 -run-pass=legalizer -global-isel-abort=2 %s -o - | FileCheck %s
---
name: scalar_to_oversize_vector
tracksRegLiveness: true
@@ -48,3 +48,24 @@ body: |
G_BR %bb.2
...
+# This test currently is expected to fall back after reaching truncstore of <8 x s8> as <8 x s1>.
+---
+name: boolean_vector_to_scalar
+tracksRegLiveness: true
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: boolean_vector_to_scalar
+ ; CHECK: %vec:_(<8 x s1>) = G_IMPLICIT_DEF
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
+ ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<8 x s8>) = G_ANYEXT %vec(<8 x s1>)
+ ; CHECK-NEXT: G_STORE [[ANYEXT]](<8 x s8>), [[FRAME_INDEX]](p0) :: (store (<8 x s1>) into %stack.0)
+ ; CHECK-NEXT: %bc:_(s8) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s8) from %stack.0)
+ ; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %bc(s8)
+ ; CHECK-NEXT: $w0 = COPY %ext(s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %vec:_(<8 x s1>) = G_IMPLICIT_DEF
+ %bc:_(s8) = G_BITCAST %vec(<8 x s1>)
+ %ext:_(s32) = G_ANYEXT %bc(s8)
+ $w0 = COPY %ext(s32)
+ RET_ReallyLR implicit $w0
+...
More information about the llvm-commits
mailing list