[InstCombine] Negator: cache negation results (PR46362)

It is possible that we can try to negate the same value multiple times.
For example, PHI nodes may happen to have multiple incoming values
(all of which must be the same value) for the same incoming basic block.
It may happen that we try to negate such a PHI node, and succeed,
and that might result in having now-different incoming values..

To avoid that, and in general to reduce the amount of duplicated
work we might be doing, let's introduce a cache where
we'll track results of negating each value.

The added test was previously failing -verify after -instcombine.

Fixes https://bugs.llvm.org/show_bug.cgi?id=46362
This commit is contained in:
Roman Lebedev 2020-06-17 21:37:19 +03:00
parent c4166f3d84
commit e3d8cb1e1d
No known key found for this signature in database
GPG Key ID: 083C3EBB4A1689E0
3 changed files with 59 additions and 2 deletions

View File

@ -16,6 +16,7 @@
#define LLVM_LIB_TRANSFORMS_INSTCOMBINE_INSTCOMBINEINTERNAL_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/InstructionSimplify.h"
@ -1040,6 +1041,8 @@ class Negator final {
const bool IsTrulyNegation;
SmallDenseMap<Value *, Value *> NegationsCache;
Negator(LLVMContext &C, const DataLayout &DL, AssumptionCache &AC,
const DominatorTree &DT, bool IsTrulyNegation);

View File

@ -14,6 +14,7 @@
#include "InstCombineInternal.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
@ -43,6 +44,7 @@
#include "llvm/Support/raw_ostream.h"
#include <functional>
#include <tuple>
#include <type_traits>
#include <utility>
namespace llvm {
@ -68,6 +70,8 @@ STATISTIC(NegatorTimesDepthLimitReached,
STATISTIC(
NegatorNumValuesVisited,
"Negator: Total number of values visited during attempts to sink negation");
STATISTIC(NegatorNumNegationsFoundInCache,
"Negator: How many negations did we retrieve/reuse from cache");
STATISTIC(NegatorMaxTotalValuesVisited,
"Negator: Maximal number of values ever visited while attempting to "
"sink negation");
@ -384,8 +388,19 @@ LLVM_NODISCARD Value *Negator::negate(Value *V, unsigned Depth) {
++NumValuesVisitedInThisNegator;
#endif
// Try negating the value.
return visitImpl(V, Depth);
// Did we already try to negate this value?
auto NegationsCacheIterator = NegationsCache.find(V);
if (NegationsCacheIterator != NegationsCache.end()) {
++NegatorNumNegationsFoundInCache;
return NegationsCacheIterator->second;
}
// No luck. Try negating it for real.
Value *NegatedV = visitImpl(V, Depth);
// And cache the result for the future.
NegationsCache[V] = NegatedV;
return NegatedV;
}
LLVM_NODISCARD Optional<Negator::Result> Negator::run(Value *Root) {

View File

@ -4,6 +4,7 @@
declare void @use4(i4)
declare void @use8(i8)
declare void @use_v2i4(<2 x i4>)
declare i1 @use32gen1(i32)
; Constant can be freely negated.
define i8 @t0(i8 %x) {
@ -349,6 +350,44 @@ end:
%n = sub i8 0, %r
ret i8 %n
}
define void @phi_with_duplicate_incoming_basic_blocks(i32 %x, i32 %y, i1 %should_lookup, i32 %z) {
; CHECK-LABEL: @phi_with_duplicate_incoming_basic_blocks(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X_INC_NEG:%.*]] = xor i32 [[X:%.*]], -1
; CHECK-NEXT: br i1 [[SHOULD_LOOKUP:%.*]], label [[LOOKUP:%.*]], label [[LOOP:%.*]]
; CHECK: lookup:
; CHECK-NEXT: [[TO_LOOKUP:%.*]] = phi i32 [ [[Y:%.*]], [[ENTRY:%.*]] ], [ [[METAVAL_NEG:%.*]], [[LOOP]] ]
; CHECK-NEXT: switch i32 [[TO_LOOKUP]], label [[END:%.*]] [
; CHECK-NEXT: i32 0, label [[LOOP]]
; CHECK-NEXT: i32 42, label [[LOOP]]
; CHECK-NEXT: ]
; CHECK: loop:
; CHECK-NEXT: [[METAVAL_NEG]] = phi i32 [ [[X_INC_NEG]], [[LOOKUP]] ], [ [[X_INC_NEG]], [[LOOKUP]] ], [ -84, [[ENTRY]] ]
; CHECK-NEXT: [[REPEAT:%.*]] = call i1 @use32gen1(i32 [[METAVAL_NEG]])
; CHECK-NEXT: br i1 [[REPEAT]], label [[LOOKUP]], label [[END]]
; CHECK: end:
; CHECK-NEXT: ret void
;
entry:
%x_inc = add i32 %x, 1
br i1 %should_lookup, label %lookup, label %loop
lookup:
%to_lookup = phi i32 [ %y, %entry ], [ %negated_metaval, %loop ]
switch i32 %to_lookup, label %end [
i32 0, label %loop
i32 42, label %loop
]
loop:
%metaval = phi i32 [ %x_inc, %lookup ], [ %x_inc, %lookup ], [ 84, %entry ]
%negated_metaval = sub i32 0, %metaval
%repeat = call i1 @use32gen1(i32 %negated_metaval)
br i1 %repeat, label %lookup, label %end
end:
ret void
}
; truncation can be negated if it's operand can be negated
define i8 @t20(i8 %x, i16 %y) {