Skip to content

Commit

Permalink
Revert "Reland [MergeICmps] Adapt to non-eq comparisons, bugfix"
Browse files Browse the repository at this point in the history
Causes miscompile. See https://reviews.llvm.org/D141188.

This reverts commit fb2c98a
  • Loading branch information
metaflow committed Jun 6, 2023
1 parent 3373c84 commit df3a8f3
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 105 deletions.
81 changes: 19 additions & 62 deletions llvm/lib/Transforms/Scalar/MergeICmps.cpp
Expand Up @@ -331,10 +331,10 @@ std::optional<BCECmp> visitICmp(const ICmpInst *const CmpI,

// Visit the given comparison block. If this is a comparison between two valid
// BCE atoms, returns the comparison.
std::optional<BCECmpBlock>
visitCmpBlock(Value *const Baseline, ICmpInst::Predicate &Predicate,
Value *const Val, BasicBlock *const Block,
const BasicBlock *const PhiBlock, BaseIdentifier &BaseId) {
std::optional<BCECmpBlock> visitCmpBlock(Value *const Val,
BasicBlock *const Block,
const BasicBlock *const PhiBlock,
BaseIdentifier &BaseId) {
if (Block->empty())
return std::nullopt;
auto *const BranchI = dyn_cast<BranchInst>(Block->getTerminator());
Expand All @@ -349,27 +349,15 @@ visitCmpBlock(Value *const Baseline, ICmpInst::Predicate &Predicate,
// that this does not mean that this is the last incoming value, blocks
// can be reordered).
Cond = Val;
const auto *const ConstBase = cast<ConstantInt>(Baseline);
assert(ConstBase->getType()->isIntegerTy(1) &&
"Select condition is not an i1?");
ExpectedPredicate =
ConstBase->isOne() ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ;

// Remember the correct predicate.
Predicate = ExpectedPredicate;
ExpectedPredicate = ICmpInst::ICMP_EQ;
} else {
// All the incoming values must be consistent.
if (Baseline != Val)
return std::nullopt;
// In this case, we expect a constant incoming value (the comparison is
// chained).
const auto *const Const = cast<ConstantInt>(Val);
assert(Const->getType()->isIntegerTy(1) &&
"Incoming value is not an i1?");
LLVM_DEBUG(dbgs() << "const i1 value\n");
if (!Const->isZero() && !Const->isOne())
LLVM_DEBUG(dbgs() << "const\n");
if (!Const->isZero())
return std::nullopt;
LLVM_DEBUG(dbgs() << *Const << "\n");
LLVM_DEBUG(dbgs() << "false\n");
assert(BranchI->getNumSuccessors() == 2 && "expecting a cond branch");
BasicBlock *const FalseBlock = BranchI->getSuccessor(1);
Cond = BranchI->getCondition();
Expand Down Expand Up @@ -430,8 +418,6 @@ class BCECmpChain {
std::vector<ContiguousBlocks> MergedBlocks_;
// The original entry block (before sorting);
BasicBlock *EntryBlock_;
// Remember the predicate type of the chain.
ICmpInst::Predicate Predicate_;
};

static bool areContiguous(const BCECmpBlock &First, const BCECmpBlock &Second) {
Expand Down Expand Up @@ -490,13 +476,10 @@ BCECmpChain::BCECmpChain(const std::vector<BasicBlock *> &Blocks, PHINode &Phi,
// Now look inside blocks to check for BCE comparisons.
std::vector<BCECmpBlock> Comparisons;
BaseIdentifier BaseId;
Value *const Baseline = Phi.getIncomingValueForBlock(Blocks[0]);
Predicate_ = CmpInst::BAD_ICMP_PREDICATE;
for (BasicBlock *const Block : Blocks) {
assert(Block && "invalid block");
std::optional<BCECmpBlock> Comparison =
visitCmpBlock(Baseline, Predicate_, Phi.getIncomingValueForBlock(Block),
Block, Phi.getParent(), BaseId);
std::optional<BCECmpBlock> Comparison = visitCmpBlock(
Phi.getIncomingValueForBlock(Block), Block, Phi.getParent(), BaseId);
if (!Comparison) {
LLVM_DEBUG(dbgs() << "chain with invalid BCECmpBlock, no merge.\n");
return;
Expand Down Expand Up @@ -615,28 +598,12 @@ class MergedBlockName {
};
} // namespace

// Check whether the current comparisons is the last comparisons.
// Only the last comparisons chain include the last link (unconditional jmp).
// Due to reordering of contiguous comparison blocks, the unconditional
// comparison of a chain maybe not placed at the end of the array comparisons.
static bool isLastLinkComparison(ArrayRef<BCECmpBlock> Comparisons) {
for (unsigned i = 0; i < Comparisons.size(); i++) {
BasicBlock *const BB = Comparisons[i].BB;
auto *const BranchI = cast<BranchInst>(BB->getTerminator());
// Only the last comparisons chain include the unconditional jmp
if (BranchI->isUnconditional())
return true;
}
return false;
}

// Merges the given contiguous comparison blocks into one memcmp block.
static BasicBlock *mergeComparisons(ArrayRef<BCECmpBlock> Comparisons,
BasicBlock *const InsertBefore,
BasicBlock *const NextCmpBlock,
PHINode &Phi, const TargetLibraryInfo &TLI,
AliasAnalysis &AA, DomTreeUpdater &DTU,
ICmpInst::Predicate Predicate) {
AliasAnalysis &AA, DomTreeUpdater &DTU) {
assert(!Comparisons.empty() && "merging zero comparisons");
LLVMContext &Context = NextCmpBlock->getContext();
const BCECmpBlock &FirstCmp = Comparisons[0];
Expand All @@ -657,7 +624,7 @@ static BasicBlock *mergeComparisons(ArrayRef<BCECmpBlock> Comparisons,
else
Rhs = FirstCmp.Rhs().LoadI->getPointerOperand();

Value *ICmpValue = nullptr;
Value *IsEqual = nullptr;
LLVM_DEBUG(dbgs() << "Merging " << Comparisons.size() << " comparisons -> "
<< BB->getName() << "\n");

Expand All @@ -671,11 +638,6 @@ static BasicBlock *mergeComparisons(ArrayRef<BCECmpBlock> Comparisons,
ToSplit->split(BB, AA);
}

// For a Icmp chain, the Predicate is record the last link in the chain of
// comparisons. When we spilt the chain The new spilted chain of comparisons
// is end with ICMP_EQ.
ICmpInst::Predicate Pred =
isLastLinkComparison(Comparisons) ? Predicate : ICmpInst::ICMP_EQ;
if (Comparisons.size() == 1) {
LLVM_DEBUG(dbgs() << "Only one comparison, updating branches\n");
// Use clone to keep the metadata
Expand All @@ -684,7 +646,7 @@ static BasicBlock *mergeComparisons(ArrayRef<BCECmpBlock> Comparisons,
LhsLoad->replaceUsesOfWith(LhsLoad->getOperand(0), Lhs);
RhsLoad->replaceUsesOfWith(RhsLoad->getOperand(0), Rhs);
// There are no blocks to merge, just do the comparison.
ICmpValue = Builder.CreateICmp(Pred, LhsLoad, RhsLoad);
IsEqual = Builder.CreateICmpEQ(LhsLoad, RhsLoad);
} else {
const unsigned TotalSizeBits = std::accumulate(
Comparisons.begin(), Comparisons.end(), 0u,
Expand All @@ -700,24 +662,21 @@ static BasicBlock *mergeComparisons(ArrayRef<BCECmpBlock> Comparisons,
Lhs, Rhs,
ConstantInt::get(Builder.getIntNTy(SizeTBits), TotalSizeBits / 8),
Builder, DL, &TLI);
ICmpValue = Builder.CreateICmp(
Pred, MemCmpCall, ConstantInt::get(Builder.getIntNTy(IntBits), 0));
IsEqual = Builder.CreateICmpEQ(
MemCmpCall, ConstantInt::get(Builder.getIntNTy(IntBits), 0));
}

BasicBlock *const PhiBB = Phi.getParent();
// Add a branch to the next basic block in the chain.
if (NextCmpBlock == PhiBB) {
// Continue to phi, passing it the comparison result.
Builder.CreateBr(PhiBB);
Phi.addIncoming(ICmpValue, BB);
Phi.addIncoming(IsEqual, BB);
DTU.applyUpdates({{DominatorTree::Insert, BB, PhiBB}});
} else {
// Continue to next block if equal, exit to phi else.
Builder.CreateCondBr(ICmpValue, NextCmpBlock, PhiBB);
Value *ConstantVal = Predicate == CmpInst::ICMP_NE
? ConstantInt::getTrue(Context)
: ConstantInt::getFalse(Context);
Phi.addIncoming(ConstantVal, BB);
Builder.CreateCondBr(IsEqual, NextCmpBlock, PhiBB);
Phi.addIncoming(ConstantInt::getFalse(Context), BB);
DTU.applyUpdates({{DominatorTree::Insert, BB, NextCmpBlock},
{DominatorTree::Insert, BB, PhiBB}});
}
Expand All @@ -734,11 +693,9 @@ bool BCECmpChain::simplify(const TargetLibraryInfo &TLI, AliasAnalysis &AA,
// so that the next block is always available to branch to.
BasicBlock *InsertBefore = EntryBlock_;
BasicBlock *NextCmpBlock = Phi_.getParent();
assert(Predicate_ != CmpInst::BAD_ICMP_PREDICATE &&
"Got the chain of comparisons");
for (const auto &Blocks : reverse(MergedBlocks_)) {
InsertBefore = NextCmpBlock = mergeComparisons(
Blocks, InsertBefore, NextCmpBlock, Phi_, TLI, AA, DTU, Predicate_);
Blocks, InsertBefore, NextCmpBlock, Phi_, TLI, AA, DTU);
}

// Replace the original cmp chain with the new cmp chain by pointing all
Expand Down
140 changes: 97 additions & 43 deletions llvm/test/Transforms/MergeICmps/X86/pr59740.ll
Expand Up @@ -8,12 +8,35 @@

define noundef i1 @full_sequent_ne(ptr nocapture readonly align 1 dereferenceable(4) %s0, ptr nocapture readonly align 1 dereferenceable(4) %s1) {
; CHECK-LABEL: @full_sequent_ne(
; CHECK-NEXT: "bb0+bb1+bb2+bb3":
; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(ptr [[S0:%.*]], ptr [[S1:%.*]], i64 4)
; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i32 [[MEMCMP]], 0
; CHECK-NEXT: br label [[BB4:%.*]]
; CHECK-NEXT: bb0:
; CHECK-NEXT: [[V0:%.*]] = load i8, ptr [[S0:%.*]], align 1
; CHECK-NEXT: [[V1:%.*]] = load i8, ptr [[S1:%.*]], align 1
; CHECK-NEXT: [[CMP0:%.*]] = icmp eq i8 [[V0]], [[V1]]
; CHECK-NEXT: br i1 [[CMP0]], label [[BB1:%.*]], label [[BB4:%.*]]
; CHECK: bb1:
; CHECK-NEXT: [[S2:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[S0]], i64 0, i32 1
; CHECK-NEXT: [[V2:%.*]] = load i8, ptr [[S2]], align 1
; CHECK-NEXT: [[S3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S1]], i64 0, i32 1
; CHECK-NEXT: [[V3:%.*]] = load i8, ptr [[S3]], align 1
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[V2]], [[V3]]
; CHECK-NEXT: br i1 [[CMP1]], label [[BB2:%.*]], label [[BB4]]
; CHECK: bb2:
; CHECK-NEXT: [[S4:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S0]], i64 0, i32 2
; CHECK-NEXT: [[V4:%.*]] = load i8, ptr [[S4]], align 1
; CHECK-NEXT: [[S5:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S1]], i64 0, i32 2
; CHECK-NEXT: [[V5:%.*]] = load i8, ptr [[S5]], align 1
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[V4]], [[V5]]
; CHECK-NEXT: br i1 [[CMP2]], label [[BB3:%.*]], label [[BB4]]
; CHECK: bb3:
; CHECK-NEXT: [[S6:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S0]], i64 0, i32 3
; CHECK-NEXT: [[V6:%.*]] = load i8, ptr [[S6]], align 1
; CHECK-NEXT: [[S7:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S1]], i64 0, i32 3
; CHECK-NEXT: [[V7:%.*]] = load i8, ptr [[S7]], align 1
; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i8 [[V6]], [[V7]]
; CHECK-NEXT: br label [[BB4]]
; CHECK: bb4:
; CHECK-NEXT: ret i1 [[TMP0]]
; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ true, [[BB0:%.*]] ], [ true, [[BB1]] ], [ true, [[BB2]] ], [ [[CMP3]], [[BB3]] ]
; CHECK-NEXT: ret i1 [[CMP]]
;
bb0:
%v0 = load i8, ptr %s0, align 1
Expand Down Expand Up @@ -136,19 +159,27 @@ bb3: ; preds = %bb0, %bb1, %bb2
; https://alive2.llvm.org/ce/z/sL5Uz6
define noundef i1 @partial_sequent_ne(ptr nocapture readonly dereferenceable(16) %s0, ptr nocapture readonly dereferenceable(16) %s1) {
; CHECK-LABEL: @partial_sequent_ne(
; CHECK-NEXT: bb01:
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[S0:%.*]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[S1:%.*]], align 8
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
; CHECK-NEXT: br i1 [[TMP2]], label %"bb1+bb2", label [[BB3:%.*]]
; CHECK: "bb1+bb2":
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT1_S:%.*]], ptr [[S0]], i64 0, i32 2
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT1_S]], ptr [[S1]], i64 0, i32 2
; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(ptr [[TMP3]], ptr [[TMP4]], i64 5)
; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i32 [[MEMCMP]], 0
; CHECK-NEXT: bb0:
; CHECK-NEXT: [[V0:%.*]] = load i32, ptr [[S0:%.*]], align 8
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[S1:%.*]], align 8
; CHECK-NEXT: [[CMP0:%.*]] = icmp eq i32 [[V0]], [[V1]]
; CHECK-NEXT: br i1 [[CMP0]], label [[BB1:%.*]], label [[BB3:%.*]]
; CHECK: bb1:
; CHECK-NEXT: [[S2:%.*]] = getelementptr inbounds [[STRUCT1_S:%.*]], ptr [[S0]], i64 0, i32 2
; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[S2]], align 8
; CHECK-NEXT: [[S3:%.*]] = getelementptr inbounds [[STRUCT1_S]], ptr [[S1]], i64 0, i32 2
; CHECK-NEXT: [[V3:%.*]] = load i32, ptr [[S3]], align 8
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[V2]], [[V3]]
; CHECK-NEXT: br i1 [[CMP1]], label [[BB2:%.*]], label [[BB3]]
; CHECK: bb2:
; CHECK-NEXT: [[S6:%.*]] = getelementptr inbounds [[STRUCT1_S]], ptr [[S0]], i64 0, i32 3
; CHECK-NEXT: [[V6:%.*]] = load i8, ptr [[S6]], align 1
; CHECK-NEXT: [[S7:%.*]] = getelementptr inbounds [[STRUCT1_S]], ptr [[S1]], i64 0, i32 3
; CHECK-NEXT: [[V7:%.*]] = load i8, ptr [[S7]], align 1
; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i8 [[V6]], [[V7]]
; CHECK-NEXT: br label [[BB3]]
; CHECK: bb3:
; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ [[TMP5]], %"bb1+bb2" ], [ true, [[BB01:%.*]] ]
; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ true, [[BB0:%.*]] ], [ true, [[BB1]] ], [ [[CMP3]], [[BB2]] ]
; CHECK-NEXT: ret i1 [[CMP]]
;
bb0:
Expand Down Expand Up @@ -181,26 +212,34 @@ bb3: ; preds = %bb0, %bb1, %bb2
; https://alive2.llvm.org/ce/z/EQtb_S
define i1 @WebrtcVideoStats(ptr nocapture noundef dereferenceable(16) %S0, ptr nocapture noundef dereferenceable(16) %S1) {
; CHECK-LABEL: @WebrtcVideoStats(
; CHECK-NEXT: bb02:
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[S0:%.*]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[S1:%.*]], align 4
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP0]], [[TMP1]]
; CHECK-NEXT: br i1 [[TMP2]], label %"bb1+bb2", label [[BB4:%.*]]
; CHECK: "bb1+bb2":
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.media::WebrtcVideoStatsDB::VideoDescKey", ptr [[S0]], i64 0, i32 1
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds %"struct.media::WebrtcVideoStatsDB::VideoDescKey", ptr [[S1]], i64 0, i32 1
; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(ptr [[TMP3]], ptr [[TMP4]], i64 5)
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[MEMCMP]], 0
; CHECK-NEXT: br i1 [[TMP5]], label [[BB31:%.*]], label [[BB4]]
; CHECK: bb31:
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds %"struct.media::WebrtcVideoStatsDB::VideoDescKey", ptr [[S0]], i64 0, i32 3
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds %"struct.media::WebrtcVideoStatsDB::VideoDescKey", ptr [[S1]], i64 0, i32 3
; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP6]], align 4
; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP7]], align 4
; CHECK-NEXT: [[TMP10:%.*]] = icmp ne i32 [[TMP8]], [[TMP9]]
; CHECK-NEXT: bb0:
; CHECK-NEXT: [[V0:%.*]] = load i8, ptr [[S0:%.*]], align 4
; CHECK-NEXT: [[V1:%.*]] = load i8, ptr [[S1:%.*]], align 4
; CHECK-NEXT: [[CMP0:%.*]] = icmp eq i8 [[V0]], [[V1]]
; CHECK-NEXT: br i1 [[CMP0]], label [[BB1:%.*]], label [[BB4:%.*]]
; CHECK: bb1:
; CHECK-NEXT: [[BASE2:%.*]] = getelementptr inbounds %"struct.media::WebrtcVideoStatsDB::VideoDescKey", ptr [[S0]], i64 0, i32 1
; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[BASE2]], align 4
; CHECK-NEXT: [[BASE3:%.*]] = getelementptr inbounds %"struct.media::WebrtcVideoStatsDB::VideoDescKey", ptr [[S1]], i64 0, i32 1
; CHECK-NEXT: [[V3:%.*]] = load i32, ptr [[BASE3]], align 4
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[V2]], [[V3]]
; CHECK-NEXT: br i1 [[CMP1]], label [[BB2:%.*]], label [[BB4]]
; CHECK: bb2:
; CHECK-NEXT: [[BASE4:%.*]] = getelementptr inbounds %"struct.media::WebrtcVideoStatsDB::VideoDescKey", ptr [[S0]], i64 0, i32 2
; CHECK-NEXT: [[V4:%.*]] = load i8, ptr [[BASE4]], align 4
; CHECK-NEXT: [[BASE5:%.*]] = getelementptr inbounds %"struct.media::WebrtcVideoStatsDB::VideoDescKey", ptr [[S1]], i64 0, i32 2
; CHECK-NEXT: [[V5:%.*]] = load i8, ptr [[BASE5]], align 4
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[V4]], [[V5]]
; CHECK-NEXT: br i1 [[CMP2]], label [[BB3:%.*]], label [[BB4]]
; CHECK: bb3:
; CHECK-NEXT: [[BASE6:%.*]] = getelementptr inbounds %"struct.media::WebrtcVideoStatsDB::VideoDescKey", ptr [[S0]], i64 0, i32 3
; CHECK-NEXT: [[V6:%.*]] = load i32, ptr [[BASE6]], align 4
; CHECK-NEXT: [[BASE7:%.*]] = getelementptr inbounds %"struct.media::WebrtcVideoStatsDB::VideoDescKey", ptr [[S1]], i64 0, i32 3
; CHECK-NEXT: [[V7:%.*]] = load i32, ptr [[BASE7]], align 4
; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i32 [[V6]], [[V7]]
; CHECK-NEXT: br label [[BB4]]
; CHECK: bb4:
; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ [[TMP10]], [[BB31]] ], [ true, %"bb1+bb2" ], [ true, [[BB02:%.*]] ]
; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ [[CMP3]], [[BB3]] ], [ true, [[BB2]] ], [ true, [[BB1]] ], [ true, [[BB0:%.*]] ]
; CHECK-NEXT: ret i1 [[RESULT]]
;
bb0:
Expand Down Expand Up @@ -240,18 +279,33 @@ bb4: ; preds = %bb3, %bb2, %bb1, %

