1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 11:13:28 +01:00

[Attributor] Manifest simplified (return) values properly

If we simplify a function return value we have to modify the return
instructions.
This commit is contained in:
Johannes Doerfert 2020-02-14 20:11:22 -06:00
parent e769d72982
commit 5ca603fd18
3 changed files with 125 additions and 13 deletions

View File

@ -4484,11 +4484,13 @@ struct AAValueSimplifyImpl : AAValueSimplify {
Value &QueryingValueSimplifiedUnwrapped =
*QueryingValueSimplified.getValue();
if (isa<UndefValue>(QueryingValueSimplifiedUnwrapped))
return true;
if (AccumulatedSimplifiedValue.hasValue())
if (AccumulatedSimplifiedValue.hasValue() &&
!isa<UndefValue>(AccumulatedSimplifiedValue.getValue()) &&
!isa<UndefValue>(QueryingValueSimplifiedUnwrapped))
return AccumulatedSimplifiedValue == QueryingValueSimplified;
if (AccumulatedSimplifiedValue.hasValue() &&
isa<UndefValue>(QueryingValueSimplifiedUnwrapped))
return true;
LLVM_DEBUG(dbgs() << "[ValueSimplify] " << QueryingValue
<< " is assumed to be "
@ -4522,13 +4524,16 @@ struct AAValueSimplifyImpl : AAValueSimplify {
ChangeStatus manifest(Attributor &A) override {
ChangeStatus Changed = ChangeStatus::UNCHANGED;
if (!SimplifiedAssociatedValue.hasValue() ||
if (SimplifiedAssociatedValue.hasValue() &&
!SimplifiedAssociatedValue.getValue())
return Changed;
if (auto *C = dyn_cast<Constant>(SimplifiedAssociatedValue.getValue())) {
Value &V = getAssociatedValue();
auto *C = SimplifiedAssociatedValue.hasValue()
? dyn_cast<Constant>(SimplifiedAssociatedValue.getValue())
: UndefValue::get(V.getType());
if (C) {
// We can replace the AssociatedValue with the constant.
Value &V = getAssociatedValue();
if (!V.user_empty() && &V != C && V.getType() == C->getType()) {
LLVM_DEBUG(dbgs() << "[ValueSimplify] " << V << " -> " << *C
<< " :: " << *this << "\n");
@ -4638,6 +4643,44 @@ struct AAValueSimplifyReturned : AAValueSimplifyImpl {
? ChangeStatus::UNCHANGED
: ChangeStatus ::CHANGED;
}
ChangeStatus manifest(Attributor &A) override {
ChangeStatus Changed = ChangeStatus::UNCHANGED;
if (SimplifiedAssociatedValue.hasValue() &&
!SimplifiedAssociatedValue.getValue())
return Changed;
Value &V = getAssociatedValue();
auto *C = SimplifiedAssociatedValue.hasValue()
? dyn_cast<Constant>(SimplifiedAssociatedValue.getValue())
: UndefValue::get(V.getType());
if (C) {
auto PredForReturned =
[&](Value &V, const SmallSetVector<ReturnInst *, 4> &RetInsts) {
// We can replace the AssociatedValue with the constant.
if (&V == C || V.getType() != C->getType() || isa<UndefValue>(V))
return true;
if (auto *CI = dyn_cast<CallInst>(&V))
if (CI->isMustTailCall())
return true;
for (ReturnInst *RI : RetInsts) {
if (RI->getFunction() != getAnchorScope())
continue;
LLVM_DEBUG(dbgs() << "[ValueSimplify] " << V << " -> " << *C
<< " in " << *RI << " :: " << *this << "\n");
if (A.changeUseAfterManifest(RI->getOperandUse(0), *C))
Changed = ChangeStatus::CHANGED;
}
return true;
};
A.checkForAllReturnedValuesAndReturnInsts(PredForReturned, *this);
}
return Changed | AAValueSimplify::manifest(A);
}
/// See AbstractAttribute::trackStatistics()
void trackStatistics() const override {
STATS_DECLTRACK_FNRET_ATTR(value_simplify)
@ -4728,7 +4771,7 @@ struct AAValueSimplifyCallSiteReturned : AAValueSimplifyReturned {
if (auto *CI = dyn_cast<CallInst>(&getAssociatedValue()))
if (CI->isMustTailCall())
return ChangeStatus::UNCHANGED;
return AAValueSimplifyReturned::manifest(A);
return AAValueSimplifyImpl::manifest(A);
}
void trackStatistics() const override {

View File

@ -1,16 +1,13 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s
; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; FIXME: Use the undef and do not pessimise the result because of it (no !range)
define i64 @fn2() {
; CHECK-LABEL: define {{[^@]+}}@fn2()
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CONV:%.*]] = sext i32 undef to i64
; CHECK-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]]
; CHECK-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]]) #1, !range !0
; CHECK-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #1, !range !0
; CHECK-NEXT: ret i64 [[CALL2]]
;
entry:
@ -36,6 +33,19 @@ entry:
ret i64 %call2
}
define i64 @fn2c() {
; CHECK-LABEL: define {{[^@]+}}@fn2c()
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 42) #1, !range !0
; CHECK-NEXT: ret i64 [[CALL2]]
;
entry:
%conv = sext i32 undef to i64
%add = add i64 42, %conv
%call2 = call i64 @fn1(i64 %add)
ret i64 %call2
}
define internal i64 @fn1(i64 %p1) {
; CHECK-LABEL: define {{[^@]+}}@fn1
; CHECK-SAME: (i64 returned [[P1:%.*]])

View File

@ -324,4 +324,63 @@ for.end:
ret void
}
; Check we merge undef and a constant properly.
; FIXME fold the addition and return the constant.
define i8 @caller0() {
; CHECK-LABEL: define {{[^@]+}}@caller0()
; CHECK-NEXT: [[C:%.*]] = call i8 @callee()
; CHECK-NEXT: ret i8 [[C]]
;
%c = call i8 @callee(i8 undef)
ret i8 %c
}
define i8 @caller1() {
; CHECK-LABEL: define {{[^@]+}}@caller1()
; CHECK-NEXT: [[C:%.*]] = call i8 @callee()
; CHECK-NEXT: ret i8 [[C]]
;
%c = call i8 @callee(i8 undef)
ret i8 %c
}
define i8 @caller2() {
; CHECK-LABEL: define {{[^@]+}}@caller2()
; CHECK-NEXT: [[C:%.*]] = call i8 @callee()
; CHECK-NEXT: ret i8 [[C]]
;
%c = call i8 @callee(i8 undef)
ret i8 %c
}
define i8 @caller_middle() {
; CHECK-LABEL: define {{[^@]+}}@caller_middle()
; CHECK-NEXT: [[C:%.*]] = call i8 @callee()
; CHECK-NEXT: ret i8 [[C]]
;
%c = call i8 @callee(i8 42)
ret i8 %c
}
define i8 @caller3() {
; CHECK-LABEL: define {{[^@]+}}@caller3()
; CHECK-NEXT: [[C:%.*]] = call i8 @callee()
; CHECK-NEXT: ret i8 [[C]]
;
%c = call i8 @callee(i8 undef)
ret i8 %c
}
define i8 @caller4() {
; CHECK-LABEL: define {{[^@]+}}@caller4()
; CHECK-NEXT: [[C:%.*]] = call i8 @callee()
; CHECK-NEXT: ret i8 [[C]]
;
%c = call i8 @callee(i8 undef)
ret i8 %c
}
define internal i8 @callee(i8 %a) {
; CHECK-LABEL: define {{[^@]+}}@callee()
; CHECK-NEXT: [[C:%.*]] = add i8 42, 7
; CHECK-NEXT: ret i8 [[C]]
;
%c = add i8 %a, 7
ret i8 %c
}
; UTC_ARGS: --disable