Skip to content

Commit

Permalink
[SelectionDAG] Split <n x T> vector types for atomic load
Browse files Browse the repository at this point in the history
`load atomic <n x T>` is not valid. This change splits
vector types of atomic load in SelectionDAG
so that it can translate vectors of >1 size with type bfloat,half.

commit-id:3a045357
  • Loading branch information
jofrn committed Dec 19, 2024
1 parent b2f0b33 commit c9bdb95
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 0 deletions.
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
void SplitVecRes_FPOp_MultiType(SDNode *N, SDValue &Lo, SDValue &Hi);
void SplitVecRes_IS_FPCLASS(SDNode *N, SDValue &Lo, SDValue &Hi);
void SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, SDValue &Hi);
void SplitVecRes_ATOMIC_LOAD(AtomicSDNode *LD, SDValue &Lo, SDValue &Hi);
void SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo, SDValue &Hi);
void SplitVecRes_VP_LOAD(VPLoadSDNode *LD, SDValue &Lo, SDValue &Hi);
void SplitVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *SLD, SDValue &Lo,
Expand Down
35 changes: 35 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,9 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
SplitVecRes_STEP_VECTOR(N, Lo, Hi);
break;
case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
case ISD::ATOMIC_LOAD:
SplitVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N), Lo, Hi);
break;
case ISD::LOAD:
SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
break;
Expand Down Expand Up @@ -2079,6 +2082,38 @@ void DAGTypeLegalizer::SplitVecRes_VP_SPLAT(SDNode *N, SDValue &Lo,
Hi = DAG.getNode(N->getOpcode(), dl, HiVT, N->getOperand(0), MaskHi, EVLHi);
}

void DAGTypeLegalizer::SplitVecRes_ATOMIC_LOAD(AtomicSDNode *LD, SDValue &Lo,
SDValue &Hi) {
EVT LoVT, HiVT;
SDLoc dl(LD);
std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));

SDValue Ch = LD->getChain();
SDValue Ptr = LD->getBasePtr();
EVT MemoryVT = LD->getMemoryVT();

EVT LoMemVT, HiMemVT;
std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);

Lo = DAG.getAtomic(ISD::ATOMIC_LOAD, dl, LoMemVT, LoMemVT, Ch, Ptr,
LD->getMemOperand());

MachinePointerInfo MPI;
IncrementPointer(LD, LoMemVT, MPI, Ptr);

Hi = DAG.getAtomic(ISD::ATOMIC_LOAD, dl, HiMemVT, HiMemVT, Ch, Ptr,
LD->getMemOperand());

// Build a factor node to remember that this load is independent of the
// other one.
Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
Hi.getValue(1));

// Legalize the chain result - switch anything that used the old chain to
// use the new one.
ReplaceValueWith(SDValue(LD, 1), Ch);
}

void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
SDValue &Hi) {
assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!");
Expand Down
56 changes: 56 additions & 0 deletions llvm/test/CodeGen/X86/atomic-load-store.ll
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,62 @@ define <2 x float> @atomic_vec2_float_align(ptr %x) nounwind {
ret <2 x float> %ret
}

define <2 x half> @atomic_vec2_half(ptr %x) {
; CHECK3-LABEL: atomic_vec2_half:
; CHECK3: ## %bb.0:
; CHECK3-NEXT: movzwl (%rdi), %eax
; CHECK3-NEXT: movzwl 2(%rdi), %ecx
; CHECK3-NEXT: pinsrw $0, %eax, %xmm0
; CHECK3-NEXT: pinsrw $0, %ecx, %xmm1
; CHECK3-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3]
; CHECK3-NEXT: retq
;
; CHECK0-LABEL: atomic_vec2_half:
; CHECK0: ## %bb.0:
; CHECK0-NEXT: movw (%rdi), %dx
; CHECK0-NEXT: movw 2(%rdi), %cx
; CHECK0-NEXT: ## implicit-def: $eax
; CHECK0-NEXT: movw %dx, %ax
; CHECK0-NEXT: ## implicit-def: $xmm0
; CHECK0-NEXT: pinsrw $0, %eax, %xmm0
; CHECK0-NEXT: ## implicit-def: $eax
; CHECK0-NEXT: movw %cx, %ax
; CHECK0-NEXT: ## implicit-def: $xmm1
; CHECK0-NEXT: pinsrw $0, %eax, %xmm1
; CHECK0-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3]
; CHECK0-NEXT: retq
%ret = load atomic <2 x half>, ptr %x acquire, align 4
ret <2 x half> %ret
}

define <2 x bfloat> @atomic_vec2_bfloat(ptr %x) {
; CHECK3-LABEL: atomic_vec2_bfloat:
; CHECK3: ## %bb.0:
; CHECK3-NEXT: movzwl (%rdi), %eax
; CHECK3-NEXT: movzwl 2(%rdi), %ecx
; CHECK3-NEXT: pinsrw $0, %ecx, %xmm1
; CHECK3-NEXT: pinsrw $0, %eax, %xmm0
; CHECK3-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3]
; CHECK3-NEXT: retq
;
; CHECK0-LABEL: atomic_vec2_bfloat:
; CHECK0: ## %bb.0:
; CHECK0-NEXT: movw (%rdi), %cx
; CHECK0-NEXT: movw 2(%rdi), %dx
; CHECK0-NEXT: ## implicit-def: $eax
; CHECK0-NEXT: movw %dx, %ax
; CHECK0-NEXT: ## implicit-def: $xmm1
; CHECK0-NEXT: pinsrw $0, %eax, %xmm1
; CHECK0-NEXT: ## implicit-def: $eax
; CHECK0-NEXT: movw %cx, %ax
; CHECK0-NEXT: ## implicit-def: $xmm0
; CHECK0-NEXT: pinsrw $0, %eax, %xmm0
; CHECK0-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3]
; CHECK0-NEXT: retq
%ret = load atomic <2 x bfloat>, ptr %x acquire, align 4
ret <2 x bfloat> %ret
}

define <1 x ptr> @atomic_vec1_ptr(ptr %x) nounwind {
; CHECK3-LABEL: atomic_vec1_ptr:
; CHECK3: ## %bb.0:
Expand Down

0 comments on commit c9bdb95

Please sign in to comment.