Home | History | Annotate | Download | only in X86
      1 ; RUN: opt -S -codegenprepare %s -o - | FileCheck %s
      2 ; RUN: opt -S -codegenprepare -addr-sink-using-gep=1 %s -o - | FileCheck -check-prefix=CHECK-GEP %s
      3 ; This file tests the different cases what are involved when codegen prepare
      4 ; tries to get sign/zero extension out of the way of addressing mode.
      5 ; This tests require an actual target as addressing mode decisions depends
      6 ; on the target.
      7 
      8 target datalayout = "e-i64:64-f80:128-s:64-n8:16:32:64-S128"
      9 target triple = "x86_64-apple-macosx"
     10 
     11 
     12 ; Check that we correctly promote both operands of the promotable add.
     13 ; CHECK-LABEL: @twoArgsPromotion
     14 ; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg1 to i64
     15 ; CHECK: [[ARG2SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg2 to i64
     16 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], [[ARG2SEXT]]
     17 ; CHECK: inttoptr i64 [[PROMOTED]] to i8*
     18 ; CHECK: ret
     19 define i8 @twoArgsPromotion(i32 %arg1, i32 %arg2) {
     20   %add = add nsw i32 %arg1, %arg2 
     21   %sextadd = sext i32 %add to i64
     22   %base = inttoptr i64 %sextadd to i8*
     23   %res = load i8, i8* %base
     24   ret i8 %res
     25 }
     26 
     27 ; Check that we do not promote both operands of the promotable add when
     28 ; the instruction will not be folded into the addressing mode.
     29 ; Otherwise, we will increase the number of instruction executed.
     30 ; (This is a heuristic of course, because the new sext could have been
     31 ; merged with something else.)
     32 ; CHECK-LABEL: @twoArgsNoPromotion
     33 ; CHECK: add nsw i32 %arg1, %arg2
     34 ; CHECK: ret
     35 define i8 @twoArgsNoPromotion(i32 %arg1, i32 %arg2, i8* %base) {
     36   %add = add nsw i32 %arg1, %arg2 
     37   %sextadd = sext i32 %add to i64
     38   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
     39   %res = load i8, i8* %arrayidx
     40   ret i8 %res
     41 }
     42 
     43 ; Check that we do not promote when the related instruction does not have
     44 ; the nsw flag.
     45 ; CHECK-LABEL: @noPromotion
     46 ; CHECK-NOT: add i64
     47 ; CHECK: ret
     48 define i8 @noPromotion(i32 %arg1, i32 %arg2, i8* %base) {
     49   %add = add i32 %arg1, %arg2 
     50   %sextadd = sext i32 %add to i64
     51   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
     52   %res = load i8, i8* %arrayidx
     53   ret i8 %res
     54 }
     55 
     56 ; Check that we correctly promote constant arguments.
     57 ; CHECK-LABEL: @oneArgPromotion
     58 ; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg1 to i64
     59 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
     60 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
     61 ; CHECK: ret
     62 define i8 @oneArgPromotion(i32 %arg1, i8* %base) {
     63   %add = add nsw i32 %arg1, 1 
     64   %sextadd = sext i32 %add to i64
     65   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
     66   %res = load i8, i8* %arrayidx
     67   ret i8 %res
     68 }
     69 
     70 ; Check that we are able to merge a sign extension with a zero extension.
     71 ; CHECK-LABEL: @oneArgPromotionZExt
     72 ; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64
     73 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1ZEXT]], 1
     74 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
     75 ; CHECK: ret
     76 define i8 @oneArgPromotionZExt(i8 %arg1, i8* %base) {
     77   %zext = zext i8 %arg1 to i32
     78   %add = add nsw i32 %zext, 1 
     79   %sextadd = sext i32 %add to i64
     80   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
     81   %res = load i8, i8* %arrayidx
     82   ret i8 %res
     83 }
     84 
     85 ; When promoting a constant zext, the IR builder returns a constant,
     86 ; not an instruction. Make sure this is properly handled. This used
     87 ; to crash.
     88 ; Note: The constant zext is promoted, but does not help matching
     89 ; more thing in the addressing mode. Therefore the modification is
     90 ; rolled back.
     91 ; Still, this test case exercises the desired code path.
     92 ; CHECK-LABEL: @oneArgPromotionCstZExt
     93 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 0, 1
     94 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
     95 ; CHECK: ret
     96 define i8 @oneArgPromotionCstZExt(i8* %base) {
     97   %cst = zext i16 undef to i32
     98   %add = add nsw i32 %cst, 1
     99   %sextadd = sext i32 %add to i64
    100   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
    101   %res = load i8, i8* %arrayidx
    102   ret i8 %res
    103 }
    104 
    105 ; Check that we do not promote truncate when we cannot determine the
    106 ; bits that are dropped.
    107 ; CHECK-LABEL: @oneArgPromotionBlockTrunc1
    108 ; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 %arg1 to i8
    109 ; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64
    110 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
    111 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    112 ; CHECK: ret
    113 define i8 @oneArgPromotionBlockTrunc1(i32 %arg1, i8* %base) {
    114   %trunc = trunc i32 %arg1 to i8
    115   %add = add nsw i8 %trunc, 1 
    116   %sextadd = sext i8 %add to i64
    117   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
    118   %res = load i8, i8* %arrayidx
    119   ret i8 %res
    120 }
    121 
    122 ; Check that we do not promote truncate when we cannot determine all the
    123 ; bits that are dropped.
    124 ; CHECK-LABEL: @oneArgPromotionBlockTrunc2
    125 ; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i16 %arg1 to i32
    126 ; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[ARG1SEXT]] to i8
    127 ; CHECK: [[ARG1SEXT64:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64
    128 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT64]], 1
    129 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    130 ; CHECK: ret
    131 define i8 @oneArgPromotionBlockTrunc2(i16 %arg1, i8* %base) {
    132   %sextarg1 = sext i16 %arg1 to i32
    133   %trunc = trunc i32 %sextarg1 to i8
    134   %add = add nsw i8 %trunc, 1 
    135   %sextadd = sext i8 %add to i64
    136   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
    137   %res = load i8, i8* %arrayidx
    138   ret i8 %res
    139 }
    140 
    141 ; Check that we are able to promote truncate when we know all the bits
    142 ; that are dropped.
    143 ; CHECK-LABEL: @oneArgPromotionPassTruncKeepSExt
    144 ; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i64
    145 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
    146 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    147 ; CHECK: ret
    148 define i8 @oneArgPromotionPassTruncKeepSExt(i1 %arg1, i8* %base) {
    149   %sextarg1 = sext i1 %arg1 to i32
    150   %trunc = trunc i32 %sextarg1 to i8
    151   %add = add nsw i8 %trunc, 1 
    152   %sextadd = sext i8 %add to i64
    153   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
    154   %res = load i8, i8* %arrayidx
    155   ret i8 %res
    156 }
    157 
    158 ; On X86 truncate are free. Check that we are able to promote the add
    159 ; to be used as addressing mode and that we insert a truncate for the other
    160 ; use. 
    161 ; CHECK-LABEL: @oneArgPromotionTruncInsert
    162 ; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64
    163 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
    164 ; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i64 [[PROMOTED]] to i8
    165 ; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    166 ; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, i8* [[GEP]]
    167 ; CHECK: add i8 [[LOAD]], [[TRUNC]]
    168 ; CHECK: ret
    169 define i8 @oneArgPromotionTruncInsert(i8 %arg1, i8* %base) {
    170   %add = add nsw i8 %arg1, 1 
    171   %sextadd = sext i8 %add to i64
    172   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
    173   %res = load i8, i8* %arrayidx
    174   %finalres = add i8 %res, %add
    175   ret i8 %finalres
    176 }
    177 
    178 ; Cannot sext from a larger type than the promoted type.
    179 ; CHECK-LABEL: @oneArgPromotionLargerType
    180 ; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i128 %arg1 to i8
    181 ; CHECK: [[ARG1SEXT64:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64
    182 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT64]], 1
    183 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    184 ; CHECK: ret
    185 define i8 @oneArgPromotionLargerType(i128 %arg1, i8* %base) {
    186   %trunc = trunc i128 %arg1 to i8
    187   %add = add nsw i8 %trunc, 1 
    188   %sextadd = sext i8 %add to i64
    189   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
    190   %res = load i8, i8* %arrayidx
    191   %finalres = add i8 %res, %add
    192   ret i8 %finalres
    193 }
    194 
    195 ; Use same inserted trunc
    196 ; On X86 truncate are free. Check that we are able to promote the add
    197 ; to be used as addressing mode and that we insert a truncate for
    198 ; *all* the other uses. 
    199 ; CHECK-LABEL: @oneArgPromotionTruncInsertSeveralUse
    200 ; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64
    201 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
    202 ; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i64 [[PROMOTED]] to i8
    203 ; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    204 ; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, i8* [[GEP]]
    205 ; CHECK: [[ADDRES:%[a-zA-Z_0-9-]+]] = add i8 [[LOAD]], [[TRUNC]]
    206 ; CHECK: add i8 [[ADDRES]], [[TRUNC]]
    207 ; CHECK: ret
    208 define i8 @oneArgPromotionTruncInsertSeveralUse(i8 %arg1, i8* %base) {
    209   %add = add nsw i8 %arg1, 1 
    210   %sextadd = sext i8 %add to i64
    211   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
    212   %res = load i8, i8* %arrayidx
    213   %almostfinalres = add i8 %res, %add
    214   %finalres = add i8 %almostfinalres, %add
    215   ret i8 %finalres
    216 }
    217 
    218 ; Check that the promoted instruction is used for all uses of the original
    219 ; sign extension.
    220 ; CHECK-LABEL: @oneArgPromotionSExtSeveralUse
    221 ; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64
    222 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
    223 ; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    224 ; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, i8* [[GEP]]
    225 ; CHECK: [[ADDRES:%[a-zA-Z_0-9-]+]] = zext i8 [[LOAD]] to i64
    226 ; CHECK: add i64 [[ADDRES]], [[PROMOTED]]
    227 ; CHECK: ret
    228 define i64 @oneArgPromotionSExtSeveralUse(i8 %arg1, i8* %base) {
    229   %add = add nsw i8 %arg1, 1 
    230   %sextadd = sext i8 %add to i64
    231   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
    232   %res = load i8, i8* %arrayidx
    233   %almostfinalres = zext i8 %res to i64
    234   %finalres = add i64 %almostfinalres, %sextadd
    235   ret i64 %finalres
    236 }
    237 
    238 ; Check all types of rollback mechanism.
    239 ; For this test, the sign extension stays in place.
    240 ; However, the matching process goes until promoting both the operands
    241 ; of the first promotable add implies.
    242 ; At this point the rollback mechanism kicks in and restores the states
    243 ; until the addressing mode matcher is able to match something: in that
    244 ; case promote nothing.
    245 ; Along the way, the promotion mechanism involves:
    246 ; - Mutating the type of %promotableadd1 and %promotableadd2.
    247 ; - Creating a sext for %arg1 and %arg2.
    248 ; - Creating a trunc for a use of %promotableadd1.
    249 ; - Replacing a bunch of uses.
    250 ; - Setting the operands of the promoted instruction with the promoted values.
    251 ; - Moving instruction around (mainly sext when promoting instruction).
    252 ; Each type of those promotions has to be undo at least once during this
    253 ; specific test. 
    254 ; CHECK-LABEL: @twoArgsPromotionNest
    255 ; CHECK: [[ORIG:%[a-zA-Z_0-9-]+]] = add nsw i32 %arg1, %arg2
    256 ; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[ORIG]], [[ORIG]]
    257 ; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64
    258 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[SEXT]]
    259 ; CHECK: ret
    260 define i8 @twoArgsPromotionNest(i32 %arg1, i32 %arg2, i8* %base) {
    261   %promotableadd1 = add nsw i32 %arg1, %arg2
    262   %promotableadd2 = add nsw i32 %promotableadd1, %promotableadd1 
    263   %sextadd = sext i32 %promotableadd2 to i64
    264   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
    265   %res = load i8, i8* %arrayidx
    266   ret i8 %res
    267 }
    268 
    269 ; Test the InstructionRemover undo, which was the only one not
    270 ; kicked in the previous test.
    271 ; The matcher first promotes the add, removes the trunc and promotes
    272 ; the sext of arg1.
    273 ; Then, the matcher cannot use an addressing mode r + r + r, thus it
    274 ; rolls back. 
    275 ; CHECK-LABEL: @twoArgsNoPromotionRemove
    276 ; CHECK: [[SEXTARG1:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i32
    277 ; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[SEXTARG1]] to i8
    278 ; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i8 [[TRUNC]], %arg2
    279 ; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i8 [[ADD]] to i64
    280 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[SEXT]]
    281 ; CHECK: ret
    282 define i8 @twoArgsNoPromotionRemove(i1 %arg1, i8 %arg2, i8* %base) {
    283   %sextarg1 = sext i1 %arg1 to i32
    284   %trunc = trunc i32 %sextarg1 to i8
    285   %add = add nsw i8 %trunc, %arg2 
    286   %sextadd = sext i8 %add to i64
    287   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
    288   %res = load i8, i8* %arrayidx
    289   ret i8 %res
    290 }
    291 
    292 ; Ensure that when the profitability checks kicks in, the IR is not modified
    293 ; will IgnoreProfitability is on.
    294 ; The profitabily check happens when a candidate instruction has several uses.
    295 ; The matcher will create a new matcher for each use and check if the
    296 ; instruction is in the list of the matched instructions of this new matcher.
    297 ; All changes made by the new matchers must be dropped before pursuing
    298 ; otherwise the state of the original matcher will be wrong.
    299 ;
    300 ; Without the profitability check, when checking for the second use of
    301 ; arrayidx, the matcher promotes everything all the way to %arg1, %arg2.
    302 ; Check that we did not promote anything in the final matching.
    303 ;
    304 ; <rdar://problem/16020230>
    305 ; CHECK-LABEL: @checkProfitability
    306 ; CHECK-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg1 to i64
    307 ; CHECK-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg2 to i64
    308 ; CHECK: [[SHL:%[a-zA-Z_0-9-]+]] = shl nsw i32 %arg1, 1
    309 ; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[SHL]], %arg2
    310 ; CHECK: [[SEXTADD:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64
    311 ; BB then
    312 ; CHECK: [[BASE1:%[a-zA-Z_0-9-]+]] = add i64 [[SEXTADD]], 48
    313 ; CHECK: [[ADDR1:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[BASE1]] to i32*
    314 ; CHECK: load i32, i32* [[ADDR1]]
    315 ; BB else
    316 ; CHECK: [[BASE2:%[a-zA-Z_0-9-]+]] = add i64 [[SEXTADD]], 48
    317 ; CHECK: [[ADDR2:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[BASE2]] to i32*
    318 ; CHECK: load i32, i32* [[ADDR2]]
    319 ; CHECK: ret
    320 ; CHECK-GEP-LABEL: @checkProfitability
    321 ; CHECK-GEP-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg1 to i64
    322 ; CHECK-GEP-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg2 to i64
    323 ; CHECK-GEP: [[SHL:%[a-zA-Z_0-9-]+]] = shl nsw i32 %arg1, 1
    324 ; CHECK-GEP: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[SHL]], %arg2
    325 ; CHECK-GEP: [[SEXTADD:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64
    326 ; BB then
    327 ; CHECK-GEP: [[BASE1:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[SEXTADD]] to i32*
    328 ; CHECK-GEP: [[BCC1:%[a-zA-Z_0-9-]+]] = bitcast i32* [[BASE1]] to i8*
    329 ; CHECK-GEP: [[FULL1:%[a-zA-Z_0-9-]+]] = getelementptr i8, i8* [[BCC1]], i64 48
    330 ; CHECK-GEP: [[ADDR1:%[a-zA-Z_0-9-]+]] = bitcast i8* [[FULL1]] to i32*
    331 ; CHECK-GEP: load i32, i32* [[ADDR1]]
    332 ; BB else
    333 ; CHECK-GEP: [[BASE2:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[SEXTADD]] to i32*
    334 ; CHECK-GEP: [[BCC2:%[a-zA-Z_0-9-]+]] = bitcast i32* [[BASE2]] to i8*
    335 ; CHECK-GEP: [[FULL2:%[a-zA-Z_0-9-]+]] = getelementptr i8, i8* [[BCC2]], i64 48
    336 ; CHECK-GEP: [[ADDR2:%[a-zA-Z_0-9-]+]] = bitcast i8* [[FULL2]] to i32*
    337 ; CHECK-GEP: load i32, i32* [[ADDR2]]
    338 ; CHECK-GEP: ret
    339 define i32 @checkProfitability(i32 %arg1, i32 %arg2, i1 %test) {
    340   %shl = shl nsw i32 %arg1, 1
    341   %add1 = add nsw i32 %shl, %arg2
    342   %sextidx1 = sext i32 %add1 to i64
    343   %tmpptr = inttoptr i64 %sextidx1 to i32*
    344   %arrayidx1 = getelementptr i32, i32* %tmpptr, i64 12
    345   br i1 %test, label %then, label %else
    346 then: 
    347   %res1 = load i32, i32* %arrayidx1
    348   br label %end
    349 else:
    350   %res2 = load i32, i32* %arrayidx1
    351   br label %end
    352 end:
    353   %tmp = phi i32 [%res1, %then], [%res2, %else]
    354   %res = add i32 %tmp, %add1
    355   %addr = inttoptr i32 %res to i32*
    356   %final = load i32, i32* %addr
    357   ret i32 %final
    358 }
    359 
    360 %struct.dns_packet = type { i32, i32, %union.anon }
    361 %union.anon = type { i32 }
    362 
    363 @a = common global i32 0, align 4
    364 @b = common global i16 0, align 2
    365 
    366 ; We used to crash on this function because we did not return the right
    367 ; promoted instruction for %conv.i.
    368 ; Make sure we generate the right code now.
    369 ; CHECK-LABEL: @fn3
    370 ; %conv.i is used twice and only one of its use is being promoted.
    371 ; Use it at the starting point for the matching.
    372 ; CHECK: %conv.i = zext i16 [[PLAIN_OPND:%[.a-zA-Z_0-9-]+]] to i32
    373 ; CHECK-NEXT: [[PROMOTED_CONV:%[.a-zA-Z_0-9-]+]] = zext i16 [[PLAIN_OPND]] to i64
    374 ; CHECK-NEXT: [[BASE:%[a-zA-Z_0-9-]+]] = ptrtoint %struct.dns_packet* %P to i64
    375 ; CHECK-NEXT: [[ADD:%[a-zA-Z_0-9-]+]] = add i64 [[BASE]], [[PROMOTED_CONV]]
    376 ; CHECK-NEXT: [[ADDR:%[a-zA-Z_0-9-]+]] = add i64 [[ADD]], 7
    377 ; CHECK-NEXT: [[CAST:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[ADDR]] to i8*
    378 ; CHECK-NEXT: load i8, i8* [[CAST]], align 1
    379 define signext i16 @fn3(%struct.dns_packet* nocapture readonly %P) {
    380 entry:
    381   %tmp = getelementptr inbounds %struct.dns_packet, %struct.dns_packet* %P, i64 0, i32 2
    382   %data.i.i = bitcast %union.anon* %tmp to [0 x i8]*
    383   br label %while.body.i.i
    384 
    385 while.body.i.i:                                   ; preds = %while.body.i.i, %entry
    386   %src.addr.0.i.i = phi i16 [ 0, %entry ], [ %inc.i.i, %while.body.i.i ]
    387   %inc.i.i = add i16 %src.addr.0.i.i, 1
    388   %idxprom.i.i = sext i16 %src.addr.0.i.i to i64
    389   %arrayidx.i.i = getelementptr inbounds [0 x i8], [0 x i8]* %data.i.i, i64 0, i64 %idxprom.i.i
    390   %tmp1 = load i8, i8* %arrayidx.i.i, align 1
    391   %conv2.i.i = zext i8 %tmp1 to i32
    392   %and.i.i = and i32 %conv2.i.i, 15
    393   store i32 %and.i.i, i32* @a, align 4
    394   %tobool.i.i = icmp eq i32 %and.i.i, 0
    395   br i1 %tobool.i.i, label %while.body.i.i, label %fn1.exit.i
    396 
    397 fn1.exit.i:                                       ; preds = %while.body.i.i
    398   %inc.i.i.lcssa = phi i16 [ %inc.i.i, %while.body.i.i ]
    399   %conv.i = zext i16 %inc.i.i.lcssa to i32
    400   %sub.i = add nsw i32 %conv.i, -1
    401   %idxprom.i = sext i32 %sub.i to i64
    402   %arrayidx.i = getelementptr inbounds [0 x i8], [0 x i8]* %data.i.i, i64 0, i64 %idxprom.i
    403   %tmp2 = load i8, i8* %arrayidx.i, align 1
    404   %conv2.i = sext i8 %tmp2 to i16
    405   store i16 %conv2.i, i16* @b, align 2
    406   %sub4.i = sub nsw i32 0, %conv.i
    407   %conv5.i = zext i16 %conv2.i to i32
    408   %cmp.i = icmp sgt i32 %conv5.i, %sub4.i
    409   br i1 %cmp.i, label %if.then.i, label %fn2.exit
    410 
    411 if.then.i:                                        ; preds = %fn1.exit.i
    412   %end.i = getelementptr inbounds %struct.dns_packet, %struct.dns_packet* %P, i64 0, i32 1
    413   %tmp3 = load i32, i32* %end.i, align 4
    414   %sub7.i = add i32 %tmp3, 65535
    415   %conv8.i = trunc i32 %sub7.i to i16
    416   br label %fn2.exit
    417 
    418 fn2.exit:                                         ; preds = %if.then.i, %fn1.exit.i
    419   %retval.0.i = phi i16 [ %conv8.i, %if.then.i ], [ undef, %fn1.exit.i ]
    420   ret i16 %retval.0.i
    421 }
    422 
    423 ; Check that we do not promote an extension if the non-wrapping flag does not
    424 ; match the kind of the extension.
    425 ; CHECK-LABEL: @noPromotionFlag
    426 ; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 %arg1, %arg2
    427 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = zext i32 [[ADD]] to i64
    428 ; CHECK: inttoptr i64 [[PROMOTED]] to i8*
    429 ; CHECK: ret
    430 define i8 @noPromotionFlag(i32 %arg1, i32 %arg2) {
    431   %add = add nsw i32 %arg1, %arg2 
    432   %zextadd = zext i32 %add to i64
    433   %base = inttoptr i64 %zextadd to i8*
    434   %res = load i8, i8* %base
    435   ret i8 %res
    436 }
    437 
    438 ; Check that we correctly promote both operands of the promotable add with zext.
    439 ; CHECK-LABEL: @twoArgsPromotionZExt
    440 ; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i32 %arg1 to i64
    441 ; CHECK: [[ARG2ZEXT:%[a-zA-Z_0-9-]+]] = zext i32 %arg2 to i64
    442 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], [[ARG2ZEXT]]
    443 ; CHECK: inttoptr i64 [[PROMOTED]] to i8*
    444 ; CHECK: ret
    445 define i8 @twoArgsPromotionZExt(i32 %arg1, i32 %arg2) {
    446   %add = add nuw i32 %arg1, %arg2 
    447   %zextadd = zext i32 %add to i64
    448   %base = inttoptr i64 %zextadd to i8*
    449   %res = load i8, i8* %base
    450   ret i8 %res
    451 }
    452 
    453 ; Check that we correctly promote constant arguments.
    454 ; CHECK-LABEL: @oneArgPromotionNegativeCstZExt
    455 ; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64
    456 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 255
    457 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    458 ; CHECK: ret
    459 define i8 @oneArgPromotionNegativeCstZExt(i8 %arg1, i8* %base) {
    460   %add = add nuw i8 %arg1, -1 
    461   %zextadd = zext i8 %add to i64
    462   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
    463   %res = load i8, i8* %arrayidx
    464   ret i8 %res
    465 }
    466 
    467 ; Check that we are able to merge two zero extensions.
    468 ; CHECK-LABEL: @oneArgPromotionZExtZExt
    469 ; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64
    470 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
    471 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    472 ; CHECK: ret
    473 define i8 @oneArgPromotionZExtZExt(i8 %arg1, i8* %base) {
    474   %zext = zext i8 %arg1 to i32
    475   %add = add nuw i32 %zext, 1 
    476   %zextadd = zext i32 %add to i64
    477   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
    478   %res = load i8, i8* %arrayidx
    479   ret i8 %res
    480 }
    481 
    482 ; Check that we do not promote truncate when the dropped bits
    483 ; are of a different kind.
    484 ; CHECK-LABEL: @oneArgPromotionBlockTruncZExt
    485 ; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i32
    486 ; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[ARG1SEXT]] to i8
    487 ; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 [[ARG1TRUNC]] to i64
    488 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
    489 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    490 ; CHECK: ret
    491 define i8 @oneArgPromotionBlockTruncZExt(i1 %arg1, i8* %base) {
    492   %sextarg1 = sext i1 %arg1 to i32
    493   %trunc = trunc i32 %sextarg1 to i8
    494   %add = add nuw i8 %trunc, 1 
    495   %zextadd = zext i8 %add to i64
    496   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
    497   %res = load i8, i8* %arrayidx
    498   ret i8 %res
    499 }
    500 
    501 ; Check that we are able to promote truncate when we know all the bits
    502 ; that are dropped.
    503 ; CHECK-LABEL: @oneArgPromotionPassTruncZExt
    504 ; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i1 %arg1 to i64
    505 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
    506 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    507 ; CHECK: ret
    508 define i8 @oneArgPromotionPassTruncZExt(i1 %arg1, i8* %base) {
    509   %sextarg1 = zext i1 %arg1 to i32
    510   %trunc = trunc i32 %sextarg1 to i8
    511   %add = add nuw i8 %trunc, 1 
    512   %zextadd = zext i8 %add to i64
    513   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
    514   %res = load i8, i8* %arrayidx
    515   ret i8 %res
    516 }
    517 
    518 ; Check that we do not promote sext with zext.
    519 ; CHECK-LABEL: @oneArgPromotionBlockSExtZExt
    520 ; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i8
    521 ; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 [[ARG1SEXT]] to i64
    522 ; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
    523 ; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
    524 ; CHECK: ret
    525 define i8 @oneArgPromotionBlockSExtZExt(i1 %arg1, i8* %base) {
    526   %sextarg1 = sext i1 %arg1 to i8
    527   %add = add nuw i8 %sextarg1, 1 
    528   %zextadd = zext i8 %add to i64
    529   %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
    530   %res = load i8, i8* %arrayidx
    531   ret i8 %res
    532 }
    533