Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 3 additions & 34 deletions llvm/lib/Transforms/Utils/SimplifyCFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,37 +520,6 @@ static bool dominatesMergePoint(
return true;
}

/// Extract ConstantInt from value, looking through IntToPtr
/// and PointerNullValue. Return NULL if value is not a constant int.
static ConstantInt *getConstantInt(Value *V, const DataLayout &DL) {
// Normal constant int.
ConstantInt *CI = dyn_cast<ConstantInt>(V);
if (CI || !isa<Constant>(V) || !V->getType()->isPointerTy() ||
DL.isNonIntegralPointerType(V->getType()))
return CI;

// This is some kind of pointer constant. Turn it into a pointer-sized
// ConstantInt if possible.
IntegerType *PtrTy = cast<IntegerType>(DL.getIntPtrType(V->getType()));

// Null pointer means 0, see SelectionDAGBuilder::getValue(const Value*).
if (isa<ConstantPointerNull>(V))
return ConstantInt::get(PtrTy, 0);

// IntToPtr const int.
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
if (CE->getOpcode() == Instruction::IntToPtr)
if (ConstantInt *CI = dyn_cast<ConstantInt>(CE->getOperand(0))) {
// The constant is very likely to have the right type already.
if (CI->getType() == PtrTy)
return CI;
else
return cast<ConstantInt>(
ConstantFoldIntegerCast(CI, PtrTy, /*isSigned=*/false, DL));
}
return nullptr;
}

