forked from OSchip/llvm-project
GlobalISel: Return APInt from getConstantVRegVal
Returning int64_t was arbitrarily limiting for wide integer types, and the functions should handle the full generality of the IR. Also changes the full form which returns the originally defined vreg. Add another wrapper for the common case of just immediately converting to int64_t (arguably this would be useful for the full return value case as well). One possible issue with this change is some of the existing uses did break without conversion to getConstantVRegSExtVal, and it's possible some without adequate test coverage are now broken.
This commit is contained in:
parent
77fb45e59e
commit
581d13f8ae
|
@ -43,7 +43,7 @@ struct ConstantMatch {
|
||||||
int64_t &CR;
|
int64_t &CR;
|
||||||
ConstantMatch(int64_t &C) : CR(C) {}
|
ConstantMatch(int64_t &C) : CR(C) {}
|
||||||
bool match(const MachineRegisterInfo &MRI, Register Reg) {
|
bool match(const MachineRegisterInfo &MRI, Register Reg) {
|
||||||
if (auto MaybeCst = getConstantVRegVal(Reg, MRI)) {
|
if (auto MaybeCst = getConstantVRegSExtVal(Reg, MRI)) {
|
||||||
CR = *MaybeCst;
|
CR = *MaybeCst;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,14 +121,19 @@ void reportGISelWarning(MachineFunction &MF, const TargetPassConfig &TPC,
|
||||||
MachineOptimizationRemarkEmitter &MORE,
|
MachineOptimizationRemarkEmitter &MORE,
|
||||||
MachineOptimizationRemarkMissed &R);
|
MachineOptimizationRemarkMissed &R);
|
||||||
|
|
||||||
|
/// If \p VReg is defined by a G_CONSTANT, return the corresponding value.
|
||||||
|
Optional<APInt> getConstantVRegVal(Register VReg,
|
||||||
|
const MachineRegisterInfo &MRI);
|
||||||
|
|
||||||
/// If \p VReg is defined by a G_CONSTANT fits in int64_t
|
/// If \p VReg is defined by a G_CONSTANT fits in int64_t
|
||||||
/// returns it.
|
/// returns it.
|
||||||
Optional<int64_t> getConstantVRegVal(Register VReg,
|
Optional<int64_t> getConstantVRegSExtVal(Register VReg,
|
||||||
const MachineRegisterInfo &MRI);
|
const MachineRegisterInfo &MRI);
|
||||||
|
|
||||||
/// Simple struct used to hold a constant integer value and a virtual
|
/// Simple struct used to hold a constant integer value and a virtual
|
||||||
/// register.
|
/// register.
|
||||||
struct ValueAndVReg {
|
struct ValueAndVReg {
|
||||||
int64_t Value;
|
APInt Value;
|
||||||
Register VReg;
|
Register VReg;
|
||||||
};
|
};
|
||||||
/// If \p VReg is defined by a statically evaluable chain of
|
/// If \p VReg is defined by a statically evaluable chain of
|
||||||
|
|
|
@ -1029,8 +1029,7 @@ static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB) {
|
||||||
unsigned NumBits = Ty.getScalarSizeInBits();
|
unsigned NumBits = Ty.getScalarSizeInBits();
|
||||||
auto ValVRegAndVal = getConstantVRegValWithLookThrough(Val, MRI);
|
auto ValVRegAndVal = getConstantVRegValWithLookThrough(Val, MRI);
|
||||||
if (!Ty.isVector() && ValVRegAndVal) {
|
if (!Ty.isVector() && ValVRegAndVal) {
|
||||||
unsigned KnownVal = ValVRegAndVal->Value;
|
APInt Scalar = ValVRegAndVal->Value.truncOrSelf(8);
|
||||||
APInt Scalar = APInt(8, KnownVal);
|
|
||||||
APInt SplatVal = APInt::getSplat(NumBits, Scalar);
|
APInt SplatVal = APInt::getSplat(NumBits, Scalar);
|
||||||
return MIB.buildConstant(Ty, SplatVal).getReg(0);
|
return MIB.buildConstant(Ty, SplatVal).getReg(0);
|
||||||
}
|
}
|
||||||
|
@ -1411,7 +1410,7 @@ bool CombinerHelper::tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen) {
|
||||||
auto LenVRegAndVal = getConstantVRegValWithLookThrough(Len, MRI);
|
auto LenVRegAndVal = getConstantVRegValWithLookThrough(Len, MRI);
|
||||||
if (!LenVRegAndVal)
|
if (!LenVRegAndVal)
|
||||||
return false; // Leave it to the legalizer to lower it to a libcall.
|
return false; // Leave it to the legalizer to lower it to a libcall.
|
||||||
unsigned KnownLen = LenVRegAndVal->Value;
|
unsigned KnownLen = LenVRegAndVal->Value.getZExtValue();
|
||||||
|
|
||||||
if (KnownLen == 0) {
|
if (KnownLen == 0) {
|
||||||
MI.eraseFromParent();
|
MI.eraseFromParent();
|
||||||
|
@ -1521,7 +1520,7 @@ bool CombinerHelper::matchPtrAddImmedChain(MachineInstr &MI,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Pass the combined immediate to the apply function.
|
// Pass the combined immediate to the apply function.
|
||||||
MatchInfo.Imm = MaybeImmVal->Value + MaybeImm2Val->Value;
|
MatchInfo.Imm = (MaybeImmVal->Value + MaybeImm2Val->Value).getSExtValue();
|
||||||
MatchInfo.Base = Base;
|
MatchInfo.Base = Base;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1571,7 +1570,7 @@ bool CombinerHelper::matchShiftImmedChain(MachineInstr &MI,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Pass the combined immediate to the apply function.
|
// Pass the combined immediate to the apply function.
|
||||||
MatchInfo.Imm = MaybeImmVal->Value + MaybeImm2Val->Value;
|
MatchInfo.Imm = (MaybeImmVal->Value + MaybeImm2Val->Value).getSExtValue();
|
||||||
MatchInfo.Reg = Base;
|
MatchInfo.Reg = Base;
|
||||||
|
|
||||||
// There is no simple replacement for a saturating unsigned left shift that
|
// There is no simple replacement for a saturating unsigned left shift that
|
||||||
|
@ -1654,7 +1653,7 @@ bool CombinerHelper::matchShiftOfShiftedLogic(MachineInstr &MI,
|
||||||
if (!MaybeImmVal)
|
if (!MaybeImmVal)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const uint64_t C1Val = MaybeImmVal->Value;
|
const uint64_t C1Val = MaybeImmVal->Value.getZExtValue();
|
||||||
|
|
||||||
auto matchFirstShift = [&](const MachineInstr *MI, uint64_t &ShiftVal) {
|
auto matchFirstShift = [&](const MachineInstr *MI, uint64_t &ShiftVal) {
|
||||||
// Shift should match previous one and should be a one-use.
|
// Shift should match previous one and should be a one-use.
|
||||||
|
@ -1668,7 +1667,7 @@ bool CombinerHelper::matchShiftOfShiftedLogic(MachineInstr &MI,
|
||||||
if (!MaybeImmVal)
|
if (!MaybeImmVal)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ShiftVal = MaybeImmVal->Value;
|
ShiftVal = MaybeImmVal->Value.getSExtValue();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1738,10 +1737,11 @@ bool CombinerHelper::matchCombineMulToShl(MachineInstr &MI,
|
||||||
assert(MI.getOpcode() == TargetOpcode::G_MUL && "Expected a G_MUL");
|
assert(MI.getOpcode() == TargetOpcode::G_MUL && "Expected a G_MUL");
|
||||||
auto MaybeImmVal =
|
auto MaybeImmVal =
|
||||||
getConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI);
|
getConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI);
|
||||||
if (!MaybeImmVal || !isPowerOf2_64(MaybeImmVal->Value))
|
if (!MaybeImmVal)
|
||||||
return false;
|
return false;
|
||||||
ShiftVal = Log2_64(MaybeImmVal->Value);
|
|
||||||
return true;
|
ShiftVal = MaybeImmVal->Value.exactLogBase2();
|
||||||
|
return (static_cast<int32_t>(ShiftVal) != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CombinerHelper::applyCombineMulToShl(MachineInstr &MI,
|
bool CombinerHelper::applyCombineMulToShl(MachineInstr &MI,
|
||||||
|
@ -1787,7 +1787,7 @@ bool CombinerHelper::matchCombineShlOfExtend(MachineInstr &MI,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t ShiftAmt = MaybeShiftAmtVal->Value;
|
int64_t ShiftAmt = MaybeShiftAmtVal->Value.getSExtValue();
|
||||||
MatchData.Reg = ExtSrc;
|
MatchData.Reg = ExtSrc;
|
||||||
MatchData.Imm = ShiftAmt;
|
MatchData.Imm = ShiftAmt;
|
||||||
|
|
||||||
|
@ -2026,7 +2026,7 @@ bool CombinerHelper::matchCombineShiftToUnmerge(MachineInstr &MI,
|
||||||
if (!MaybeImmVal)
|
if (!MaybeImmVal)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ShiftVal = MaybeImmVal->Value;
|
ShiftVal = MaybeImmVal->Value.getSExtValue();
|
||||||
return ShiftVal >= Size / 2 && ShiftVal < Size;
|
return ShiftVal >= Size / 2 && ShiftVal < Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2200,7 +2200,7 @@ bool CombinerHelper::matchCombineConstPtrAddToI2P(MachineInstr &MI,
|
||||||
Register RHS = MI.getOperand(2).getReg();
|
Register RHS = MI.getOperand(2).getReg();
|
||||||
MachineRegisterInfo &MRI = Builder.getMF().getRegInfo();
|
MachineRegisterInfo &MRI = Builder.getMF().getRegInfo();
|
||||||
|
|
||||||
if (auto RHSCst = getConstantVRegVal(RHS, MRI)) {
|
if (auto RHSCst = getConstantVRegSExtVal(RHS, MRI)) {
|
||||||
int64_t Cst;
|
int64_t Cst;
|
||||||
if (mi_match(LHS, MRI, m_GIntToPtr(m_ICst(Cst)))) {
|
if (mi_match(LHS, MRI, m_GIntToPtr(m_ICst(Cst)))) {
|
||||||
NewCst = Cst + *RHSCst;
|
NewCst = Cst + *RHSCst;
|
||||||
|
@ -2441,7 +2441,7 @@ bool CombinerHelper::matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx) {
|
||||||
assert(MI.getOpcode() == TargetOpcode::G_SELECT);
|
assert(MI.getOpcode() == TargetOpcode::G_SELECT);
|
||||||
if (auto MaybeCstCmp =
|
if (auto MaybeCstCmp =
|
||||||
getConstantVRegValWithLookThrough(MI.getOperand(1).getReg(), MRI)) {
|
getConstantVRegValWithLookThrough(MI.getOperand(1).getReg(), MRI)) {
|
||||||
OpIdx = MaybeCstCmp->Value ? 2 : 3;
|
OpIdx = MaybeCstCmp->Value.isNullValue() ? 3 : 2;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -50,7 +50,7 @@ bool InstructionSelector::isOperandImmEqual(
|
||||||
const MachineRegisterInfo &MRI) const {
|
const MachineRegisterInfo &MRI) const {
|
||||||
if (MO.isReg() && MO.getReg())
|
if (MO.isReg() && MO.getReg())
|
||||||
if (auto VRegVal = getConstantVRegValWithLookThrough(MO.getReg(), MRI))
|
if (auto VRegVal = getConstantVRegValWithLookThrough(MO.getReg(), MRI))
|
||||||
return VRegVal->Value == Value;
|
return VRegVal->Value.getSExtValue() == Value;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -255,7 +255,7 @@ void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
|
||||||
reportGISelFailure(MF, TPC, MORE, R);
|
reportGISelFailure(MF, TPC, MORE, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<int64_t> llvm::getConstantVRegVal(Register VReg,
|
Optional<APInt> llvm::getConstantVRegVal(Register VReg,
|
||||||
const MachineRegisterInfo &MRI) {
|
const MachineRegisterInfo &MRI) {
|
||||||
Optional<ValueAndVReg> ValAndVReg =
|
Optional<ValueAndVReg> ValAndVReg =
|
||||||
getConstantVRegValWithLookThrough(VReg, MRI, /*LookThroughInstrs*/ false);
|
getConstantVRegValWithLookThrough(VReg, MRI, /*LookThroughInstrs*/ false);
|
||||||
|
@ -266,6 +266,14 @@ Optional<int64_t> llvm::getConstantVRegVal(Register VReg,
|
||||||
return ValAndVReg->Value;
|
return ValAndVReg->Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<int64_t> llvm::getConstantVRegSExtVal(Register VReg,
|
||||||
|
const MachineRegisterInfo &MRI) {
|
||||||
|
Optional<APInt> Val = getConstantVRegVal(VReg, MRI);
|
||||||
|
if (Val && Val->getBitWidth() <= 64)
|
||||||
|
return Val->getSExtValue();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
Optional<ValueAndVReg> llvm::getConstantVRegValWithLookThrough(
|
Optional<ValueAndVReg> llvm::getConstantVRegValWithLookThrough(
|
||||||
Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs,
|
Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs,
|
||||||
bool HandleFConstant) {
|
bool HandleFConstant) {
|
||||||
|
@ -337,10 +345,7 @@ Optional<ValueAndVReg> llvm::getConstantVRegValWithLookThrough(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Val.getBitWidth() > 64)
|
return ValueAndVReg{Val, VReg};
|
||||||
return None;
|
|
||||||
|
|
||||||
return ValueAndVReg{Val.getSExtValue(), VReg};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ConstantFP *
|
const ConstantFP *
|
||||||
|
@ -413,9 +418,8 @@ Optional<APInt> llvm::ConstantFoldBinOp(unsigned Opcode, const Register Op1,
|
||||||
if (!MaybeOp1Cst)
|
if (!MaybeOp1Cst)
|
||||||
return None;
|
return None;
|
||||||
|
|
||||||
LLT Ty = MRI.getType(Op1);
|
const APInt &C1 = *MaybeOp1Cst;
|
||||||
APInt C1(Ty.getSizeInBits(), *MaybeOp1Cst, true);
|
const APInt &C2 = *MaybeOp2Cst;
|
||||||
APInt C2(Ty.getSizeInBits(), *MaybeOp2Cst, true);
|
|
||||||
switch (Opcode) {
|
switch (Opcode) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -535,13 +539,13 @@ Optional<APInt> llvm::ConstantFoldExtOp(unsigned Opcode, const Register Op1,
|
||||||
const MachineRegisterInfo &MRI) {
|
const MachineRegisterInfo &MRI) {
|
||||||
auto MaybeOp1Cst = getConstantVRegVal(Op1, MRI);
|
auto MaybeOp1Cst = getConstantVRegVal(Op1, MRI);
|
||||||
if (MaybeOp1Cst) {
|
if (MaybeOp1Cst) {
|
||||||
LLT Ty = MRI.getType(Op1);
|
|
||||||
APInt C1(Ty.getSizeInBits(), *MaybeOp1Cst, true);
|
|
||||||
switch (Opcode) {
|
switch (Opcode) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
case TargetOpcode::G_SEXT_INREG:
|
case TargetOpcode::G_SEXT_INREG: {
|
||||||
return C1.trunc(Imm).sext(C1.getBitWidth());
|
LLT Ty = MRI.getType(Op1);
|
||||||
|
return MaybeOp1Cst->trunc(Imm).sext(Ty.getScalarSizeInBits());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -574,7 +574,7 @@ static Optional<uint64_t> getImmedFromMO(const MachineOperand &Root) {
|
||||||
getConstantVRegValWithLookThrough(Root.getReg(), MRI, true);
|
getConstantVRegValWithLookThrough(Root.getReg(), MRI, true);
|
||||||
if (!ValAndVReg)
|
if (!ValAndVReg)
|
||||||
return None;
|
return None;
|
||||||
Immed = ValAndVReg->Value;
|
Immed = ValAndVReg->Value.getSExtValue();
|
||||||
} else
|
} else
|
||||||
return None;
|
return None;
|
||||||
return Immed;
|
return Immed;
|
||||||
|
@ -1109,8 +1109,8 @@ AArch64InstructionSelector::emitSelect(Register Dst, Register True,
|
||||||
|
|
||||||
Register ZReg = Is32Bit ? AArch64::WZR : AArch64::XZR;
|
Register ZReg = Is32Bit ? AArch64::WZR : AArch64::XZR;
|
||||||
if (TrueCst && FalseCst) {
|
if (TrueCst && FalseCst) {
|
||||||
auto T = TrueCst->Value;
|
int64_t T = TrueCst->Value.getSExtValue();
|
||||||
auto F = FalseCst->Value;
|
int64_t F = FalseCst->Value.getSExtValue();
|
||||||
|
|
||||||
if (T == 0 && F == 1) {
|
if (T == 0 && F == 1) {
|
||||||
// G_SELECT cc, 0, 1 -> CSINC zreg, zreg, cc
|
// G_SELECT cc, 0, 1 -> CSINC zreg, zreg, cc
|
||||||
|
@ -1130,7 +1130,7 @@ AArch64InstructionSelector::emitSelect(Register Dst, Register True,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TrueCst) {
|
if (TrueCst) {
|
||||||
auto T = TrueCst->Value;
|
int64_t T = TrueCst->Value.getSExtValue();
|
||||||
if (T == 1) {
|
if (T == 1) {
|
||||||
// G_SELECT cc, 1, f -> CSINC f, zreg, inv_cc
|
// G_SELECT cc, 1, f -> CSINC f, zreg, inv_cc
|
||||||
Opc = Is32Bit ? AArch64::CSINCWr : AArch64::CSINCXr;
|
Opc = Is32Bit ? AArch64::CSINCWr : AArch64::CSINCXr;
|
||||||
|
@ -1151,7 +1151,7 @@ AArch64InstructionSelector::emitSelect(Register Dst, Register True,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FalseCst) {
|
if (FalseCst) {
|
||||||
auto F = FalseCst->Value;
|
int64_t F = FalseCst->Value.getSExtValue();
|
||||||
if (F == 1) {
|
if (F == 1) {
|
||||||
// G_SELECT cc, t, 1 -> CSINC t, zreg, cc
|
// G_SELECT cc, t, 1 -> CSINC t, zreg, cc
|
||||||
Opc = Is32Bit ? AArch64::CSINCWr : AArch64::CSINCXr;
|
Opc = Is32Bit ? AArch64::CSINCWr : AArch64::CSINCXr;
|
||||||
|
@ -1304,7 +1304,7 @@ static Register getTestBitReg(Register Reg, uint64_t &Bit, bool &Invert,
|
||||||
VRegAndVal = getConstantVRegValWithLookThrough(ConstantReg, MRI);
|
VRegAndVal = getConstantVRegValWithLookThrough(ConstantReg, MRI);
|
||||||
}
|
}
|
||||||
if (VRegAndVal)
|
if (VRegAndVal)
|
||||||
C = VRegAndVal->Value;
|
C = VRegAndVal->Value.getSExtValue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TargetOpcode::G_ASHR:
|
case TargetOpcode::G_ASHR:
|
||||||
|
@ -1314,7 +1314,7 @@ static Register getTestBitReg(Register Reg, uint64_t &Bit, bool &Invert,
|
||||||
auto VRegAndVal =
|
auto VRegAndVal =
|
||||||
getConstantVRegValWithLookThrough(MI->getOperand(2).getReg(), MRI);
|
getConstantVRegValWithLookThrough(MI->getOperand(2).getReg(), MRI);
|
||||||
if (VRegAndVal)
|
if (VRegAndVal)
|
||||||
C = VRegAndVal->Value;
|
C = VRegAndVal->Value.getSExtValue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1442,10 +1442,13 @@ bool AArch64InstructionSelector::tryOptAndIntoCompareBranch(
|
||||||
// (e.g, ANDing with 8 == ANDing with 000...100 == testing if bit 3 is set)
|
// (e.g, ANDing with 8 == ANDing with 000...100 == testing if bit 3 is set)
|
||||||
auto MaybeBit = getConstantVRegValWithLookThrough(
|
auto MaybeBit = getConstantVRegValWithLookThrough(
|
||||||
AndInst.getOperand(2).getReg(), *MIB.getMRI());
|
AndInst.getOperand(2).getReg(), *MIB.getMRI());
|
||||||
if (!MaybeBit || !isPowerOf2_64(MaybeBit->Value))
|
if (!MaybeBit)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int32_t Bit = MaybeBit->Value.exactLogBase2();
|
||||||
|
if (Bit < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint64_t Bit = Log2_64(static_cast<uint64_t>(MaybeBit->Value));
|
|
||||||
Register TestReg = AndInst.getOperand(1).getReg();
|
Register TestReg = AndInst.getOperand(1).getReg();
|
||||||
|
|
||||||
// Emit a TB(N)Z.
|
// Emit a TB(N)Z.
|
||||||
|
@ -1522,7 +1525,7 @@ bool AArch64InstructionSelector::tryOptCompareBranchFedByICmp(
|
||||||
// Note that we don't want to do this when we have a G_AND because it can
|
// Note that we don't want to do this when we have a G_AND because it can
|
||||||
// become a tst. The tst will make the test bit in the TB(N)Z redundant.
|
// become a tst. The tst will make the test bit in the TB(N)Z redundant.
|
||||||
if (VRegAndVal && !AndInst) {
|
if (VRegAndVal && !AndInst) {
|
||||||
int64_t C = VRegAndVal->Value;
|
int64_t C = VRegAndVal->Value.getSExtValue();
|
||||||
|
|
||||||
// When we have a greater-than comparison, we can just test if the msb is
|
// When we have a greater-than comparison, we can just test if the msb is
|
||||||
// zero.
|
// zero.
|
||||||
|
@ -1654,8 +1657,8 @@ static Optional<int64_t> getVectorShiftImm(Register Reg,
|
||||||
return None;
|
return None;
|
||||||
|
|
||||||
if (Idx == 1)
|
if (Idx == 1)
|
||||||
ImmVal = VRegAndVal->Value;
|
ImmVal = VRegAndVal->Value.getSExtValue();
|
||||||
if (ImmVal != VRegAndVal->Value)
|
if (ImmVal != VRegAndVal->Value.getSExtValue())
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2735,7 +2738,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
|
||||||
|
|
||||||
case TargetOpcode::G_PTRMASK: {
|
case TargetOpcode::G_PTRMASK: {
|
||||||
Register MaskReg = I.getOperand(2).getReg();
|
Register MaskReg = I.getOperand(2).getReg();
|
||||||
Optional<int64_t> MaskVal = getConstantVRegVal(MaskReg, MRI);
|
Optional<int64_t> MaskVal = getConstantVRegSExtVal(MaskReg, MRI);
|
||||||
// TODO: Implement arbitrary cases
|
// TODO: Implement arbitrary cases
|
||||||
if (!MaskVal || !isShiftedMask_64(*MaskVal))
|
if (!MaskVal || !isShiftedMask_64(*MaskVal))
|
||||||
return false;
|
return false;
|
||||||
|
@ -3749,7 +3752,7 @@ bool AArch64InstructionSelector::selectExtractElt(
|
||||||
auto VRegAndVal = getConstantVRegValWithLookThrough(LaneIdxOp.getReg(), MRI);
|
auto VRegAndVal = getConstantVRegValWithLookThrough(LaneIdxOp.getReg(), MRI);
|
||||||
if (!VRegAndVal)
|
if (!VRegAndVal)
|
||||||
return false;
|
return false;
|
||||||
unsigned LaneIdx = VRegAndVal->Value;
|
unsigned LaneIdx = VRegAndVal->Value.getSExtValue();
|
||||||
|
|
||||||
MachineIRBuilder MIRBuilder(I);
|
MachineIRBuilder MIRBuilder(I);
|
||||||
|
|
||||||
|
@ -4116,10 +4119,11 @@ AArch64InstructionSelector::emitTST(MachineOperand &LHS, MachineOperand &RHS,
|
||||||
// ANDS needs a logical immediate for its immediate form. Check if we can
|
// ANDS needs a logical immediate for its immediate form. Check if we can
|
||||||
// fold one in.
|
// fold one in.
|
||||||
if (auto ValAndVReg = getConstantVRegValWithLookThrough(RHS.getReg(), MRI)) {
|
if (auto ValAndVReg = getConstantVRegValWithLookThrough(RHS.getReg(), MRI)) {
|
||||||
if (AArch64_AM::isLogicalImmediate(ValAndVReg->Value, RegSize)) {
|
int64_t Imm = ValAndVReg->Value.getSExtValue();
|
||||||
|
|
||||||
|
if (AArch64_AM::isLogicalImmediate(Imm, RegSize)) {
|
||||||
auto TstMI = MIRBuilder.buildInstr(OpcTable[0][Is32Bit], {Ty}, {LHS});
|
auto TstMI = MIRBuilder.buildInstr(OpcTable[0][Is32Bit], {Ty}, {LHS});
|
||||||
TstMI.addImm(
|
TstMI.addImm(AArch64_AM::encodeLogicalImmediate(Imm, RegSize));
|
||||||
AArch64_AM::encodeLogicalImmediate(ValAndVReg->Value, RegSize));
|
|
||||||
constrainSelectedInstRegOperands(*TstMI, TII, TRI, RBI);
|
constrainSelectedInstRegOperands(*TstMI, TII, TRI, RBI);
|
||||||
return &*TstMI;
|
return &*TstMI;
|
||||||
}
|
}
|
||||||
|
@ -4658,7 +4662,7 @@ bool AArch64InstructionSelector::selectInsertElt(
|
||||||
auto VRegAndVal = getConstantVRegValWithLookThrough(IdxReg, MRI);
|
auto VRegAndVal = getConstantVRegValWithLookThrough(IdxReg, MRI);
|
||||||
if (!VRegAndVal)
|
if (!VRegAndVal)
|
||||||
return false;
|
return false;
|
||||||
unsigned LaneIdx = VRegAndVal->Value;
|
unsigned LaneIdx = VRegAndVal->Value.getSExtValue();
|
||||||
|
|
||||||
// Perform the lane insert.
|
// Perform the lane insert.
|
||||||
Register SrcReg = I.getOperand(1).getReg();
|
Register SrcReg = I.getOperand(1).getReg();
|
||||||
|
@ -5198,7 +5202,7 @@ AArch64InstructionSelector::selectExtendedSHL(
|
||||||
|
|
||||||
// The value must fit into 3 bits, and must be positive. Make sure that is
|
// The value must fit into 3 bits, and must be positive. Make sure that is
|
||||||
// true.
|
// true.
|
||||||
int64_t ImmVal = ValAndVReg->Value;
|
int64_t ImmVal = ValAndVReg->Value.getSExtValue();
|
||||||
|
|
||||||
// Since we're going to pull this into a shift, the constant value must be
|
// Since we're going to pull this into a shift, the constant value must be
|
||||||
// a power of 2. If we got a multiply, then we need to check this.
|
// a power of 2. If we got a multiply, then we need to check this.
|
||||||
|
@ -5362,7 +5366,7 @@ AArch64InstructionSelector::selectAddrModeXRO(MachineOperand &Root,
|
||||||
getConstantVRegValWithLookThrough(PtrAdd->getOperand(2).getReg(), MRI);
|
getConstantVRegValWithLookThrough(PtrAdd->getOperand(2).getReg(), MRI);
|
||||||
if (ValAndVReg) {
|
if (ValAndVReg) {
|
||||||
unsigned Scale = Log2_32(SizeInBytes);
|
unsigned Scale = Log2_32(SizeInBytes);
|
||||||
int64_t ImmOff = ValAndVReg->Value;
|
int64_t ImmOff = ValAndVReg->Value.getSExtValue();
|
||||||
|
|
||||||
// Skip immediates that can be selected in the load/store addresing
|
// Skip immediates that can be selected in the load/store addresing
|
||||||
// mode.
|
// mode.
|
||||||
|
@ -5821,7 +5825,8 @@ void AArch64InstructionSelector::renderTruncImm(MachineInstrBuilder &MIB,
|
||||||
const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
|
const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
|
||||||
assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
|
assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
|
||||||
"Expected G_CONSTANT");
|
"Expected G_CONSTANT");
|
||||||
Optional<int64_t> CstVal = getConstantVRegVal(MI.getOperand(0).getReg(), MRI);
|
Optional<int64_t> CstVal =
|
||||||
|
getConstantVRegSExtVal(MI.getOperand(0).getReg(), MRI);
|
||||||
assert(CstVal && "Expected constant value");
|
assert(CstVal && "Expected constant value");
|
||||||
MIB.addImm(CstVal.getValue());
|
MIB.addImm(CstVal.getValue());
|
||||||
}
|
}
|
||||||
|
|
|
@ -837,7 +837,7 @@ bool AArch64LegalizerInfo::legalizeShlAshrLshr(
|
||||||
if (!VRegAndVal)
|
if (!VRegAndVal)
|
||||||
return true;
|
return true;
|
||||||
// Check the shift amount is in range for an immediate form.
|
// Check the shift amount is in range for an immediate form.
|
||||||
int64_t Amount = VRegAndVal->Value;
|
int64_t Amount = VRegAndVal->Value.getSExtValue();
|
||||||
if (Amount > 31)
|
if (Amount > 31)
|
||||||
return true; // This will have to remain a register variant.
|
return true; // This will have to remain a register variant.
|
||||||
auto ExtCst = MIRBuilder.buildConstant(LLT::scalar(64), Amount);
|
auto ExtCst = MIRBuilder.buildConstant(LLT::scalar(64), Amount);
|
||||||
|
|
|
@ -130,7 +130,7 @@ bool matchAArch64MulConstCombine(
|
||||||
if (!Const)
|
if (!Const)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const APInt &ConstValue = APInt(Ty.getSizeInBits(), Const->Value, true);
|
const APInt ConstValue = Const->Value.sextOrSelf(Ty.getSizeInBits());
|
||||||
// The following code is ported from AArch64ISelLowering.
|
// The following code is ported from AArch64ISelLowering.
|
||||||
// Multiplication of a power of two plus/minus one can be done more
|
// Multiplication of a power of two plus/minus one can be done more
|
||||||
// cheaply as as shift+add/sub. For now, this is true unilaterally. If
|
// cheaply as as shift+add/sub. For now, this is true unilaterally. If
|
||||||
|
|
|
@ -438,7 +438,7 @@ tryAdjustICmpImmAndPred(Register RHS, CmpInst::Predicate P,
|
||||||
auto ValAndVReg = getConstantVRegValWithLookThrough(RHS, MRI);
|
auto ValAndVReg = getConstantVRegValWithLookThrough(RHS, MRI);
|
||||||
if (!ValAndVReg)
|
if (!ValAndVReg)
|
||||||
return None;
|
return None;
|
||||||
uint64_t C = ValAndVReg->Value;
|
uint64_t C = ValAndVReg->Value.getZExtValue();
|
||||||
if (isLegalArithImmed(C))
|
if (isLegalArithImmed(C))
|
||||||
return None;
|
return None;
|
||||||
|
|
||||||
|
|
|
@ -611,8 +611,10 @@ bool AMDGPUInstructionSelector::selectG_BUILD_VECTOR_TRUNC(
|
||||||
if (ConstSrc1) {
|
if (ConstSrc1) {
|
||||||
auto ConstSrc0 = getConstantVRegValWithLookThrough(Src0, *MRI, true, true);
|
auto ConstSrc0 = getConstantVRegValWithLookThrough(Src0, *MRI, true, true);
|
||||||
if (ConstSrc0) {
|
if (ConstSrc0) {
|
||||||
uint32_t Lo16 = static_cast<uint32_t>(ConstSrc0->Value) & 0xffff;
|
const int64_t K0 = ConstSrc0->Value.getSExtValue();
|
||||||
uint32_t Hi16 = static_cast<uint32_t>(ConstSrc1->Value) & 0xffff;
|
const int64_t K1 = ConstSrc1->Value.getSExtValue();
|
||||||
|
uint32_t Lo16 = static_cast<uint32_t>(K0) & 0xffff;
|
||||||
|
uint32_t Hi16 = static_cast<uint32_t>(K1) & 0xffff;
|
||||||
|
|
||||||
BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_MOV_B32), Dst)
|
BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_MOV_B32), Dst)
|
||||||
.addImm(Lo16 | (Hi16 << 16));
|
.addImm(Lo16 | (Hi16 << 16));
|
||||||
|
@ -820,7 +822,7 @@ bool AMDGPUInstructionSelector::selectWritelane(MachineInstr &MI) const {
|
||||||
// The selector has to be an inline immediate, so we can use whatever for
|
// The selector has to be an inline immediate, so we can use whatever for
|
||||||
// the other operands.
|
// the other operands.
|
||||||
MIB.addReg(Val);
|
MIB.addReg(Val);
|
||||||
MIB.addImm(ConstSelect->Value &
|
MIB.addImm(ConstSelect->Value.getSExtValue() &
|
||||||
maskTrailingOnes<uint64_t>(STI.getWavefrontSizeLog2()));
|
maskTrailingOnes<uint64_t>(STI.getWavefrontSizeLog2()));
|
||||||
} else {
|
} else {
|
||||||
Optional<ValueAndVReg> ConstVal =
|
Optional<ValueAndVReg> ConstVal =
|
||||||
|
@ -828,9 +830,9 @@ bool AMDGPUInstructionSelector::selectWritelane(MachineInstr &MI) const {
|
||||||
|
|
||||||
// If the value written is an inline immediate, we can get away without a
|
// If the value written is an inline immediate, we can get away without a
|
||||||
// copy to m0.
|
// copy to m0.
|
||||||
if (ConstVal && AMDGPU::isInlinableLiteral32(ConstVal->Value,
|
if (ConstVal && AMDGPU::isInlinableLiteral32(ConstVal->Value.getSExtValue(),
|
||||||
STI.hasInv2PiInlineImm())) {
|
STI.hasInv2PiInlineImm())) {
|
||||||
MIB.addImm(ConstVal->Value);
|
MIB.addImm(ConstVal->Value.getSExtValue());
|
||||||
MIB.addReg(LaneSelect);
|
MIB.addReg(LaneSelect);
|
||||||
} else {
|
} else {
|
||||||
MIB.addReg(Val);
|
MIB.addReg(Val);
|
||||||
|
@ -1101,7 +1103,7 @@ bool AMDGPUInstructionSelector::selectBallot(MachineInstr &I) const {
|
||||||
getConstantVRegValWithLookThrough(I.getOperand(2).getReg(), *MRI, true);
|
getConstantVRegValWithLookThrough(I.getOperand(2).getReg(), *MRI, true);
|
||||||
|
|
||||||
if (Arg.hasValue()) {
|
if (Arg.hasValue()) {
|
||||||
const int64_t Value = Arg.getValue().Value;
|
const int64_t Value = Arg.getValue().Value.getSExtValue();
|
||||||
if (Value == 0) {
|
if (Value == 0) {
|
||||||
unsigned Opcode = Is64 ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
|
unsigned Opcode = Is64 ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
|
||||||
BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg).addImm(0);
|
BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg).addImm(0);
|
||||||
|
@ -3430,7 +3432,7 @@ AMDGPUInstructionSelector::selectFlatOffsetImpl(MachineOperand &Root) const {
|
||||||
return Default;
|
return Default;
|
||||||
|
|
||||||
Optional<int64_t> Offset =
|
Optional<int64_t> Offset =
|
||||||
getConstantVRegVal(OpDef->getOperand(2).getReg(), *MRI);
|
getConstantVRegSExtVal(OpDef->getOperand(2).getReg(), *MRI);
|
||||||
if (!Offset.hasValue())
|
if (!Offset.hasValue())
|
||||||
return Default;
|
return Default;
|
||||||
|
|
||||||
|
@ -3919,7 +3921,7 @@ AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
|
||||||
= getConstantVRegValWithLookThrough(RHS.getReg(), MRI, true);
|
= getConstantVRegValWithLookThrough(RHS.getReg(), MRI, true);
|
||||||
if (!MaybeOffset)
|
if (!MaybeOffset)
|
||||||
return {Root, 0};
|
return {Root, 0};
|
||||||
return {RootI->getOperand(1).getReg(), MaybeOffset->Value};
|
return {RootI->getOperand(1).getReg(), MaybeOffset->Value.getSExtValue()};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addZeroImm(MachineInstrBuilder &MIB) {
|
static void addZeroImm(MachineInstrBuilder &MIB) {
|
||||||
|
@ -4247,7 +4249,7 @@ AMDGPUInstructionSelector::selectMUBUFOffsetAtomic(MachineOperand &Root) const {
|
||||||
static Optional<uint64_t> getConstantZext32Val(Register Reg,
|
static Optional<uint64_t> getConstantZext32Val(Register Reg,
|
||||||
const MachineRegisterInfo &MRI) {
|
const MachineRegisterInfo &MRI) {
|
||||||
// getConstantVRegVal sexts any values, so see if that matters.
|
// getConstantVRegVal sexts any values, so see if that matters.
|
||||||
Optional<int64_t> OffsetVal = getConstantVRegVal(Reg, MRI);
|
Optional<int64_t> OffsetVal = getConstantVRegSExtVal(Reg, MRI);
|
||||||
if (!OffsetVal || !isInt<32>(*OffsetVal))
|
if (!OffsetVal || !isInt<32>(*OffsetVal))
|
||||||
return None;
|
return None;
|
||||||
return Lo_32(*OffsetVal);
|
return Lo_32(*OffsetVal);
|
||||||
|
|
|
@ -2087,10 +2087,11 @@ bool AMDGPULegalizerInfo::legalizeExtractVectorElt(
|
||||||
// FIXME: Artifact combiner probably should have replaced the truncated
|
// FIXME: Artifact combiner probably should have replaced the truncated
|
||||||
// constant before this, so we shouldn't need
|
// constant before this, so we shouldn't need
|
||||||
// getConstantVRegValWithLookThrough.
|
// getConstantVRegValWithLookThrough.
|
||||||
Optional<ValueAndVReg> IdxVal = getConstantVRegValWithLookThrough(
|
Optional<ValueAndVReg> MaybeIdxVal =
|
||||||
MI.getOperand(2).getReg(), MRI);
|
getConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI);
|
||||||
if (!IdxVal) // Dynamic case will be selected to register indexing.
|
if (!MaybeIdxVal) // Dynamic case will be selected to register indexing.
|
||||||
return true;
|
return true;
|
||||||
|
const int64_t IdxVal = MaybeIdxVal->Value.getSExtValue();
|
||||||
|
|
||||||
Register Dst = MI.getOperand(0).getReg();
|
Register Dst = MI.getOperand(0).getReg();
|
||||||
Register Vec = MI.getOperand(1).getReg();
|
Register Vec = MI.getOperand(1).getReg();
|
||||||
|
@ -2099,8 +2100,8 @@ bool AMDGPULegalizerInfo::legalizeExtractVectorElt(
|
||||||
LLT EltTy = VecTy.getElementType();
|
LLT EltTy = VecTy.getElementType();
|
||||||
assert(EltTy == MRI.getType(Dst));
|
assert(EltTy == MRI.getType(Dst));
|
||||||
|
|
||||||
if (IdxVal->Value < VecTy.getNumElements())
|
if (IdxVal < VecTy.getNumElements())
|
||||||
B.buildExtract(Dst, Vec, IdxVal->Value * EltTy.getSizeInBits());
|
B.buildExtract(Dst, Vec, IdxVal * EltTy.getSizeInBits());
|
||||||
else
|
else
|
||||||
B.buildUndef(Dst);
|
B.buildUndef(Dst);
|
||||||
|
|
||||||
|
@ -2118,11 +2119,12 @@ bool AMDGPULegalizerInfo::legalizeInsertVectorElt(
|
||||||
// FIXME: Artifact combiner probably should have replaced the truncated
|
// FIXME: Artifact combiner probably should have replaced the truncated
|
||||||
// constant before this, so we shouldn't need
|
// constant before this, so we shouldn't need
|
||||||
// getConstantVRegValWithLookThrough.
|
// getConstantVRegValWithLookThrough.
|
||||||
Optional<ValueAndVReg> IdxVal = getConstantVRegValWithLookThrough(
|
Optional<ValueAndVReg> MaybeIdxVal =
|
||||||
MI.getOperand(3).getReg(), MRI);
|
getConstantVRegValWithLookThrough(MI.getOperand(3).getReg(), MRI);
|
||||||
if (!IdxVal) // Dynamic case will be selected to register indexing.
|
if (!MaybeIdxVal) // Dynamic case will be selected to register indexing.
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
int64_t IdxVal = MaybeIdxVal->Value.getSExtValue();
|
||||||
Register Dst = MI.getOperand(0).getReg();
|
Register Dst = MI.getOperand(0).getReg();
|
||||||
Register Vec = MI.getOperand(1).getReg();
|
Register Vec = MI.getOperand(1).getReg();
|
||||||
Register Ins = MI.getOperand(2).getReg();
|
Register Ins = MI.getOperand(2).getReg();
|
||||||
|
@ -2131,8 +2133,8 @@ bool AMDGPULegalizerInfo::legalizeInsertVectorElt(
|
||||||
LLT EltTy = VecTy.getElementType();
|
LLT EltTy = VecTy.getElementType();
|
||||||
assert(EltTy == MRI.getType(Ins));
|
assert(EltTy == MRI.getType(Ins));
|
||||||
|
|
||||||
if (IdxVal->Value < VecTy.getNumElements())
|
if (IdxVal < VecTy.getNumElements())
|
||||||
B.buildInsert(Dst, Vec, Ins, IdxVal->Value * EltTy.getSizeInBits());
|
B.buildInsert(Dst, Vec, Ins, IdxVal * EltTy.getSizeInBits());
|
||||||
else
|
else
|
||||||
B.buildUndef(Dst);
|
B.buildUndef(Dst);
|
||||||
|
|
||||||
|
@ -2643,7 +2645,7 @@ bool AMDGPULegalizerInfo::legalizeBuildVector(
|
||||||
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI) {
|
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI) {
|
||||||
if (MI.getOpcode() != TargetOpcode::G_XOR)
|
if (MI.getOpcode() != TargetOpcode::G_XOR)
|
||||||
return false;
|
return false;
|
||||||
auto ConstVal = getConstantVRegVal(MI.getOperand(2).getReg(), MRI);
|
auto ConstVal = getConstantVRegSExtVal(MI.getOperand(2).getReg(), MRI);
|
||||||
return ConstVal && *ConstVal == -1;
|
return ConstVal && *ConstVal == -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1331,7 +1331,7 @@ static unsigned setBufferOffsets(MachineIRBuilder &B,
|
||||||
const LLT S32 = LLT::scalar(32);
|
const LLT S32 = LLT::scalar(32);
|
||||||
MachineRegisterInfo *MRI = B.getMRI();
|
MachineRegisterInfo *MRI = B.getMRI();
|
||||||
|
|
||||||
if (Optional<int64_t> Imm = getConstantVRegVal(CombinedOffset, *MRI)) {
|
if (Optional<int64_t> Imm = getConstantVRegSExtVal(CombinedOffset, *MRI)) {
|
||||||
uint32_t SOffset, ImmOffset;
|
uint32_t SOffset, ImmOffset;
|
||||||
if (AMDGPU::splitMUBUFOffset(*Imm, SOffset, ImmOffset, &RBI.Subtarget,
|
if (AMDGPU::splitMUBUFOffset(*Imm, SOffset, ImmOffset, &RBI.Subtarget,
|
||||||
Alignment)) {
|
Alignment)) {
|
||||||
|
|
|
@ -479,7 +479,7 @@ static void X86SelectAddress(const MachineInstr &I,
|
||||||
"unsupported type.");
|
"unsupported type.");
|
||||||
|
|
||||||
if (I.getOpcode() == TargetOpcode::G_PTR_ADD) {
|
if (I.getOpcode() == TargetOpcode::G_PTR_ADD) {
|
||||||
if (auto COff = getConstantVRegVal(I.getOperand(2).getReg(), MRI)) {
|
if (auto COff = getConstantVRegSExtVal(I.getOperand(2).getReg(), MRI)) {
|
||||||
int64_t Imm = *COff;
|
int64_t Imm = *COff;
|
||||||
if (isInt<32>(Imm)) { // Check for displacement overflow.
|
if (isInt<32>(Imm)) { // Check for displacement overflow.
|
||||||
AM.Disp = static_cast<int32_t>(Imm);
|
AM.Disp = static_cast<int32_t>(Imm);
|
||||||
|
|
Loading…
Reference in New Issue