[llvm] [GlobalISel][ARM] Support missing case for G_CONSTANT (PR #79022)

Serge Pavlov via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 22 09:45:56 PST 2024


https://github.com/spavloff created https://github.com/llvm/llvm-project/pull/79022

The instruction:

    %0:gprb(s32) = G_CONSTANT i32 -1

now cannot be selected on ARM. In DAG selector the similar instruction is selected with the help of `mod_imm_not`, which is a PatLeaf node. This node is specified with a transformation helper (imm_not_XFORM), that creates a new SDValue. Such rules are not processed by TableGen now and the generated match table does not contain records that could be used to select such instruction.

This change implements selection for this case.

>From e0b6198711588cf2176d1e8d60f8c8e331378ba8 Mon Sep 17 00:00:00 2001
From: Serge Pavlov <sepavloff at gmail.com>
Date: Mon, 22 Jan 2024 22:26:18 +0700
Subject: [PATCH] [GlobalISel][ARM] Support missing case for G_CONSTANT

The instruction:

    %0:gprb(s32) = G_CONSTANT i32 -1

now cannot be selected on ARM. In DAG selector the similar instruction
is selected with the help of `mod_imm_not`, which is a PatLeaf node.
This node is specified with a transformation helper (imm_not_XFORM),
that creates a new SDValue. Such rules are not processed by TableGen now
and the generated match table does not contain records that could be
used to select such instruction.

This change implements selection for this case.
---
 .../lib/Target/ARM/ARMInstructionSelector.cpp | 71 +++++++++++++------
 .../CodeGen/ARM/GlobalISel/select-imm.mir     | 25 +++++++
 2 files changed, 74 insertions(+), 22 deletions(-)
 create mode 100644 llvm/test/CodeGen/ARM/GlobalISel/select-imm.mir

diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
index f391058a70514c3..f4c5513d857b587 100644
--- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
+++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
@@ -60,6 +60,7 @@ class ARMInstructionSelector : public InstructionSelector {
   bool selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
   bool selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
   bool selectShift(unsigned ShiftOpc, MachineInstrBuilder &MIB) const;
+  bool selectConstant(MachineInstrBuilder &MIB) const;
 
   // Check if the types match and both operands have the expected size and
   // register bank.
@@ -810,6 +811,31 @@ bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,
   return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
 }
 
+bool ARMInstructionSelector::selectConstant(MachineInstrBuilder &MIB) const {
+  MachineInstr &MI = *MIB;
+  assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && "Expected G_CONSTANT");
+
+  auto &Val = MI.getOperand(1);
+  uint32_t ImmValue;
+  if (Val.isImm())
+    ImmValue = Val.getImm();
+  else if (Val.isCImm())
+    ImmValue = Val.getCImm()->getZExtValue();
+  else
+    return false;
+
+  // Process nodes didn't handled by TableGen-based selector.
+  if (!STI.isThumb()) {
+    if (int Imm12 = ARM_AM::getSOImmVal(~ImmValue); Imm12 != -1) {
+      MI.setDesc(TII.get(ARM::MVNi));
+      Val.ChangeToImmediate(Imm12);
+      MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
+      return constrainSelectedInstRegOperands(MI, TII, TRI, RBI);
+    }
+  }
+  return false;
+}
+
 void ARMInstructionSelector::renderVFPF32Imm(
   MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst,
   int OpIdx) const {
@@ -958,33 +984,34 @@ bool ARMInstructionSelector::select(MachineInstr &I) {
     I.setDesc(TII.get(COPY));
     return selectCopy(I, TII, MRI, TRI, RBI);
   }
-  case G_CONSTANT: {
-    if (!MRI.getType(I.getOperand(0).getReg()).isPointer()) {
-      // Non-pointer constants should be handled by TableGen.
-      LLVM_DEBUG(dbgs() << "Unsupported constant type\n");
-      return false;
-    }
-
-    auto &Val = I.getOperand(1);
-    if (Val.isCImm()) {
-      if (!Val.getCImm()->isZero()) {
-        LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
+  case G_CONSTANT:
+    if (!selectConstant(MIB)) {
+      auto &Val = MIB->getOperand(1);
+      if (!MRI.getType(I.getOperand(0).getReg()).isPointer()) {
+        // Non-pointer constants should be handled by TableGen.
+        LLVM_DEBUG(dbgs() << "Unsupported constant type\n");
         return false;
       }
-      Val.ChangeToImmediate(0);
-    } else {
-      assert(Val.isImm() && "Unexpected operand for G_CONSTANT");
-      if (Val.getImm() != 0) {
-        LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
-        return false;
+
+      if (Val.isCImm()) {
+        if (!Val.getCImm()->isZero()) {
+          LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
+          return false;
+        }
+        Val.ChangeToImmediate(0);
+      } else {
+        assert(Val.isImm() && "Unexpected operand for G_CONSTANT");
+        if (Val.getImm() != 0) {
+          LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
+          return false;
+        }
       }
-    }
 
-    assert(!STI.isThumb() && "Unsupported subtarget");
-    I.setDesc(TII.get(ARM::MOVi));
-    MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
+      assert(!STI.isThumb() && "Unsupported subtarget");
+      I.setDesc(TII.get(ARM::MOVi));
+      MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
+    }
     break;
-  }
   case G_FCONSTANT: {
     // Load from constant pool
     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() / 8;
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/select-imm.mir b/llvm/test/CodeGen/ARM/GlobalISel/select-imm.mir
new file mode 100644
index 000000000000000..59e983bb8c46b93
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/GlobalISel/select-imm.mir
@@ -0,0 +1,25 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
+# RUN: llc -mtriple arm-- -mattr=+v6 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name:            get_const_01
+legalized:       true
+regBankSelected: true
+selected:        false
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gprb }
+body:             |
+  bb.0:
+    liveins: $r0
+    ; CHECK-LABEL: name: get_const_01
+    ; CHECK: liveins: $r0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[MVNi:%[0-9]+]]:gpr = MVNi 0, 14 /* CC::al */, $noreg, $noreg
+    ; CHECK-NEXT: $r0 = COPY [[MVNi]]
+    ; CHECK-NEXT: MOVPCLR 14 /* CC::al */, $noreg, implicit $r0
+    %0:gprb(s32) = G_CONSTANT i32 -1
+    $r0 = COPY %0(s32)
+    MOVPCLR 14 /* CC::al */, $noreg, implicit $r0
+
+...



More information about the llvm-commits mailing list