forked from OSchip/llvm-project
[Attributor] Add flag for undef value to the state of AAPotentialValues
Currently, an undef value is reduced to 0 when it is added to a set of potential values. This patch introduces a flag for under values. By this, for example, we can merge two states `{undef}`, `{1}` to `{1}` (because we can reduce the undef to 1). Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D85592
This commit is contained in:
parent
03141aa04a
commit
6c25eca614
|
@ -3368,9 +3368,10 @@ template <typename MemberTy, typename KeyInfo = DenseMapInfo<MemberTy>>
|
|||
struct PotentialValuesState : AbstractState {
|
||||
using SetTy = DenseSet<MemberTy, KeyInfo>;
|
||||
|
||||
PotentialValuesState() : IsValidState(true) {}
|
||||
PotentialValuesState() : IsValidState(true), UndefIsContained(false) {}
|
||||
|
||||
PotentialValuesState(bool IsValid) : IsValidState(IsValid) {}
|
||||
PotentialValuesState(bool IsValid)
|
||||
: IsValidState(IsValid), UndefIsContained(false) {}
|
||||
|
||||
/// See AbstractState::isValidState(...)
|
||||
bool isValidState() const override { return IsValidState.isValidState(); }
|
||||
|
@ -3399,11 +3400,19 @@ struct PotentialValuesState : AbstractState {
|
|||
return Set;
|
||||
}
|
||||
|
||||
/// Returns whether this state contains an undef value or not.
|
||||
bool undefIsContained() const {
|
||||
assert(isValidState() && "This flag shoud not be used when it is invalid!");
|
||||
return UndefIsContained;
|
||||
}
|
||||
|
||||
bool operator==(const PotentialValuesState &RHS) const {
|
||||
if (isValidState() != RHS.isValidState())
|
||||
return false;
|
||||
if (!isValidState() && !RHS.isValidState())
|
||||
return true;
|
||||
if (undefIsContained() != RHS.undefIsContained())
|
||||
return false;
|
||||
return Set == RHS.getAssumedSet();
|
||||
}
|
||||
|
||||
|
@ -3431,6 +3440,9 @@ struct PotentialValuesState : AbstractState {
|
|||
/// Union assumed set with assumed set of the passed state \p PVS.
|
||||
void unionAssumed(const PotentialValuesState &PVS) { unionWith(PVS); }
|
||||
|
||||
/// Union assumed set with an undef value.
|
||||
void unionAssumedWithUndef() { unionWithUndef(); }
|
||||
|
||||
/// "Clamp" this state with \p PVS.
|
||||
PotentialValuesState operator^=(const PotentialValuesState &PVS) {
|
||||
IsValidState ^= PVS.IsValidState;
|
||||
|
@ -3452,6 +3464,10 @@ private:
|
|||
indicatePessimisticFixpoint();
|
||||
}
|
||||
|
||||
/// If this state contains both undef and not undef, we can reduce
|
||||
/// undef to the not undef value.
|
||||
void reduceUndefValue() { UndefIsContained = UndefIsContained & Set.empty(); }
|
||||
|
||||
/// Insert an element into this set.
|
||||
void insert(const MemberTy &C) {
|
||||
if (!isValidState())
|
||||
|
@ -3472,9 +3488,17 @@ private:
|
|||
}
|
||||
for (const MemberTy &C : R.Set)
|
||||
Set.insert(C);
|
||||
UndefIsContained |= R.undefIsContained();
|
||||
reduceUndefValue();
|
||||
checkAndInvalidate();
|
||||
}
|
||||
|
||||
/// Take union with an undef value.
|
||||
void unionWithUndef() {
|
||||
UndefIsContained = true;
|
||||
reduceUndefValue();
|
||||
}
|
||||
|
||||
/// Take intersection with R.
|
||||
void intersectWith(const PotentialValuesState &R) {
|
||||
/// If R is a full set, do nothing.
|
||||
|
@ -3491,6 +3515,8 @@ private:
|
|||
IntersectSet.insert(C);
|
||||
}
|
||||
Set = IntersectSet;
|
||||
UndefIsContained &= R.undefIsContained();
|
||||
reduceUndefValue();
|
||||
}
|
||||
|
||||
/// A helper state which indicate whether this state is valid or not.
|
||||
|
@ -3498,6 +3524,9 @@ private:
|
|||
|
||||
/// Container for potential values
|
||||
SetTy Set;
|
||||
|
||||
/// Flag for undef value
|
||||
bool UndefIsContained;
|
||||
};
|
||||
|
||||
using PotentialConstantIntValuesState = PotentialValuesState<APInt>;
|
||||
|
@ -3544,8 +3573,12 @@ struct AAPotentialValues
|
|||
if (getAssumedSet().size() == 1)
|
||||
return cast<ConstantInt>(ConstantInt::get(getAssociatedValue().getType(),
|
||||
*(getAssumedSet().begin())));
|
||||
if (getAssumedSet().size() == 0)
|
||||
if (getAssumedSet().size() == 0) {
|
||||
if (undefIsContained())
|
||||
return cast<ConstantInt>(
|
||||
ConstantInt::get(getAssociatedValue().getType(), 0));
|
||||
return llvm::None;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -2165,9 +2165,12 @@ raw_ostream &llvm::operator<<(raw_ostream &OS,
|
|||
OS << "set-state(< {";
|
||||
if (!S.isValidState())
|
||||
OS << "full-set";
|
||||
else
|
||||
else {
|
||||
for (auto &it : S.getAssumedSet())
|
||||
OS << it << ", ";
|
||||
if (S.undefIsContained())
|
||||
OS << "undef ";
|
||||
}
|
||||
OS << "} >)";
|
||||
|
||||
return OS;
|
||||
|
|
|
@ -7353,10 +7353,7 @@ struct AAPotentialValuesFloating : AAPotentialValuesImpl {
|
|||
}
|
||||
|
||||
if (isa<UndefValue>(&V)) {
|
||||
// Collapse the undef state to 0.
|
||||
unionAssumed(
|
||||
APInt(/* numBits */ getAssociatedType()->getIntegerBitWidth(),
|
||||
/* val */ 0));
|
||||
unionAssumedWithUndef();
|
||||
indicateOptimisticFixpoint();
|
||||
return;
|
||||
}
|
||||
|
@ -7477,6 +7474,20 @@ struct AAPotentialValuesFloating : AAPotentialValuesImpl {
|
|||
}
|
||||
}
|
||||
|
||||
bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,
|
||||
const APInt &LHS, const APInt &RHS) {
|
||||
bool SkipOperation = false;
|
||||
bool Unsupported = false;
|
||||
APInt Result =
|
||||
calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);
|
||||
if (Unsupported)
|
||||
return false;
|
||||
// If SkipOperation is true, we can ignore this operand pair (L, R).
|
||||
if (!SkipOperation)
|
||||
unionAssumed(Result);
|
||||
return isValidState();
|
||||
}
|
||||
|
||||
ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {
|
||||
auto AssumedBefore = getAssumed();
|
||||
Value *LHS = ICI->getOperand(0);
|
||||
|
@ -7495,16 +7506,40 @@ struct AAPotentialValuesFloating : AAPotentialValuesImpl {
|
|||
const DenseSet<APInt> &LHSAAPVS = LHSAA.getAssumedSet();
|
||||
const DenseSet<APInt> &RHSAAPVS = RHSAA.getAssumedSet();
|
||||
|
||||
// TODO: Handle undef correctly.
|
||||
// TODO: make use of undef flag to limit potential values aggressively.
|
||||
bool MaybeTrue = false, MaybeFalse = false;
|
||||
for (const APInt &L : LHSAAPVS) {
|
||||
const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);
|
||||
if (LHSAA.undefIsContained() && RHSAA.undefIsContained()) {
|
||||
// The result of any comparison between undefs can be soundly replaced
|
||||
// with undef.
|
||||
unionAssumedWithUndef();
|
||||
} else if (LHSAA.undefIsContained()) {
|
||||
bool MaybeTrue = false, MaybeFalse = false;
|
||||
for (const APInt &R : RHSAAPVS) {
|
||||
bool CmpResult = calculateICmpInst(ICI, L, R);
|
||||
bool CmpResult = calculateICmpInst(ICI, Zero, R);
|
||||
MaybeTrue |= CmpResult;
|
||||
MaybeFalse |= !CmpResult;
|
||||
if (MaybeTrue & MaybeFalse)
|
||||
return indicatePessimisticFixpoint();
|
||||
}
|
||||
} else if (RHSAA.undefIsContained()) {
|
||||
for (const APInt &L : LHSAAPVS) {
|
||||
bool CmpResult = calculateICmpInst(ICI, L, Zero);
|
||||
MaybeTrue |= CmpResult;
|
||||
MaybeFalse |= !CmpResult;
|
||||
if (MaybeTrue & MaybeFalse)
|
||||
return indicatePessimisticFixpoint();
|
||||
}
|
||||
} else {
|
||||
for (const APInt &L : LHSAAPVS) {
|
||||
for (const APInt &R : RHSAAPVS) {
|
||||
bool CmpResult = calculateICmpInst(ICI, L, R);
|
||||
MaybeTrue |= CmpResult;
|
||||
MaybeFalse |= !CmpResult;
|
||||
if (MaybeTrue & MaybeFalse)
|
||||
return indicatePessimisticFixpoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (MaybeTrue)
|
||||
unionAssumed(APInt(/* numBits */ 1, /* val */ 1));
|
||||
|
@ -7530,8 +7565,13 @@ struct AAPotentialValuesFloating : AAPotentialValuesImpl {
|
|||
if (!RHSAA.isValidState())
|
||||
return indicatePessimisticFixpoint();
|
||||
|
||||
unionAssumed(LHSAA);
|
||||
unionAssumed(RHSAA);
|
||||
if (LHSAA.undefIsContained() && RHSAA.undefIsContained())
|
||||
// select i1 *, undef , undef => undef
|
||||
unionAssumedWithUndef();
|
||||
else {
|
||||
unionAssumed(LHSAA);
|
||||
unionAssumed(RHSAA);
|
||||
}
|
||||
return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
|
||||
: ChangeStatus::CHANGED;
|
||||
}
|
||||
|
@ -7547,11 +7587,14 @@ struct AAPotentialValuesFloating : AAPotentialValuesImpl {
|
|||
if (!SrcAA.isValidState())
|
||||
return indicatePessimisticFixpoint();
|
||||
const DenseSet<APInt> &SrcAAPVS = SrcAA.getAssumedSet();
|
||||
for (const APInt &S : SrcAAPVS) {
|
||||
APInt T = calculateCastInst(CI, S, ResultBitWidth);
|
||||
unionAssumed(T);
|
||||
if (SrcAA.undefIsContained())
|
||||
unionAssumedWithUndef();
|
||||
else {
|
||||
for (const APInt &S : SrcAAPVS) {
|
||||
APInt T = calculateCastInst(CI, S, ResultBitWidth);
|
||||
unionAssumed(T);
|
||||
}
|
||||
}
|
||||
// TODO: Handle undef correctly.
|
||||
return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
|
||||
: ChangeStatus::CHANGED;
|
||||
}
|
||||
|
@ -7573,19 +7616,28 @@ struct AAPotentialValuesFloating : AAPotentialValuesImpl {
|
|||
|
||||
const DenseSet<APInt> &LHSAAPVS = LHSAA.getAssumedSet();
|
||||
const DenseSet<APInt> &RHSAAPVS = RHSAA.getAssumedSet();
|
||||
const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);
|
||||
|
||||
// TODO: Handle undef correctly
|
||||
for (const APInt &L : LHSAAPVS) {
|
||||
// TODO: make use of undef flag to limit potential values aggressively.
|
||||
if (LHSAA.undefIsContained() && RHSAA.undefIsContained()) {
|
||||
if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
|
||||
return indicatePessimisticFixpoint();
|
||||
} else if (LHSAA.undefIsContained()) {
|
||||
for (const APInt &R : RHSAAPVS) {
|
||||
bool SkipOperation = false;
|
||||
bool Unsupported = false;
|
||||
APInt Result =
|
||||
calculateBinaryOperator(BinOp, L, R, SkipOperation, Unsupported);
|
||||
if (Unsupported)
|
||||
if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
|
||||
return indicatePessimisticFixpoint();
|
||||
// If SkipOperation is true, we can ignore this operand pair (L, R).
|
||||
if (!SkipOperation)
|
||||
unionAssumed(Result);
|
||||
}
|
||||
} else if (RHSAA.undefIsContained()) {
|
||||
for (const APInt &L : LHSAAPVS) {
|
||||
if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
|
||||
return indicatePessimisticFixpoint();
|
||||
}
|
||||
} else {
|
||||
for (const APInt &L : LHSAAPVS) {
|
||||
for (const APInt &R : RHSAAPVS) {
|
||||
if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
|
||||
return indicatePessimisticFixpoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
|
||||
|
@ -7600,7 +7652,10 @@ struct AAPotentialValuesFloating : AAPotentialValuesImpl {
|
|||
*this, IRPosition::value(*IncomingValue));
|
||||
if (!PotentialValuesAA.isValidState())
|
||||
return indicatePessimisticFixpoint();
|
||||
unionAssumed(PotentialValuesAA.getAssumed());
|
||||
if (PotentialValuesAA.undefIsContained())
|
||||
unionAssumedWithUndef();
|
||||
else
|
||||
unionAssumed(PotentialValuesAA.getAssumed());
|
||||
}
|
||||
return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
|
||||
: ChangeStatus::CHANGED;
|
||||
|
@ -7688,10 +7743,7 @@ struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
|
|||
}
|
||||
|
||||
if (isa<UndefValue>(&V)) {
|
||||
// Collapse the undef state to 0.
|
||||
unionAssumed(
|
||||
APInt(/* numBits */ getAssociatedType()->getIntegerBitWidth(),
|
||||
/* val */ 0));
|
||||
unionAssumedWithUndef();
|
||||
indicateOptimisticFixpoint();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -493,20 +493,6 @@ end:
|
|||
; and returned value of @potential_test10 can be simplified to 0(false)
|
||||
|
||||
define internal i32 @may_return_undef(i32 %c) {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@may_return_undef
|
||||
; IS__TUNIT____-SAME: (i32 [[C:%.*]])
|
||||
; IS__TUNIT____-NEXT: switch i32 [[C]], label [[OTHERWISE:%.*]] [
|
||||
; IS__TUNIT____-NEXT: i32 1, label [[A:%.*]]
|
||||
; IS__TUNIT____-NEXT: i32 -1, label [[B:%.*]]
|
||||
; IS__TUNIT____-NEXT: ]
|
||||
; IS__TUNIT____: a:
|
||||
; IS__TUNIT____-NEXT: ret i32 1
|
||||
; IS__TUNIT____: b:
|
||||
; IS__TUNIT____-NEXT: ret i32 -1
|
||||
; IS__TUNIT____: otherwise:
|
||||
; IS__TUNIT____-NEXT: ret i32 undef
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@may_return_undef
|
||||
; IS__CGSCC____-SAME: (i32 [[C:%.*]])
|
||||
|
@ -532,19 +518,10 @@ otherwise:
|
|||
}
|
||||
|
||||
define i1 @potential_test10(i32 %c) {
|
||||
; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test10
|
||||
; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]])
|
||||
; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = call i32 @may_return_undef(i32 [[C]]) [[ATTR0]], [[RNG2:!range !.*]]
|
||||
; IS__TUNIT_OPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RET]], 0
|
||||
; IS__TUNIT_OPM-NEXT: ret i1 [[CMP]]
|
||||
;
|
||||
; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test10
|
||||
; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]])
|
||||
; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = call i32 @may_return_undef(i32 [[C]]) [[ATTR0]], [[RNG3:!range !.*]]
|
||||
; IS__TUNIT_NPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RET]], 0
|
||||
; IS__TUNIT_NPM-NEXT: ret i1 [[CMP]]
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test10
|
||||
; IS__TUNIT____-SAME: (i32 [[C:%.*]])
|
||||
; IS__TUNIT____-NEXT: ret i1 false
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@potential_test10
|
||||
|
@ -558,15 +535,350 @@ define i1 @potential_test10(i32 %c) {
|
|||
ret i1 %cmp
|
||||
}
|
||||
|
||||
define i32 @optimize_undef_1(i1 %c) {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@optimize_undef_1
|
||||
; IS__TUNIT____-SAME: (i1 [[C:%.*]])
|
||||
; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
||||
; IS__TUNIT____: t:
|
||||
; IS__TUNIT____-NEXT: ret i32 0
|
||||
; IS__TUNIT____: f:
|
||||
; IS__TUNIT____-NEXT: ret i32 1
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@optimize_undef_1
|
||||
; IS__CGSCC____-SAME: (i1 [[C:%.*]])
|
||||
; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
||||
; IS__CGSCC____: t:
|
||||
; IS__CGSCC____-NEXT: ret i32 0
|
||||
; IS__CGSCC____: f:
|
||||
; IS__CGSCC____-NEXT: ret i32 1
|
||||
;
|
||||
br i1 %c, label %t, label %f
|
||||
t:
|
||||
ret i32 0
|
||||
f:
|
||||
%undef = add i32 undef, 1
|
||||
ret i32 %undef
|
||||
}
|
||||
|
||||
define i32 @optimize_undef_2(i1 %c) {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@optimize_undef_2
|
||||
; IS__TUNIT____-SAME: (i1 [[C:%.*]])
|
||||
; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
||||
; IS__TUNIT____: t:
|
||||
; IS__TUNIT____-NEXT: ret i32 0
|
||||
; IS__TUNIT____: f:
|
||||
; IS__TUNIT____-NEXT: ret i32 -1
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@optimize_undef_2
|
||||
; IS__CGSCC____-SAME: (i1 [[C:%.*]])
|
||||
; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
||||
; IS__CGSCC____: t:
|
||||
; IS__CGSCC____-NEXT: ret i32 0
|
||||
; IS__CGSCC____: f:
|
||||
; IS__CGSCC____-NEXT: ret i32 -1
|
||||
;
|
||||
br i1 %c, label %t, label %f
|
||||
t:
|
||||
ret i32 0
|
||||
f:
|
||||
%undef = sub i32 undef, 1
|
||||
ret i32 %undef
|
||||
}
|
||||
|
||||
define i32 @optimize_undef_3(i1 %c) {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@optimize_undef_3
|
||||
; IS__TUNIT____-SAME: (i1 [[C:%.*]])
|
||||
; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
||||
; IS__TUNIT____: t:
|
||||
; IS__TUNIT____-NEXT: ret i32 0
|
||||
; IS__TUNIT____: f:
|
||||
; IS__TUNIT____-NEXT: ret i32 1
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@optimize_undef_3
|
||||
; IS__CGSCC____-SAME: (i1 [[C:%.*]])
|
||||
; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
||||
; IS__CGSCC____: t:
|
||||
; IS__CGSCC____-NEXT: ret i32 0
|
||||
; IS__CGSCC____: f:
|
||||
; IS__CGSCC____-NEXT: ret i32 1
|
||||
;
|
||||
br i1 %c, label %t, label %f
|
||||
t:
|
||||
ret i32 0
|
||||
f:
|
||||
%undef = icmp eq i32 undef, 0
|
||||
%undef2 = zext i1 %undef to i32
|
||||
ret i32 %undef2
|
||||
}
|
||||
|
||||
|
||||
; FIXME: returned value can be simplified to 0
|
||||
define i32 @potential_test11(i1 %c) {
|
||||
; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test11
|
||||
; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]])
|
||||
; IS__TUNIT_OPM-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) [[ATTR0]], [[RNG2:!range !.*]]
|
||||
; IS__TUNIT_OPM-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) [[ATTR0]], [[RNG3:!range !.*]]
|
||||
; IS__TUNIT_OPM-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]]
|
||||
; IS__TUNIT_OPM-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], 0
|
||||
; IS__TUNIT_OPM-NEXT: ret i32 [[ACC2]]
|
||||
;
|
||||
; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test11
|
||||
; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]])
|
||||
; IS__TUNIT_NPM-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) [[ATTR0]], [[RNG0]]
|
||||
; IS__TUNIT_NPM-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) [[ATTR0]], [[RNG3:!range !.*]]
|
||||
; IS__TUNIT_NPM-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]]
|
||||
; IS__TUNIT_NPM-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], 0
|
||||
; IS__TUNIT_NPM-NEXT: ret i32 [[ACC2]]
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@potential_test11
|
||||
; IS__CGSCC____-SAME: (i1 [[C:%.*]])
|
||||
; IS__CGSCC____-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]])
|
||||
; IS__CGSCC____-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]])
|
||||
; IS__CGSCC____-NEXT: [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]])
|
||||
; IS__CGSCC____-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]]
|
||||
; IS__CGSCC____-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]]
|
||||
; IS__CGSCC____-NEXT: ret i32 [[ACC2]]
|
||||
;
|
||||
%zero1 = call i32 @optimize_undef_1(i1 %c)
|
||||
%zero2 = call i32 @optimize_undef_2(i1 %c)
|
||||
%zero3 = call i32 @optimize_undef_3(i1 %c)
|
||||
%acc1 = add i32 %zero1, %zero2
|
||||
%acc2 = add i32 %acc1, %zero3
|
||||
ret i32 %acc2
|
||||
}
|
||||
|
||||
define i32 @optimize_poison_1(i1 %c) {
|
||||
; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@optimize_poison_1
|
||||
; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]])
|
||||
; IS__TUNIT_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
||||
; IS__TUNIT_OPM: t:
|
||||
; IS__TUNIT_OPM-NEXT: ret i32 0
|
||||
; IS__TUNIT_OPM: f:
|
||||
; IS__TUNIT_OPM-NEXT: ret i32 -1
|
||||
;
|
||||
; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@optimize_poison_1
|
||||
; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]])
|
||||
; IS__TUNIT_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
||||
; IS__TUNIT_NPM: t:
|
||||
; IS__TUNIT_NPM-NEXT: ret i32 0
|
||||
; IS__TUNIT_NPM: f:
|
||||
; IS__TUNIT_NPM-NEXT: ret i32 undef
|
||||
;
|
||||
; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@optimize_poison_1
|
||||
; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]])
|
||||
; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
||||
; IS__CGSCC_OPM: t:
|
||||
; IS__CGSCC_OPM-NEXT: ret i32 0
|
||||
; IS__CGSCC_OPM: f:
|
||||
; IS__CGSCC_OPM-NEXT: ret i32 -1
|
||||
;
|
||||
; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@optimize_poison_1
|
||||
; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]])
|
||||
; IS__CGSCC_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
||||
; IS__CGSCC_NPM: t:
|
||||
; IS__CGSCC_NPM-NEXT: ret i32 0
|
||||
; IS__CGSCC_NPM: f:
|
||||
; IS__CGSCC_NPM-NEXT: ret i32 undef
|
||||
;
|
||||
br i1 %c, label %t, label %f
|
||||
t:
|
||||
ret i32 0
|
||||
f:
|
||||
%poison = sub nuw i32 0, 1
|
||||
ret i32 %poison
|
||||
}
|
||||
|
||||
; FIXME: returned value can be simplified to 0
|
||||
define i32 @potential_test12(i1 %c) {
|
||||
; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test12
|
||||
; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]])
|
||||
; IS__TUNIT_OPM-NEXT: [[ZERO:%.*]] = call i32 @optimize_poison_1(i1 [[C]]) [[ATTR0]], [[RNG3]]
|
||||
; IS__TUNIT_OPM-NEXT: ret i32 [[ZERO]]
|
||||
;
|
||||
; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test12
|
||||
; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]])
|
||||
; IS__TUNIT_NPM-NEXT: ret i32 0
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@potential_test12
|
||||
; IS__CGSCC____-SAME: (i1 [[C:%.*]])
|
||||
; IS__CGSCC____-NEXT: [[ZERO:%.*]] = call i32 @optimize_poison_1(i1 [[C]])
|
||||
; IS__CGSCC____-NEXT: ret i32 [[ZERO]]
|
||||
;
|
||||
%zero = call i32 @optimize_poison_1(i1 %c)
|
||||
ret i32 %zero
|
||||
}
|
||||
|
||||
; Test 13
|
||||
; Do not simplify %ret in the callee to `%c`.
|
||||
; The potential value of %c is {0, 1} (undef is merged).
|
||||
; However, we should not simplify `and i32 %c, 3` to `%c`
|
||||
|
||||
define internal i32 @potential_test13_callee(i32 %c) {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test13_callee
|
||||
; IS__TUNIT____-SAME: (i32 [[C:%.*]])
|
||||
; IS__TUNIT____-NEXT: [[RET:%.*]] = and i32 [[C]], 3
|
||||
; IS__TUNIT____-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@potential_test13_callee
|
||||
; IS__CGSCC____-SAME: (i32 [[C:%.*]])
|
||||
; IS__CGSCC____-NEXT: [[RET:%.*]] = and i32 [[C]], 3
|
||||
; IS__CGSCC____-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%ret = and i32 %c, 3
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @potential_test13_caller1() {
|
||||
; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test13_caller1()
|
||||
; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 0) [[ATTR0]], [[RNG2]]
|
||||
; IS__TUNIT_OPM-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test13_caller1()
|
||||
; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 0) [[ATTR0]], [[RNG0]]
|
||||
; IS__TUNIT_NPM-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@potential_test13_caller1()
|
||||
; IS__CGSCC____-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 0)
|
||||
; IS__CGSCC____-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%ret = call i32 @potential_test13_callee(i32 0)
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @potential_test13_caller2() {
|
||||
; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test13_caller2()
|
||||
; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 1) [[ATTR0]], [[RNG2]]
|
||||
; IS__TUNIT_OPM-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test13_caller2()
|
||||
; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 1) [[ATTR0]], [[RNG0]]
|
||||
; IS__TUNIT_NPM-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@potential_test13_caller2()
|
||||
; IS__CGSCC____-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 1)
|
||||
; IS__CGSCC____-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%ret = call i32 @potential_test13_callee(i32 1)
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @potential_test13_caller3() {
|
||||
; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test13_caller3()
|
||||
; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) [[ATTR0]], [[RNG2]]
|
||||
; IS__TUNIT_OPM-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test13_caller3()
|
||||
; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) [[ATTR0]], [[RNG0]]
|
||||
; IS__TUNIT_NPM-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@potential_test13_caller3()
|
||||
; IS__CGSCC____-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef)
|
||||
; IS__CGSCC____-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%ret = call i32 @potential_test13_callee(i32 undef)
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i1 @potential_test14(i1 %c0, i1 %c1, i1 %c2, i1 %c3) {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test14
|
||||
; IS__TUNIT____-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]])
|
||||
; IS__TUNIT____-NEXT: [[X0:%.*]] = select i1 [[C0]], i32 0, i32 1
|
||||
; IS__TUNIT____-NEXT: [[X1:%.*]] = select i1 [[C1]], i32 [[X0]], i32 undef
|
||||
; IS__TUNIT____-NEXT: [[Y2:%.*]] = select i1 [[C2]], i32 0, i32 7
|
||||
; IS__TUNIT____-NEXT: [[Z3:%.*]] = select i1 [[C3]], i32 [[X1]], i32 [[Y2]]
|
||||
; IS__TUNIT____-NEXT: [[RET:%.*]] = icmp slt i32 [[Z3]], 7
|
||||
; IS__TUNIT____-NEXT: ret i1 [[RET]]
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@potential_test14
|
||||
; IS__CGSCC____-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]])
|
||||
; IS__CGSCC____-NEXT: [[X0:%.*]] = select i1 [[C0]], i32 0, i32 1
|
||||
; IS__CGSCC____-NEXT: [[X1:%.*]] = select i1 [[C1]], i32 [[X0]], i32 undef
|
||||
; IS__CGSCC____-NEXT: [[Y2:%.*]] = select i1 [[C2]], i32 0, i32 7
|
||||
; IS__CGSCC____-NEXT: [[Z3:%.*]] = select i1 [[C3]], i32 [[X1]], i32 [[Y2]]
|
||||
; IS__CGSCC____-NEXT: [[RET:%.*]] = icmp slt i32 [[Z3]], 7
|
||||
; IS__CGSCC____-NEXT: ret i1 [[RET]]
|
||||
;
|
||||
%x0 = select i1 %c0, i32 0, i32 1
|
||||
%x1 = select i1 %c1, i32 %x0, i32 undef
|
||||
%y2 = select i1 %c2, i32 0, i32 7
|
||||
%z3 = select i1 %c3, i32 %x1, i32 %y2
|
||||
%ret = icmp slt i32 %z3, 7
|
||||
ret i1 %ret
|
||||
}
|
||||
|
||||
define i1 @potential_test15(i1 %c0, i1 %c1) {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test15
|
||||
; IS__TUNIT____-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]])
|
||||
; IS__TUNIT____-NEXT: ret i1 false
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@potential_test15
|
||||
; IS__CGSCC____-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]])
|
||||
; IS__CGSCC____-NEXT: ret i1 false
|
||||
;
|
||||
%x0 = select i1 %c0, i32 0, i32 1
|
||||
%x1 = select i1 %c1, i32 %x0, i32 undef
|
||||
%ret = icmp eq i32 %x1, 7
|
||||
ret i1 %ret
|
||||
}
|
||||
|
||||
define i1 @potential_test16(i1 %c0, i1 %c1) {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test16
|
||||
; IS__TUNIT____-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]])
|
||||
; IS__TUNIT____-NEXT: ret i1 false
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@potential_test16
|
||||
; IS__CGSCC____-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]])
|
||||
; IS__CGSCC____-NEXT: ret i1 false
|
||||
;
|
||||
%x0 = select i1 %c0, i32 0, i32 undef
|
||||
%x1 = select i1 %c1, i32 %x0, i32 1
|
||||
%ret = icmp eq i32 %x1, 7
|
||||
ret i1 %ret
|
||||
}
|
||||
|
||||
; IS__TUNIT_NPM: !0 = !{i32 0, i32 2}
|
||||
; IS__TUNIT_NPM: !1 = !{i32 1, i32 4}
|
||||
; IS__TUNIT_NPM: !2 = !{i32 3, i32 5}
|
||||
; IS__TUNIT_NPM: !3 = !{i32 -1, i32 2}
|
||||
; IS__TUNIT_NPM: !3 = !{i32 -1, i32 1}
|
||||
; IS__TUNIT_NPM-NOT: !4
|
||||
|
||||
; IS__TUNIT_OPM: !0 = !{i32 1, i32 4}
|
||||
; IS__TUNIT_OPM: !1 = !{i32 3, i32 5}
|
||||
; IS__TUNIT_OPM: !2 = !{i32 -1, i32 2}
|
||||
; IS__TUNIT_OPM-NOT: !3
|
||||
; IS__TUNIT_OPM: !2 = !{i32 0, i32 2}
|
||||
; IS__TUNIT_OPM: !3 = !{i32 -1, i32 1}
|
||||
; IS__TUNIT_OPM-NOT: !4
|
||||
|
||||
; IS__CGSCC____-NOT: !0
|
||||
|
|
|
@ -644,12 +644,10 @@ for.end:
|
|||
}
|
||||
|
||||
; Check we merge undef and a constant properly.
|
||||
; FIXME fold the addition and return the constant.
|
||||
define i8 @caller0() {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@caller0()
|
||||
; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee()
|
||||
; IS__TUNIT____-NEXT: ret i8 [[C]]
|
||||
; IS__TUNIT____-NEXT: ret i8 49
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@caller0()
|
||||
|
@ -662,8 +660,7 @@ define i8 @caller0() {
|
|||
define i8 @caller1() {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@caller1()
|
||||
; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee()
|
||||
; IS__TUNIT____-NEXT: ret i8 [[C]]
|
||||
; IS__TUNIT____-NEXT: ret i8 49
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@caller1()
|
||||
|
@ -676,8 +673,7 @@ define i8 @caller1() {
|
|||
define i8 @caller2() {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@caller2()
|
||||
; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee()
|
||||
; IS__TUNIT____-NEXT: ret i8 [[C]]
|
||||
; IS__TUNIT____-NEXT: ret i8 49
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@caller2()
|
||||
|
@ -690,8 +686,7 @@ define i8 @caller2() {
|
|||
define i8 @caller_middle() {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@caller_middle()
|
||||
; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee()
|
||||
; IS__TUNIT____-NEXT: ret i8 [[C]]
|
||||
; IS__TUNIT____-NEXT: ret i8 49
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@caller_middle()
|
||||
|
@ -704,8 +699,7 @@ define i8 @caller_middle() {
|
|||
define i8 @caller3() {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@caller3()
|
||||
; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee()
|
||||
; IS__TUNIT____-NEXT: ret i8 [[C]]
|
||||
; IS__TUNIT____-NEXT: ret i8 49
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@caller3()
|
||||
|
@ -718,8 +712,7 @@ define i8 @caller3() {
|
|||
define i8 @caller4() {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@caller4()
|
||||
; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee()
|
||||
; IS__TUNIT____-NEXT: ret i8 [[C]]
|
||||
; IS__TUNIT____-NEXT: ret i8 49
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@caller4()
|
||||
|
@ -730,15 +723,9 @@ define i8 @caller4() {
|
|||
ret i8 %c
|
||||
}
|
||||
define internal i8 @callee(i8 %a) {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@callee()
|
||||
; IS__TUNIT____-NEXT: [[C:%.*]] = add i8 42, 7
|
||||
; IS__TUNIT____-NEXT: ret i8 [[C]]
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@callee()
|
||||
; IS__CGSCC____-NEXT: [[C:%.*]] = add i8 42, 7
|
||||
; IS__CGSCC____-NEXT: ret i8 [[C]]
|
||||
; IS__CGSCC____-NEXT: ret i8 49
|
||||
;
|
||||
%c = add i8 %a, 7
|
||||
ret i8 %c
|
||||
|
|
Loading…
Reference in New Issue