1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[GISel] Allow getConstantVRegVal() to return G_FCONSTANT values.

In GISel we have both G_CONSTANT and G_FCONSTANT, but because
in GISel we don't really have a concept of Float vs Int value
the only difference between the two is where the data originates
from.

What both G_CONSTANT and G_FCONSTANT return is just a bag of bits
with the constant representation in it.

By making getConstantVRegVal() return G_FCONSTANTs bit representation
as well we allow ConstantFold and other things to operate with
G_FCONSTANT.

Adding tests that show ConstantFolding to work on mixed G_CONSTANT
and G_FCONSTANT sources.

Differential Revision: https://reviews.llvm.org/D68739

llvm-svn: 374458
This commit is contained in:
Marcello Maggioni 2019-10-10 21:46:26 +00:00
parent 09a67d006e
commit c808ecf651
4 changed files with 220 additions and 38 deletions

View File

@ -119,14 +119,16 @@ struct ValueAndVReg {
unsigned VReg;
};
/// If \p VReg is defined by a statically evaluable chain of
/// instructions rooted on a G_CONSTANT (\p LookThroughInstrs == true)
/// and that constant fits in int64_t, returns its value as well as
/// the virtual register defined by this G_CONSTANT.
/// When \p LookThroughInstrs == false, this function behaves like
/// instructions rooted on a G_F/CONSTANT (\p LookThroughInstrs == true)
/// and that constant fits in int64_t, returns its value as well as the
/// virtual register defined by this G_F/CONSTANT.
/// When \p LookThroughInstrs == false this function behaves like
/// getConstantVRegVal.
/// When \p HandleFConstants == false the function bails on G_FCONSTANTs.
Optional<ValueAndVReg>
getConstantVRegValWithLookThrough(unsigned VReg, const MachineRegisterInfo &MRI,
bool LookThroughInstrs = true);
bool LookThroughInstrs = true,
bool HandleFConstants = true);
const ConstantFP* getConstantFPVRegVal(unsigned VReg,
const MachineRegisterInfo &MRI);

View File

