Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions llvm/lib/Target/ARM/ARMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19863,7 +19863,31 @@ void ARMTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
Known.Zero = IsVORR ? (KnownLHS.Zero & ~Imm) : (KnownLHS.Zero | Imm);
break;
}
case ARMISD::VMOVIMM:
case ARMISD::VMVNIMM: {
unsigned Encoded = Op.getConstantOperandVal(0);
unsigned DecEltBits = 0;
uint64_t DecodedVal = ARM_AM::decodeVMOVModImm(Encoded, DecEltBits);

unsigned EltBits = Op.getScalarValueSizeInBits();
if (EltBits != DecEltBits)
break;

APInt Imm(DecEltBits, DecodedVal);

if (Op.getOpcode() == ARMISD::VMVNIMM)
Imm.flipAllBits();

Known = KnownBits::makeConstant(Imm);
break;
}
}
}

bool ARMTargetLowering::isTargetCanonicalConstantNode(SDValue Op) const {
return Op.getOpcode() == ARMISD::VMOVIMM ||
Op.getOpcode() == ARMISD::VMVNIMM ||
TargetLowering::isTargetCanonicalConstantNode(Op);
}

bool ARMTargetLowering::targetShrinkDemandedConstant(
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/ARM/ARMISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ class VectorType;
const SelectionDAG &DAG,
unsigned Depth) const override;

bool isTargetCanonicalConstantNode(SDValue Op) const override;

bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits,
const APInt &DemandedElts,
TargetLoweringOpt &TLO) const override;
Expand Down
32 changes: 32 additions & 0 deletions llvm/unittests/Target/ARM/ARMSelectionDAGTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,36 @@ TEST_F(ARMSelectionDAGTest, computeKnownBits_VBICIMM_cmode2_lhs_ones) {
EXPECT_EQ(Known.Zero, APInt(32, 0x0000AA00));
}

/// VMOVIMM: Move immediate to vector register.
/// cmode=0x0 puts imm8 in byte0 => per-lane constant = 0x000000AA.
TEST_F(ARMSelectionDAGTest, computeKnownBits_VMOVIMM) {
SDLoc DL;
EVT VT = MVT::v4i32;

SDValue EncSD =
DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x0, 0xAA), DL, MVT::i32);
SDValue Op = DAG->getNode(ARMISD::VMOVIMM, DL, VT, EncSD);

APInt DemandedElts = APInt::getAllOnes(4);
KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
EXPECT_EQ(Known.One, APInt(32, 0x000000AA));
EXPECT_EQ(Known.Zero, APInt(32, 0xFFFFFF55));
}

/// VMVNIMM: Move NOT immediate to vector register.
/// cmode=0x0 puts imm8 in byte0 => decoded = 0x000000AA, result = ~0x000000AA.
TEST_F(ARMSelectionDAGTest, computeKnownBits_VMVNIMM) {
SDLoc DL;
EVT VT = MVT::v4i32;

SDValue EncSD =
DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x0, 0xAA), DL, MVT::i32);
SDValue Op = DAG->getNode(ARMISD::VMVNIMM, DL, VT, EncSD);

APInt DemandedElts = APInt::getAllOnes(4);
KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
EXPECT_EQ(Known.One, APInt(32, 0xFFFFFF55));
EXPECT_EQ(Known.Zero, APInt(32, 0x000000AA));
}

} // end namespace llvm
Loading