From 0c23f4cf6c8f94d3a678e1cb8683b1a85064ed70 Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Fri, 13 Feb 2015 16:33:34 +0000 Subject: [PATCH] [InstCombine] Fix regression introduced at r227197. This patch fixes a problem I accidentally introduced in an instruction combine on select instructions added at r227197. That revision taught the instruction combiner how to fold a cttz/ctlz followed by a icmp plus select into a single cttz/ctlz with flag 'is_zero_undef' cleared. However, the new rule added at r227197 would have produced wrong results in the case where a cttz/ctlz with flag 'is_zero_undef' cleared was follwed by a zero-extend or truncate. In that case, the folded instruction would have been inserted in a wrong location thus leaving the CFG in an inconsistent state. This patch fixes the problem and add two reproducible test cases to existing test 'InstCombine/select-cmp-cttz-ctlz.ll'. llvm-svn: 229124 --- .../InstCombine/InstCombineSelect.cpp | 16 +++++------ .../InstCombine/select-cmp-cttz-ctlz.ll | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index 0debe63faf4..b92d90d0789 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -482,16 +482,12 @@ static Value *foldSelectCttzCtlz(ICmpInst *ICI, Value *TrueVal, Value *FalseVal, match(Count, m_Intrinsic(m_Specific(CmpLHS)))) { IntrinsicInst *II = cast(Count); IRBuilder<> Builder(II); - if (cast(II->getArgOperand(1))->isOne()) { - // Explicitly clear the 'undef_on_zero' flag. - IntrinsicInst *NewI = cast(II->clone()); - Type *Ty = NewI->getArgOperand(1)->getType(); - NewI->setArgOperand(1, Constant::getNullValue(Ty)); - Builder.Insert(NewI); - Count = NewI; - } - - return Builder.CreateZExtOrTrunc(Count, ValueOnZero->getType()); + // Explicitly clear the 'undef_on_zero' flag. + IntrinsicInst *NewI = cast(II->clone()); + Type *Ty = NewI->getArgOperand(1)->getType(); + NewI->setArgOperand(1, Constant::getNullValue(Ty)); + Builder.Insert(NewI); + return Builder.CreateZExtOrTrunc(NewI, ValueOnZero->getType()); } return nullptr; diff --git a/test/Transforms/InstCombine/select-cmp-cttz-ctlz.ll b/test/Transforms/InstCombine/select-cmp-cttz-ctlz.ll index 390e6bc51f8..894bf6db0a4 100644 --- a/test/Transforms/InstCombine/select-cmp-cttz-ctlz.ll +++ b/test/Transforms/InstCombine/select-cmp-cttz-ctlz.ll @@ -292,6 +292,33 @@ entry: ret i16 %cond } +define i64 @select_bug1(i32 %x) { +; CHECK-LABEL: @select_bug1( +; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) +; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64 +; CHECK-NEXT: ret i64 [[VAR2]] +entry: + %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) + %conv = zext i32 %0 to i64 + %tobool = icmp ne i32 %x, 0 + %cond = select i1 %tobool, i64 %conv, i64 32 + ret i64 %cond +} + +define i16 @select_bug2(i32 %x) { +; CHECK-LABEL: @select_bug2( +; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) +; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16 +; CHECK-NEXT: ret i16 [[VAR2]] +entry: + %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) + %conv = trunc i32 %0 to i16 + %tobool = icmp ne i32 %x, 0 + %cond = select i1 %tobool, i16 %conv, i16 32 + ret i16 %cond +} + + declare i16 @llvm.ctlz.i16(i16, i1) declare i32 @llvm.ctlz.i32(i32, i1) declare i64 @llvm.ctlz.i64(i64, i1)