1; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s 2 3;; Simple case: a zext nneg can be replaced with a sext. Make sure BasicAA 4;; understands that. 5define void @t1(i32 %a, i32 %b) { 6; CHECK-LABEL: Function: t1 7; CHECK: NoAlias: float* %gep1, float* %gep2 8 9 %1 = alloca [8 x float], align 4 10 %or1 = or i32 %a, 1 11 %2 = sext i32 %or1 to i64 12 %gep1 = getelementptr inbounds float, ptr %1, i64 %2 13 14 %shl1 = shl i32 %b, 1 15 %3 = zext nneg i32 %shl1 to i64 16 %gep2 = getelementptr inbounds float, ptr %1, i64 %3 17 18 load float, ptr %gep1 19 load float, ptr %gep2 20 ret void 21} 22 23;; A (zext nneg (sext V)) is equivalent to a (zext (sext V)) as long as the 24;; total number of zext+sext bits is the same for both. 25define void @t2(i8 %a, i8 %b) { 26; CHECK-LABEL: Function: t2 27; CHECK: NoAlias: float* %gep1, float* %gep2 28 %1 = alloca [8 x float], align 4 29 %or1 = or i8 %a, 1 30 %2 = sext i8 %or1 to i32 31 %3 = zext i32 %2 to i64 32 %gep1 = getelementptr inbounds float, ptr %1, i64 %3 33 34 %shl1 = shl i8 %b, 1 35 %4 = sext i8 %shl1 to i16 36 %5 = zext nneg i16 %4 to i64 37 %gep2 = getelementptr inbounds float, ptr %1, i64 %5 38 39 load float, ptr %gep1 40 load float, ptr %gep2 41 ret void 42} 43 44;; Here the %a and %b are knowably non-equal. In this cases we can distribute 45;; the zext, preserving the nneg flag, through the shl because it has a nsw flag 46define void @t3(i8 %v) { 47; CHECK-LABEL: Function: t3 48; CHECK: NoAlias: <2 x float>* %gep1, <2 x float>* %gep2 49 %a = or i8 %v, 1 50 %b = and i8 %v, 2 51 52 %1 = alloca [8 x float], align 4 53 %or1 = shl nuw nsw i8 %a, 1 54 %2 = zext nneg i8 %or1 to i64 55 %gep1 = getelementptr inbounds float, ptr %1, i64 %2 56 57 %m = mul nsw nuw i8 %b, 2 58 %3 = sext i8 %m to i16 59 %4 = zext i16 %3 to i64 60 %gep2 = getelementptr inbounds float, ptr %1, i64 %4 61 62 load <2 x float>, ptr %gep1 63 load <2 x float>, ptr %gep2 64 ret void 65} 66 67;; This is the same as above, but this time the shl does not have the nsw flag. 68;; the nneg cannot be kept on the zext. 69define void @t4(i8 %v) { 70; CHECK-LABEL: Function: t4 71; CHECK: MayAlias: <2 x float>* %gep1, <2 x float>* %gep2 72 %a = or i8 %v, 1 73 %b = and i8 %v, 2 74 75 %1 = alloca [8 x float], align 4 76 %or1 = shl nuw i8 %a, 1 77 %2 = zext nneg i8 %or1 to i64 78 %gep1 = getelementptr inbounds float, ptr %1, i64 %2 79 80 %m = mul nsw nuw i8 %b, 2 81 %3 = sext i8 %m to i16 82 %4 = zext i16 %3 to i64 83 %gep2 = getelementptr inbounds float, ptr %1, i64 %4 84 85 load <2 x float>, ptr %gep1 86 load <2 x float>, ptr %gep2 87 ret void 88} 89 90;; Verify a zext nneg and a zext are understood as the same 91define void @t5(ptr %p, i16 %i) { 92; CHECK-LABEL: Function: t5 93; CHECK: NoAlias: i32* %pi, i32* %pi.next 94 %i1 = zext nneg i16 %i to i32 95 %pi = getelementptr i32, ptr %p, i32 %i1 96 97 %i.next = add i16 %i, 1 98 %i.next2 = zext i16 %i.next to i32 99 %pi.next = getelementptr i32, ptr %p, i32 %i.next2 100 101 load i32, ptr %pi 102 load i32, ptr %pi.next 103 ret void 104} 105 106;; This is not very idiomatic, but still possible, verify the nneg is propagated 107;; outward. and that no alias is correctly identified. 108define void @t6(i8 %a) { 109; CHECK-LABEL: Function: t6 110; CHECK: NoAlias: float* %gep1, float* %gep2 111 %1 = alloca [8 x float], align 4 112 %a.add = add i8 %a, 1 113 %2 = zext nneg i8 %a.add to i16 114 %3 = sext i16 %2 to i32 115 %4 = zext i32 %3 to i64 116 %gep1 = getelementptr inbounds float, ptr %1, i64 %4 117 118 %5 = sext i8 %a to i64 119 %gep2 = getelementptr inbounds float, ptr %1, i64 %5 120 121 load float, ptr %gep1 122 load float, ptr %gep2 123 ret void 124} 125 126;; This is even less idiomatic, but still possible, verify the nneg is not 127;; propagated inward. and that may alias is correctly identified. 128define void @t7(i8 %a) { 129; CHECK-LABEL: Function: t7 130; CHECK: MayAlias: float* %gep1, float* %gep2 131 %1 = alloca [8 x float], align 4 132 %a.add = add i8 %a, 1 133 %2 = zext i8 %a.add to i16 134 %3 = sext i16 %2 to i32 135 %4 = zext nneg i32 %3 to i64 136 %gep1 = getelementptr inbounds float, ptr %1, i64 %4 137 138 %5 = sext i8 %a to i64 139 %gep2 = getelementptr inbounds float, ptr %1, i64 %5 140 141 load float, ptr %gep1 142 load float, ptr %gep2 143 ret void 144} 145 146;; Verify the nneg survives an implicit trunc of fewer bits then the zext. 147define void @t8(i8 %a) { 148; CHECK-LABEL: Function: t8 149; CHECK: NoAlias: float* %gep1, float* %gep2 150 %1 = alloca [8 x float], align 4 151 %a.add = add i8 %a, 1 152 %2 = zext nneg i8 %a.add to i128 153 %gep1 = getelementptr inbounds float, ptr %1, i128 %2 154 155 %3 = sext i8 %a to i64 156 %gep2 = getelementptr inbounds float, ptr %1, i64 %3 157 158 load float, ptr %gep1 159 load float, ptr %gep2 160 ret void 161} 162 163;; Ensure that the nneg is never propagated past this trunc and that these 164;; casted values are understood as non-equal. 165define void @t9(i8 %a) { 166; CHECK-LABEL: Function: t9 167; CHECK: MayAlias: float* %gep1, float* %gep2 168 %1 = alloca [8 x float], align 4 169 %a.add = add i8 %a, 1 170 %2 = zext i8 %a.add to i16 171 %3 = trunc i16 %2 to i1 172 %4 = zext nneg i1 %3 to i64 173 %gep1 = getelementptr inbounds float, ptr %1, i64 %4 174 175 %5 = sext i8 %a to i64 176 %gep2 = getelementptr inbounds float, ptr %1, i64 %5 177 178 load float, ptr %gep1 179 load float, ptr %gep2 180 ret void 181} 182