Skip to content

Commit 8f18cf7

Browse files
committed
AMDGPU: Check for implicit defs before constant folding instruction
Can't delete the constant folded instruction if scc is used. Fixes #63986 https://reviews.llvm.org/D157504
1 parent 1030483 commit 8f18cf7

File tree

5 files changed

+471
-0
lines changed

5 files changed

+471
-0
lines changed

llvm/include/llvm/CodeGen/MachineInstr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,9 @@ class MachineInstr
17451745
/// Return true if all the defs of this instruction are dead.
17461746
bool allDefsAreDead() const;
17471747

1748+
/// Return true if all the implicit defs of this instruction are dead.
1749+
bool allImplicitDefsAreDead() const;
1750+
17481751
/// Return a valid size if the instruction is a spill instruction.
17491752
std::optional<unsigned> getSpillSize(const TargetInstrInfo *TII) const;
17501753

llvm/lib/CodeGen/MachineInstr.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,16 @@ bool MachineInstr::allDefsAreDead() const {
14971497
return true;
14981498
}
14991499

1500+
bool MachineInstr::allImplicitDefsAreDead() const {
1501+
for (const MachineOperand &MO : implicit_operands()) {
1502+
if (!MO.isReg() || MO.isUse())
1503+
continue;
1504+
if (!MO.isDead())
1505+
return false;
1506+
}
1507+
return true;
1508+
}
1509+
15001510
/// copyImplicitOps - Copy implicit register operands from specified
15011511
/// instruction to this instruction.
15021512
void MachineInstr::copyImplicitOps(MachineFunction &MF,

llvm/lib/Target/AMDGPU/SIFoldOperands.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,9 @@ SIFoldOperands::getImmOrMaterializedImm(MachineOperand &Op) const {
10351035
// selection.
10361036
// TODO: See if a frame index with a fixed offset can fold.
10371037
bool SIFoldOperands::tryConstantFoldOp(MachineInstr *MI) const {
1038+
if (!MI->allImplicitDefsAreDead())
1039+
return false;
1040+
10381041
unsigned Opc = MI->getOpcode();
10391042

10401043
int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);

llvm/test/CodeGen/AMDGPU/constant-fold-imm-immreg.mir

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,3 +790,139 @@ body: |
790790
S_ENDPGM 0, implicit %4
791791
792792
...
793+
794+
---
795+
name: constant_s_and_b32_only_implicit_def_scc_is_used
796+
tracksRegLiveness: true
797+
body: |
798+
bb.0:
799+
; GCN-LABEL: name: constant_s_and_b32_only_implicit_def_scc_is_used
800+
; GCN: [[S_AND_B32_:%[0-9]+]]:sgpr_32 = S_AND_B32 32, 15, implicit-def $scc
801+
; GCN-NEXT: S_ENDPGM 0, implicit $scc
802+
%0:sgpr_32 = S_MOV_B32 32
803+
%1:sgpr_32 = S_MOV_B32 15
804+
%2:sgpr_32 = S_AND_B32 %0, %1, implicit-def $scc
805+
S_ENDPGM 0, implicit $scc
806+
807+
...
808+
809+
---
810+
name: constant_s_and_b32_implicit_def_scc_is_used
811+
tracksRegLiveness: true
812+
body: |
813+
bb.0:
814+
; GCN-LABEL: name: constant_s_and_b32_implicit_def_scc_is_used
815+
; GCN: [[S_AND_B32_:%[0-9]+]]:sgpr_32 = S_AND_B32 32, 15, implicit-def $scc
816+
; GCN-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]], implicit $scc
817+
%0:sgpr_32 = S_MOV_B32 32
818+
%1:sgpr_32 = S_MOV_B32 15
819+
%2:sgpr_32 = S_AND_B32 %0, %1, implicit-def $scc
820+
S_ENDPGM 0, implicit %2, implicit $scc
821+
822+
...
823+
824+
---
825+
name: constant_s_and_b32_only_implicit_def_scc_is_dead
826+
tracksRegLiveness: true
827+
body: |
828+
bb.0:
829+
; GCN-LABEL: name: constant_s_and_b32_only_implicit_def_scc_is_dead
830+
; GCN: S_ENDPGM 0, implicit undef $scc
831+
%0:sgpr_32 = S_MOV_B32 32
832+
%1:sgpr_32 = S_MOV_B32 15
833+
%2:sgpr_32 = S_AND_B32 %0, %1, implicit-def dead $scc
834+
S_ENDPGM 0, implicit undef $scc
835+
836+
...
837+
838+
---
839+
name: constant_s_or_b32_only_implicit_def_scc_is_used
840+
tracksRegLiveness: true
841+
body: |
842+
bb.0:
843+
; GCN-LABEL: name: constant_s_or_b32_only_implicit_def_scc_is_used
844+
; GCN: [[S_OR_B32_:%[0-9]+]]:sgpr_32 = S_OR_B32 32, 15, implicit-def $scc
845+
; GCN-NEXT: S_ENDPGM 0, implicit $scc
846+
%0:sgpr_32 = S_MOV_B32 32
847+
%1:sgpr_32 = S_MOV_B32 15
848+
%2:sgpr_32 = S_OR_B32 %0, %1, implicit-def $scc
849+
S_ENDPGM 0, implicit $scc
850+
851+
...
852+
853+
---
854+
name: constant_s_xor_b32_only_implicit_def_scc_is_used
855+
tracksRegLiveness: true
856+
body: |
857+
bb.0:
858+
; GCN-LABEL: name: constant_s_xor_b32_only_implicit_def_scc_is_used
859+
; GCN: [[S_XOR_B32_:%[0-9]+]]:sgpr_32 = S_XOR_B32 32, 15, implicit-def $scc
860+
; GCN-NEXT: S_ENDPGM 0, implicit $scc
861+
%0:sgpr_32 = S_MOV_B32 32
862+
%1:sgpr_32 = S_MOV_B32 15
863+
%2:sgpr_32 = S_XOR_B32 %0, %1, implicit-def $scc
864+
S_ENDPGM 0, implicit $scc
865+
866+
...
867+
868+
---
869+
name: constant_s_not_b32_only_implicit_def_scc_is_used
870+
tracksRegLiveness: true
871+
body: |
872+
bb.0:
873+
; GCN-LABEL: name: constant_s_not_b32_only_implicit_def_scc_is_used
874+
; GCN: [[S_NOT_B32_:%[0-9]+]]:sgpr_32 = S_NOT_B32 32, implicit-def $scc
875+
; GCN-NEXT: S_ENDPGM 0, implicit $scc
876+
%0:sgpr_32 = S_MOV_B32 32
877+
%1:sgpr_32 = S_NOT_B32 %0, implicit-def $scc
878+
S_ENDPGM 0, implicit $scc
879+
880+
...
881+
882+
# Really really implicit operand
883+
---
884+
name: constant_v_and_b32_implicit_def_scc_is_used
885+
tracksRegLiveness: true
886+
body: |
887+
bb.0:
888+
; GCN-LABEL: name: constant_v_and_b32_implicit_def_scc_is_used
889+
; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 15, implicit $exec
890+
; GCN-NEXT: [[V_AND_B32_e32_:%[0-9]+]]:vgpr_32 = V_AND_B32_e32 32, [[V_MOV_B32_e32_]], implicit $exec, implicit-def $scc
891+
; GCN-NEXT: S_ENDPGM 0, implicit $scc
892+
%0:vgpr_32 = V_MOV_B32_e32 32, implicit $exec
893+
%1:vgpr_32 = V_MOV_B32_e32 15, implicit $exec
894+
%2:vgpr_32 = V_AND_B32_e32 %0, %1, implicit $exec, implicit-def $scc
895+
S_ENDPGM 0, implicit $scc
896+
897+
...
898+
899+
---
900+
name: constant_v_and_b32_implicit_def_vreg_is_used
901+
tracksRegLiveness: true
902+
body: |
903+
bb.0:
904+
; GCN-LABEL: name: constant_v_and_b32_implicit_def_vreg_is_used
905+
; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 15, implicit $exec
906+
; GCN-NEXT: [[V_AND_B32_e32_:%[0-9]+]]:vgpr_32 = V_AND_B32_e32 32, [[V_MOV_B32_e32_]], implicit $exec, implicit-def %3
907+
; GCN-NEXT: S_ENDPGM 0, implicit %3
908+
%0:vgpr_32 = V_MOV_B32_e32 32, implicit $exec
909+
%1:vgpr_32 = V_MOV_B32_e32 15, implicit $exec
910+
%2:vgpr_32 = V_AND_B32_e32 %0, %1, implicit $exec, implicit-def %3:vgpr_32
911+
S_ENDPGM 0, implicit %3
912+
913+
...
914+
---
915+
name: constant_v_and_b32_implicit_use
916+
tracksRegLiveness: true
917+
body: |
918+
bb.0:
919+
; GCN-LABEL: name: constant_v_and_b32_implicit_use
920+
; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
921+
; GCN-NEXT: S_ENDPGM 0, implicit [[V_MOV_B32_e32_]]
922+
%0:vgpr_32 = V_MOV_B32_e32 32, implicit $exec
923+
%1:vgpr_32 = V_MOV_B32_e32 15, implicit $exec
924+
%2:vgpr_32 = V_MOV_B32_e32 24, implicit $exec
925+
%3:vgpr_32 = V_AND_B32_e32 %0, %1, implicit $exec, implicit %2:vgpr_32
926+
S_ENDPGM 0, implicit %3
927+
928+
...

0 commit comments

Comments
 (0)