[llvm] 010f1ea - [DAG][ARM] ComputeKnownBitsForTargetNode - add handling for ARMISD VORRIMM\VBICIMM nodes (#149494)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 4 00:56:35 PDT 2025


Author: woruyu
Date: 2025-09-04T15:56:31+08:00
New Revision: 010f1ea3b3f425a1ef8bf4d25b89eae990ef591a

URL: https://github.com/llvm/llvm-project/commit/010f1ea3b3f425a1ef8bf4d25b89eae990ef591a
DIFF: https://github.com/llvm/llvm-project/commit/010f1ea3b3f425a1ef8bf4d25b89eae990ef591a.diff

LOG: [DAG][ARM] ComputeKnownBitsForTargetNode - add handling for ARMISD VORRIMM\VBICIMM nodes (#149494)

### Summary
This PR resolves https://github.com/llvm/llvm-project/issues/147179

Added: 
    llvm/unittests/Target/ARM/ARMSelectionDAGTest.cpp

Modified: 
    llvm/lib/Target/ARM/ARMISelLowering.cpp
    llvm/unittests/Target/ARM/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 5ac09e2f9fb1c..601806dacf092 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -20065,6 +20065,29 @@ void ARMTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
     Known = KnownOp0.intersectWith(KnownOp1);
     break;
   }
+  case ARMISD::VORRIMM:
+  case ARMISD::VBICIMM: {
+    unsigned Encoded = Op.getConstantOperandVal(1);
+    unsigned DecEltBits = 0;
+    uint64_t DecodedVal = ARM_AM::decodeVMOVModImm(Encoded, DecEltBits);
+
+    unsigned EltBits = Op.getScalarValueSizeInBits();
+    if (EltBits != DecEltBits) {
+      // Be conservative: only update Known when EltBits == DecEltBits.
+      // This is believed to always be true for VORRIMM/VBICIMM today, but if
+      // that changes in the future, doing nothing here is safer than risking
+      // subtle bugs.
+      break;
+    }
+
+    KnownBits KnownLHS = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
+    bool IsVORR = Op.getOpcode() == ARMISD::VORRIMM;
+    APInt Imm(DecEltBits, DecodedVal);
+
+    Known.One = IsVORR ? (KnownLHS.One | Imm) : (KnownLHS.One & ~Imm);
+    Known.Zero = IsVORR ? (KnownLHS.Zero & ~Imm) : (KnownLHS.Zero | Imm);
+    break;
+  }
   }
 }
 

