Skip to content

Commit 41ebbed

Browse files
authored
[AArch64][GlobalISel] Legalize vector boolean bitcasts to scalars by lowering via stack.
Reviewers: davemgreen, topperc, arsenm Reviewed By: arsenm Pull Request: #121171
1 parent 7e3180a commit 41ebbed

File tree

5 files changed

+67
-1
lines changed

5 files changed

+67
-1
lines changed

llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
2424
#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
25+
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
2526
#include "llvm/CodeGen/RuntimeLibcallUtil.h"
2627
#include "llvm/CodeGen/TargetOpcodes.h"
2728

@@ -297,6 +298,10 @@ class LegalizerHelper {
297298
MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment,
298299
MachinePointerInfo &PtrInfo);
299300

301+
/// Create a store of \p Val to a stack temporary and return a load as the
302+
/// same type as \p Res.
303+
MachineInstrBuilder createStackStoreLoad(const DstOp &Res, const SrcOp &Val);
304+
300305
/// Get a pointer to vector element \p Index located in memory for a vector of
301306
/// type \p VecTy starting at a base address of \p VecPtr. If \p Index is out
302307
/// of bounds the returned pointer is unspecified, but will be within the

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
2323
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
2424
#include "llvm/CodeGen/GlobalISel/Utils.h"
25+
#include "llvm/CodeGen/LowLevelTypeUtils.h"
2526
#include "llvm/CodeGen/MachineConstantPool.h"
2627
#include "llvm/CodeGen/MachineFrameInfo.h"
2728
#include "llvm/CodeGen/MachineRegisterInfo.h"
@@ -4664,6 +4665,20 @@ LegalizerHelper::createStackTemporary(TypeSize Bytes, Align Alignment,
46644665
return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
46654666
}
46664667

4668+
MachineInstrBuilder LegalizerHelper::createStackStoreLoad(const DstOp &Res,
4669+
const SrcOp &Val) {
4670+
LLT SrcTy = Val.getLLTTy(MRI);
4671+
Align StackTypeAlign =
4672+
std::max(getStackTemporaryAlignment(SrcTy),
4673+
getStackTemporaryAlignment(Res.getLLTTy(MRI)));
4674+
MachinePointerInfo PtrInfo;
4675+
auto StackTemp =
4676+
createStackTemporary(SrcTy.getSizeInBytes(), StackTypeAlign, PtrInfo);
4677+
4678+
MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4679+
return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4680+
}
4681+
46674682
static Register clampVectorIndex(MachineIRBuilder &B, Register IdxReg,
46684683
LLT VecTy) {
46694684
LLT IdxTy = B.getMRI()->getType(IdxReg);

llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,13 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
862862
.legalForCartesianProduct({s32, v2s16, v4s8})
863863
.legalForCartesianProduct({s64, v8s8, v4s16, v2s32})
864864
.legalForCartesianProduct({s128, v16s8, v8s16, v4s32, v2s64, v2p0})
865+
.customIf([=](const LegalityQuery &Query) {
866+
// Handle casts from i1 vectors to scalars.
867+
LLT DstTy = Query.Types[0];
868+
LLT SrcTy = Query.Types[1];
869+
return DstTy.isScalar() && SrcTy.isVector() &&
870+
SrcTy.getScalarSizeInBits() == 1;
871+
})
865872
.lowerIf([=](const LegalityQuery &Query) {
866873
return Query.Types[0].isVector() != Query.Types[1].isVector();
867874
})
@@ -1406,11 +1413,28 @@ bool AArch64LegalizerInfo::legalizeCustom(
14061413
return Helper.lowerAbsToCNeg(MI);
14071414
case TargetOpcode::G_ICMP:
14081415
return legalizeICMP(MI, MRI, MIRBuilder);
1416+
case TargetOpcode::G_BITCAST:
1417+
return legalizeBitcast(MI, Helper);
14091418
}
14101419

14111420
llvm_unreachable("expected switch to return");
14121421
}
14131422

1423+
bool AArch64LegalizerInfo::legalizeBitcast(MachineInstr &MI,
1424+
LegalizerHelper &Helper) const {
1425+
assert(MI.getOpcode() == TargetOpcode::G_BITCAST && "Unexpected opcode");
1426+
auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
1427+
// We're trying to handle casts from i1 vectors to scalars but reloading from
1428+
// stack.
1429+
if (!DstTy.isScalar() || !SrcTy.isVector() ||
1430+
SrcTy.getElementType() != LLT::scalar(1))
1431+
return false;
1432+
1433+
Helper.createStackStoreLoad(DstReg, SrcReg);
1434+
MI.eraseFromParent();
1435+
return true;
1436+
}
1437+
14141438
bool AArch64LegalizerInfo::legalizeFunnelShift(MachineInstr &MI,
14151439
MachineRegisterInfo &MRI,
14161440
MachineIRBuilder &MIRBuilder,

llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class AArch64LegalizerInfo : public LegalizerInfo {
6666
LegalizerHelper &Helper) const;
6767
bool legalizeDynStackAlloc(MachineInstr &MI, LegalizerHelper &Helper) const;
6868
bool legalizePrefetch(MachineInstr &MI, LegalizerHelper &Helper) const;
69+
bool legalizeBitcast(MachineInstr &MI, LegalizerHelper &Helper) const;
6970
const AArch64Subtarget *ST;
7071
};
7172
} // End llvm namespace.

llvm/test/CodeGen/AArch64/GlobalISel/legalize-bitcast.mir

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
2-
# RUN: llc -mtriple=aarch64 -run-pass=legalizer -global-isel-abort=1 %s -o - | FileCheck %s
2+
# RUN: llc -mtriple=aarch64 -run-pass=legalizer -global-isel-abort=2 %s -o - | FileCheck %s
33
---
44
name: scalar_to_oversize_vector
55
tracksRegLiveness: true
@@ -48,3 +48,24 @@ body: |
4848
G_BR %bb.2
4949
5050
...
51+
# This test currently is expected to fall back after reaching truncstore of <8 x s8> as <8 x s1>.
52+
---
53+
name: boolean_vector_to_scalar
54+
tracksRegLiveness: true
55+
body: |
56+
bb.1:
57+
; CHECK-LABEL: name: boolean_vector_to_scalar
58+
; CHECK: %vec:_(<8 x s1>) = G_IMPLICIT_DEF
59+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
60+
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<8 x s8>) = G_ANYEXT %vec(<8 x s1>)
61+
; CHECK-NEXT: G_STORE [[ANYEXT]](<8 x s8>), [[FRAME_INDEX]](p0) :: (store (<8 x s1>) into %stack.0)
62+
; CHECK-NEXT: %bc:_(s8) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s8) from %stack.0)
63+
; CHECK-NEXT: %ext:_(s32) = G_ANYEXT %bc(s8)
64+
; CHECK-NEXT: $w0 = COPY %ext(s32)
65+
; CHECK-NEXT: RET_ReallyLR implicit $w0
66+
%vec:_(<8 x s1>) = G_IMPLICIT_DEF
67+
%bc:_(s8) = G_BITCAST %vec(<8 x s1>)
68+
%ext:_(s32) = G_ANYEXT %bc(s8)
69+
$w0 = COPY %ext(s32)
70+
RET_ReallyLR implicit $w0
71+
...

0 commit comments

Comments
 (0)