; the comparison link sequence will be reordered according the memory offset,
; and the unconditionla comparison will not at the end of the chain.
define i1 @full_revert_order_ne(ptr nocapture noundef nonnull readonly dereferenceable(24) %0,
define i1 @full_revert_order_ne(ptr nocapture noundef nonnull readonly dereferenceable(24) %0, ptr nocapture noundef nonnull readonly dereferenceable(24) %1) {
; CHECK-LABEL: @full_revert_order_ne(
; CHECK-NEXT: "bb2+bb1+bb0":
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[C:%.*]], ptr [[TMP0:%.*]], i64 0, i32 0
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[C]], ptr [[TMP1:%.*]], i64 0, i32 0
; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(ptr [[TMP2]], ptr [[TMP3]], i64 12)
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[MEMCMP]], 0
; CHECK-NEXT: br label [[BB3:%.*]]
; CHECK-NEXT: bb0:
; CHECK-NEXT: [[S0:%.*]] = getelementptr inbounds [[C:%.*]], ptr [[TMP0:%.*]], i64 0, i32 2
; CHECK-NEXT: [[V0:%.*]] = load i32, ptr [[S0]], align 4
; CHECK-NEXT: [[S1:%.*]] = getelementptr inbounds [[C]], ptr [[TMP1:%.*]], i64 0, i32 2
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[S1]], align 4
; CHECK-NEXT: [[CMP0:%.*]] = icmp eq i32 [[V0]], [[V1]]
; CHECK-NEXT: br i1 [[CMP0]], label [[BB1:%.*]], label [[BB3:%.*]]
; CHECK: bb1:
; CHECK-NEXT: [[S2:%.*]] = getelementptr inbounds [[C]], ptr [[TMP0]], i64 0, i32 1
; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[S2]], align 4
; CHECK-NEXT: [[S3:%.*]] = getelementptr inbounds [[C]], ptr [[TMP1]], i64 0, i32 1
; CHECK-NEXT: [[V3:%.*]] = load i32, ptr [[S3]], align 4
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[V2]], [[V3]]
; CHECK-NEXT: br i1 [[CMP1]], label [[BB2:%.*]], label [[BB3]]
; CHECK: bb2:
; CHECK-NEXT: [[S4:%.*]] = getelementptr inbounds [[C]], ptr [[TMP0]], i64 0, i32 0
; CHECK-NEXT: [[V4:%.*]] = load i32, ptr [[S4]], align 4
; CHECK-NEXT: [[S5:%.*]] = getelementptr inbounds [[C]], ptr [[TMP1]], i64 0, i32 0
; CHECK-NEXT: [[V5:%.*]] = load i32, ptr [[S5]], align 4
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[V4]], [[V5]]
; CHECK-NEXT: br label [[BB3]]
; CHECK: bb3:
; CHECK-NEXT: ret i1 [[TMP4]]
; CHECK-NEXT: [[CMP3:%.*]] = phi i1 [ true, [[BB1]] ], [ true, [[BB0:%.*]] ], [ [[CMP2]], [[BB2]] ]
; CHECK-NEXT: ret i1 [[CMP3]]
;
ptr nocapture noundef nonnull readonly dereferenceable(24) %1) {
bb0:
%s0 = getelementptr inbounds %"c", ptr %0, i64 0, i32 2
%v0 = load i32, ptr %s0, align 4
Expand Down

0 comments on commit df3a8f3

Please sign in to comment.