diff options
Diffstat (limited to 'test/CodeGen/X86/codegen-prepare-addrmode-sext.ll')
-rw-r--r-- | test/CodeGen/X86/codegen-prepare-addrmode-sext.ll | 213 |
1 files changed, 212 insertions, 1 deletions
diff --git a/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll b/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll index 78e1dd2..85bfff2 100644 --- a/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll +++ b/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll @@ -1,7 +1,7 @@ ; RUN: opt -S -codegenprepare %s -o - | FileCheck %s ; RUN: opt -S -codegenprepare -addr-sink-using-gep=1 %s -o - | FileCheck -check-prefix=CHECK-GEP %s ; This file tests the different cases what are involved when codegen prepare -; tries to get sign extension out of the way of addressing mode. +; tries to get sign/zero extension out of the way of addressing mode. ; This tests require an actual target as addressing mode decisions depends ; on the target. @@ -67,6 +67,43 @@ define i8 @oneArgPromotion(i32 %arg1, i8* %base) { ret i8 %res } +; Check that we are able to merge a sign extension with a zero extension. +; CHECK-LABEL: @oneArgPromotionZExt +; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64 +; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1ZEXT]], 1 +; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] +; CHECK: ret +define i8 @oneArgPromotionZExt(i8 %arg1, i8* %base) { + %zext = zext i8 %arg1 to i32 + %add = add nsw i32 %zext, 1 + %sextadd = sext i32 %add to i64 + %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd + %res = load i8* %arrayidx + ret i8 %res +} + +; When promoting a constant zext, the IR builder returns a constant, +; not an instruction. Make sure this is properly handled. This used +; to crash. +; Note: The constant zext is promoted, but does not help matching +; more thing in the addressing mode. Therefore the modification is +; rolled back. +; Still, this test case exercises the desired code path. +; CHECK-LABEL: @oneArgPromotionCstZExt +; CHECK: [[ZEXT:%[a-zA-Z_0-9-]+]] = zext i16 undef to i32 +; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i32 [[ZEXT]] to i64 +; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[SEXT]], 1 +; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] +; CHECK: ret +define i8 @oneArgPromotionCstZExt(i8* %base) { + %cst = zext i16 undef to i32 + %add = add nsw i32 %cst, 1 + %sextadd = sext i32 %add to i64 + %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd + %res = load i8* %arrayidx + ret i8 %res +} + ; Check that we do not promote truncate when we cannot determine the ; bits that are dropped. ; CHECK-LABEL: @oneArgPromotionBlockTrunc1 @@ -321,3 +358,177 @@ 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 +} + +; Check that we do not promote an extension if the non-wrapping flag does not +; match the kind of the extension. +; CHECK-LABEL: @noPromotionFlag +; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 %arg1, %arg2 +; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = zext i32 [[ADD]] to i64 +; CHECK: inttoptr i64 [[PROMOTED]] to i8* +; CHECK: ret +define i8 @noPromotionFlag(i32 %arg1, i32 %arg2) { + %add = add nsw i32 %arg1, %arg2 + %zextadd = zext i32 %add to i64 + %base = inttoptr i64 %zextadd to i8* + %res = load i8* %base + ret i8 %res +} + +; Check that we correctly promote both operands of the promotable add with zext. +; CHECK-LABEL: @twoArgsPromotionZExt +; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i32 %arg1 to i64 +; CHECK: [[ARG2ZEXT:%[a-zA-Z_0-9-]+]] = zext i32 %arg2 to i64 +; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], [[ARG2ZEXT]] +; CHECK: inttoptr i64 [[PROMOTED]] to i8* +; CHECK: ret +define i8 @twoArgsPromotionZExt(i32 %arg1, i32 %arg2) { + %add = add nuw i32 %arg1, %arg2 + %zextadd = zext i32 %add to i64 + %base = inttoptr i64 %zextadd to i8* + %res = load i8* %base + ret i8 %res +} + +; Check that we correctly promote constant arguments. +; CHECK-LABEL: @oneArgPromotionNegativeCstZExt +; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64 +; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 255 +; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] +; CHECK: ret +define i8 @oneArgPromotionNegativeCstZExt(i8 %arg1, i8* %base) { + %add = add nuw i8 %arg1, -1 + %zextadd = zext i8 %add to i64 + %arrayidx = getelementptr inbounds i8* %base, i64 %zextadd + %res = load i8* %arrayidx + ret i8 %res +} + +; Check that we are able to merge two zero extensions. +; CHECK-LABEL: @oneArgPromotionZExtZExt +; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64 +; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1 +; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] +; CHECK: ret +define i8 @oneArgPromotionZExtZExt(i8 %arg1, i8* %base) { + %zext = zext i8 %arg1 to i32 + %add = add nuw i32 %zext, 1 + %zextadd = zext i32 %add to i64 + %arrayidx = getelementptr inbounds i8* %base, i64 %zextadd + %res = load i8* %arrayidx + ret i8 %res +} + +; Check that we do not promote truncate when the dropped bits +; are of a different kind. +; CHECK-LABEL: @oneArgPromotionBlockTruncZExt +; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i32 +; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[ARG1SEXT]] to i8 +; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 [[ARG1TRUNC]] to i64 +; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1 +; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] +; CHECK: ret +define i8 @oneArgPromotionBlockTruncZExt(i1 %arg1, i8* %base) { + %sextarg1 = sext i1 %arg1 to i32 + %trunc = trunc i32 %sextarg1 to i8 + %add = add nuw i8 %trunc, 1 + %zextadd = zext i8 %add to i64 + %arrayidx = getelementptr inbounds i8* %base, i64 %zextadd + %res = load i8* %arrayidx + ret i8 %res +} + +; Check that we are able to promote truncate when we know all the bits +; that are dropped. +; CHECK-LABEL: @oneArgPromotionPassTruncZExt +; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i1 %arg1 to i64 +; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1 +; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] +; CHECK: ret +define i8 @oneArgPromotionPassTruncZExt(i1 %arg1, i8* %base) { + %sextarg1 = zext i1 %arg1 to i32 + %trunc = trunc i32 %sextarg1 to i8 + %add = add nuw i8 %trunc, 1 + %zextadd = zext i8 %add to i64 + %arrayidx = getelementptr inbounds i8* %base, i64 %zextadd + %res = load i8* %arrayidx + ret i8 %res +} + +; Check that we do not promote sext with zext. +; CHECK-LABEL: @oneArgPromotionBlockSExtZExt +; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i8 +; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 [[ARG1SEXT]] to i64 +; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1 +; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] +; CHECK: ret +define i8 @oneArgPromotionBlockSExtZExt(i1 %arg1, i8* %base) { + %sextarg1 = sext i1 %arg1 to i8 + %add = add nuw i8 %sextarg1, 1 + %zextadd = zext i8 %add to i64 + %arrayidx = getelementptr inbounds i8* %base, i64 %zextadd + %res = load i8* %arrayidx + ret i8 %res +} |