diff --git a/llvm/include/llvm/Analysis/ValueLattice.h b/llvm/include/llvm/Analysis/ValueLattice.h --- a/llvm/include/llvm/Analysis/ValueLattice.h +++ b/llvm/include/llvm/Analysis/ValueLattice.h @@ -36,8 +36,6 @@ /// as constant.) constant, - forcedconstant, - /// This Value is known to not have the specified value. (For constant /// integers, constantrange is used instead. As above, integer typed /// constantexprs can appear here.) @@ -71,7 +69,6 @@ case overdefined: case undefined: case constant: - case forcedconstant: case notconstant: break; case constantrange: @@ -108,7 +105,6 @@ Range = Other.Range; break; case constant: - case forcedconstant: case notconstant: ConstVal = Other.ConstVal; break; @@ -145,15 +141,13 @@ bool isUndefined() const { return Tag == undefined; } bool isUnknown() const { return Tag == undefined; } - bool isConstant() const { return Tag == constant || Tag == forcedconstant; } - bool isForcedConstant() const { return Tag == forcedconstant; } + bool isConstant() const { return Tag == constant; } bool isNotConstant() const { return Tag == notconstant; } bool isConstantRange() const { return Tag == constantrange; } bool isOverdefined() const { return Tag == overdefined; } Constant *getConstant() const { - assert((isConstant() || isForcedConstant()) && - "Cannot get the constant of a non-constant!"); + assert(isConstant() && "Cannot get the constant of a non-constant!"); return ConstVal; } @@ -194,9 +188,6 @@ assert(V && "Marking constant with NULL"); - if (isForcedConstant() && V != getConstant()) - return markOverdefined(); - if (isConstant()) { assert(getConstant() == V && "Marking constant with different value"); return false; @@ -211,19 +202,6 @@ return true; } - bool markForcedConstant(Constant *V) { - assert(V && "Marking constant with NULL"); - if (isa(V)) - return false; - - assert((!isForcedConstant() || getConstant() == V) && - "Marking constant with different value"); - assert(isUndefined()); - Tag = forcedconstant; - ConstVal = V; - return true; - } - bool markNotConstant(Constant *V) { assert(V && "Marking constant with NULL"); if (ConstantInt *CI = dyn_cast(V)) @@ -280,10 +258,6 @@ return !RHS.isUndefined(); } - if (isForcedConstant() || RHS.isForcedConstant()) { - markOverdefined(); - return true; - } if (isConstant()) { if (RHS.isConstant() && getConstant() == RHS.getConstant()) return false; @@ -315,7 +289,7 @@ } ConstantInt *getConstantInt() const { - assert((isConstant() || isForcedConstant()) && "No integer constant"); + assert(isConstant() && "No integer constant"); return dyn_cast(getConstant()); } diff --git a/llvm/lib/Analysis/ValueLattice.cpp b/llvm/lib/Analysis/ValueLattice.cpp --- a/llvm/lib/Analysis/ValueLattice.cpp +++ b/llvm/lib/Analysis/ValueLattice.cpp @@ -20,8 +20,6 @@ if (Val.isConstantRange()) return OS << "constantrange<" << Val.getConstantRange().getLower() << ", " << Val.getConstantRange().getUpper() << ">"; - if (Val.isForcedConstant()) - return OS << "forcedconstant<" << *Val.getConstant() << ">"; return OS << "constant<" << *Val.getConstant() << ">"; } } // end namespace llvm diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -347,7 +347,7 @@ return cast_or_null(getConstant(IV)); } - // pushToWorkList - Helper for markConstant/markForcedConstant/markOverdefined + // pushToWorkList - Helper for markConstant/markOverdefined void pushToWorkList(LatticeVal &IV, Value *V) { if (IV.isOverdefined()) return OverdefinedInstWorkList.push_back(V); @@ -378,14 +378,6 @@ return markConstant(ValueState[V], V, C); } - void markForcedConstant(Value *V, Constant *C) { - assert(!V->getType()->isStructTy() && "structs should use mergeInValue"); - LatticeVal &IV = ValueState[V]; - IV.markForcedConstant(C); - LLVM_DEBUG(dbgs() << "markForcedConstant: " << *C << ": " << *V << '\n'); - pushToWorkList(IV, V); - } - // markOverdefined - Make a value be marked as "overdefined". If the // value is not already overdefined, add it to the overdefined instruction // work list so that the users of the instruction are updated later. @@ -1453,10 +1445,7 @@ case Instruction::FDiv: case Instruction::FRem: // Floating-point binary operation: be conservative. - if (Op0LV.isUnknown() && Op1LV.isUnknown()) - markForcedConstant(&I, Constant::getNullValue(ITy)); - else - markOverdefined(&I); + markOverdefined(&I); return true; case Instruction::FNeg: break; // fneg undef -> undef @@ -1470,7 +1459,7 @@ case Instruction::SIToFP: case Instruction::UIToFP: // undef -> 0; some outputs are impossible - markForcedConstant(&I, Constant::getNullValue(ITy)); + markConstant(&I, Constant::getNullValue(ITy)); return true; case Instruction::Mul: case Instruction::And: @@ -1479,21 +1468,21 @@ break; // undef * X -> 0. X could be zero. // undef & X -> 0. X could be zero. - markForcedConstant(&I, Constant::getNullValue(ITy)); + markConstant(&I, Constant::getNullValue(ITy)); return true; case Instruction::Or: // Both operands undef -> undef if (Op0LV.isUnknown() && Op1LV.isUnknown()) break; // undef | X -> -1. X could be -1. - markForcedConstant(&I, Constant::getAllOnesValue(ITy)); + markConstant(&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.isUnknown() && Op1LV.isUnknown()) { - markForcedConstant(&I, Constant::getNullValue(ITy)); + markConstant(&I, Constant::getNullValue(ITy)); return true; } // undef ^ X -> undef @@ -1513,7 +1502,7 @@ // undef / X -> 0. X could be maxint. // undef % X -> 0. X could be 1. - markForcedConstant(&I, Constant::getNullValue(ITy)); + markConstant(&I, Constant::getNullValue(ITy)); return true; case Instruction::AShr: // X >>a undef -> undef. @@ -1526,7 +1515,7 @@ break; // undef >>a X -> 0 - markForcedConstant(&I, Constant::getNullValue(ITy)); + markConstant(&I, Constant::getNullValue(ITy)); return true; case Instruction::LShr: case Instruction::Shl: @@ -1542,9 +1531,9 @@ // undef << X -> 0 // undef >> X -> 0 - markForcedConstant(&I, Constant::getNullValue(ITy)); + markConstant(&I, Constant::getNullValue(ITy)); return true; - case Instruction::Select: + case Instruction::Select: { Op1LV = getValueState(I.getOperand(1)); // undef ? X : Y -> X or Y. There could be commonality between X/Y. if (Op0LV.isUnknown()) { @@ -1560,11 +1549,13 @@ // Leave Op1LV as Operand(1)'s LatticeValue. } - if (Constant *C = getConstant(Op1LV)) - markForcedConstant(&I, C); - else - markOverdefined(&I); + Constant *C = getConstant(Op1LV); + if (C && C->getType()->isIntegerTy()) + markConstant(&I, C); + else + markOverdefined(&I); return true; + } 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 diff --git a/llvm/test/Transforms/SCCP/undef-constant.ll b/llvm/test/Transforms/SCCP/undef-constant.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SCCP/undef-constant.ll @@ -0,0 +1,65 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -sccp -S < %s | FileCheck %s + +define i32 @test_zext() { +; CHECK-LABEL: @test_zext( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[BB3:%.*]], label [[BB4:%.*]] +; CHECK: bb3: +; CHECK-NEXT: ret i32 10 +; CHECK: bb4: +; CHECK-NEXT: ret i32 20 +; +entry: + %tmp = zext i8 undef to i32 + %cmp = icmp eq i32 %tmp, 10 + br i1 %cmp, label %bb3, label %bb4 + +bb3: ; preds = %bb2 + ret i32 10 + +bb4: ; preds = %bb2 + ret i32 20 +} + +define i32 @test_and() { +; CHECK-LABEL: @test_and( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[BB3:%.*]], label [[BB4:%.*]] +; CHECK: bb3: +; CHECK-NEXT: ret i32 10 +; CHECK: bb4: +; CHECK-NEXT: ret i32 20 +; +entry: + %tmp = and i8 undef, 15 + %cmp = icmp eq i8 %tmp, 10 + br i1 %cmp, label %bb3, label %bb4 + +bb3: ; preds = %bb2 + ret i32 10 + +bb4: ; preds = %bb2 + ret i32 20 +} + +define i32 @test_mul() { +; CHECK-LABEL: @test_mul( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[BB3:%.*]], label [[BB4:%.*]] +; CHECK: bb3: +; CHECK-NEXT: ret i32 10 +; CHECK: bb4: +; CHECK-NEXT: ret i32 20 +; +entry: + %tmp = mul i8 undef, 15 + %cmp = icmp eq i8 %tmp, 10 + br i1 %cmp, label %bb3, label %bb4 + +bb3: ; preds = %bb2 + ret i32 10 + +bb4: ; preds = %bb2 + ret i32 20 +}