Why should I know this?

[VectorCombine] Shuffle Kind 본문

LLVM-WORK-LOG/VectorCombine

[VectorCombine] Shuffle Kind

die4taoam 2025. 1. 20. 04:23

 

 

   
SK_Select Selects elements from the corresponding lane of either source operand. This is equivalent to a vector select with a constant condition operand.
   
   
   
   
SK_PermuteTwoSrc Merge elements from two source vectors into one with any shuffle mask.
SK_PermuteSingleSrc Shuffle elements of single source vector with any shuffle mask.
   

 

 

 

#SK_Select

소스 피연산자의 해당 레인에서 요소를 선택합니다. 이는 상수 조건 피연산자를 가진 벡터 선택과 동일합니다.

 

예)

define <4 x float> @ext0_v4f32(<4 x float> %x, <4 x float> %y) {
; CHECK-LABEL: @ext0_v4f32(
; CHECK-NEXT:    [[TMP1:%.*]] = fneg <4 x float> [[X:%.*]]
; CHECK-NEXT:    [[R:%.*]] = shufflevector <4 x float> [[Y:%.*]], <4 x float> [[TMP1]], <4 x i32> <i32 4, i32 1, i32 2, i32 3>
; CHECK-NEXT:    ret <4 x float> [[R]]
;
  %e = extractelement <4 x float> %x, i32 0
  %n = fneg float %e
  %r = insertelement <4 x float> %y, float %n, i32 0
  ret <4 x float> %r
}

 

https://github.com/ParkHanbum/llvm-project/commit/baab4aa1ba5f6

 

[VectorCombine] convert scalar fneg with insert/extract to vector fneg · ParkHanbum/llvm-project@baab4aa

insertelt DestVec, (fneg (extractelt SrcVec, Index)), Index --> shuffle DestVec, (fneg SrcVec), Mask This is a specialized form of what could be a more general fold for a binop. It's also p...

github.com

 

  InstructionCost NewCost =
      TTI.getArithmeticInstrCost(Instruction::FNeg, VecTy, CostKind) +
      TTI.getShuffleCost(TargetTransformInfo::SK_Select, VecTy, Mask, CostKind);

 

위 커밋을 통해 SK_Select 가 의미하는 바를 추정하면,

벡터간 내부 요소의 순서를 변경하는 경우에 사용되는 것으로 보인다.

이 경우 다른 Shuffle 보다 비용이 "싸다"

 

 

#SK_PermuteTwoSrc

두 소스 벡터의 요소를 셔플 마스크를 사용하여 하나로 병합합니다.

define <8 x i32> @test1(<4 x i32> %0, <4 x i32> %1) {
; CHECK-LABEL: @test1(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP0:%.*]], <4 x i32> [[TMP1:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
; CHECK-NEXT:    [[TMP3:%.*]] = call <8 x i32> @llvm.abs.v8i32(<8 x i32> [[TMP2]], i1 false)
; CHECK-NEXT:    ret <8 x i32> [[TMP3]]
;
entry:
  %2 = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %0, i1 false)
  %3 = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %1, i1 false)
  %4 = shufflevector <4 x i32> %2, <4 x i32> %3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  ret <8 x i32> %4
}

위의 예처럼 두 개의 벡터를 하나로 합치는 경우

 

#SK_PermuteSingleSrc

단일 소스 벡터의 요소를 셔플 마스크와 함께 셔플합니다.

define <2 x double> @src_ins1_v2f64_ext3_v4f64(<2 x double> %a, <4 x double> %b) {
; CHECK-LABEL: @src_ins1_v2f64_ext3_v4f64(
; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x double> [[B:%.*]], <4 x double> poison, <2 x i32> <i32 3, i32 poison>
; CHECK-NEXT:    [[INS:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> [[TMP1]], <2 x i32> <i32 0, i32 2>
; CHECK-NEXT:    ret <2 x double> [[INS]]
;
  %ext = extractelement <4 x double> %b, i32 3
  %ins = insertelement <2 x double> %a, double %ext, i32 1
  ret <2 x double> %ins
}

위의 예제와 같이 첫 번째 Shuffle 을 할 때, 지정대는 요소의 대상은 모두 Source 에 있는 경우.

 

 

Comments