@@ -172,6 +172,11 @@ class AArch64InstructionSelector : public InstructionSelector {
172
172
emitIntegerCompare (MachineOperand &LHS, MachineOperand &RHS,
173
173
MachineOperand &Predicate,
174
174
MachineIRBuilder &MIRBuilder) const ;
175
+
176
+ // / Emit a floating point comparison between \p LHS and \p RHS.
177
+ MachineInstr *emitFPCompare (Register LHS, Register RHS,
178
+ MachineIRBuilder &MIRBuilder) const ;
179
+
175
180
MachineInstr *emitInstr (unsigned Opcode,
176
181
std::initializer_list<llvm::DstOp> DstOps,
177
182
std::initializer_list<llvm::SrcOp> SrcOps,
@@ -238,9 +243,16 @@ class AArch64InstructionSelector : public InstructionSelector {
238
243
MachineInstr *emitFMovForFConstant (MachineInstr &MI,
239
244
MachineRegisterInfo &MRI) const ;
240
245
241
- // / Emit a CSet for a compare.
246
+ // / Emit a CSet for an integer compare.
247
+ // /
248
+ // / \p DefReg is expected to be a 32-bit scalar register.
242
249
MachineInstr *emitCSetForICMP (Register DefReg, unsigned Pred,
243
250
MachineIRBuilder &MIRBuilder) const ;
251
+ // / Emit a CSet for a FP compare.
252
+ // /
253
+ // / \p Dst is expected to be a 32-bit scalar register.
254
+ MachineInstr *emitCSetForFCmp (Register Dst, CmpInst::Predicate Pred,
255
+ MachineIRBuilder &MIRBuilder) const ;
244
256
245
257
// / Emit a TB(N)Z instruction which tests \p Bit in \p TestReg.
246
258
// / \p IsNegative is true if the test should be "not zero".
@@ -998,20 +1010,6 @@ static unsigned selectSelectOpc(MachineInstr &I, MachineRegisterInfo &MRI,
998
1010
return 0 ;
999
1011
}
1000
1012
1001
- // / Helper function to select the opcode for a G_FCMP.
1002
- static unsigned selectFCMPOpc (MachineInstr &I, MachineRegisterInfo &MRI) {
1003
- // If this is a compare against +0.0, then we don't have to explicitly
1004
- // materialize a constant.
1005
- const ConstantFP *FPImm = getConstantFPVRegVal (I.getOperand (3 ).getReg (), MRI);
1006
- bool ShouldUseImm = FPImm && (FPImm->isZero () && !FPImm->isNegative ());
1007
- unsigned OpSize = MRI.getType (I.getOperand (2 ).getReg ()).getSizeInBits ();
1008
- if (OpSize != 32 && OpSize != 64 )
1009
- return 0 ;
1010
- unsigned CmpOpcTbl[2 ][2 ] = {{AArch64::FCMPSrr, AArch64::FCMPDrr},
1011
- {AArch64::FCMPSri, AArch64::FCMPDri}};
1012
- return CmpOpcTbl[ShouldUseImm][OpSize == 64 ];
1013
- }
1014
-
1015
1013
// / Returns true if \p P is an unsigned integer comparison predicate.
1016
1014
static bool isUnsignedICMPPred (const CmpInst::Predicate P) {
1017
1015
switch (P) {
@@ -2882,64 +2880,13 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
2882
2880
}
2883
2881
2884
2882
case TargetOpcode::G_FCMP: {
2885
- if (Ty != LLT::scalar (32 )) {
2886
- LLVM_DEBUG (dbgs () << " G_FCMP result has type: " << Ty
2887
- << " , expected: " << LLT::scalar (32 ) << ' \n ' );
2888
- return false ;
2889
- }
2890
-
2891
- unsigned CmpOpc = selectFCMPOpc (I, MRI);
2892
- if (!CmpOpc)
2883
+ MachineIRBuilder MIRBuilder (I);
2884
+ CmpInst::Predicate Pred =
2885
+ static_cast <CmpInst::Predicate>(I.getOperand (1 ).getPredicate ());
2886
+ if (!emitFPCompare (I.getOperand (2 ).getReg (), I.getOperand (3 ).getReg (),
2887
+ MIRBuilder) ||
2888
+ !emitCSetForFCmp (I.getOperand (0 ).getReg (), Pred, MIRBuilder))
2893
2889
return false ;
2894
-
2895
- // FIXME: regbank
2896
-
2897
- AArch64CC::CondCode CC1, CC2;
2898
- changeFCMPPredToAArch64CC (
2899
- (CmpInst::Predicate)I.getOperand (1 ).getPredicate (), CC1, CC2);
2900
-
2901
- // Partially build the compare. Decide if we need to add a use for the
2902
- // third operand based off whether or not we're comparing against 0.0.
2903
- auto CmpMI = BuildMI (MBB, I, I.getDebugLoc (), TII.get (CmpOpc))
2904
- .addUse (I.getOperand (2 ).getReg ());
2905
-
2906
- // If we don't have an immediate compare, then we need to add a use of the
2907
- // register which wasn't used for the immediate.
2908
- // Note that the immediate will always be the last operand.
2909
- if (CmpOpc != AArch64::FCMPSri && CmpOpc != AArch64::FCMPDri)
2910
- CmpMI = CmpMI.addUse (I.getOperand (3 ).getReg ());
2911
-
2912
- const Register DefReg = I.getOperand (0 ).getReg ();
2913
- Register Def1Reg = DefReg;
2914
- if (CC2 != AArch64CC::AL)
2915
- Def1Reg = MRI.createVirtualRegister (&AArch64::GPR32RegClass);
2916
-
2917
- MachineInstr &CSetMI =
2918
- *BuildMI (MBB, I, I.getDebugLoc (), TII.get (AArch64::CSINCWr))
2919
- .addDef (Def1Reg)
2920
- .addUse (AArch64::WZR)
2921
- .addUse (AArch64::WZR)
2922
- .addImm (getInvertedCondCode (CC1));
2923
-
2924
- if (CC2 != AArch64CC::AL) {
2925
- Register Def2Reg = MRI.createVirtualRegister (&AArch64::GPR32RegClass);
2926
- MachineInstr &CSet2MI =
2927
- *BuildMI (MBB, I, I.getDebugLoc (), TII.get (AArch64::CSINCWr))
2928
- .addDef (Def2Reg)
2929
- .addUse (AArch64::WZR)
2930
- .addUse (AArch64::WZR)
2931
- .addImm (getInvertedCondCode (CC2));
2932
- MachineInstr &OrMI =
2933
- *BuildMI (MBB, I, I.getDebugLoc (), TII.get (AArch64::ORRWrr))
2934
- .addDef (DefReg)
2935
- .addUse (Def1Reg)
2936
- .addUse (Def2Reg);
2937
- constrainSelectedInstRegOperands (OrMI, TII, TRI, RBI);
2938
- constrainSelectedInstRegOperands (CSet2MI, TII, TRI, RBI);
2939
- }
2940
- constrainSelectedInstRegOperands (*CmpMI, TII, TRI, RBI);
2941
- constrainSelectedInstRegOperands (CSetMI, TII, TRI, RBI);
2942
-
2943
2890
I.eraseFromParent ();
2944
2891
return true ;
2945
2892
}
@@ -3984,6 +3931,66 @@ AArch64InstructionSelector::emitIntegerCompare(
3984
3931
return {&*CmpMI, P};
3985
3932
}
3986
3933
3934
+ MachineInstr *AArch64InstructionSelector::emitCSetForFCmp (
3935
+ Register Dst, CmpInst::Predicate Pred, MachineIRBuilder &MIRBuilder) const {
3936
+ MachineRegisterInfo &MRI = *MIRBuilder.getMRI ();
3937
+ #ifndef NDEBUG
3938
+ LLT Ty = MRI.getType (Dst);
3939
+ assert (!Ty.isVector () && Ty.getSizeInBits () == 32 &&
3940
+ " Expected a 32-bit scalar register?" );
3941
+ #endif
3942
+ const Register ZeroReg = AArch64::WZR;
3943
+ auto EmitCSet = [&](Register CsetDst, AArch64CC::CondCode CC) {
3944
+ auto CSet =
3945
+ MIRBuilder.buildInstr (AArch64::CSINCWr, {CsetDst}, {ZeroReg, ZeroReg})
3946
+ .addImm (getInvertedCondCode (CC));
3947
+ constrainSelectedInstRegOperands (*CSet, TII, TRI, RBI);
3948
+ return &*CSet;
3949
+ };
3950
+
3951
+ AArch64CC::CondCode CC1, CC2;
3952
+ changeFCMPPredToAArch64CC (Pred, CC1, CC2);
3953
+ if (CC2 == AArch64CC::AL)
3954
+ return EmitCSet (Dst, CC1);
3955
+
3956
+ const TargetRegisterClass *RC = &AArch64::GPR32RegClass;
3957
+ Register Def1Reg = MRI.createVirtualRegister (RC);
3958
+ Register Def2Reg = MRI.createVirtualRegister (RC);
3959
+ EmitCSet (Def1Reg, CC1);
3960
+ EmitCSet (Def2Reg, CC2);
3961
+ auto OrMI = MIRBuilder.buildInstr (AArch64::ORRWrr, {Dst}, {Def1Reg, Def2Reg});
3962
+ constrainSelectedInstRegOperands (*OrMI, TII, TRI, RBI);
3963
+ return &*OrMI;
3964
+ }
3965
+
3966
+ MachineInstr *
3967
+ AArch64InstructionSelector::emitFPCompare (Register LHS, Register RHS,
3968
+ MachineIRBuilder &MIRBuilder) const {
3969
+ MachineRegisterInfo &MRI = *MIRBuilder.getMRI ();
3970
+ LLT Ty = MRI.getType (LHS);
3971
+ if (Ty.isVector ())
3972
+ return nullptr ;
3973
+ unsigned OpSize = Ty.getSizeInBits ();
3974
+ if (OpSize != 32 && OpSize != 64 )
3975
+ return nullptr ;
3976
+
3977
+ // If this is a compare against +0.0, then we don't have
3978
+ // to explicitly materialize a constant.
3979
+ const ConstantFP *FPImm = getConstantFPVRegVal (RHS, MRI);
3980
+ bool ShouldUseImm = FPImm && (FPImm->isZero () && !FPImm->isNegative ());
3981
+ unsigned CmpOpcTbl[2 ][2 ] = {{AArch64::FCMPSrr, AArch64::FCMPDrr},
3982
+ {AArch64::FCMPSri, AArch64::FCMPDri}};
3983
+ unsigned CmpOpc = CmpOpcTbl[ShouldUseImm][OpSize == 64 ];
3984
+
3985
+ // Partially build the compare. Decide if we need to add a use for the
3986
+ // third operand based off whether or not we're comparing against 0.0.
3987
+ auto CmpMI = MIRBuilder.buildInstr (CmpOpc).addUse (LHS);
3988
+ if (!ShouldUseImm)
3989
+ CmpMI.addUse (RHS);
3990
+ constrainSelectedInstRegOperands (*CmpMI, TII, TRI, RBI);
3991
+ return &*CmpMI;
3992
+ }
3993
+
3987
3994
MachineInstr *AArch64InstructionSelector::emitVectorConcat (
3988
3995
Optional<Register> Dst, Register Op1, Register Op2,
3989
3996
MachineIRBuilder &MIRBuilder) const {
@@ -4169,10 +4176,10 @@ bool AArch64InstructionSelector::tryOptSelect(MachineInstr &I) const {
4169
4176
CondCode = changeICMPPredToAArch64CC (Pred);
4170
4177
} else {
4171
4178
// Get the condition code for the select.
4179
+ CmpInst::Predicate Pred =
4180
+ static_cast <CmpInst::Predicate>(CondDef->getOperand (1 ).getPredicate ());
4172
4181
AArch64CC::CondCode CondCode2;
4173
- changeFCMPPredToAArch64CC (
4174
- (CmpInst::Predicate)CondDef->getOperand (1 ).getPredicate (), CondCode,
4175
- CondCode2);
4182
+ changeFCMPPredToAArch64CC (Pred, CondCode, CondCode2);
4176
4183
4177
4184
// changeFCMPPredToAArch64CC sets CondCode2 to AL when we require two
4178
4185
// instructions to emit the comparison.
@@ -4181,16 +4188,11 @@ bool AArch64InstructionSelector::tryOptSelect(MachineInstr &I) const {
4181
4188
if (CondCode2 != AArch64CC::AL)
4182
4189
return false ;
4183
4190
4184
- // Make sure we'll be able to select the compare.
4185
- unsigned CmpOpc = selectFCMPOpc (* CondDef, MRI);
4186
- if (!CmpOpc)
4191
+ if (! emitFPCompare (CondDef-> getOperand ( 2 ). getReg (),
4192
+ CondDef-> getOperand ( 3 ). getReg (), MIB)) {
4193
+ LLVM_DEBUG ( dbgs () << " Couldn't emit compare for select! \n " );
4187
4194
return false ;
4188
-
4189
- // Emit a new compare.
4190
- auto Cmp = MIB.buildInstr (CmpOpc, {}, {CondDef->getOperand (2 ).getReg ()});
4191
- if (CmpOpc != AArch64::FCMPSri && CmpOpc != AArch64::FCMPDri)
4192
- Cmp.addUse (CondDef->getOperand (3 ).getReg ());
4193
- constrainSelectedInstRegOperands (*Cmp, TII, TRI, RBI);
4195
+ }
4194
4196
}
4195
4197
4196
4198
// Emit the select.
0 commit comments