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