New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[X86][CodeGen] Support EVEX compression: NDD to nonNDD #77731
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@llvm/pr-subscribers-backend-x86 Author: Shengchen Kan (KanRobert) ChangesFull diff: https://github.com/llvm/llvm-project/pull/77731.diff 9 Files Affected:
diff --git a/llvm/lib/Target/X86/X86CompressEVEX.cpp b/llvm/lib/Target/X86/X86CompressEVEX.cpp
index b95baddd9dea96..fc73638987c4f7 100644
--- a/llvm/lib/Target/X86/X86CompressEVEX.cpp
+++ b/llvm/lib/Target/X86/X86CompressEVEX.cpp
@@ -220,6 +220,29 @@ static bool performCustomAdjustments(MachineInstr &MI, unsigned NewOpc) {
return true;
}
+static bool isRedundantNewDataDest(MachineInstr &MI, const X86Subtarget &ST) {
+ // addq %rax, %rbx, %rbx / addq %rbx, %rax, %rbx -> addq %rax, %rbx
+ const MCInstrDesc &Desc = MI.getDesc();
+ Register Reg0 = MI.getOperand(0).getReg();
+ const MachineOperand &Op1 = MI.getOperand(1);
+ if (!Op1.isReg())
+ return false;
+ Register Reg1 = Op1.getReg();
+ if (Reg1 == Reg0)
+ return true;
+
+ bool IsCommutable = Desc.isCommutable();
+ unsigned NumOps = Desc.getNumOperands();
+ // Op1 and Op2 may be commutable for ND instructions.
+ if (!IsCommutable || NumOps < 3 || !MI.getOperand(2).isReg() ||
+ MI.getOperand(2).getReg() != Reg0)
+ return false;
+ // Opcode may change after commute, e.g. SHRD -> SHLD
+ // TODO: Add test for this after ND SHRD/SHLD is supported
+ ST.getInstrInfo()->commuteInstruction(MI, false, 1, 2);
+ return true;
+}
+
static bool CompressEVEXImpl(MachineInstr &MI, const X86Subtarget &ST) {
uint64_t TSFlags = MI.getDesc().TSFlags;
@@ -241,19 +264,27 @@ static bool CompressEVEXImpl(MachineInstr &MI, const X86Subtarget &ST) {
//
// For AVX512 cases, EVEX prefix is needed in order to carry this information
// thus preventing the transformation to VEX encoding.
- if (TSFlags & X86II::EVEX_B)
+ bool IsND = X86II::hasNewDataDest(TSFlags);
+ if (TSFlags & X86II::EVEX_B && !IsND)
+ return false;
+
+ if (IsND && !isRedundantNewDataDest(MI, ST))
return false;
ArrayRef<X86CompressEVEXTableEntry> Table = ArrayRef(X86CompressEVEXTable);
unsigned Opc = MI.getOpcode();
const auto *I = llvm::lower_bound(Table, Opc);
- if (I == Table.end() || I->OldOpc != Opc)
+ if (I == Table.end() || I->OldOpc != Opc) {
+ assert(!IsND && "Missing entry for ND instruction");
return false;
+ }
- if (usesExtendedRegister(MI) || !checkVEXInstPredicate(Opc, ST) ||
- !performCustomAdjustments(MI, I->NewOpc))
- return false;
+ if (!IsND) {
+ if (usesExtendedRegister(MI) || !checkVEXInstPredicate(Opc, ST) ||
+ !performCustomAdjustments(MI, I->NewOpc))
+ return false;
+ }
const MCInstrDesc &NewDesc = ST.getInstrInfo()->get(I->NewOpc);
MI.setDesc(NewDesc);
@@ -261,6 +292,9 @@ static bool CompressEVEXImpl(MachineInstr &MI, const X86Subtarget &ST) {
auto AsmComment =
(Encoding == X86II::VEX) ? X86::AC_EVEX_2_VEX : X86::AC_EVEX_2_LEGACY;
MI.setAsmPrinterFlag(AsmComment);
+ if (IsND)
+ MI.tieOperands(0, 1);
+
return true;
}
diff --git a/llvm/test/CodeGen/X86/apx/adc.ll b/llvm/test/CodeGen/X86/apx/adc.ll
index 8e2df5c2772019..af9458e1b01f39 100644
--- a/llvm/test/CodeGen/X86/apx/adc.ll
+++ b/llvm/test/CodeGen/X86/apx/adc.ll
@@ -114,7 +114,7 @@ define i16 @adc16ri8(i16 %a, i16 %x, i16 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subw %si, %dx, %ax
; CHECK-NEXT: adcw $0, %di, %ax
-; CHECK-NEXT: addl $123, %eax, %eax
+; CHECK-NEXT: addl $123, %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
%s = add i16 %a, 123
@@ -168,7 +168,7 @@ define i16 @adc16ri(i16 %a, i16 %x, i16 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subw %si, %dx, %ax
; CHECK-NEXT: adcw $0, %di, %ax
-; CHECK-NEXT: addl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT: addl $1234, %eax # imm = 0x4D2
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
%s = add i16 %a, 1234
@@ -265,7 +265,7 @@ define i16 @adc16mi8(ptr %ptr, i16 %x, i16 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subw %si, %dx, %ax
; CHECK-NEXT: adcw $0, (%rdi), %ax
-; CHECK-NEXT: addl $123, %eax, %eax
+; CHECK-NEXT: addl $123, %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
%a = load i16, ptr %ptr
@@ -323,7 +323,7 @@ define i16 @adc16mi(ptr %ptr, i16 %x, i16 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subw %si, %dx, %ax
; CHECK-NEXT: adcw $0, (%rdi), %ax
-; CHECK-NEXT: addl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT: addl $1234, %eax # imm = 0x4D2
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
%a = load i16, ptr %ptr
@@ -442,7 +442,7 @@ define void @adc16mi_legacy(ptr %ptr, i16 %x, i16 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subw %si, %dx, %ax
; CHECK-NEXT: adcw $0, (%rdi), %ax
-; CHECK-NEXT: addl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT: addl $1234, %eax # imm = 0x4D2
; CHECK-NEXT: movw %ax, (%rdi)
; CHECK-NEXT: retq
%a = load i16, ptr %ptr
diff --git a/llvm/test/CodeGen/X86/apx/add.ll b/llvm/test/CodeGen/X86/apx/add.ll
index 7502cde2df3cef..971ba80eb6c620 100644
--- a/llvm/test/CodeGen/X86/apx/add.ll
+++ b/llvm/test/CodeGen/X86/apx/add.ll
@@ -206,7 +206,7 @@ define i16 @add16mi8(ptr %a) {
; CHECK-LABEL: add16mi8:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movzwl (%rdi), %eax
-; CHECK-NEXT: addl $123, %eax, %eax
+; CHECK-NEXT: addl $123, %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
entry:
@@ -252,7 +252,7 @@ define i16 @add16mi(ptr %a) {
; CHECK-LABEL: add16mi:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movzwl (%rdi), %eax
-; CHECK-NEXT: addl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT: addl $1234, %eax # imm = 0x4D2
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
entry:
@@ -489,8 +489,8 @@ define i1 @add64ri_reloc(i16 %k) {
; CHECK: # %bb.0:
; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
; CHECK-NEXT: movswq %di, %rax
-; CHECK-NEXT: addq %rax, %rax, %rax
-; CHECK-NEXT: addq $val, %rax, %rax
+; CHECK-NEXT: addq %rax, %rax
+; CHECK-NEXT: addq $val, %rax
; CHECK-NEXT: setne %al
; CHECK-NEXT: retq
%g = getelementptr inbounds i16, ptr @val, i16 %k
diff --git a/llvm/test/CodeGen/X86/apx/dec.ll b/llvm/test/CodeGen/X86/apx/dec.ll
index d79f1f5886bad6..fcb2cae3b5cad8 100644
--- a/llvm/test/CodeGen/X86/apx/dec.ll
+++ b/llvm/test/CodeGen/X86/apx/dec.ll
@@ -57,7 +57,7 @@ define i16 @dec16m(ptr %ptr) {
; CHECK-LABEL: dec16m:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movzwl (%rdi), %eax
-; CHECK-NEXT: decl %eax, %eax
+; CHECK-NEXT: decl %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
entry:
diff --git a/llvm/test/CodeGen/X86/apx/inc.ll b/llvm/test/CodeGen/X86/apx/inc.ll
index 28dbf75f5ada5c..613f7866c9ac5c 100644
--- a/llvm/test/CodeGen/X86/apx/inc.ll
+++ b/llvm/test/CodeGen/X86/apx/inc.ll
@@ -57,7 +57,7 @@ define i16 @inc16m(ptr %ptr) {
; CHECK-LABEL: inc16m:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movzwl (%rdi), %eax
-; CHECK-NEXT: incl %eax, %eax
+; CHECK-NEXT: incl %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
entry:
diff --git a/llvm/test/CodeGen/X86/apx/or.ll b/llvm/test/CodeGen/X86/apx/or.ll
index bd814981820309..abd74059dff01b 100644
--- a/llvm/test/CodeGen/X86/apx/or.ll
+++ b/llvm/test/CodeGen/X86/apx/or.ll
@@ -207,7 +207,7 @@ define i16 @or16mi8(ptr %a) {
; CHECK-LABEL: or16mi8:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movzwl (%rdi), %eax
-; CHECK-NEXT: orl $123, %eax, %eax
+; CHECK-NEXT: orl $123, %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
entry:
@@ -253,7 +253,7 @@ define i16 @or16mi(ptr %a) {
; CHECK-LABEL: or16mi:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movzwl (%rdi), %eax
-; CHECK-NEXT: orl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT: orl $1234, %eax # imm = 0x4D2
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
entry:
diff --git a/llvm/test/CodeGen/X86/apx/sbb.ll b/llvm/test/CodeGen/X86/apx/sbb.ll
index 72a488e70b2c99..256a1c7c381f44 100644
--- a/llvm/test/CodeGen/X86/apx/sbb.ll
+++ b/llvm/test/CodeGen/X86/apx/sbb.ll
@@ -114,7 +114,7 @@ define i16 @sbb16ri8(i16 %a, i16 %x, i16 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subw %si, %dx, %ax
; CHECK-NEXT: sbbw $0, %di, %ax
-; CHECK-NEXT: addl $-123, %eax, %eax
+; CHECK-NEXT: addl $-123, %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
%s = sub i16 %a, 123
@@ -129,7 +129,7 @@ define i32 @sbb32ri8(i32 %a, i32 %x, i32 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subl %esi, %edx, %eax
; CHECK-NEXT: sbbl $0, %edi, %eax
-; CHECK-NEXT: addl $-123, %eax, %eax
+; CHECK-NEXT: addl $-123, %eax
; CHECK-NEXT: retq
%s = sub i32 %a, 123
%k = icmp ugt i32 %x, %y
@@ -143,7 +143,7 @@ define i64 @sbb64ri8(i64 %a, i64 %x, i64 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subq %rsi, %rdx, %rax
; CHECK-NEXT: sbbq $0, %rdi, %rax
-; CHECK-NEXT: addq $-123, %rax, %rax
+; CHECK-NEXT: addq $-123, %rax
; CHECK-NEXT: retq
%s = sub i64 %a, 123
%k = icmp ugt i64 %x, %y
@@ -157,7 +157,7 @@ define i8 @sbb8ri(i8 %a, i8 %x, i8 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subb %sil, %dl, %al
; CHECK-NEXT: sbbb $0, %dil, %al
-; CHECK-NEXT: addb $-123, %al, %al
+; CHECK-NEXT: addb $-123, %al
; CHECK-NEXT: retq
%s = sub i8 %a, 123
%k = icmp ugt i8 %x, %y
@@ -171,7 +171,7 @@ define i16 @sbb16ri(i16 %a, i16 %x, i16 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subw %si, %dx, %ax
; CHECK-NEXT: sbbw $0, %di, %ax
-; CHECK-NEXT: addl $-1234, %eax, %eax # imm = 0xFB2E
+; CHECK-NEXT: addl $-1234, %eax # imm = 0xFB2E
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
%s = sub i16 %a, 1234
@@ -186,7 +186,7 @@ define i32 @sbb32ri(i32 %a, i32 %x, i32 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subl %esi, %edx, %eax
; CHECK-NEXT: sbbl $0, %edi, %eax
-; CHECK-NEXT: addl $-123456, %eax, %eax # imm = 0xFFFE1DC0
+; CHECK-NEXT: addl $-123456, %eax # imm = 0xFFFE1DC0
; CHECK-NEXT: retq
%s = sub i32 %a, 123456
%k = icmp ugt i32 %x, %y
@@ -200,7 +200,7 @@ define i64 @sbb64ri(i64 %a, i64 %x, i64 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subq %rsi, %rdx, %rax
; CHECK-NEXT: sbbq $0, %rdi, %rax
-; CHECK-NEXT: addq $-123456, %rax, %rax # imm = 0xFFFE1DC0
+; CHECK-NEXT: addq $-123456, %rax # imm = 0xFFFE1DC0
; CHECK-NEXT: retq
%s = sub i64 %a, 123456
%k = icmp ugt i64 %x, %y
@@ -270,7 +270,7 @@ define i16 @sbb16mi8(ptr %ptr, i16 %x, i16 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subw %si, %dx, %ax
; CHECK-NEXT: sbbw $0, (%rdi), %ax
-; CHECK-NEXT: addl $-123, %eax, %eax
+; CHECK-NEXT: addl $-123, %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
%a = load i16, ptr %ptr
@@ -286,7 +286,7 @@ define i32 @sbb32mi8(ptr %ptr, i32 %x, i32 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subl %esi, %edx, %eax
; CHECK-NEXT: sbbl $0, (%rdi), %eax
-; CHECK-NEXT: addl $-123, %eax, %eax
+; CHECK-NEXT: addl $-123, %eax
; CHECK-NEXT: retq
%a = load i32, ptr %ptr
%s = sub i32 %a, 123
@@ -301,7 +301,7 @@ define i64 @sbb64mi8(ptr %ptr, i64 %x, i64 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subq %rsi, %rdx, %rax
; CHECK-NEXT: sbbq $0, (%rdi), %rax
-; CHECK-NEXT: addq $-123, %rax, %rax
+; CHECK-NEXT: addq $-123, %rax
; CHECK-NEXT: retq
%a = load i64, ptr %ptr
%s = sub i64 %a, 123
@@ -316,7 +316,7 @@ define i8 @sbb8mi(ptr %ptr, i8 %x, i8 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subb %sil, %dl, %al
; CHECK-NEXT: sbbb $0, (%rdi), %al
-; CHECK-NEXT: addb $-123, %al, %al
+; CHECK-NEXT: addb $-123, %al
; CHECK-NEXT: retq
%a = load i8, ptr %ptr
%s = sub i8 %a, 123
@@ -331,7 +331,7 @@ define i16 @sbb16mi(ptr %ptr, i16 %x, i16 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subw %si, %dx, %ax
; CHECK-NEXT: sbbw $0, (%rdi), %ax
-; CHECK-NEXT: addl $-1234, %eax, %eax # imm = 0xFB2E
+; CHECK-NEXT: addl $-1234, %eax # imm = 0xFB2E
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
%a = load i16, ptr %ptr
@@ -347,7 +347,7 @@ define i32 @sbb32mi(ptr %ptr, i32 %x, i32 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subl %esi, %edx, %eax
; CHECK-NEXT: sbbl $0, (%rdi), %eax
-; CHECK-NEXT: addl $-123456, %eax, %eax # imm = 0xFFFE1DC0
+; CHECK-NEXT: addl $-123456, %eax # imm = 0xFFFE1DC0
; CHECK-NEXT: retq
%a = load i32, ptr %ptr
%s = sub i32 %a, 123456
@@ -362,7 +362,7 @@ define i64 @sbb64mi(ptr %ptr, i64 %x, i64 %y) nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: subq %rsi, %rdx, %rax
; CHECK-NEXT: sbbq $0, (%rdi), %rax
-; CHECK-NEXT: addq $-123456, %rax, %rax # imm = 0xFFFE1DC0
+; CHECK-NEXT: addq $-123456, %rax # imm = 0xFFFE1DC0
; CHECK-NEXT: retq
%a = load i64, ptr %ptr
%s = sub i64 %a, 123456
diff --git a/llvm/test/CodeGen/X86/apx/sub.ll b/llvm/test/CodeGen/X86/apx/sub.ll
index a6c76fe081b2d8..862d17a6e8d1f7 100644
--- a/llvm/test/CodeGen/X86/apx/sub.ll
+++ b/llvm/test/CodeGen/X86/apx/sub.ll
@@ -173,7 +173,7 @@ define i16 @sub16mr(ptr %a, i16 noundef %b) {
; CHECK-LABEL: sub16mr:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movzwl (%rdi), %eax
-; CHECK-NEXT: subl %esi, %eax, %eax
+; CHECK-NEXT: subl %esi, %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
entry:
@@ -208,7 +208,7 @@ define i16 @sub16mi8(ptr %a) {
; CHECK-LABEL: sub16mi8:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movzwl (%rdi), %eax
-; CHECK-NEXT: addl $-123, %eax, %eax
+; CHECK-NEXT: addl $-123, %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
entry:
@@ -254,7 +254,7 @@ define i16 @sub16mi(ptr %a) {
; CHECK-LABEL: sub16mi:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movzwl (%rdi), %eax
-; CHECK-NEXT: addl $-1234, %eax, %eax # imm = 0xFB2E
+; CHECK-NEXT: addl $-1234, %eax # imm = 0xFB2E
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
entry:
diff --git a/llvm/test/CodeGen/X86/apx/xor.ll b/llvm/test/CodeGen/X86/apx/xor.ll
index 53f26f04333108..980119cb5218ae 100644
--- a/llvm/test/CodeGen/X86/apx/xor.ll
+++ b/llvm/test/CodeGen/X86/apx/xor.ll
@@ -207,7 +207,7 @@ define i16 @xor16mi8(ptr %a) {
; CHECK-LABEL: xor16mi8:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movzwl (%rdi), %eax
-; CHECK-NEXT: xorl $123, %eax, %eax
+; CHECK-NEXT: xorl $123, %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
entry:
@@ -253,7 +253,7 @@ define i16 @xor16mi(ptr %a) {
; CHECK-LABEL: xor16mi:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movzwl (%rdi), %eax
-; CHECK-NEXT: xorl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT: xorl $1234, %eax # imm = 0x4D2
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
; CHECK-NEXT: retq
entry:
|
KanRobert
requested review from
RKSimon,
phoebewang,
e-kud,
topperc and
XinWang10
January 11, 2024 06:33
phoebewang
reviewed
Jan 11, 2024
KanRobert
added a commit
that referenced
this pull request
Jan 11, 2024
phoebewang
approved these changes
Jan 11, 2024
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM except for one nit.
@phoebewang Thanks! |
justinfargnoli
pushed a commit
to justinfargnoli/llvm-project
that referenced
this pull request
Jan 28, 2024
justinfargnoli
pushed a commit
to justinfargnoli/llvm-project
that referenced
this pull request
Jan 28, 2024
XinWang10
added a commit
that referenced
this pull request
Jan 30, 2024
APX promoted MOVBE instructions were supported in #77431. The reg2reg variants of MOVBE are newly introduced by APX and can be optimized to BSWAP instruction when the 2 register operands are same. This patch adds manual entries for MOVBErr instructions when we do ndd to non-ndd compression #77731. RFC: https://discourse.llvm.org/t/rfc-design-for-apx-feature-egpr-and-ndd-support/73031/4
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.