mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
[SCCP] Don't violate the lattice invariants
We marked values which are 'undef' as constant instead of undefined which violates SCCP's invariants. If we can figure out that a computation results in 'undef', leave it in the undefined state. This fixes PR16052. llvm-svn: 257102
This commit is contained in:
parent
b8ea306e3f
commit
2296864d81
@ -757,9 +757,14 @@ void SCCPSolver::visitCastInst(CastInst &I) {
|
|||||||
LatticeVal OpSt = getValueState(I.getOperand(0));
|
LatticeVal OpSt = getValueState(I.getOperand(0));
|
||||||
if (OpSt.isOverdefined()) // Inherit overdefinedness of operand
|
if (OpSt.isOverdefined()) // Inherit overdefinedness of operand
|
||||||
markOverdefined(&I);
|
markOverdefined(&I);
|
||||||
else if (OpSt.isConstant()) // Propagate constant value
|
else if (OpSt.isConstant()) {
|
||||||
markConstant(&I, ConstantExpr::getCast(I.getOpcode(),
|
Constant *C =
|
||||||
OpSt.getConstant(), I.getType()));
|
ConstantExpr::getCast(I.getOpcode(), OpSt.getConstant(), I.getType());
|
||||||
|
if (isa<UndefValue>(C))
|
||||||
|
return;
|
||||||
|
// Propagate constant value
|
||||||
|
markConstant(&I, C);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -859,10 +864,14 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
|
|||||||
LatticeVal &IV = ValueState[&I];
|
LatticeVal &IV = ValueState[&I];
|
||||||
if (IV.isOverdefined()) return;
|
if (IV.isOverdefined()) return;
|
||||||
|
|
||||||
if (V1State.isConstant() && V2State.isConstant())
|
if (V1State.isConstant() && V2State.isConstant()) {
|
||||||
return markConstant(IV, &I,
|
Constant *C = ConstantExpr::get(I.getOpcode(), V1State.getConstant(),
|
||||||
ConstantExpr::get(I.getOpcode(), V1State.getConstant(),
|
V2State.getConstant());
|
||||||
V2State.getConstant()));
|
// X op Y -> undef.
|
||||||
|
if (isa<UndefValue>(C))
|
||||||
|
return;
|
||||||
|
return markConstant(IV, &I, C);
|
||||||
|
}
|
||||||
|
|
||||||
// If something is undef, wait for it to resolve.
|
// If something is undef, wait for it to resolve.
|
||||||
if (!V1State.isOverdefined() && !V2State.isOverdefined())
|
if (!V1State.isOverdefined() && !V2State.isOverdefined())
|
||||||
@ -917,10 +926,13 @@ void SCCPSolver::visitCmpInst(CmpInst &I) {
|
|||||||
LatticeVal &IV = ValueState[&I];
|
LatticeVal &IV = ValueState[&I];
|
||||||
if (IV.isOverdefined()) return;
|
if (IV.isOverdefined()) return;
|
||||||
|
|
||||||
if (V1State.isConstant() && V2State.isConstant())
|
if (V1State.isConstant() && V2State.isConstant()) {
|
||||||
return markConstant(IV, &I, ConstantExpr::getCompare(I.getPredicate(),
|
Constant *C = ConstantExpr::getCompare(
|
||||||
V1State.getConstant(),
|
I.getPredicate(), V1State.getConstant(), V2State.getConstant());
|
||||||
V2State.getConstant()));
|
if (isa<UndefValue>(C))
|
||||||
|
return;
|
||||||
|
return markConstant(IV, &I, C);
|
||||||
|
}
|
||||||
|
|
||||||
// If operands are still undefined, wait for it to resolve.
|
// If operands are still undefined, wait for it to resolve.
|
||||||
if (!V1State.isOverdefined() && !V2State.isOverdefined())
|
if (!V1State.isOverdefined() && !V2State.isOverdefined())
|
||||||
@ -1020,8 +1032,11 @@ void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) {
|
|||||||
|
|
||||||
Constant *Ptr = Operands[0];
|
Constant *Ptr = Operands[0];
|
||||||
auto Indices = makeArrayRef(Operands.begin() + 1, Operands.end());
|
auto Indices = makeArrayRef(Operands.begin() + 1, Operands.end());
|
||||||
markConstant(&I, ConstantExpr::getGetElementPtr(I.getSourceElementType(), Ptr,
|
Constant *C =
|
||||||
Indices));
|
ConstantExpr::getGetElementPtr(I.getSourceElementType(), Ptr, Indices);
|
||||||
|
if (isa<UndefValue>(C))
|
||||||
|
return;
|
||||||
|
markConstant(&I, C);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCCPSolver::visitStoreInst(StoreInst &SI) {
|
void SCCPSolver::visitStoreInst(StoreInst &SI) {
|
||||||
@ -1079,8 +1094,11 @@ void SCCPSolver::visitLoadInst(LoadInst &I) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transform load from a constant into a constant if possible.
|
// Transform load from a constant into a constant if possible.
|
||||||
if (Constant *C = ConstantFoldLoadFromConstPtr(Ptr, DL))
|
if (Constant *C = ConstantFoldLoadFromConstPtr(Ptr, DL)) {
|
||||||
|
if (isa<UndefValue>(C))
|
||||||
|
return;
|
||||||
return markConstant(IV, &I, C);
|
return markConstant(IV, &I, C);
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise we cannot say for certain what value this load will produce.
|
// Otherwise we cannot say for certain what value this load will produce.
|
||||||
// Bail out.
|
// Bail out.
|
||||||
@ -1122,8 +1140,12 @@ CallOverdefined:
|
|||||||
|
|
||||||
// If we can constant fold this, mark the result of the call as a
|
// If we can constant fold this, mark the result of the call as a
|
||||||
// constant.
|
// constant.
|
||||||
if (Constant *C = ConstantFoldCall(F, Operands, TLI))
|
if (Constant *C = ConstantFoldCall(F, Operands, TLI)) {
|
||||||
|
// call -> undef.
|
||||||
|
if (isa<UndefValue>(C))
|
||||||
|
return;
|
||||||
return markConstant(I, C);
|
return markConstant(I, C);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we don't know anything about this call, mark it overdefined.
|
// Otherwise, we don't know anything about this call, mark it overdefined.
|
||||||
@ -1379,6 +1401,11 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
|
|||||||
// X % undef -> undef. No change.
|
// X % undef -> undef. No change.
|
||||||
if (Op1LV.isUndefined()) break;
|
if (Op1LV.isUndefined()) break;
|
||||||
|
|
||||||
|
// X / 0 -> undef. No change.
|
||||||
|
// X % 0 -> undef. No change.
|
||||||
|
if (Op1LV.isConstant() && Op1LV.getConstant()->isZeroValue())
|
||||||
|
break;
|
||||||
|
|
||||||
// undef / X -> 0. X could be maxint.
|
// undef / X -> 0. X could be maxint.
|
||||||
// undef % X -> 0. X could be 1.
|
// undef % X -> 0. X could be 1.
|
||||||
markForcedConstant(&I, Constant::getNullValue(ITy));
|
markForcedConstant(&I, Constant::getNullValue(ITy));
|
||||||
|
26
test/Transforms/IPConstantProp/PR16052.ll
Normal file
26
test/Transforms/IPConstantProp/PR16052.ll
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
; RUN: opt < %s -S -ipsccp | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
define i64 @fn2() {
|
||||||
|
entry:
|
||||||
|
%conv = sext i32 undef to i64
|
||||||
|
%div = sdiv i64 8, %conv
|
||||||
|
%call2 = call i64 @fn1(i64 %div)
|
||||||
|
ret i64 %call2
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-DAG: define i64 @fn2(
|
||||||
|
; CHECK: %[[CALL:.*]] = call i64 @fn1(i64 undef)
|
||||||
|
|
||||||
|
define internal i64 @fn1(i64 %p1) {
|
||||||
|
entry:
|
||||||
|
%tobool = icmp ne i64 %p1, 0
|
||||||
|
%cond = select i1 %tobool, i64 %p1, i64 %p1
|
||||||
|
ret i64 %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-DAG: define internal i64 @fn1(
|
||||||
|
; CHECK: %[[SEL:.*]] = select i1 undef, i64 undef, i64 undef
|
||||||
|
; CHECK: ret i64 %[[SEL]]
|
Loading…
Reference in New Issue
Block a user