Skip to content

[DirectX] [Scalarizer] Validator is erroring with Instructions must be of an allowed type. #139020

Open
@farzonl

Description

@farzonl

We are generating code that looks like this:

  %43 = bitcast i64 %42 to <2 x i32>
  %44 = extractelement <2 x i32> %43, i32 0
  %45 = extractelement <2 x i32> %43, i32 1

There are 160 errors that look just like this. In all cases it is an extractelement <2 x i32> we emit the error for both index extractions.

The code is coming from the InstCombinePass

This appears to be a bug in the scalarizer missing the scalarization of the bitcast:

  1. running scalarizer with insertelement: https://godbolt.org/z/6aExzxdPM
  2. running scalarizer with bitcast: https://godbolt.org/z/s8fb7936E

The fix likely needs to be in:

bool ScalarizerVisitor::visitBitCastInst(BitCastInst &BCI) {

The issue is this InstCombinePass is trying to split an i64 into its low and high half. A quick hack to confirm this fixes all cases would be to convert

%bc = bitcast i64 %42 to <2 x i32>
%low = extractelement <2 x i32> %bc, i32 0 ; low 32 bits
%high = extractelement <2 x i32> %bc, i32 1 ; high 32 bits

to

%low  = trunc i64 %42 to i32
%high = lshr i64 %42, 32
%high = trunc i64 %high to i32

We can test this out this fix via the legalizer.

diff --git a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
index be77a70fa46b..46cbb53debfa 100644
--- a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
+++ b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp
@@ -8,6 +8,8 @@
 
 #include "DXILLegalizePass.h"
 #include "DirectX.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InstIterator.h"
@@ -317,6 +319,47 @@ static void removeMemSet(Instruction &I,
   ToRemove.push_back(CI);
 }
 
+static void
+legalizeGetHighLowi64Bytes(Instruction &I,
+                            SmallVectorImpl<Instruction *> &ToRemove,
+                            DenseMap<Value *, Value *> &ReplacedValues) {
+  if (auto *BitCast = dyn_cast<BitCastInst>(&I)) {
+    if (BitCast->getDestTy() ==
+            FixedVectorType::get(Type::getInt32Ty(I.getContext()), 2) &&
+        BitCast->getSrcTy()->isIntegerTy(64)) {
+      ToRemove.push_back(BitCast);
+      ReplacedValues[BitCast] = BitCast->getOperand(0);
+    }
+  }
+
+  if (auto *Extract = dyn_cast<ExtractElementInst>(&I)) {
+    auto *VecTy = dyn_cast<FixedVectorType>(Extract->getVectorOperandType());
+    if (VecTy && VecTy->getElementType()->isIntegerTy(32) &&
+        VecTy->getNumElements() == 2) {
+      if (auto *Index = dyn_cast<ConstantInt>(Extract->getIndexOperand())) {
+        unsigned Idx = Index->getZExtValue();
+        IRBuilder<> Builder(&I);
+        assert(dyn_cast<BitCastInst>(Extract->getVectorOperand()));
+        auto *Replacement = ReplacedValues[Extract->getVectorOperand()];
+        if (Idx == 0) {
+          Value *LowBytes = Builder.CreateTrunc(
+              Replacement, Type::getInt32Ty(I.getContext()));
+          ReplacedValues[Extract] = LowBytes;
+        } else {
+          assert(Idx == 1);
+          Value *LogicalShiftRight = Builder.CreateLShr(
+              Replacement,
+              ConstantInt::get(Replacement->getType(),
+                              APInt(Replacement->getType()->getIntegerBitWidth(), 32)));
+          Value *HighBytes = Builder.CreateTrunc(
+              LogicalShiftRight, Type::getInt32Ty(I.getContext()));
+          ReplacedValues[Extract] = HighBytes;
+        }
+        ToRemove.push_back(Extract);
+      }
+    }
+  }
+}
 namespace {
 class DXILLegalizationPipeline {
 
@@ -349,6 +391,7 @@ private:
     LegalizationPipeline.push_back(downcastI64toI32InsertExtractElements);
     LegalizationPipeline.push_back(legalizeFreeze);
     LegalizationPipeline.push_back(removeMemSet);
+    LegalizationPipeline.push_back(legalizeGetHighLowi64Bytes);

Metadata

Metadata

Assignees

Type

Projects

Status

Active

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions