From 49e423ca30f4746949bbad734b8a6152d792d8bb Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Mon, 15 Sep 2014 18:26:58 +0000 Subject: [PATCH] [CodeGenPrepare][AddressingModeMatcher] Fix a think-o for the sext(zext) -> zext promotion introduced in r217629. We were returning the old sext instead of the new zext as the promoted instruction! Thanks Joerg Sonnenberger for the test case. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217800 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenPrepare.cpp | 16 +++--- test/CodeGen/X86/codegen-prepare-addrmode-sext.ll | 63 +++++++++++++++++++++++ 2 files changed, 72 insertions(+), 7 deletions(-) diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp index c8d203d9978..55476328963 100644 --- a/lib/CodeGen/CodeGenPrepare.cpp +++ b/lib/CodeGen/CodeGenPrepare.cpp @@ -1849,6 +1849,7 @@ Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt( // By construction, the operand of SExt is an instruction. Otherwise we cannot // get through it and this method should not be called. Instruction *SExtOpnd = cast(SExt->getOperand(0)); + Instruction *ExtInst = SExt; if (isa(SExtOpnd)) { // Replace sext(zext(opnd)) // => zext(opnd). @@ -1856,6 +1857,7 @@ Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt( TPT.createZExt(SExt, SExtOpnd->getOperand(0), SExt->getType()); TPT.replaceAllUsesWith(SExt, ZExt); TPT.eraseInstruction(SExt); + ExtInst = ZExt; } else { // Replace sext(trunc(opnd)) or sext(sext(opnd)) // => sext(opnd). @@ -1867,14 +1869,14 @@ Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt( if (SExtOpnd->use_empty()) TPT.eraseInstruction(SExtOpnd); - // Check if the sext is still needed. - if (SExt->getType() != SExt->getOperand(0)->getType()) - return SExt; + // Check if the extension is still needed. + if (ExtInst->getType() != ExtInst->getOperand(0)->getType()) + return ExtInst; - // At this point we have: sext ty opnd to ty. - // Reassign the uses of SExt to the opnd and remove SExt. - Value *NextVal = SExt->getOperand(0); - TPT.eraseInstruction(SExt, NextVal); + // At this point we have: ext ty opnd to ty. + // Reassign the uses of ExtInst to the opnd and remove ExtInst. + Value *NextVal = ExtInst->getOperand(0); + TPT.eraseInstruction(ExtInst, NextVal); return NextVal; } diff --git a/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll b/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll index af2d1dbeebf..aafbd3e2797 100644 --- a/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll +++ b/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll @@ -336,3 +336,66 @@ end: %final = load i32* %addr ret i32 %final } + +%struct.dns_packet = type { i32, i32, %union.anon } +%union.anon = type { i32 } + +@a = common global i32 0, align 4 +@b = common global i16 0, align 2 + +; We used to crash on this function because we did not return the right +; promoted instruction for %conv.i. +; Make sure we generate the right code now. +; CHECK-LABEL: @fn3 +; %conv.i is used twice and only one of its use is being promoted. +; Use it at the starting point for the matching. +; CHECK: %conv.i = zext i16 [[PLAIN_OPND:%[.a-zA-Z_0-9-]+]] to i32 +; CHECK-NEXT: [[PROMOTED_CONV:%[.a-zA-Z_0-9-]+]] = zext i16 [[PLAIN_OPND]] to i64 +; CHECK-NEXT: [[BASE:%[a-zA-Z_0-9-]+]] = ptrtoint %struct.dns_packet* %P to i64 +; CHECK-NEXT: [[ADD:%[a-zA-Z_0-9-]+]] = add i64 [[BASE]], [[PROMOTED_CONV]] +; CHECK-NEXT: [[ADDR:%[a-zA-Z_0-9-]+]] = add i64 [[ADD]], 7 +; CHECK-NEXT: [[CAST:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[ADDR]] to i8* +; CHECK-NEXT: load i8* [[CAST]], align 1 +define signext i16 @fn3(%struct.dns_packet* nocapture readonly %P) { +entry: + %tmp = getelementptr inbounds %struct.dns_packet* %P, i64 0, i32 2 + %data.i.i = bitcast %union.anon* %tmp to [0 x i8]* + br label %while.body.i.i + +while.body.i.i: ; preds = %while.body.i.i, %entry + %src.addr.0.i.i = phi i16 [ 0, %entry ], [ %inc.i.i, %while.body.i.i ] + %inc.i.i = add i16 %src.addr.0.i.i, 1 + %idxprom.i.i = sext i16 %src.addr.0.i.i to i64 + %arrayidx.i.i = getelementptr inbounds [0 x i8]* %data.i.i, i64 0, i64 %idxprom.i.i + %tmp1 = load i8* %arrayidx.i.i, align 1 + %conv2.i.i = zext i8 %tmp1 to i32 + %and.i.i = and i32 %conv2.i.i, 15 + store i32 %and.i.i, i32* @a, align 4 + %tobool.i.i = icmp eq i32 %and.i.i, 0 + br i1 %tobool.i.i, label %while.body.i.i, label %fn1.exit.i + +fn1.exit.i: ; preds = %while.body.i.i + %inc.i.i.lcssa = phi i16 [ %inc.i.i, %while.body.i.i ] + %conv.i = zext i16 %inc.i.i.lcssa to i32 + %sub.i = add nsw i32 %conv.i, -1 + %idxprom.i = sext i32 %sub.i to i64 + %arrayidx.i = getelementptr inbounds [0 x i8]* %data.i.i, i64 0, i64 %idxprom.i + %tmp2 = load i8* %arrayidx.i, align 1 + %conv2.i = sext i8 %tmp2 to i16 + store i16 %conv2.i, i16* @b, align 2 + %sub4.i = sub nsw i32 0, %conv.i + %conv5.i = zext i16 %conv2.i to i32 + %cmp.i = icmp sgt i32 %conv5.i, %sub4.i + br i1 %cmp.i, label %if.then.i, label %fn2.exit + +if.then.i: ; preds = %fn1.exit.i + %end.i = getelementptr inbounds %struct.dns_packet* %P, i64 0, i32 1 + %tmp3 = load i32* %end.i, align 4 + %sub7.i = add i32 %tmp3, 65535 + %conv8.i = trunc i32 %sub7.i to i16 + br label %fn2.exit + +fn2.exit: ; preds = %if.then.i, %fn1.exit.i + %retval.0.i = phi i16 [ %conv8.i, %if.then.i ], [ undef, %fn1.exit.i ] + ret i16 %retval.0.i +} -- 2.11.0