snu-sf-class / swpp202401

Principles and Practices of Software Development Main Repository
14 stars 4 forks source link

[Project] Vector operation Error #88

Open Wits15730 opened 6 months ago

Wits15730 commented 6 months ago

Vector operation을 사용한 .ll 코드를 컴파일 할 때 backend의 버그가 존재하는 듯합니다. 벡터 operation 을 사용하지 않으면 에러가 발생하지 않으나, 최적화를 통해 vector operation을 만들면 문제가 발생합니다.

최적화의 결과 사용하는 vector operation의 종류는 다음과 같습니다.

%sum.0 = phi <4 x i64> [ zeroinitializer, %for.body3 ], [ %add12, %for.inc ] %vec_a = load <4 x i64>, ptr %arrayidx, align 8 %vec_mul = mul <4 x i64> %vec_a, %vec_b %add12 = add <4 x i64> %sum.0, %vec_mul %32 = call i64 @llvm.vector.reduce.add.v4i64(<4 x i64> %30)

다음과 같은 에러가 발생하고 있습니다. static BinaryOperator llvm::BinaryOperator::Create(BinaryOps, Value , Value , const Twine &, Instruction ): Assertion `S1->getType() == S2->getType() && "Cannot create binary operator with two operands of differing type!"' failed.

제가 확인해 보지는 못하였으나, 아마도 PHI instruction을 사용하는 과정에서 register_allocate.cpp의 resolvePHIInterference 함수에서 문제가 발생하는 것이 아닐까 싶습니다.

Wits15730 commented 6 months ago

Reproducing Example

run the program below with no optimization passes applied

define dso_local i64 @matmul(i32 noundef %dim, i64 %y, ptr nocapture noundef writeonly %c, ptr nocapture noundef readonly %a, ptr nocapture noundef readonly %b) local_unnamed_addr #0 {
entry:
  ; Define a constant vector with specific values
  br label %vector.body

restart:
  br label %vector.body

vector.body:                                      ; preds = %vector.body, %vector.ph
  %offset.idx = phi i64 [ 0, %entry ], [ %z, %restart ]
  %vec.phi = phi <4 x i64> [ zeroinitializer, %entry ], [ %27, %restart ]
  %16 = trunc i64 %offset.idx to i32
  %17 = add i32 %16, 4
  %19 = zext i32 %17 to i64
  %20 = getelementptr inbounds i64, ptr %a, i64 %19
  %21 = getelementptr inbounds i64, ptr %20, i32 0
  %wide.load = load <4 x i64>, ptr %21, align 8
  %22 = add i32 %17, %17
  %23 = zext i32 %22 to i64
  %24 = getelementptr inbounds i64, ptr %b, i64 %23
  %25 = getelementptr inbounds i64, ptr %24, i32 0
  %wide.load11 = load <4 x i64>, ptr %25, align 8
  %26 = mul <4 x i64> %wide.load11, %wide.load
  %27 = add <4 x i64> %26, %vec.phi
  %z = add nuw i64 %offset.idx, 4
  %28 = icmp eq i64 %z, %y
  br i1 %28, label %for.end22, label %restart

for.end22:    
  %32 = call i64 @llvm.vector.reduce.add.v4i64(<4 x i64> %27)                                    ; preds = %for.end22.loopexit, %entry
  ret i64 %32
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i64 @llvm.vector.reduce.add.v4i64(<4 x i64>) #4
strikef commented 6 months ago

저희 환경에서는 제공해주신 reproduction example에서 다른 오류가 발생하여서, 정확한 문제 지점을 파악하는 데 조금 시간이 걸리고 있습니다. 최대한 빠르게 파악 후 수정할 수 있도록 하겠습니다.

strikef commented 6 months ago

제공해주신 example을 컴파일하지 못하는 이유가 일차적으로는 다음과 같습니다.

전자는 zeroinitializer 대신 call @vbcast_i64x4 같은 SWPP intrinsic을 사용하는 식으로 대체 가능하며, 후자는 LLVM 내장 intrinsic에 대한 지원 계획이 없으므로 별도로 유사한 동작을 재구현하셔야 합니다.

다만, vector 연산을 emit하는 과정에서 잘못된 casting으로 인한 크래시를 발견해 수정했습니다.