A bunch of misc fixes to SCCPSolver::ResolvedUndefsIn, including a fix to stop

making random bad assumptions about instructions which are not explicitly listed.  

Includes fix for rdar://9956541, a version of "undef ^ undef should return
0 because it's easier than arguing with users".



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137777 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eli Friedman 2011-08-16 22:06:31 +00:00
parent f213ad1a55
commit 054ddf799b
2 changed files with 129 additions and 40 deletions

View File

@ -1445,54 +1445,78 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
}
continue;
}
LatticeVal &LV = getValueState(I);
if (!LV.isUndefined()) continue;
// No instructions using structs need disambiguation.
if (I->getOperand(0)->getType()->isStructTy())
continue;
// Get the lattice values of the first two operands for use below.
LatticeVal Op0LV = getValueState(I->getOperand(0));
LatticeVal Op1LV;
if (I->getNumOperands() == 2) {
// No instructions using structs need disambiguation.
if (I->getOperand(1)->getType()->isStructTy())
continue;
// If this is a two-operand instruction, and if both operands are
// undefs, the result stays undef.
if (I->getNumOperands() == 2)
Op1LV = getValueState(I->getOperand(1));
if (Op0LV.isUndefined() && Op1LV.isUndefined())
continue;
}
// If this is an instructions whose result is defined even if the input is
// not fully defined, propagate the information.
Type *ITy = I->getType();
switch (I->getOpcode()) {
default: break; // Leave the instruction as an undef.
case Instruction::ExtractValue:
break; // Extract of undef -> undef
case Instruction::Add:
case Instruction::Sub:
case Instruction::Trunc:
case Instruction::FPTrunc:
case Instruction::BitCast:
break; // Any undef -> undef
case Instruction::FSub:
case Instruction::FAdd:
case Instruction::FMul:
case Instruction::FDiv:
case Instruction::FRem:
// Floating-point binary operation: be conservative.
if (Op0LV.isUndefined() && Op1LV.isUndefined())
markForcedConstant(I, Constant::getNullValue(ITy));
else
markOverdefined(I);
return true;
case Instruction::ZExt:
// After a zero extend, we know the top part is zero. SExt doesn't have
// to be handled here, because we don't know whether the top part is 1's
// or 0's.
case Instruction::SIToFP: // some FP values are not possible, just use 0.
case Instruction::UIToFP: // some FP values are not possible, just use 0.
case Instruction::SExt:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::FPExt:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::SIToFP:
case Instruction::UIToFP:
// undef -> 0; some outputs are impossible
markForcedConstant(I, Constant::getNullValue(ITy));
return true;
case Instruction::Mul:
case Instruction::And:
// Both operands undef -> undef
if (Op0LV.isUndefined() && Op1LV.isUndefined())
break;
// undef * X -> 0. X could be zero.
// undef & X -> 0. X could be zero.
markForcedConstant(I, Constant::getNullValue(ITy));
return true;
case Instruction::Or:
// Both operands undef -> undef
if (Op0LV.isUndefined() && Op1LV.isUndefined())
break;
// undef | X -> -1. X could be -1.
markForcedConstant(I, Constant::getAllOnesValue(ITy));
return true;
case Instruction::Xor:
// undef ^ undef -> 0; strictly speaking, this is not strictly
// necessary, but we try to be nice to people who expect this
// behavior in simple cases
if (Op0LV.isUndefined() && Op1LV.isUndefined()) {
markForcedConstant(I, Constant::getNullValue(ITy));
return true;
}
// undef ^ X -> undef
break;
case Instruction::SDiv:
case Instruction::UDiv:
case Instruction::SRem:
@ -1507,26 +1531,24 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
return true;
case Instruction::AShr:
// undef >>s X -> undef. No change.
if (Op0LV.isUndefined()) break;
// X >>s undef -> X. X could be 0, X could have the high-bit known set.
if (Op0LV.isConstant())
markForcedConstant(I, Op0LV.getConstant());
else
markOverdefined(I);
// X >>a undef -> undef.
if (Op1LV.isUndefined()) break;
// undef >>a X -> all ones
markForcedConstant(I, Constant::getAllOnesValue(ITy));
return true;
case Instruction::LShr:
case Instruction::Shl:
// undef >> X -> undef. No change.
// undef << X -> undef. No change.
if (Op0LV.isUndefined()) break;
// X >> undef -> 0. X could be 0.
// X << undef -> 0. X could be 0.
// X << undef -> undef.
// X >> undef -> undef.
if (Op1LV.isUndefined()) break;
// undef << X -> 0
// undef >> X -> 0
markForcedConstant(I, Constant::getNullValue(ITy));
return true;
case Instruction::Select:
Op1LV = getValueState(I->getOperand(1));
// undef ? X : Y -> X or Y. There could be commonality between X/Y.
if (Op0LV.isUndefined()) {
if (!Op1LV.isConstant()) // Pick the constant one if there is any.
@ -1546,9 +1568,19 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
else
markOverdefined(I);
return true;
case Instruction::Call:
// If a call has an undef result, it is because it is constant foldable
// but one of the inputs was undef. Just force the result to
case Instruction::Load:
// A load here means one of two things: a load of undef from a global,
// a load from an unknown pointer. Either way, having it return undef
// is okay.
break;
case Instruction::ICmp:
// X == undef -> undef. Other comparisons get more complicated.
if (cast<ICmpInst>(I)->isEquality())
break;
markOverdefined(I);
return true;
default:
// If we don't know what should happen here, conservatively mark it
// overdefined.
markOverdefined(I);
return true;

View File

@ -104,3 +104,60 @@ bb1.us-lcssa: ; preds = %control
bb1: ; preds = %bb1.us-lcssa, %bb1.us-lcssa.us
ret i32 0
}
; Make sure SCCP honors the xor "idiom"
; rdar://9956541
define i32 @test3() {
%t = xor i32 undef, undef
ret i32 %t
; CHECK: @test3
; CHECK: ret i32 0
}
; Be conservative with FP ops
define double @test4(double %x) {
%t = fadd double %x, undef
ret double %t
; CHECK: @test4
; CHECK: fadd double %x, undef
}
; Make sure casts produce a possible value
define i32 @test5() {
%t = sext i8 undef to i32
ret i32 %t
; CHECK: @test5
; CHECK: ret i32 0
}
; Make sure ashr produces a possible value
define i32 @test6() {
%t = ashr i32 undef, 31
ret i32 %t
; CHECK: @test6
; CHECK: ret i32 -1
}
; Make sure lshr produces a possible value
define i32 @test7() {
%t = lshr i32 undef, 31
ret i32 %t
; CHECK: @test7
; CHECK: ret i32 0
}
; icmp eq with undef simplifies to undef
define i1 @test8() {
%t = icmp eq i32 undef, -1
ret i1 %t
; CHECK: @test8
; CHECK: ret i1 undef
}
; Make sure we don't conclude that relational comparisons simplify to undef
define i1 @test9() {
%t = icmp ugt i32 undef, -1
ret i1 %t
; CHECK: @test9
; CHECK: icmp ugt
}