}
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:
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) {
; 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)
; 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)
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
\ No newline at end of file