namespace {

/// Given a chain of or (||) or and (&&) comparison of a value against a
Expand Down Expand Up @@ -641,7 +610,7 @@ struct ConstantComparesGatherer {
ICmpInst *ICI;
ConstantInt *C;
if (!((ICI = dyn_cast<ICmpInst>(I)) &&
(C = getConstantInt(I->getOperand(1), DL)))) {
match(I->getOperand(1), m_ConstantInt(C)))) {
return false;
}

Expand Down Expand Up @@ -858,7 +827,7 @@ Value *SimplifyCFGOpt::isValueEqualityComparison(Instruction *TI) {
} else if (BranchInst *BI = dyn_cast<BranchInst>(TI))
if (BI->isConditional() && BI->getCondition()->hasOneUse()) {
if (ICmpInst *ICI = dyn_cast<ICmpInst>(BI->getCondition())) {
if (ICI->isEquality() && getConstantInt(ICI->getOperand(1), DL))
if (ICI->isEquality() && match(ICI->getOperand(1), m_ConstantInt()))
CV = ICI->getOperand(0);
} else if (auto *Trunc = dyn_cast<TruncInst>(BI->getCondition())) {
if (Trunc->hasNoUnsignedWrap())
Expand Down Expand Up @@ -895,7 +864,7 @@ BasicBlock *SimplifyCFGOpt::getValueEqualityComparisonCases(
ConstantInt *C;
if (auto *ICI = dyn_cast<ICmpInst>(Cond)) {
Pred = ICI->getPredicate();
C = getConstantInt(ICI->getOperand(1), DL);
match(ICI->getOperand(1), m_ConstantInt(C));
} else {
Pred = ICmpInst::ICMP_NE;
auto *Trunc = cast<TruncInst>(Cond);
Expand Down
86 changes: 69 additions & 17 deletions llvm/test/Transforms/SimplifyCFG/X86/MagicPointer.ll
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Test that simplifycfg can create switch instructions from constant pointers.
;
; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
Expand All @@ -19,14 +20,40 @@ declare i32 @puts(ptr)
declare i32 @puts_as1(ptr addrspace(1))

define void @f(ptr %x) nounwind ssp {
; CHECK-LABEL: @f(
; CHECK: switch i64 %magicptr
; CHECK: i64 0, label
; CHECK: i64 1, label
; CHECK: i64 2, label
; CHECK: i64 3, label
; CHECK: i64 4, label
; CHECK: }
; CHECK-LABEL: define void @f(
; CHECK-SAME: ptr [[X:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq ptr [[X]], null
; CHECK-NEXT: br i1 [[TOBOOL]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
; CHECK: [[IF_THEN]]:
; CHECK-NEXT: [[CALL:%.*]] = call i32 @puts(ptr @.str) #[[ATTR1:[0-9]+]]
; CHECK-NEXT: br label %[[IF_END21:.*]]
; CHECK: [[IF_ELSE]]:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[X]], inttoptr (i64 1 to ptr)
; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN2:.*]], label %[[IF_ELSE4:.*]]
; CHECK: [[IF_THEN2]]:
; CHECK-NEXT: [[CALL3:%.*]] = call i32 @puts(ptr @.str1) #[[ATTR1]]
; CHECK-NEXT: br label %[[IF_END21]]
; CHECK: [[IF_ELSE4]]:
; CHECK-NEXT: [[CMP6:%.*]] = icmp eq ptr [[X]], inttoptr (i64 2 to ptr)
; CHECK-NEXT: [[CMP8:%.*]] = icmp eq ptr [[X]], inttoptr (i64 3 to ptr)
; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP6]], [[CMP8]]
; CHECK-NEXT: br i1 [[OR_COND]], label %[[IF_THEN9:.*]], label %[[IF_ELSE11:.*]]
; CHECK: [[IF_THEN9]]:
; CHECK-NEXT: [[CALL10:%.*]] = call i32 @puts(ptr @.str2) #[[ATTR1]]
; CHECK-NEXT: br label %[[IF_END21]]
; CHECK: [[IF_ELSE11]]:
; CHECK-NEXT: [[CMP13:%.*]] = icmp eq ptr [[X]], inttoptr (i64 4 to ptr)
; CHECK-NEXT: br i1 [[CMP13]], label %[[IF_THEN14:.*]], label %[[IF_ELSE16:.*]]
; CHECK: [[IF_THEN14]]:
; CHECK-NEXT: [[CALL15:%.*]] = call i32 @puts(ptr @.str3) #[[ATTR1]]
; CHECK-NEXT: br label %[[IF_END21]]
; CHECK: [[IF_ELSE16]]:
; CHECK-NEXT: [[CALL18:%.*]] = call i32 @puts(ptr [[X]]) #[[ATTR1]]
; CHECK-NEXT: br label %[[IF_END21]]
; CHECK: [[IF_END21]]:
; CHECK-NEXT: ret void
;

entry:
%tobool = icmp eq ptr %x, null ; <i1> [#uses=1]
Expand Down Expand Up @@ -84,15 +111,40 @@ if.end21: ; preds = %if.end20, %if.then
; Is it useful to test a version where the ptrtoints are to the same
; size?
define void @f_as1(ptr addrspace(1) %x) nounwind ssp {
; CHECK-LABEL: @f_as1(
; CHECK: ptrtoint ptr addrspace(1) %x to i16
; CHECK: switch i16 %magicptr
; CHECK: i16 0, label
; CHECK: i16 1, label
; CHECK: i16 2, label
; CHECK: i16 3, label
; CHECK: i16 4, label
; CHECK: }
; CHECK-LABEL: define void @f_as1(
; CHECK-SAME: ptr addrspace(1) [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq ptr addrspace(1) [[X]], null
; CHECK-NEXT: br i1 [[TOBOOL]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
; CHECK: [[IF_THEN]]:
; CHECK-NEXT: [[CALL:%.*]] = call i32 @puts_as1(ptr addrspace(1) @.str_as1) #[[ATTR1]]
; CHECK-NEXT: br label %[[IF_END21:.*]]
; CHECK: [[IF_ELSE]]:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr addrspace(1) [[X]], inttoptr (i64 1 to ptr addrspace(1))
; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN2:.*]], label %[[IF_ELSE4:.*]]
; CHECK: [[IF_THEN2]]:
; CHECK-NEXT: [[CALL3:%.*]] = call i32 @puts_as1(ptr addrspace(1) @.str1_as1) #[[ATTR1]]
; CHECK-NEXT: br label %[[IF_END21]]
; CHECK: [[IF_ELSE4]]:
; CHECK-NEXT: [[CMP6:%.*]] = icmp eq ptr addrspace(1) [[X]], inttoptr (i64 2 to ptr addrspace(1))
; CHECK-NEXT: [[CMP8:%.*]] = icmp eq ptr addrspace(1) [[X]], inttoptr (i64 3 to ptr addrspace(1))
; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP6]], [[CMP8]]
; CHECK-NEXT: br i1 [[OR_COND]], label %[[IF_THEN9:.*]], label %[[IF_ELSE11:.*]]
; CHECK: [[IF_THEN9]]:
; CHECK-NEXT: [[CALL10:%.*]] = call i32 @puts_as1(ptr addrspace(1) @.str2_as1) #[[ATTR1]]
; CHECK-NEXT: br label %[[IF_END21]]
; CHECK: [[IF_ELSE11]]:
; CHECK-NEXT: [[CMP13:%.*]] = icmp eq ptr addrspace(1) [[X]], inttoptr (i64 4 to ptr addrspace(1))
; CHECK-NEXT: br i1 [[CMP13]], label %[[IF_THEN14:.*]], label %[[IF_ELSE16:.*]]
; CHECK: [[IF_THEN14]]:
; CHECK-NEXT: [[CALL15:%.*]] = call i32 @puts_as1(ptr addrspace(1) @.str3_as1) #[[ATTR1]]
; CHECK-NEXT: br label %[[IF_END21]]
; CHECK: [[IF_ELSE16]]:
; CHECK-NEXT: [[CALL18:%.*]] = call i32 @puts_as1(ptr addrspace(1) [[X]]) #[[ATTR1]]
; CHECK-NEXT: br label %[[IF_END21]]
; CHECK: [[IF_END21]]:
; CHECK-NEXT: ret void
;

entry:
%tobool = icmp eq ptr addrspace(1) %x, null ; <i1> [#uses=1]
Expand Down
18 changes: 8 additions & 10 deletions llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@ F: ; preds = %0

define void @test1_ptr(ptr %V) {
; CHECK-LABEL: @test1_ptr(
; CHECK-NEXT: [[MAGICPTR:%.*]] = ptrtoint ptr [[V:%.*]] to i40
; CHECK-NEXT: switch i40 [[MAGICPTR]], label [[F:%.*]] [
; CHECK-NEXT: i40 17, label [[T:%.*]]
; CHECK-NEXT: i40 4, label [[T]]
; CHECK-NEXT: ]
; CHECK-NEXT: [[C1:%.*]] = icmp eq ptr [[V:%.*]], inttoptr (i32 4 to ptr)
; CHECK-NEXT: [[C2:%.*]] = icmp eq ptr [[V]], inttoptr (i32 17 to ptr)
; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]]
; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]]
; CHECK: common.ret:
; CHECK-NEXT: ret void
; CHECK: T:
Expand All @@ -63,11 +62,10 @@ F: ; preds = %0

define void @test1_ptr_as1(ptr addrspace(1) %V) {
; CHECK-LABEL: @test1_ptr_as1(
; CHECK-NEXT: [[MAGICPTR:%.*]] = ptrtoint ptr addrspace(1) [[V:%.*]] to i40
; CHECK-NEXT: switch i40 [[MAGICPTR]], label [[F:%.*]] [
; CHECK-NEXT: i40 17, label [[T:%.*]]
; CHECK-NEXT: i40 4, label [[T]]
; CHECK-NEXT: ]
; CHECK-NEXT: [[C1:%.*]] = icmp eq ptr addrspace(1) [[V:%.*]], inttoptr (i32 4 to ptr addrspace(1))
; CHECK-NEXT: [[C2:%.*]] = icmp eq ptr addrspace(1) [[V]], inttoptr (i32 17 to ptr addrspace(1))
; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]]
; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]]
; CHECK: common.ret:
; CHECK-NEXT: ret void
; CHECK: T:
Expand Down
56 changes: 28 additions & 28 deletions llvm/test/Transforms/SimplifyCFG/switch_create.ll
Original file line number Diff line number Diff line change
Expand Up @@ -61,20 +61,19 @@ F:
}

define void @test1_ptr(ptr %V) {
; DL-LABEL: @test1_ptr(
; DL-NEXT: [[MAGICPTR:%.*]] = ptrtoint ptr [[V:%.*]] to i32
; DL-NEXT: switch i32 [[MAGICPTR]], label [[F:%.*]] [
; DL-NEXT: i32 17, label [[T:%.*]]
; DL-NEXT: i32 4, label [[T]]
; DL-NEXT: ]
; DL: common.ret:
; DL-NEXT: ret void
; DL: T:
; DL-NEXT: call void @foo1()
; DL-NEXT: br label [[COMMON_RET:%.*]]
; DL: F:
; DL-NEXT: call void @foo2()
; DL-NEXT: br label [[COMMON_RET]]
; CHECK-LABEL: @test1_ptr(
; CHECK-NEXT: [[C1:%.*]] = icmp eq ptr [[V:%.*]], inttoptr (i32 4 to ptr)
; CHECK-NEXT: [[C2:%.*]] = icmp eq ptr [[V]], inttoptr (i32 17 to ptr)
; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]]
; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]]
; CHECK: common.ret:
; CHECK-NEXT: ret void
; CHECK: T:
; CHECK-NEXT: call void @foo1()
; CHECK-NEXT: br label [[COMMON_RET:%.*]]
; CHECK: F:
; CHECK-NEXT: call void @foo2()
; CHECK-NEXT: br label [[COMMON_RET]]
;
%C1 = icmp eq ptr %V, inttoptr (i32 4 to ptr)
%C2 = icmp eq ptr %V, inttoptr (i32 17 to ptr)
Expand All @@ -89,20 +88,19 @@ F: ; preds = %0
}

