Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- InstCombineAtomicRMW.cpp -------------------------------------------===//
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
// This file implements the visit functions for atomic rmw instructions.
10
//
11
//===----------------------------------------------------------------------===//
12
#include "InstCombineInternal.h"
13
#include "llvm/IR/Instructions.h"
14
15
using namespace llvm;
16
17
namespace {
18
/// Return true if and only if the given instruction does not modify the memory
19
/// location referenced.  Note that an idemptent atomicrmw may still have
20
/// ordering effects on nearby instructions, or be volatile.
21
/// TODO: Common w/ the version in AtomicExpandPass, and change the term used.
22
/// Idemptotent is confusing in this context.
23
230k
bool isIdempotentRMW(AtomicRMWInst& RMWI) {
24
230k
  if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand()))
25
11
    switch(RMWI.getOperation()) {
26
11
    case AtomicRMWInst::FAdd: // -0.0
27
5
      return CF->isZero() && CF->isNegative();
28
11
    case AtomicRMWInst::FSub: // +0.0
29
2
      return CF->isZero() && !CF->isNegative();
30
11
    default:
31
4
      return false;
32
230k
    };
33
230k
  
34
230k
  auto C = dyn_cast<ConstantInt>(RMWI.getValOperand());
35
230k
  if(!C)
36
83.9k
    return false;
37
146k
38
146k
  switch(RMWI.getOperation()) {
39
146k
    case AtomicRMWInst::Add:
40
59.6k
    case AtomicRMWInst::Sub:
41
59.6k
    case AtomicRMWInst::Or:
42
59.6k
    case AtomicRMWInst::Xor:
43
59.6k
      return C->isZero();
44
59.6k
    case AtomicRMWInst::And:
45
1
      return C->isMinusOne();
46
59.6k
    case AtomicRMWInst::Min:
47
1
      return C->isMaxValue(true);
48
59.6k
    case AtomicRMWInst::Max:
49
1
      return C->isMinValue(true);
50
59.6k
    case AtomicRMWInst::UMin:
51
1
      return C->isMaxValue(false);
52
59.6k
    case AtomicRMWInst::UMax:
53
1
      return C->isMinValue(false);
54
86.5k
    default:
55
86.5k
      return false;
56
146k
  }
57
146k
}
58
59
/// Return true if the given instruction always produces a value in memory
60
/// equivalent to its value operand.
61
230k
bool isSaturating(AtomicRMWInst& RMWI) {
62
230k
  if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand()))
63
15
    switch(RMWI.getOperation()) {
64
15
    case AtomicRMWInst::FAdd:
65
10
    case AtomicRMWInst::FSub:
66
10
      return CF->isNaN();
67
10
    default:
68
5
      return false;
69
230k
    };
70
230k
71
230k
  auto C = dyn_cast<ConstantInt>(RMWI.getValOperand());
72
230k
  if(!C)
73
83.9k
    return false;
74
146k
75
146k
  switch(RMWI.getOperation()) {
76
146k
  default:
77
59.6k
    return false;
78
146k
  case AtomicRMWInst::Xchg:
79
86.5k
    return true;
80
146k
  case AtomicRMWInst::Or:
81
18
    return C->isAllOnesValue();
82
146k
  case AtomicRMWInst::And:
83
2
    return C->isZero();
84
146k
  case AtomicRMWInst::Min:
85
2
    return C->isMinValue(true);
86
146k
  case AtomicRMWInst::Max:
87
2
    return C->isMaxValue(true);
88
146k
  case AtomicRMWInst::UMin:
89
2
    return C->isMinValue(false);
90
146k
  case AtomicRMWInst::UMax:
91
2
    return C->isMaxValue(false);
92
0
  };
93
0
}
94
}
95
96
231k
Instruction *InstCombiner::visitAtomicRMWInst(AtomicRMWInst &RMWI) {
97
231k
98
231k
  // Volatile RMWs perform a load and a store, we cannot replace this by just a
99
231k
  // load or just a store. We chose not to canonicalize out of general paranoia
100
231k
  // about user expectations around volatile. 
101
231k
  if (RMWI.isVolatile())
102
1.71k
    return nullptr;
103
230k
104
230k
  // Any atomicrmw op which produces a known result in memory can be
105
230k
  // replaced w/an atomicrmw xchg.
106
230k
  if (isSaturating(RMWI) &&
107
230k
      
RMWI.getOperation() != AtomicRMWInst::Xchg86.5k
) {
108
10
    RMWI.setOperation(AtomicRMWInst::Xchg);
109
10
    return &RMWI;
110
10
  }
111
230k
112
230k
  AtomicOrdering Ordering = RMWI.getOrdering();
113
230k
  assert(Ordering != AtomicOrdering::NotAtomic &&
114
230k
         Ordering != AtomicOrdering::Unordered &&
115
230k
         "AtomicRMWs don't make sense with Unordered or NotAtomic");
116
230k
117
230k
  // Any atomicrmw xchg with no uses can be converted to a atomic store if the
118
230k
  // ordering is compatible. 
119
230k
  if (RMWI.getOperation() == AtomicRMWInst::Xchg &&
120
230k
      
RMWI.use_empty()90.7k
) {
121
6
    if (Ordering != AtomicOrdering::Release &&
122
6
        
Ordering != AtomicOrdering::Monotonic5
)
123
1
      return nullptr;
124
5
    auto *SI = new StoreInst(RMWI.getValOperand(),
125
5
                             RMWI.getPointerOperand(), &RMWI);
126
5
    SI->setAtomic(Ordering, RMWI.getSyncScopeID());
127
5
    SI->setAlignment(DL.getABITypeAlignment(RMWI.getType()));
128
5
    return eraseInstFromFunction(RMWI);
129
5
  }
130
230k
  
131
230k
  if (!isIdempotentRMW(RMWI))
132
230k
    return nullptr;
133
35
134
35
  // We chose to canonicalize all idempotent operations to an single
135
35
  // operation code and constant.  This makes it easier for the rest of the
136
35
  // optimizer to match easily.  The choices of or w/0 and fadd w/-0.0 are
137
35
  // arbitrary. 
138
35
  if (RMWI.getType()->isIntegerTy() &&
139
35
      
RMWI.getOperation() != AtomicRMWInst::Or28
) {
140
12
    RMWI.setOperation(AtomicRMWInst::Or);
141
12
    RMWI.setOperand(1, ConstantInt::get(RMWI.getType(), 0));
142
12
    return &RMWI;
143
23
  } else if (RMWI.getType()->isFloatingPointTy() &&
144
23
             
RMWI.getOperation() != AtomicRMWInst::FAdd7
) {
145
2
    RMWI.setOperation(AtomicRMWInst::FAdd);
146
2
    RMWI.setOperand(1, ConstantFP::getNegativeZero(RMWI.getType()));
147
2
    return &RMWI;
148
2
  }
149
21
150
21
  // Check if the required ordering is compatible with an atomic load.
151
21
  if (Ordering != AtomicOrdering::Acquire &&
152
21
      
Ordering != AtomicOrdering::Monotonic20
)
153
9
    return nullptr;
154
12
  
155
12
  LoadInst *Load = new LoadInst(RMWI.getType(), RMWI.getPointerOperand());
156
12
  Load->setAtomic(Ordering, RMWI.getSyncScopeID());
157
12
  Load->setAlignment(DL.getABITypeAlignment(RMWI.getType()));
158
12
  return Load;
159
12
}