Subzero: ARM32: lowering of vector insert and extract.

BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4076
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/1655313002 .
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index 4b70dad..099ceb2 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -296,7 +296,9 @@
   llvm::SmallBitVector Float32Registers(RegARM32::Reg_NUM);
   llvm::SmallBitVector Float64Registers(RegARM32::Reg_NUM);
   llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM);
+  llvm::SmallBitVector QtoSRegisters(RegARM32::Reg_NUM);
   llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM);
+  const unsigned EncodedReg_q8 = RegARM32::RegTable[RegARM32::Reg_q8].Encoding;
   for (int i = 0; i < RegARM32::Reg_NUM; ++i) {
     const auto &Entry = RegARM32::RegTable[i];
     IntegerRegisters[i] = Entry.IsInt;
@@ -305,6 +307,9 @@
     Float64Registers[i] = Entry.IsFP64;
     VectorRegisters[i] = Entry.IsVec128;
     RegisterAliases[i].resize(RegARM32::Reg_NUM);
+    // TODO(eholk): It would be better to store a QtoS flag in the
+    // IceRegistersARM32 table than to compare their encodings here.
+    QtoSRegisters[i] = Entry.IsVec128 && Entry.Encoding < EncodedReg_q8;
     for (int j = 0; j < Entry.NumAliases; ++j) {
       assert(i == j || !RegisterAliases[i][Entry.Aliases[j]]);
       RegisterAliases[i].set(Entry.Aliases[j]);
@@ -340,6 +345,7 @@
   TypeToRegisterSet[IceType_v8i16] = VectorRegisters;
   TypeToRegisterSet[IceType_v4i32] = VectorRegisters;
   TypeToRegisterSet[IceType_v4f32] = VectorRegisters;
+  TypeToRegisterSet[RegARM32::RCARM32_QtoS] = QtoSRegisters;
 
   for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i)
     TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i];
@@ -3834,7 +3840,28 @@
 }
 
 void TargetARM32::lowerExtractElement(const InstExtractElement *Instr) {
-  UnimplementedLoweringError(this, Instr);
+  Variable *Dest = Instr->getDest();
+  Type DestTy = Dest->getType();
+
+  Variable *Src0 = legalizeToReg(Instr->getSrc(0));
+  Operand *Src1 = Instr->getSrc(1);
+
+  if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src1)) {
+    const uint32_t Index = Imm->getValue();
+    Variable *T = makeReg(DestTy);
+    Variable *TSrc0 = makeReg(Src0->getType());
+
+    if (isFloatingType(DestTy)) {
+      // We need to make sure the source is in a suitable register.
+      TSrc0->setRegClass(RegARM32::RCARM32_QtoS);
+    }
+
+    _mov(TSrc0, Src0);
+    _extractelement(T, TSrc0, Index);
+    _mov(Dest, T);
+    return;
+  }
+  assert(false && "extractelement requires a constant index");
 }
 
 namespace {
@@ -4229,7 +4256,28 @@
 }
 
 void TargetARM32::lowerInsertElement(const InstInsertElement *Instr) {
-  UnimplementedLoweringError(this, Instr);
+  Variable *Dest = Instr->getDest();
+  Type DestTy = Dest->getType();
+
+  Variable *Src0 = legalizeToReg(Instr->getSrc(0));
+  Variable *Src1 = legalizeToReg(Instr->getSrc(1));
+  Operand *Src2 = Instr->getSrc(2);
+
+  if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2)) {
+    const uint32_t Index = Imm->getValue();
+    Variable *T = makeReg(DestTy);
+
+    if (isFloatingType(DestTy)) {
+      T->setRegClass(RegARM32::RCARM32_QtoS);
+    }
+
+    _mov(T, Src0);
+    _insertelement(T, Src1, Index);
+    _set_dest_redefined();
+    _mov(Dest, T);
+    return;
+  }
+  assert(false && "insertelement requires a constant index");
 }
 
 namespace {