This is an archive of the discontinued LLVM Phabricator instance.

[RISCV] Fix the bug in the register allocator caused by reserved BP.
ClosedPublic

Authored by HsiangKai on Jan 19 2022, 5:33 AM.

Details

Summary

Originally, hasRVVFrameObject() will scan all the stack objects to check
whether if there is any scalable vector object on the stack or not.
However, it causes errors in the register allocator. In issue 53016, it
returns false before RA because there is no RVV stack objects. After RA,
it returns true because there are spilling slots for RVV values during RA.
The compiler will not reserve BP during register allocation and generate BP
access in the PEI pass due to the inconsistent behavior of the function.

The function is changed to use hasStdExtV() as the return value. It is
not precise, but it can make the register allocation correct.

Refer to https://github.com/llvm/llvm-project/issues/53016.

Diff Detail

Event Timeline

HsiangKai created this revision.Jan 19 2022, 5:33 AM
HsiangKai requested review of this revision.Jan 19 2022, 5:33 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 19 2022, 5:33 AM
kito-cheng added a comment.EditedJan 19 2022, 5:49 AM

Share you my reduced case for that issue, did you mind add that to this patch?

Command:
$ llc -mtriple=riscv64 -mattr=+experimental-v,+f -riscv-v-vector-bits-min=128

define void @foo(i32* nocapture noundef %p1) {
entry:
  %vla = alloca [10 x i32], align 64
  %0 = bitcast [10 x i32]* %vla to i8*
  call void @llvm.lifetime.start.p0i8(i64 40, i8* nonnull %0)
  %1 = bitcast i32* %p1 to <8 x float>*
  %2 = load <8 x float>, <8 x float>* %1, align 32
  %arraydecay = getelementptr inbounds [10 x i32], [10 x i32]* %vla, i64 0, i64 0
  call void @bar(i32 noundef signext 1, i32 noundef signext 2, i32 noundef signext 3, i32 noundef signext 4, i32 noundef signext 5, i32 noundef signext 6, i32 noundef signext 7, i32 noundef signext 8, i32* noundef nonnull %arraydecay)
  %3 = load <8 x float>, <8 x float>* %1, align 32
  %add = fadd <8 x float> %2, %3
  store <8 x float> %add, <8 x float>* %1, align 32
  call void @llvm.lifetime.end.p0i8(i64 40, i8* nonnull %0)
  ret void
}

declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1

declare void @bar(i32 noundef signext, i32 noundef signext, i32 noundef signext, i32 noundef signext, i32 noundef signext, i32 noundef signext, i32 noundef signext, i32 noundef signext, i32* noundef)

declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1

attributes #1 = { argmemonly mustprogress nofree nosync nounwind willreturn }
kito-cheng added inline comments.Jan 19 2022, 6:04 AM
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
959

Maybe MF.getSubtarget<RISCVSubtarget>().hasVInstructions()? although that same as hasStdExtV for now, but that prevent we need to check zve* ext. here in future.

frasercrmck added inline comments.Jan 19 2022, 6:17 AM
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
959

Yeah, I think that would be best.

craig.topper added inline comments.Jan 19 2022, 2:50 PM
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
959

+1

Share you my reduced case for that issue, did you mind add that to this patch?

Command:
$ llc -mtriple=riscv64 -mattr=+experimental-v,+f -riscv-v-vector-bits-min=128

define void @foo(i32* nocapture noundef %p1) {
entry:
  %vla = alloca [10 x i32], align 64
  %0 = bitcast [10 x i32]* %vla to i8*
  call void @llvm.lifetime.start.p0i8(i64 40, i8* nonnull %0)
  %1 = bitcast i32* %p1 to <8 x float>*
  %2 = load <8 x float>, <8 x float>* %1, align 32
  %arraydecay = getelementptr inbounds [10 x i32], [10 x i32]* %vla, i64 0, i64 0
  call void @bar(i32 noundef signext 1, i32 noundef signext 2, i32 noundef signext 3, i32 noundef signext 4, i32 noundef signext 5, i32 noundef signext 6, i32 noundef signext 7, i32 noundef signext 8, i32* noundef nonnull %arraydecay)
  %3 = load <8 x float>, <8 x float>* %1, align 32
  %add = fadd <8 x float> %2, %3
  store <8 x float> %add, <8 x float>* %1, align 32
  call void @llvm.lifetime.end.p0i8(i64 40, i8* nonnull %0)
  ret void
}

declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1

declare void @bar(i32 noundef signext, i32 noundef signext, i32 noundef signext, i32 noundef signext, i32 noundef signext, i32 noundef signext, i32 noundef signext, i32 noundef signext, i32* noundef)

declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1

attributes #1 = { argmemonly mustprogress nofree nosync nounwind willreturn }

It is very helpful. Thank you!
I created a patch D117738 for review.

HsiangKai updated this revision to Diff 401473.Jan 19 2022, 6:33 PM

Address comments and add a test case from D117738.

kito-cheng added inline comments.Jan 19 2022, 6:37 PM
llvm/test/CodeGen/RISCV/rvv/reg-alloc-reserve-bp.ll
23

Just highlight the code gen issue here, use use s1as BP but we use s1again here, and that what we want to fix by this patch.

frasercrmck accepted this revision.Jan 20 2022, 3:12 AM

LGTM. You've explained the issue well.

llvm/test/CodeGen/RISCV/rvv/reg-alloc-reserve-bp.ll
23

Thanks, that's helpful!

This revision is now accepted and ready to land.Jan 20 2022, 3:12 AM
asb accepted this revision.Jan 20 2022, 6:08 AM