[llvm] [AArch64][GlobalISel] Vector Constant Materialization (PR #67149)

David Green via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 25 00:42:23 PDT 2023


================
@@ -5433,6 +5448,188 @@ bool AArch64InstructionSelector::selectInsertElt(MachineInstr &I,
   return true;
 }
 
+MachineInstr *AArch64InstructionSelector::tryAdvSIMDModImm8(
+    Register Dst, unsigned DstSize, APInt Bits, MachineIRBuilder &builder) {
+  unsigned int Op;
+  if (DstSize == 128) {
+    if (Bits.getHiBits(64) != Bits.getLoBits(64))
+      return nullptr;
+    Op = AArch64::MOVIv16b_ns;
+  } else {
+    Op = AArch64::MOVIv8b_ns;
+  }
+
+  uint64_t val = Bits.zextOrTrunc(64).getZExtValue();
+
+  if (AArch64_AM::isAdvSIMDModImmType9(val)) {
+    val = AArch64_AM::encodeAdvSIMDModImmType9(val);
+    auto Mov = builder.buildInstr(Op, {Dst}, {}).addImm(val);
+    constrainSelectedInstRegOperands(*Mov, TII, TRI, RBI);
+    return &*Mov;
+  }
+  return nullptr;
+}
+
+MachineInstr *AArch64InstructionSelector::tryAdvSIMDModImm16(
+    Register Dst, unsigned DstSize, APInt Bits, MachineIRBuilder &builder,
+    bool inv) {
+
+  unsigned int Op;
+  if (DstSize == 128) {
+    if (Bits.getHiBits(64) != Bits.getLoBits(64))
+      return nullptr;
+    Op = inv ? AArch64::MVNIv8i16 : AArch64::MOVIv8i16;
+  } else {
+    Op = inv ? AArch64::MVNIv4i16 : AArch64::MOVIv4i16;
+  }
+
+  uint64_t val = Bits.zextOrTrunc(64).getZExtValue();
+
+  bool isAdvSIMDModImm = false;
+  uint64_t Shift;
+
+  if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType5(val))) {
+    val = AArch64_AM::encodeAdvSIMDModImmType5(val);
+    Shift = 0;
+  } else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType6(val))) {
+    val = AArch64_AM::encodeAdvSIMDModImmType6(val);
+    Shift = 8;
+  }
+
+  if (isAdvSIMDModImm) {
+    auto Mov = builder.buildInstr(Op, {Dst}, {}).addImm(val).addImm(Shift);
+    constrainSelectedInstRegOperands(*Mov, TII, TRI, RBI);
+    return &*Mov;
+  }
+  return nullptr;
+}
+
+MachineInstr *AArch64InstructionSelector::tryAdvSIMDModImm32(
+    Register Dst, unsigned DstSize, APInt Bits, MachineIRBuilder &builder,
+    bool inv) {
+
+  unsigned int Op;
+  if (DstSize == 128) {
+    if (Bits.getHiBits(64) != Bits.getLoBits(64))
+      return nullptr;
+    Op = inv ? AArch64::MVNIv4i32 : AArch64::MOVIv4i32;
+  } else {
+    Op = inv ? AArch64::MVNIv2i32 : AArch64::MOVIv2i32;
+  }
+
+  uint64_t val = Bits.zextOrTrunc(64).getZExtValue();
+  bool isAdvSIMDModImm = false;
+  uint64_t Shift;
+
+  if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType1(val))) {
+    val = AArch64_AM::encodeAdvSIMDModImmType1(val);
+    Shift = 0;
+  } else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType2(val))) {
+    val = AArch64_AM::encodeAdvSIMDModImmType2(val);
+    Shift = 8;
+  } else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType3(val))) {
+    val = AArch64_AM::encodeAdvSIMDModImmType3(val);
+    Shift = 16;
+  } else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType4(val))) {
+    val = AArch64_AM::encodeAdvSIMDModImmType4(val);
+    Shift = 24;
+  }
+
+  if (isAdvSIMDModImm) {
----------------
davemgreen wrote:

I think I would personally do:
```
if (AArch64_AM::isAdvSIMDModImmType1(val)) {
 ..
} else if (..) {
 //
} else
  return nullptr;
```
That way after the if's we know we are creating the instruction, and the isAdvSIMDModImm hopefully isn't needed any more.

https://github.com/llvm/llvm-project/pull/67149


More information about the llvm-commits mailing list