@ -216,11 +216,34 @@ Optional<int64_t> llvm::getConstantVRegVal(unsigned VReg,
}
Optional<ValueAndVReg> llvm::getConstantVRegValWithLookThrough(
unsigned VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) {
unsigned VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs,
bool HandleFConstant) {
SmallVector<std::pair<unsigned, unsigned>, 4> SeenOpcodes;
MachineInstr *MI;
while ((MI = MRI.getVRegDef(VReg)) &&
MI->getOpcode() != TargetOpcode::G_CONSTANT && LookThroughInstrs) {
auto IsConstantOpcode = [HandleFConstant](unsigned Opcode) {
return Opcode == TargetOpcode::G_CONSTANT ||
(HandleFConstant && Opcode == TargetOpcode::G_FCONSTANT);
};
auto GetImmediateValue = [HandleFConstant,
&MRI](const MachineInstr &MI) -> Optional<APInt> {
const MachineOperand &CstVal = MI.getOperand(1);
if (!CstVal.isImm() && !CstVal.isCImm() &&
(!HandleFConstant || !CstVal.isFPImm()))
return None;
if (!CstVal.isFPImm()) {
unsigned BitWidth =
MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
APInt Val = CstVal.isImm() ? APInt(BitWidth, CstVal.getImm())
: CstVal.getCImm()->getValue();
assert(Val.getBitWidth() == BitWidth &&
"Value bitwidth doesn't match definition type");
return Val;
} else {
return CstVal.getFPImm()->getValueAPF().bitcastToAPInt();
}
};
while ((MI = MRI.getVRegDef(VReg)) && !IsConstantOpcode(MI->getOpcode()) &&
LookThroughInstrs) {
switch (MI->getOpcode()) {
case TargetOpcode::G_TRUNC:
case TargetOpcode::G_SEXT:
@ -242,16 +265,13 @@ Optional<ValueAndVReg> llvm::getConstantVRegValWithLookThrough(
return None;
}
}
if (!MI || MI->getOpcode() != TargetOpcode::G_CONSTANT ||
(!MI->getOperand(1).isImm() && !MI->getOperand(1).isCImm()))
if (!MI || !IsConstantOpcode(MI->getOpcode()))
return None;
const MachineOperand &CstVal = MI->getOperand(1);
unsigned BitWidth = MRI.getType(MI->getOperand(0).getReg()).getSizeInBits();
APInt Val = CstVal.isImm() ? APInt(BitWidth, CstVal.getImm())
: CstVal.getCImm()->getValue();
assert(Val.getBitWidth() == BitWidth &&
"Value bitwidth doesn't match definition type");
Optional<APInt> MaybeVal = GetImmediateValue(*MI);
if (!MaybeVal)
return None;
APInt &Val = *MaybeVal;
while (!SeenOpcodes.empty()) {
std::pair<unsigned, unsigned> OpcodeAndSize = SeenOpcodes.pop_back_val();
switch (OpcodeAndSize.first) {

View File

@ -56,18 +56,14 @@ body: |
; SI-LABEL: name: test_frint_s64
; SI: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1
; SI: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x4330000000000000
; SI: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808
; SI: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807
; SI: [[AND:%[0-9]+]]:_(s64) = G_AND [[C]], [[C2]]
; SI: [[AND1:%[0-9]+]]:_(s64) = G_AND [[C]], [[C1]]
; SI: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]], [[AND1]]
; SI: [[FADD:%[0-9]+]]:_(s64) = G_FADD [[COPY]], [[OR]]
; SI: [[FNEG:%[0-9]+]]:_(s64) = G_FNEG [[OR]]
; SI: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4841369599423283200
; SI: [[COPY1:%[0-9]+]]:_(s64) = COPY [[C]](s64)
; SI: [[FADD:%[0-9]+]]:_(s64) = G_FADD [[COPY]], [[COPY1]]
; SI: [[FNEG:%[0-9]+]]:_(s64) = G_FNEG [[COPY1]]
; SI: [[FADD1:%[0-9]+]]:_(s64) = G_FADD [[FADD]], [[FNEG]]
; SI: [[C3:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x432FFFFFFFFFFFFF
; SI: [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x432FFFFFFFFFFFFF
; SI: [[FABS:%[0-9]+]]:_(s64) = G_FABS [[COPY]]
; SI: [[FCMP:%[0-9]+]]:_(s1) = G_FCMP floatpred(ogt), [[FABS]](s64), [[C3]]
; SI: [[FCMP:%[0-9]+]]:_(s1) = G_FCMP floatpred(ogt), [[FABS]](s64), [[C1]]
; SI: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[FCMP]](s1), [[COPY]], [[FADD1]]
; SI: [[FRINT:%[0-9]+]]:_(s64) = G_FRINT [[COPY]]
; SI: $vgpr0_vgpr1 = COPY [[FRINT]](s64)
@ -131,26 +127,22 @@ body: |
; SI-LABEL: name: test_frint_v2s64
; SI: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3
; SI: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>)
; SI: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x4330000000000000
; SI: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808
; SI: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807
; SI: [[AND:%[0-9]+]]:_(s64) = G_AND [[C]], [[C2]]
; SI: [[AND1:%[0-9]+]]:_(s64) = G_AND [[C]], [[C1]]
; SI: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]], [[AND1]]
; SI: [[COPY1:%[0-9]+]]:_(s64) = COPY [[OR]](s64)
; SI: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4841369599423283200
; SI: [[COPY1:%[0-9]+]]:_(s64) = COPY [[C]](s64)
; SI: [[FADD:%[0-9]+]]:_(s64) = G_FADD [[UV]], [[COPY1]]
; SI: [[FNEG:%[0-9]+]]:_(s64) = G_FNEG [[COPY1]]
; SI: [[FADD1:%[0-9]+]]:_(s64) = G_FADD [[FADD]], [[FNEG]]
; SI: [[C3:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x432FFFFFFFFFFFFF
; SI: [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x432FFFFFFFFFFFFF
; SI: [[FABS:%[0-9]+]]:_(s64) = G_FABS [[UV]]
; SI: [[FCMP:%[0-9]+]]:_(s1) = G_FCMP floatpred(ogt), [[FABS]](s64), [[C3]]
; SI: [[FCMP:%[0-9]+]]:_(s1) = G_FCMP floatpred(ogt), [[FABS]](s64), [[C1]]
; SI: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[FCMP]](s1), [[UV]], [[FADD1]]
; SI: [[FRINT:%[0-9]+]]:_(s64) = G_FRINT [[UV]]
; SI: [[FADD2:%[0-9]+]]:_(s64) = G_FADD [[UV1]], [[OR]]
; SI: [[FNEG1:%[0-9]+]]:_(s64) = G_FNEG [[OR]]
; SI: [[COPY2:%[0-9]+]]:_(s64) = COPY [[C]](s64)
; SI: [[FADD2:%[0-9]+]]:_(s64) = G_FADD [[UV1]], [[COPY2]]
; SI: [[FNEG1:%[0-9]+]]:_(s64) = G_FNEG [[COPY2]]
; SI: [[FADD3:%[0-9]+]]:_(s64) = G_FADD [[FADD2]], [[FNEG1]]
; SI: [[FABS1:%[0-9]+]]:_(s64) = G_FABS [[UV1]]
; SI: [[FCMP1:%[0-9]+]]:_(s1) = G_FCMP floatpred(ogt), [[FABS1]](s64), [[C3]]
; SI: [[FCMP1:%[0-9]+]]:_(s1) = G_FCMP floatpred(ogt), [[FABS1]](s64), [[C1]]
; SI: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[FCMP1]](s1), [[UV1]], [[FADD3]]
; SI: [[FRINT1:%[0-9]+]]:_(s64) = G_FRINT [[UV1]]
; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[FRINT]](s64), [[FRINT1]](s64)

View File

@ -68,4 +68,172 @@ TEST_F(GISelMITest, FoldWithBuilder) {
EXPECT_EQ(-0x80, Cst);
}
TEST_F(GISelMITest, FoldBinOp) {
setUp();
if (!TM)
return;
LLT s32{LLT::scalar(32)};
auto MIBCst1 = B.buildConstant(s32, 16);
auto MIBCst2 = B.buildConstant(s32, 9);
auto MIBFCst1 = B.buildFConstant(s32, 1.0000001);
auto MIBFCst2 = B.buildFConstant(s32, 2.0);
// Test G_ADD folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGAddInt =
ConstantFoldBinOp(TargetOpcode::G_ADD, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGAddInt.hasValue());
EXPECT_EQ(25ULL, FoldGAddInt.getValue().getLimitedValue());
Optional<APInt> FoldGAddMix =
ConstantFoldBinOp(TargetOpcode::G_ADD, MIBCst1->getOperand(0).getReg(),
MIBFCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGAddMix.hasValue());
EXPECT_EQ(1073741840ULL, FoldGAddMix.getValue().getLimitedValue());
// Test G_AND folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGAndInt =
ConstantFoldBinOp(TargetOpcode::G_AND, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGAndInt.hasValue());
EXPECT_EQ(0ULL, FoldGAndInt.getValue().getLimitedValue());
Optional<APInt> FoldGAndMix =
ConstantFoldBinOp(TargetOpcode::G_AND, MIBCst2->getOperand(0).getReg(),
MIBFCst1->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGAndMix.hasValue());
EXPECT_EQ(1ULL, FoldGAndMix.getValue().getLimitedValue());
// Test G_ASHR folding Integer + Mixed cases
Optional<APInt> FoldGAShrInt =
ConstantFoldBinOp(TargetOpcode::G_ASHR, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGAShrInt.hasValue());
EXPECT_EQ(0ULL, FoldGAShrInt.getValue().getLimitedValue());
Optional<APInt> FoldGAShrMix =
ConstantFoldBinOp(TargetOpcode::G_ASHR, MIBFCst2->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGAShrMix.hasValue());
EXPECT_EQ(2097152ULL, FoldGAShrMix.getValue().getLimitedValue());
// Test G_LSHR folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGLShrInt =
ConstantFoldBinOp(TargetOpcode::G_LSHR, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGLShrInt.hasValue());
EXPECT_EQ(0ULL, FoldGLShrInt.getValue().getLimitedValue());
Optional<APInt> FoldGLShrMix =
ConstantFoldBinOp(TargetOpcode::G_LSHR, MIBFCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGLShrMix.hasValue());
EXPECT_EQ(2080768ULL, FoldGLShrMix.getValue().getLimitedValue());
// Test G_MUL folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGMulInt =
ConstantFoldBinOp(TargetOpcode::G_MUL, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGMulInt.hasValue());
EXPECT_EQ(144ULL, FoldGMulInt.getValue().getLimitedValue());
Optional<APInt> FoldGMulMix =
ConstantFoldBinOp(TargetOpcode::G_MUL, MIBCst1->getOperand(0).getReg(),
MIBFCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGMulMix.hasValue());
EXPECT_EQ(0ULL, FoldGMulMix.getValue().getLimitedValue());
// Test G_OR folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGOrInt =
ConstantFoldBinOp(TargetOpcode::G_OR, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGOrInt.hasValue());
EXPECT_EQ(25ULL, FoldGOrInt.getValue().getLimitedValue());
Optional<APInt> FoldGOrMix =
ConstantFoldBinOp(TargetOpcode::G_OR, MIBCst1->getOperand(0).getReg(),
MIBFCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGOrMix.hasValue());
EXPECT_EQ(1073741840ULL, FoldGOrMix.getValue().getLimitedValue());
// Test G_SHL folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGShlInt =
ConstantFoldBinOp(TargetOpcode::G_SHL, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGShlInt.hasValue());
EXPECT_EQ(8192ULL, FoldGShlInt.getValue().getLimitedValue());
Optional<APInt> FoldGShlMix =
ConstantFoldBinOp(TargetOpcode::G_SHL, MIBCst1->getOperand(0).getReg(),
MIBFCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGShlMix.hasValue());
EXPECT_EQ(0ULL, FoldGShlMix.getValue().getLimitedValue());
// Test G_SUB folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGSubInt =
ConstantFoldBinOp(TargetOpcode::G_SUB, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGSubInt.hasValue());
EXPECT_EQ(7ULL, FoldGSubInt.getValue().getLimitedValue());
Optional<APInt> FoldGSubMix =
ConstantFoldBinOp(TargetOpcode::G_SUB, MIBCst1->getOperand(0).getReg(),
MIBFCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGSubMix.hasValue());
EXPECT_EQ(3221225488ULL, FoldGSubMix.getValue().getLimitedValue());
// Test G_XOR folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGXorInt =
ConstantFoldBinOp(TargetOpcode::G_XOR, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGXorInt.hasValue());
EXPECT_EQ(25ULL, FoldGXorInt.getValue().getLimitedValue());
Optional<APInt> FoldGXorMix =
ConstantFoldBinOp(TargetOpcode::G_XOR, MIBCst1->getOperand(0).getReg(),
MIBFCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGXorMix.hasValue());
EXPECT_EQ(1073741840ULL, FoldGXorMix.getValue().getLimitedValue());
// Test G_UDIV folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGUdivInt =
ConstantFoldBinOp(TargetOpcode::G_UDIV, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGUdivInt.hasValue());
EXPECT_EQ(1ULL, FoldGUdivInt.getValue().getLimitedValue());
Optional<APInt> FoldGUdivMix =
ConstantFoldBinOp(TargetOpcode::G_UDIV, MIBCst1->getOperand(0).getReg(),
MIBFCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGUdivMix.hasValue());
EXPECT_EQ(0ULL, FoldGUdivMix.getValue().getLimitedValue());
// Test G_SDIV folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGSdivInt =
ConstantFoldBinOp(TargetOpcode::G_SDIV, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGSdivInt.hasValue());
EXPECT_EQ(1ULL, FoldGSdivInt.getValue().getLimitedValue());
Optional<APInt> FoldGSdivMix =
ConstantFoldBinOp(TargetOpcode::G_SDIV, MIBCst1->getOperand(0).getReg(),
MIBFCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGSdivMix.hasValue());
EXPECT_EQ(0ULL, FoldGSdivMix.getValue().getLimitedValue());
// Test G_UREM folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGUremInt =
ConstantFoldBinOp(TargetOpcode::G_UDIV, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGUremInt.hasValue());
EXPECT_EQ(1ULL, FoldGUremInt.getValue().getLimitedValue());
Optional<APInt> FoldGUremMix =
ConstantFoldBinOp(TargetOpcode::G_UDIV, MIBCst1->getOperand(0).getReg(),
MIBFCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGUremMix.hasValue());
EXPECT_EQ(0ULL, FoldGUremMix.getValue().getLimitedValue());
// Test G_SREM folding Integer + Mixed Int-Float cases
Optional<APInt> FoldGSremInt =
ConstantFoldBinOp(TargetOpcode::G_SREM, MIBCst1->getOperand(0).getReg(),
MIBCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGSremInt.hasValue());
EXPECT_EQ(7ULL, FoldGSremInt.getValue().getLimitedValue());
Optional<APInt> FoldGSremMix =
ConstantFoldBinOp(TargetOpcode::G_SREM, MIBCst1->getOperand(0).getReg(),
MIBFCst2->getOperand(0).getReg(), *MRI);
EXPECT_TRUE(FoldGSremMix.hasValue());
EXPECT_EQ(16ULL, FoldGSremMix.getValue().getLimitedValue());
}
} // namespace