Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/Hexagon/HexagonOptimizeSZextends.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- HexagonOptimizeSZextends.cpp - Remove unnecessary argument extends -===//
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
// Pass that removes sign extends for function parameters. These parameters
10
// are already sign extended by the caller per Hexagon's ABI
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "llvm/CodeGen/StackProtector.h"
15
#include "llvm/IR/Function.h"
16
#include "llvm/IR/Instructions.h"
17
#include "llvm/IR/IntrinsicInst.h"
18
#include "llvm/Pass.h"
19
#include "llvm/Transforms/Scalar.h"
20
21
#include "Hexagon.h"
22
23
using namespace llvm;
24
25
namespace llvm {
26
  FunctionPass *createHexagonOptimizeSZextends();
27
  void initializeHexagonOptimizeSZextendsPass(PassRegistry&);
28
}
29
30
namespace {
31
  struct HexagonOptimizeSZextends : public FunctionPass {
32
  public:
33
    static char ID;
34
862
    HexagonOptimizeSZextends() : FunctionPass(ID) {
35
862
      initializeHexagonOptimizeSZextendsPass(*PassRegistry::getPassRegistry());
36
862
    }
37
    bool runOnFunction(Function &F) override;
38
39
3.36k
    StringRef getPassName() const override { return "Remove sign extends"; }
40
41
855
    void getAnalysisUsage(AnalysisUsage &AU) const override {
42
855
      AU.addPreserved<StackProtector>();
43
855
      FunctionPass::getAnalysisUsage(AU);
44
855
    }
45
46
    bool intrinsicAlreadySextended(Intrinsic::ID IntID);
47
  };
48
}
49
50
char HexagonOptimizeSZextends::ID = 0;
51
52
INITIALIZE_PASS(HexagonOptimizeSZextends, "reargs",
53
                "Remove Sign and Zero Extends for Args", false, false)
54
55
19
bool HexagonOptimizeSZextends::intrinsicAlreadySextended(Intrinsic::ID IntID) {
56
19
  switch(IntID) {
57
19
    case llvm::Intrinsic::hexagon_A2_addh_l16_sat_ll:
58
3
      return true;
59
19
    default:
60
16
      break;
61
16
  }
62
16
  return false;
63
16
}
64
65
3.36k
bool HexagonOptimizeSZextends::runOnFunction(Function &F) {
66
3.36k
  if (skipFunction(F))
67
10
    return false;
68
3.35k
69
3.35k
  unsigned Idx = 1;
70
3.35k
  // Try to optimize sign extends in formal parameters. It's relying on
71
3.35k
  // callee already sign extending the values. I'm not sure if our ABI
72
3.35k
  // requires callee to sign extend though.
73
5.65k
  for (auto &Arg : F.args()) {
74
5.65k
    if (F.getAttributes().hasAttribute(Idx, Attribute::SExt)) {
75
97
      if (!isa<PointerType>(Arg.getType())) {
76
200
        for (auto UI = Arg.use_begin(); UI != Arg.use_end();) {
77
103
          if (isa<SExtInst>(*UI)) {
78
0
            Instruction* Use = cast<Instruction>(*UI);
79
0
            SExtInst* SI = new SExtInst(&Arg, Use->getType());
80
0
            assert (EVT::getEVT(SI->getType()) ==
81
0
                    (EVT::getEVT(Use->getType())));
82
0
            ++UI;
83
0
            Use->replaceAllUsesWith(SI);
84
0
            Instruction* First = &F.getEntryBlock().front();
85
0
            SI->insertBefore(First);
86
0
            Use->eraseFromParent();
87
103
          } else {
88
103
            ++UI;
89
103
          }
90
103
        }
91
97
      }
92
97
    }
93
5.65k
    ++Idx;
94
5.65k
  }
95
3.35k
96
3.35k
  // Try to remove redundant sext operations on Hexagon. The hardware
97
3.35k
  // already sign extends many 16 bit intrinsic operations to 32 bits.
98
3.35k
  // For example:
99
3.35k
  // %34 = tail call i32 @llvm.hexagon.A2.addh.l16.sat.ll(i32 %x, i32 %y)
100
3.35k
  // %sext233 = shl i32 %34, 16
101
3.35k
  // %conv52 = ashr exact i32 %sext233, 16
102
4.94k
  for (auto &B : F) {
103
26.2k
    for (auto &I : B) {
104
26.2k
      // Look for arithmetic shift right by 16.
105
26.2k
      BinaryOperator *Ashr = dyn_cast<BinaryOperator>(&I);
106
26.2k
      if (!(Ashr && 
Ashr->getOpcode() == Instruction::AShr3.68k
))
107
26.1k
        continue;
108
141
      Value *AshrOp1 = Ashr->getOperand(1);
109
141
      ConstantInt *C = dyn_cast<ConstantInt>(AshrOp1);
110
141
      // Right shifted by 16.
111
141
      if (!(C && 
C->getSExtValue() == 16115
))
112
95
        continue;
113
46
114
46
      // The first operand of Ashr comes from logical shift left.
115
46
      Instruction *Shl = dyn_cast<Instruction>(Ashr->getOperand(0));
116
46
      if (!(Shl && 
Shl->getOpcode() == Instruction::Shl44
))
117
15
        continue;
118
31
      Value *Intr = Shl->getOperand(0);
119
31
      Value *ShlOp1 = Shl->getOperand(1);
120
31
      C = dyn_cast<ConstantInt>(ShlOp1);
121
31
      // Left shifted by 16.
122
31
      if (!(C && C->getSExtValue() == 16))
123
2
        continue;
124
29
125
29
      // The first operand of Shl comes from an intrinsic.
126
29
      if (IntrinsicInst *I = dyn_cast<IntrinsicInst>(Intr)) {
127
19
        if (!intrinsicAlreadySextended(I->getIntrinsicID()))
128
16
          continue;
129
3
        // All is well. Replace all uses of AShr with I.
130
3
        for (auto UI = Ashr->user_begin(), UE = Ashr->user_end();
131
10
             UI != UE; 
++UI7
) {
132
7
          const Use &TheUse = UI.getUse();
133
7
          if (Instruction *J = dyn_cast<Instruction>(TheUse.getUser())) {
134
7
            J->replaceUsesOfWith(Ashr, I);
135
7
          }
136
7
        }
137
3
      }
138
29
    }
139
4.94k
  }
140
3.35k
141
3.35k
  return true;
142
3.35k
}
143
144
145
862
FunctionPass *llvm::createHexagonOptimizeSZextends() {
146
862
  return new HexagonOptimizeSZextends();
147
862
}