aboutsummaryrefslogtreecommitdiffstats
path: root/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGen/X86/codegen-prepare-addrmode-sext.ll')
-rw-r--r--test/CodeGen/X86/codegen-prepare-addrmode-sext.ll213
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
+}