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
+ }
0 commit comments