define void @test1_ptr_as1(ptr addrspace(1) %V) {
; DL-LABEL: @test1_ptr_as1(
; DL-NEXT: [[MAGICPTR:%.*]] = ptrtoint ptr addrspace(1) [[V:%.*]] to i16
; DL-NEXT: switch i16 [[MAGICPTR]], label [[F:%.*]] [
; DL-NEXT: i16 17, label [[T:%.*]]
; DL-NEXT: i16 4, label [[T]]
; DL-NEXT: ]
; DL: common.ret:
; DL-NEXT: ret void
; DL: T:
; DL-NEXT: call void @foo1()
; DL-NEXT: br label [[COMMON_RET:%.*]]
; DL: F:
; DL-NEXT: call void @foo2()
; DL-NEXT: br label [[COMMON_RET]]
; CHECK-LABEL: @test1_ptr_as1(
; CHECK-NEXT: [[C1:%.*]] = icmp eq ptr addrspace(1) [[V:%.*]], inttoptr (i32 4 to ptr addrspace(1))
; CHECK-NEXT: [[C2:%.*]] = icmp eq ptr addrspace(1) [[V]], inttoptr (i32 17 to ptr addrspace(1))
; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]]
; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]]
; CHECK: common.ret:
; CHECK-NEXT: ret void
; CHECK: T:
; CHECK-NEXT: call void @foo1()
; CHECK-NEXT: br label [[COMMON_RET:%.*]]
; CHECK: F:
; CHECK-NEXT: call void @foo2()
; CHECK-NEXT: br label [[COMMON_RET]]
;
%C1 = icmp eq ptr addrspace(1) %V, inttoptr (i32 4 to ptr addrspace(1))
%C2 = icmp eq ptr addrspace(1) %V, inttoptr (i32 17 to ptr addrspace(1))
Expand Down Expand Up @@ -1313,3 +1311,5 @@ if.then:
if.end:
ret void
}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; DL: {{.*}}