diff  --git a/llvm/unittests/Target/ARM/ARMSelectionDAGTest.cpp b/llvm/unittests/Target/ARM/ARMSelectionDAGTest.cpp
new file mode 100644
index 0000000000000..7a47807679120
--- /dev/null
+++ b/llvm/unittests/Target/ARM/ARMSelectionDAGTest.cpp
@@ -0,0 +1,179 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMISelLowering.h"
+#include "MCTargetDesc/ARMAddressingModes.h"
+#include "llvm/Analysis/OptimizationRemarkEmitter.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/KnownBits.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+
+class ARMSelectionDAGTest : public testing::Test {
+protected:
+  static void SetUpTestCase() {
+    LLVMInitializeARMTargetInfo();
+    LLVMInitializeARMTarget();
+    LLVMInitializeARMTargetMC();
+  }
+
+  void SetUp() override {
+    StringRef Assembly = "define void @f() { ret void }";
+
+    Triple TargetTriple("armv7-unknown-none-eabi");
+
+    std::string Error;
+    const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
+
+    TargetOptions Options;
+    TM = std::unique_ptr<TargetMachine>(
+        T->createTargetMachine(TargetTriple,
+                               /*CPU*/ "cortex-a9",
+                               /*Features*/ "+neon", Options, std::nullopt,
+                               std::nullopt, CodeGenOptLevel::Aggressive));
+
+    SMDiagnostic SMError;
+    M = parseAssemblyString(Assembly, SMError, Context);
+    if (!M)
+      report_fatal_error(SMError.getMessage());
+    M->setDataLayout(TM->createDataLayout());
+
+    F = M->getFunction("f");
+    if (!F)
+      report_fatal_error("Function 'f' not found");
+
+    MachineModuleInfo MMI(TM.get());
+
+    MF = std::make_unique<MachineFunction>(*F, *TM, *TM->getSubtargetImpl(*F),
+                                           MMI.getContext(), /*FunctionNum*/ 0);
+
+    DAG = std::make_unique<SelectionDAG>(*TM, CodeGenOptLevel::None);
+    if (!DAG)
+      report_fatal_error("SelectionDAG allocation failed");
+
+    OptimizationRemarkEmitter ORE(F);
+    DAG->init(*MF, ORE, /*LibInfo*/ nullptr, /*AA*/ nullptr,
+              /*AC*/ nullptr, /*MDT*/ nullptr, /*MSDT*/ nullptr, MMI, nullptr);
+  }
+
+  TargetLoweringBase::LegalizeTypeAction getTypeAction(EVT VT) {
+    return DAG->getTargetLoweringInfo().getTypeAction(Context, VT);
+  }
+
+  EVT getTypeToTransformTo(EVT VT) {
+    return DAG->getTargetLoweringInfo().getTypeToTransformTo(Context, VT);
+  }
+
+  LLVMContext Context;
+  std::unique_ptr<TargetMachine> TM;
+  std::unique_ptr<Module> M;
+  Function *F = nullptr;
+  std::unique_ptr<MachineFunction> MF;
+  std::unique_ptr<SelectionDAG> DAG;
+};
+
+/// VORR (immediate): per-lane OR with 32-bit elements.
+/// cmode=0x0 puts imm8 in byte0 => per-lane constant = 0x000000AA.
+TEST_F(ARMSelectionDAGTest, computeKnownBits_VORRIMM) {
+  SDLoc DL;
+  EVT VT = MVT::v4i32;
+  SDValue LHS = DAG->getRegister(0, VT);
+
+  SDValue EncSD =
+      DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x0, 0xAA), DL, MVT::i32);
+  SDValue Op = DAG->getNode(ARMISD::VORRIMM, DL, VT, LHS, EncSD);
+
+  // LHS(per-lane)     = ???????? ???????? ???????? ????????
+  // Encoded(per-lane) = 00000000 00000000 00000000 10101010  (0x000000AA)
+  //  =>
+  // Known.One  = 00000000 00000000 00000000 10101010  (0x000000AA)
+  // Known.Zero = 00000000 00000000 00000000 00000000  (0x00000000)
+  APInt DemandedElts = APInt::getAllOnes(4);
+  KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
+  EXPECT_EQ(Known.One, APInt(32, 0xAA));
+  EXPECT_EQ(Known.Zero, APInt(32, 0x0));
+}
+
+/// VBIC (immediate): x & ~imm with 32-bit elements.
+/// LHS(per-lane)=0xFFFFFFFF; imm per-lane = 0x000000AA => result = 0xFFFFFF55
+TEST_F(ARMSelectionDAGTest, computeKnownBits_VBICIMM) {
+  SDLoc DL;
+  EVT VT = MVT::v4i32;
+
+  SDValue LHS = DAG->getConstant(APInt(32, 0xFFFFFFFF), DL, VT);
+
+  SDValue EncSD =
+      DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x0, 0xAA), DL, MVT::i32);
+  SDValue Op = DAG->getNode(ARMISD::VBICIMM, DL, VT, LHS, EncSD);
+
+  // LHS(per-lane)     = 11111111 11111111 11111111 11111111  (0xFFFFFFFF)
+  // Encoded(per-lane) = 00000000 00000000 00000000 10101010  (0x000000AA)
+  //  =>
+  // Known.One  = 11111111 11111111 11111111 01010101  (0xFFFFFF55)
+  // Known.Zero = 00000000 00000000 00000000 10101010  (0x000000AA)
+  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));
+}
+
+/// VORR (immediate): per-lane OR with 32-bit elements.
+/// Encoded = 0x2AA (cmode=0x2, imm8=0xAA) => per-lane constant = 0x0000AA00.
+TEST_F(ARMSelectionDAGTest, computeKnownBits_VORRIMM_cmode2) {
+  SDLoc DL;
+  EVT VT = MVT::v4i32;
+  SDValue LHS = DAG->getRegister(0, VT);
+
+  // Use the exact encoded immediate the reviewer asked for.
+  SDValue EncSD =
+      DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x2, 0xAA), DL, MVT::i32);
+  SDValue Op = DAG->getNode(ARMISD::VORRIMM, DL, VT, LHS, EncSD);
+
+  // LHS (per-lane)     = ???????? ???????? ???????? ????????
+  // Encoded (per-lane) = 00000000 00000000 10101010 00000000  (0x0000AA00)
+  //  =>
+  // Known.One          = 00000000 00000000 10101010 00000000  (0x0000AA00)
+  // Known.Zero         = 00000000 00000000 00000000 00000000  (0x00000000)
+  APInt DemandedElts = APInt::getAllOnes(4);
+  KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
+  EXPECT_EQ(Known.One, APInt(32, 0x0000AA00));
+  EXPECT_EQ(Known.Zero, APInt(32, 0x00000000));
+}
+
+/// VBIC (immediate) with constant-all-ones LHS:
+/// Encoded = 0x2AA => per-lane constant = 0x0000AA00; VBIC = A & ~Imm.
+TEST_F(ARMSelectionDAGTest, computeKnownBits_VBICIMM_cmode2_lhs_ones) {
+  SDLoc DL;
+  EVT VT = MVT::v4i32;
+
+  SDValue LHS = DAG->getConstant(APInt(32, 0xFFFFFFFF), DL, VT);
+  SDValue EncSD =
+      DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x2, 0xAA), DL, MVT::i32);
+  SDValue Op = DAG->getNode(ARMISD::VBICIMM, DL, VT, LHS, EncSD);
+
+  // LHS (per-lane)     = 11111111 11111111 11111111 11111111
+  // Encoded (per-lane) = 00000000 00000000 10101010 00000000  (0x0000AA00)
+  //  =>
+  // Known.One          = 11111111 11111111 01010101 11111111  (0xFFFF55FF)
+  // Known.Zero         = 00000000 00000000 10101010 00000000  (0x0000AA00)
+  APInt DemandedElts = APInt::getAllOnes(4);
+  KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
+  EXPECT_EQ(Known.One, APInt(32, 0xFFFF55FF));
+  EXPECT_EQ(Known.Zero, APInt(32, 0x0000AA00));
+}
+
+} // end namespace llvm

diff  --git a/llvm/unittests/Target/ARM/CMakeLists.txt b/llvm/unittests/Target/ARM/CMakeLists.txt
index 5da249708abf9..1bd2eda4e23c9 100644
--- a/llvm/unittests/Target/ARM/CMakeLists.txt
+++ b/llvm/unittests/Target/ARM/CMakeLists.txt
@@ -22,4 +22,5 @@ set(LLVM_LINK_COMPONENTS
 add_llvm_target_unittest(ARMTests
   MachineInstrTest.cpp
   InstSizes.cpp
+  ARMSelectionDAGTest.cpp
   )


        


More information about the llvm-commits mailing list