22
22
#include " llvm/MC/MCInst.h"
23
23
#include " llvm/Support/ErrorHandling.h"
24
24
#include " llvm/Support/TargetRegistry.h"
25
+ #include < algorithm>
25
26
26
27
using namespace llvm ;
27
28
@@ -790,48 +791,68 @@ static unsigned convertFlagSettingOpcode(const MachineInstr *MI) {
790
791
}
791
792
}
792
793
793
- // / True when condition code could be modified on the instruction
794
- // / trace starting at from and ending at to.
795
- static bool modifiesConditionCode (MachineInstr *From, MachineInstr *To,
796
- const bool CheckOnlyCCWrites,
797
- const TargetRegisterInfo *TRI) {
794
+ enum AccessKind {
795
+ AK_Write = 0x01 ,
796
+ AK_Read = 0x10 ,
797
+ AK_All = 0x11
798
+ };
799
+
800
+ // / True when condition flags are accessed (either by writing or reading)
801
+ // / on the instruction trace starting at From and ending at To.
802
+ // /
803
+ // / Note: If From and To are from different blocks it's assumed CC are accessed
804
+ // / on the path.
805
+ static bool areCFlagsAccessedBetweenInstrs (MachineInstr *From, MachineInstr *To,
806
+ const TargetRegisterInfo *TRI,
807
+ const AccessKind AccessToCheck = AK_All) {
798
808
// We iterate backward starting \p To until we hit \p From
799
809
MachineBasicBlock::iterator I = To, E = From, B = To->getParent ()->begin ();
800
810
801
811
// Early exit if To is at the beginning of the BB.
802
812
if (I == B)
803
813
return true ;
804
814
805
- // Check whether the definition of SrcReg is in the same basic block as
806
- // Compare. If not, assume the condition code gets modified on some path .
815
+ // Check whether the instructions are in the same basic block
816
+ // If not, assume the condition flags might get modified somewhere .
807
817
if (To->getParent () != From->getParent ())
808
818
return true ;
809
819
810
- // Check that NZCV isn't set on the trace.
820
+ // From must be above To.
821
+ assert (std::find_if (MachineBasicBlock::reverse_iterator (To),
822
+ To->getParent ()->rend (),
823
+ [From](MachineInstr &MI) {
824
+ return &MI == From;
825
+ }) != To->getParent ()->rend ());
826
+
811
827
for (--I; I != E; --I) {
812
828
const MachineInstr &Instr = *I;
813
829
814
- if (Instr.modifiesRegister (AArch64::NZCV, TRI) ||
815
- (!CheckOnlyCCWrites && Instr.readsRegister (AArch64::NZCV, TRI)))
816
- // This instruction modifies or uses NZCV after the one we want to
817
- // change.
818
- return true ;
819
- if (I == B)
820
- // We currently don't allow the instruction trace to cross basic
821
- // block boundaries
830
+ if ( ((AccessToCheck & AK_Write) && Instr.modifiesRegister (AArch64::NZCV, TRI)) ||
831
+ ((AccessToCheck & AK_Read) && Instr.readsRegister (AArch64::NZCV, TRI)))
822
832
return true ;
823
833
}
824
834
return false ;
825
835
}
826
- // / optimizeCompareInstr - Convert the instruction supplying the argument to the
827
- // / comparison into one that sets the zero bit in the flags register.
836
+
837
+ // / Try to optimize a compare instruction. A compare instruction is an
838
+ // / instruction which produces AArch64::NZCV. It can be truly compare instruction
839
+ // / when there are no uses of its destination register.
840
+ // /
841
+ // / The following steps are tried in order:
842
+ // / 1. Convert CmpInstr into an unconditional version.
843
+ // / 2. Remove CmpInstr if above there is an instruction producing a needed
844
+ // / condition code or an instruction which can be converted into such an instruction.
845
+ // / Only comparison with zero is supported.
828
846
bool AArch64InstrInfo::optimizeCompareInstr (
829
847
MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2, int CmpMask,
830
848
int CmpValue, const MachineRegisterInfo *MRI) const {
849
+ assert (CmpInstr);
850
+ assert (CmpInstr->getParent ());
851
+ assert (MRI);
831
852
832
853
// Replace SUBSWrr with SUBWrr if NZCV is not used.
833
- int Cmp_NZCV = CmpInstr->findRegisterDefOperandIdx (AArch64::NZCV, true );
834
- if (Cmp_NZCV != -1 ) {
854
+ int DeadNZCVIdx = CmpInstr->findRegisterDefOperandIdx (AArch64::NZCV, true );
855
+ if (DeadNZCVIdx != -1 ) {
835
856
if (CmpInstr->definesRegister (AArch64::WZR) ||
836
857
CmpInstr->definesRegister (AArch64::XZR)) {
837
858
CmpInstr->eraseFromParent ();
@@ -843,7 +864,7 @@ bool AArch64InstrInfo::optimizeCompareInstr(
843
864
return false ;
844
865
const MCInstrDesc &MCID = get (NewOpc);
845
866
CmpInstr->setDesc (MCID);
846
- CmpInstr->RemoveOperand (Cmp_NZCV );
867
+ CmpInstr->RemoveOperand (DeadNZCVIdx );
847
868
bool succeeded = UpdateOperandRegClass (CmpInstr);
848
869
(void )succeeded;
849
870
assert (succeeded && " Some operands reg class are incompatible!" );
@@ -861,20 +882,18 @@ bool AArch64InstrInfo::optimizeCompareInstr(
861
882
if (!MRI->use_nodbg_empty (CmpInstr->getOperand (0 ).getReg ()))
862
883
return false ;
863
884
864
- // Get the unique definition of SrcReg.
865
- MachineInstr *MI = MRI->getUniqueVRegDef (SrcReg);
866
- if (!MI)
867
- return false ;
868
-
869
- bool CheckOnlyCCWrites = false ;
870
- const TargetRegisterInfo *TRI = &getRegisterInfo ();
871
- if (modifiesConditionCode (MI, CmpInstr, CheckOnlyCCWrites, TRI))
872
- return false ;
885
+ return substituteCmpInstr (CmpInstr, SrcReg, MRI);
886
+ }
873
887
874
- unsigned NewOpc = MI->getOpcode ();
875
- switch (MI->getOpcode ()) {
888
+ // / Get opcode of S version of Instr.
889
+ // / If Instr is S version its opcode is returned.
890
+ // / AArch64::INSTRUCTION_LIST_END is returned if Instr does not have S version
891
+ // / or we are not interested in it.
892
+ static unsigned sForm (MachineInstr &Instr) {
893
+ switch (Instr.getOpcode ()) {
876
894
default :
877
- return false ;
895
+ return AArch64::INSTRUCTION_LIST_END;
896
+
878
897
case AArch64::ADDSWrr:
879
898
case AArch64::ADDSWri:
880
899
case AArch64::ADDSXrr:
@@ -883,22 +902,50 @@ bool AArch64InstrInfo::optimizeCompareInstr(
883
902
case AArch64::SUBSWri:
884
903
case AArch64::SUBSXrr:
885
904
case AArch64::SUBSXri:
886
- break ;
887
- case AArch64::ADDWrr: NewOpc = AArch64::ADDSWrr; break ;
888
- case AArch64::ADDWri: NewOpc = AArch64::ADDSWri; break ;
889
- case AArch64::ADDXrr: NewOpc = AArch64::ADDSXrr; break ;
890
- case AArch64::ADDXri: NewOpc = AArch64::ADDSXri; break ;
891
- case AArch64::ADCWr: NewOpc = AArch64::ADCSWr; break ;
892
- case AArch64::ADCXr: NewOpc = AArch64::ADCSXr; break ;
893
- case AArch64::SUBWrr: NewOpc = AArch64::SUBSWrr; break ;
894
- case AArch64::SUBWri: NewOpc = AArch64::SUBSWri; break ;
895
- case AArch64::SUBXrr: NewOpc = AArch64::SUBSXrr; break ;
896
- case AArch64::SUBXri: NewOpc = AArch64::SUBSXri; break ;
897
- case AArch64::SBCWr: NewOpc = AArch64::SBCSWr; break ;
898
- case AArch64::SBCXr: NewOpc = AArch64::SBCSXr; break ;
899
- case AArch64::ANDWri: NewOpc = AArch64::ANDSWri; break ;
900
- case AArch64::ANDXri: NewOpc = AArch64::ANDSXri; break ;
901
- }
905
+ return Instr.getOpcode ();;
906
+
907
+ case AArch64::ADDWrr: return AArch64::ADDSWrr;
908
+ case AArch64::ADDWri: return AArch64::ADDSWri;
909
+ case AArch64::ADDXrr: return AArch64::ADDSXrr;
910
+ case AArch64::ADDXri: return AArch64::ADDSXri;
911
+ case AArch64::ADCWr: return AArch64::ADCSWr;
912
+ case AArch64::ADCXr: return AArch64::ADCSXr;
913
+ case AArch64::SUBWrr: return AArch64::SUBSWrr;
914
+ case AArch64::SUBWri: return AArch64::SUBSWri;
915
+ case AArch64::SUBXrr: return AArch64::SUBSXrr;
916
+ case AArch64::SUBXri: return AArch64::SUBSXri;
917
+ case AArch64::SBCWr: return AArch64::SBCSWr;
918
+ case AArch64::SBCXr: return AArch64::SBCSXr;
919
+ case AArch64::ANDWri: return AArch64::ANDSWri;
920
+ case AArch64::ANDXri: return AArch64::ANDSXri;
921
+ }
922
+ }
923
+
924
+ // / Check if AArch64::NZCV should be alive in successors of MBB.
925
+ static bool areCFlagsAliveInSuccessors (MachineBasicBlock *MBB) {
926
+ for (auto *BB : MBB->successors ())
927
+ if (BB->isLiveIn (AArch64::NZCV))
928
+ return true ;
929
+ return false ;
930
+ }
931
+
932
+ // / Substitute CmpInstr with another instruction which produces a needed
933
+ // / condition code.
934
+ // / Return true on success.
935
+ bool AArch64InstrInfo::substituteCmpInstr (MachineInstr *CmpInstr,
936
+ unsigned SrcReg, const MachineRegisterInfo *MRI) const {
937
+ // Get the unique definition of SrcReg.
938
+ MachineInstr *MI = MRI->getUniqueVRegDef (SrcReg);
939
+ if (!MI)
940
+ return false ;
941
+
942
+ const TargetRegisterInfo *TRI = &getRegisterInfo ();
943
+ if (areCFlagsAccessedBetweenInstrs (MI, CmpInstr, TRI))
944
+ return false ;
945
+
946
+ unsigned NewOpc = sForm (*MI);
947
+ if (NewOpc == AArch64::INSTRUCTION_LIST_END)
948
+ return false ;
902
949
903
950
// Scan forward for the use of NZCV.
904
951
// When checking against MI: if it's a conditional code requires
@@ -966,12 +1013,8 @@ bool AArch64InstrInfo::optimizeCompareInstr(
966
1013
967
1014
// If NZCV is not killed nor re-defined, we should check whether it is
968
1015
// live-out. If it is live-out, do not optimize.
969
- if (!IsSafe) {
970
- MachineBasicBlock *ParentBlock = CmpInstr->getParent ();
971
- for (auto *MBB : ParentBlock->successors ())
972
- if (MBB->isLiveIn (AArch64::NZCV))
973
- return false ;
974
- }
1016
+ if (!IsSafe && areCFlagsAliveInSuccessors (CmpInstr->getParent ()))
1017
+ return false ;
975
1018
976
1019
// Update the instruction to set NZCV.
977
1020
MI->setDesc (get (NewOpc));
@@ -3201,11 +3244,10 @@ bool AArch64InstrInfo::optimizeCondBranch(MachineInstr *MI) const {
3201
3244
return false ;
3202
3245
3203
3246
AArch64CC::CondCode CC = (AArch64CC::CondCode)DefMI->getOperand (3 ).getImm ();
3204
- bool CheckOnlyCCWrites = true ;
3205
3247
// Convert only when the condition code is not modified between
3206
3248
// the CSINC and the branch. The CC may be used by other
3207
3249
// instructions in between.
3208
- if (modifiesConditionCode (DefMI, MI, CheckOnlyCCWrites, &getRegisterInfo ()))
3250
+ if (areCFlagsAccessedBetweenInstrs (DefMI, MI, &getRegisterInfo (), AK_Write ))
3209
3251
return false ;
3210
3252
MachineBasicBlock &RefToMBB = *MBB;
3211
3253
MachineBasicBlock *TBB = MI->getOperand (TargetBBInMI).getMBB ();
0 commit comments