Skip to content

Commit 34939c8

Browse files
committed
[DirectX] Working i8 legalization pass
1 parent 57d87ed commit 34939c8

File tree

7 files changed

+177
-0
lines changed

7 files changed

+177
-0
lines changed

llvm/lib/Target/DirectX/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ add_llvm_target(DirectXCodeGen
3232
DXILShaderFlags.cpp
3333
DXILTranslateMetadata.cpp
3434
DXILRootSignature.cpp
35+
LegalizeI8Pass.cpp
3536

3637
LINK_COMPONENTS
3738
Analysis

llvm/lib/Target/DirectX/DirectX.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ void initializeDXILFlattenArraysLegacyPass(PassRegistry &);
4747
/// Pass to flatten arrays into a one dimensional DXIL legal form
4848
ModulePass *createDXILFlattenArraysLegacyPass();
4949

50+
/// Initializer I8 legalizationPass
51+
void initializeLegalizeI8LegacyPass(PassRegistry &);
52+
53+
/// Pass to remove i8 truncations
54+
FunctionPass *createLegalizeI8LegacyPass();
55+
5056
/// Initializer for DXILOpLowering
5157
void initializeDXILOpLoweringLegacyPass(PassRegistry &);
5258

llvm/lib/Target/DirectX/DirectXPassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ MODULE_PASS("print<dxil-root-signature>", dxil::RootSignatureAnalysisPrinter(dbg
3838
#define FUNCTION_PASS(NAME, CREATE_PASS)
3939
#endif
4040
FUNCTION_PASS("dxil-resource-access", DXILResourceAccess())
41+
FUNCTION_PASS("dxil-legalize-i8", LegalizeI8Pass())
4142
#undef FUNCTION_PASS

llvm/lib/Target/DirectX/DirectXTargetMachine.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "DirectX.h"
2626
#include "DirectXSubtarget.h"
2727
#include "DirectXTargetTransformInfo.h"
28+
#include "LegalizeI8Pass.h"
2829
#include "TargetInfo/DirectXTargetInfo.h"
2930
#include "llvm/CodeGen/MachineModuleInfo.h"
3031
#include "llvm/CodeGen/Passes.h"
@@ -52,6 +53,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTarget() {
5253
initializeDXILDataScalarizationLegacyPass(*PR);
5354
initializeDXILFlattenArraysLegacyPass(*PR);
5455
initializeScalarizerLegacyPassPass(*PR);
56+
initializeLegalizeI8LegacyPass(*PR);
5557
initializeDXILPrepareModulePass(*PR);
5658
initializeEmbedDXILPassPass(*PR);
5759
initializeWriteDXILPassPass(*PR);
@@ -100,6 +102,7 @@ class DirectXPassConfig : public TargetPassConfig {
100102
DxilScalarOptions.ScalarizeLoadStore = true;
101103
addPass(createScalarizerPass(DxilScalarOptions));
102104
addPass(createDXILTranslateMetadataLegacyPass());
105+
addPass(createLegalizeI8LegacyPass());
103106
addPass(createDXILOpLoweringLegacyPass());
104107
addPass(createDXILPrepareModulePass());
105108
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//===- LegalizeI8Pass.cpp - A pass that reverts i8 conversions-*- C++ ---*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===---------------------------------------------------------------------===//
8+
//===---------------------------------------------------------------------===//
9+
///
10+
/// \file This file contains a pass to remove i8 truncations.
11+
///
12+
//===----------------------------------------------------------------------===//
13+
#include "DirectX.h"
14+
#include "LegalizeI8Pass.h"
15+
#include "llvm/IR/Function.h"
16+
#include "llvm/IR/IRBuilder.h"
17+
#include "llvm/IR/InstIterator.h"
18+
#include "llvm/IR/Instruction.h"
19+
#include "llvm/Pass.h"
20+
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
21+
#include <map>
22+
#include <stack>
23+
24+
#define DEBUG_TYPE "dxil-legalize-i8"
25+
26+
using namespace llvm;
27+
namespace {
28+
29+
class LegalizeI8Legacy : public FunctionPass {
30+
31+
public:
32+
bool runOnFunction(Function &F) override;
33+
LegalizeI8Legacy() : FunctionPass(ID) {}
34+
35+
static char ID; // Pass identification.
36+
};
37+
} // namespace
38+
39+
static bool fixI8TruncUseChain(Function &F) {
40+
std::stack<Instruction*> ToRemove;
41+
std::map<Value*, Value*> ReplacedValues;
42+
43+
for (auto &I : instructions(F)) {
44+
if (auto *Trunc = dyn_cast<TruncInst>(&I)) {
45+
if (Trunc->getDestTy()->isIntegerTy(8)) {
46+
ReplacedValues[Trunc] = Trunc->getOperand(0);
47+
ToRemove.push(Trunc);
48+
}
49+
} else if (I.getType()->isIntegerTy(8)) {
50+
IRBuilder<> Builder(&I);
51+
52+
std::vector<Value*> NewOperands;
53+
Type* InstrType = nullptr;
54+
for (unsigned OpIdx = 0; OpIdx < I.getNumOperands(); ++OpIdx) {
55+
Value *Op = I.getOperand(OpIdx);
56+
if (ReplacedValues.count(Op)) {
57+
InstrType = ReplacedValues[Op]->getType();
58+
NewOperands.push_back(ReplacedValues[Op]);
59+
}
60+
else if (auto *Imm = dyn_cast<ConstantInt>(Op)) {
61+
APInt Value = Imm->getValue();
62+
unsigned NewBitWidth = InstrType->getIntegerBitWidth();
63+
// Note: options here are sext or sextOrTrunc.
64+
// Since i8 isn't suppport we assume new values
65+
// will always have a higher bitness.
66+
APInt NewValue = Value.sext(NewBitWidth);
67+
NewOperands.push_back(ConstantInt::get(InstrType, NewValue));
68+
} else {
69+
assert(!Op->getType()->isIntegerTy(8));
70+
NewOperands.push_back(Op);
71+
}
72+
73+
}
74+
75+
Value *NewInst = nullptr;
76+
if (auto *BO = dyn_cast<BinaryOperator>(&I))
77+
NewInst = Builder.CreateBinOp(BO->getOpcode(), NewOperands[0], NewOperands[1]);
78+
else if (auto *Cmp = dyn_cast<CmpInst>(&I))
79+
NewInst = Builder.CreateCmp(Cmp->getPredicate(), NewOperands[0], NewOperands[1]);
80+
else if (auto *Cast = dyn_cast<CastInst>(&I))
81+
NewInst = Builder.CreateCast(Cast->getOpcode(), NewOperands[0], Cast->getDestTy());
82+
else if (auto *UnaryOp = dyn_cast<UnaryOperator>(&I))
83+
NewInst = Builder.CreateUnOp(UnaryOp->getOpcode(), NewOperands[0]);
84+
85+
if (NewInst) {
86+
ReplacedValues[&I] = NewInst;
87+
ToRemove.push(&I);
88+
}
89+
} else if (auto *Sext = dyn_cast<SExtInst>(&I)) {
90+
if (Sext->getSrcTy()->isIntegerTy(8)) {
91+
ToRemove.push(Sext);
92+
Sext->replaceAllUsesWith(ReplacedValues[Sext->getOperand(0)]);
93+
}
94+
}
95+
}
96+
97+
while (!ToRemove.empty()) {
98+
Instruction *I = ToRemove.top();
99+
I->eraseFromParent();
100+
ToRemove.pop();
101+
}
102+
103+
return true;
104+
}
105+
106+
PreservedAnalyses LegalizeI8Pass::run(Function &F, FunctionAnalysisManager &FAM) {
107+
bool MadeChanges = fixI8TruncUseChain(F);
108+
if (!MadeChanges)
109+
return PreservedAnalyses::all();
110+
PreservedAnalyses PA;
111+
return PA;
112+
}
113+
114+
bool LegalizeI8Legacy::runOnFunction(Function &F) {
115+
return fixI8TruncUseChain(F);
116+
}
117+
118+
char LegalizeI8Legacy::ID = 0;
119+
120+
INITIALIZE_PASS_BEGIN(LegalizeI8Legacy, DEBUG_TYPE,
121+
"DXIL I8 Legalizer", false, false)
122+
INITIALIZE_PASS_END(LegalizeI8Legacy, DEBUG_TYPE, "DXIL I8 Legalizer",
123+
false, false)
124+
125+
FunctionPass *llvm::createLegalizeI8LegacyPass() {
126+
return new LegalizeI8Legacy();
127+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===- LegalizeI8Pass.h - A pass that reverts i8 conversions-*- C++ -----*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===---------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_TARGET_DIRECTX_LEGALIZEI8_H
10+
#define LLVM_TARGET_DIRECTX_LEGALIZEI8_H
11+
12+
#include "llvm/IR/PassManager.h"
13+
14+
namespace llvm {
15+
16+
/// A pass that transforms multidimensional arrays into one-dimensional arrays.
17+
class LegalizeI8Pass : public PassInfoMixin<LegalizeI8Pass> {
18+
public:
19+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
20+
};
21+
} // namespace llvm
22+
23+
#endif // LLVM_TARGET_DIRECTX_LEGALIZEI8_H
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; RUN: opt -S -passes='dxil-legalize-i8' -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
2+
3+
define i32 @i8trunc(float %0) #0 {
4+
; CHECK-NOT: %4 = trunc nsw i32 %3 to i8
5+
; CHECK: add i32
6+
; CHECK: srem i32
7+
; CHECK-NOT: %7 = sext i8 %6 to i32
8+
9+
%2 = fptosi float %0 to i32
10+
%3 = srem i32 %2, 8
11+
%4 = trunc nsw i32 %3 to i8
12+
%5 = add nsw i8 %4, 1
13+
%6 = srem i8 %5, 8
14+
%7 = sext i8 %6 to i32
15+
ret i32 %7
16+
}

0 commit comments

Comments
 (0)