1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

GlobalISel: Implement lower for min/max

llvm-svn: 364816
This commit is contained in:
Matt Arsenault 2019-07-01 17:18:03 +00:00
parent b7ef706144
commit c1bba51aca
3 changed files with 115 additions and 0 deletions

View File

@ -218,6 +218,7 @@ private:
LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI);
LegalizeResult lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
LegalizeResult lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
LegalizeResult lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
MachineRegisterInfo &MRI;
const LegalizerInfo &LI;

View File

@ -1612,6 +1612,11 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
return lowerUITOFP(MI, TypeIdx, Ty);
case G_SITOFP:
return lowerSITOFP(MI, TypeIdx, Ty);
case G_SMIN:
case G_SMAX:
case G_UMIN:
case G_UMAX:
return lowerMinMax(MI, TypeIdx, Ty);
}
}
@ -3110,3 +3115,34 @@ LegalizerHelper::lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
return UnableToLegalize;
}
static CmpInst::Predicate minMaxToCompare(unsigned Opc) {
switch (Opc) {
case TargetOpcode::G_SMIN:
return CmpInst::ICMP_SLT;
case TargetOpcode::G_SMAX:
return CmpInst::ICMP_SGT;
case TargetOpcode::G_UMIN:
return CmpInst::ICMP_ULT;
case TargetOpcode::G_UMAX:
return CmpInst::ICMP_UGT;
default:
llvm_unreachable("not in integer min/max");
}
}
LegalizerHelper::LegalizeResult
LegalizerHelper::lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Register Dst = MI.getOperand(0).getReg();
Register Src0 = MI.getOperand(1).getReg();
Register Src1 = MI.getOperand(2).getReg();
const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
LLT CmpType = MRI.getType(Dst).changeElementSize(1);
auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
MI.eraseFromParent();
return Legalized;
}

View File

@ -775,4 +775,82 @@ TEST_F(GISelMITest, LowerFNEG) {
// Check
EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
}
TEST_F(GISelMITest, LowerMinMax) {
if (!TM)
return;
LLT s64 = LLT::scalar(64);
LLT v2s32 = LLT::vector(2, 32);
DefineLegalizerInfo(A, {
getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
.lowerFor({s64, LLT::vector(2, s32)});
});
auto SMin = B.buildSMin(s64, Copies[0], Copies[1]);
auto SMax = B.buildSMax(s64, Copies[0], Copies[1]);
auto UMin = B.buildUMin(s64, Copies[0], Copies[1]);
auto UMax = B.buildUMax(s64, Copies[0], Copies[1]);
auto VecVal0 = B.buildBitcast(v2s32, Copies[0]);
auto VecVal1 = B.buildBitcast(v2s32, Copies[1]);
auto SMinV = B.buildSMin(v2s32, VecVal0, VecVal1);
auto SMaxV = B.buildSMax(v2s32, VecVal0, VecVal1);
auto UMinV = B.buildUMin(v2s32, VecVal0, VecVal1);
auto UMaxV = B.buildUMax(v2s32, VecVal0, VecVal1);
AInfo Info(MF->getSubtarget());
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer, B);
EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
Helper.lower(*SMin, 0, s64));
EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
Helper.lower(*SMax, 0, s64));
EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
Helper.lower(*UMin, 0, s64));
EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
Helper.lower(*UMax, 0, s64));
EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
Helper.lower(*SMinV, 0, v2s32));
EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
Helper.lower(*SMaxV, 0, v2s32));
EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
Helper.lower(*UMinV, 0, v2s32));
EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
Helper.lower(*UMaxV, 0, v2s32));
auto CheckStr = R"(
CHECK: [[CMP0:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), %0:_(s64), %1:_
CHECK: [[SMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP0]]:_(s1), %0:_, %1:_
CHECK: [[CMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), %0:_(s64), %1:_
CHECK: [[SMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP1]]:_(s1), %0:_, %1:_
CHECK: [[CMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(ult), %0:_(s64), %1:_
CHECK: [[UMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP2]]:_(s1), %0:_, %1:_
CHECK: [[CMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), %0:_(s64), %1:_
CHECK: [[UMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP3]]:_(s1), %0:_, %1:_
CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64)
CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64)
CHECK: [[VCMP0:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(slt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
CHECK: [[SMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP0]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
CHECK: [[VCMP1:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(sgt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
CHECK: [[SMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP1]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
CHECK: [[VCMP2:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ult), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
CHECK: [[UMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP2]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
CHECK: [[VCMP3:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ugt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
CHECK: [[UMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP3]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
)";
EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
}
} // namespace