1; RUN: opt -S -codegenprepare %s -o - | FileCheck %s 2; This file tests the different cases what are involved when codegen prepare 3; tries to get sign extension out of the way of addressing mode. 4; This tests require an actual target as addressing mode decisions depends 5; on the target. 6 7target datalayout = "e-i64:64-f80:128-s:64-n8:16:32:64-S128" 8target triple = "x86_64-apple-macosx" 9 10 11; Check that we correctly promote both operands of the promotable add. 12; CHECK-LABEL: @twoArgsPromotion 13; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg1 to i64 14; CHECK: [[ARG2SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg2 to i64 15; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], [[ARG2SEXT]] 16; CHECK: inttoptr i64 [[PROMOTED]] to i8* 17; CHECK: ret 18define i8 @twoArgsPromotion(i32 %arg1, i32 %arg2) { 19 %add = add nsw i32 %arg1, %arg2 20 %sextadd = sext i32 %add to i64 21 %base = inttoptr i64 %sextadd to i8* 22 %res = load i8* %base 23 ret i8 %res 24} 25 26; Check that we do not promote both operands of the promotable add when 27; the instruction will not be folded into the addressing mode. 28; Otherwise, we will increase the number of instruction executed. 29; (This is a heuristic of course, because the new sext could have been 30; merged with something else.) 31; CHECK-LABEL: @twoArgsNoPromotion 32; CHECK: add nsw i32 %arg1, %arg2 33; CHECK: ret 34define i8 @twoArgsNoPromotion(i32 %arg1, i32 %arg2, i8* %base) { 35 %add = add nsw i32 %arg1, %arg2 36 %sextadd = sext i32 %add to i64 37 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 38 %res = load i8* %arrayidx 39 ret i8 %res 40} 41 42; Check that we do not promote when the related instruction does not have 43; the nsw flag. 44; CHECK-LABEL: @noPromotion 45; CHECK-NOT: add i64 46; CHECK: ret 47define i8 @noPromotion(i32 %arg1, i32 %arg2, i8* %base) { 48 %add = add i32 %arg1, %arg2 49 %sextadd = sext i32 %add to i64 50 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 51 %res = load i8* %arrayidx 52 ret i8 %res 53} 54 55; Check that we correctly promote constant arguments. 56; CHECK-LABEL: @oneArgPromotion 57; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg1 to i64 58; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 59; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] 60; CHECK: ret 61define i8 @oneArgPromotion(i32 %arg1, i8* %base) { 62 %add = add nsw i32 %arg1, 1 63 %sextadd = sext i32 %add to i64 64 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 65 %res = load i8* %arrayidx 66 ret i8 %res 67} 68 69; Check that we do not promote truncate when we cannot determine the 70; bits that are dropped. 71; CHECK-LABEL: @oneArgPromotionBlockTrunc1 72; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 %arg1 to i8 73; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64 74; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 75; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] 76; CHECK: ret 77define i8 @oneArgPromotionBlockTrunc1(i32 %arg1, i8* %base) { 78 %trunc = trunc i32 %arg1 to i8 79 %add = add nsw i8 %trunc, 1 80 %sextadd = sext i8 %add to i64 81 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 82 %res = load i8* %arrayidx 83 ret i8 %res 84} 85 86; Check that we do not promote truncate when we cannot determine all the 87; bits that are dropped. 88; CHECK-LABEL: @oneArgPromotionBlockTrunc2 89; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i16 %arg1 to i32 90; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[ARG1SEXT]] to i8 91; CHECK: [[ARG1SEXT64:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64 92; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT64]], 1 93; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] 94; CHECK: ret 95define i8 @oneArgPromotionBlockTrunc2(i16 %arg1, i8* %base) { 96 %sextarg1 = sext i16 %arg1 to i32 97 %trunc = trunc i32 %sextarg1 to i8 98 %add = add nsw i8 %trunc, 1 99 %sextadd = sext i8 %add to i64 100 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 101 %res = load i8* %arrayidx 102 ret i8 %res 103} 104 105; Check that we are able to promote truncate when we know all the bits 106; that are dropped. 107; CHECK-LABEL: @oneArgPromotionPassTruncKeepSExt 108; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i64 109; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 110; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] 111; CHECK: ret 112define i8 @oneArgPromotionPassTruncKeepSExt(i1 %arg1, i8* %base) { 113 %sextarg1 = sext i1 %arg1 to i32 114 %trunc = trunc i32 %sextarg1 to i8 115 %add = add nsw i8 %trunc, 1 116 %sextadd = sext i8 %add to i64 117 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 118 %res = load i8* %arrayidx 119 ret i8 %res 120} 121 122; On X86 truncate are free. Check that we are able to promote the add 123; to be used as addressing mode and that we insert a truncate for the other 124; use. 125; CHECK-LABEL: @oneArgPromotionTruncInsert 126; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64 127; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 128; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i64 [[PROMOTED]] to i8 129; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8* %base, i64 [[PROMOTED]] 130; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8* [[GEP]] 131; CHECK: add i8 [[LOAD]], [[TRUNC]] 132; CHECK: ret 133define i8 @oneArgPromotionTruncInsert(i8 %arg1, i8* %base) { 134 %add = add nsw i8 %arg1, 1 135 %sextadd = sext i8 %add to i64 136 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 137 %res = load i8* %arrayidx 138 %finalres = add i8 %res, %add 139 ret i8 %finalres 140} 141 142; Cannot sext from a larger type than the promoted type. 143; CHECK-LABEL: @oneArgPromotionLargerType 144; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i128 %arg1 to i8 145; CHECK: [[ARG1SEXT64:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64 146; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT64]], 1 147; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] 148; CHECK: ret 149define i8 @oneArgPromotionLargerType(i128 %arg1, i8* %base) { 150 %trunc = trunc i128 %arg1 to i8 151 %add = add nsw i8 %trunc, 1 152 %sextadd = sext i8 %add to i64 153 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 154 %res = load i8* %arrayidx 155 %finalres = add i8 %res, %add 156 ret i8 %finalres 157} 158 159; Use same inserted trunc 160; On X86 truncate are free. Check that we are able to promote the add 161; to be used as addressing mode and that we insert a truncate for 162; *all* the other uses. 163; CHECK-LABEL: @oneArgPromotionTruncInsertSeveralUse 164; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64 165; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 166; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i64 [[PROMOTED]] to i8 167; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8* %base, i64 [[PROMOTED]] 168; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8* [[GEP]] 169; CHECK: [[ADDRES:%[a-zA-Z_0-9-]+]] = add i8 [[LOAD]], [[TRUNC]] 170; CHECK: add i8 [[ADDRES]], [[TRUNC]] 171; CHECK: ret 172define i8 @oneArgPromotionTruncInsertSeveralUse(i8 %arg1, i8* %base) { 173 %add = add nsw i8 %arg1, 1 174 %sextadd = sext i8 %add to i64 175 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 176 %res = load i8* %arrayidx 177 %almostfinalres = add i8 %res, %add 178 %finalres = add i8 %almostfinalres, %add 179 ret i8 %finalres 180} 181 182; Check that the promoted instruction is used for all uses of the original 183; sign extension. 184; CHECK-LABEL: @oneArgPromotionSExtSeveralUse 185; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64 186; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 187; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8* %base, i64 [[PROMOTED]] 188; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8* [[GEP]] 189; CHECK: [[ADDRES:%[a-zA-Z_0-9-]+]] = zext i8 [[LOAD]] to i64 190; CHECK: add i64 [[ADDRES]], [[PROMOTED]] 191; CHECK: ret 192define i64 @oneArgPromotionSExtSeveralUse(i8 %arg1, i8* %base) { 193 %add = add nsw i8 %arg1, 1 194 %sextadd = sext i8 %add to i64 195 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 196 %res = load i8* %arrayidx 197 %almostfinalres = zext i8 %res to i64 198 %finalres = add i64 %almostfinalres, %sextadd 199 ret i64 %finalres 200} 201 202; Check all types of rollback mechanism. 203; For this test, the sign extension stays in place. 204; However, the matching process goes until promoting both the operands 205; of the first promotable add implies. 206; At this point the rollback mechanism kicks in and restores the states 207; until the addressing mode matcher is able to match something: in that 208; case promote nothing. 209; Along the way, the promotion mechanism involves: 210; - Mutating the type of %promotableadd1 and %promotableadd2. 211; - Creating a sext for %arg1 and %arg2. 212; - Creating a trunc for a use of %promotableadd1. 213; - Replacing a bunch of uses. 214; - Setting the operands of the promoted instruction with the promoted values. 215; - Moving instruction around (mainly sext when promoting instruction). 216; Each type of those promotions has to be undo at least once during this 217; specific test. 218; CHECK-LABEL: @twoArgsPromotionNest 219; CHECK: [[ORIG:%[a-zA-Z_0-9-]+]] = add nsw i32 %arg1, %arg2 220; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[ORIG]], [[ORIG]] 221; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64 222; CHECK: getelementptr inbounds i8* %base, i64 [[SEXT]] 223; CHECK: ret 224define i8 @twoArgsPromotionNest(i32 %arg1, i32 %arg2, i8* %base) { 225 %promotableadd1 = add nsw i32 %arg1, %arg2 226 %promotableadd2 = add nsw i32 %promotableadd1, %promotableadd1 227 %sextadd = sext i32 %promotableadd2 to i64 228 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 229 %res = load i8* %arrayidx 230 ret i8 %res 231} 232 233; Test the InstructionRemover undo, which was the only one not 234; kicked in the previous test. 235; The matcher first promotes the add, removes the trunc and promotes 236; the sext of arg1. 237; Then, the matcher cannot use an addressing mode r + r + r, thus it 238; rolls back. 239; CHECK-LABEL: @twoArgsNoPromotionRemove 240; CHECK: [[SEXTARG1:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i32 241; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[SEXTARG1]] to i8 242; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i8 [[TRUNC]], %arg2 243; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i8 [[ADD]] to i64 244; CHECK: getelementptr inbounds i8* %base, i64 [[SEXT]] 245; CHECK: ret 246define i8 @twoArgsNoPromotionRemove(i1 %arg1, i8 %arg2, i8* %base) { 247 %sextarg1 = sext i1 %arg1 to i32 248 %trunc = trunc i32 %sextarg1 to i8 249 %add = add nsw i8 %trunc, %arg2 250 %sextadd = sext i8 %add to i64 251 %arrayidx = getelementptr inbounds i8* %base, i64 %sextadd 252 %res = load i8* %arrayidx 253 ret i8 %res 254} 255 256; Ensure that when the profitability checks kicks in, the IR is not modified 257; will IgnoreProfitability is on. 258; The profitabily check happens when a candidate instruction has several uses. 259; The matcher will create a new matcher for each use and check if the 260; instruction is in the list of the matched instructions of this new matcher. 261; All changes made by the new matchers must be dropped before pursuing 262; otherwise the state of the original matcher will be wrong. 263; 264; Without the profitability check, when checking for the second use of 265; arrayidx, the matcher promotes everything all the way to %arg1, %arg2. 266; Check that we did not promote anything in the final matching. 267; 268; <rdar://problem/16020230> 269; CHECK-LABEL: @checkProfitability 270; CHECK-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg1 to i64 271; CHECK-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg2 to i64 272; CHECK: [[SHL:%[a-zA-Z_0-9-]+]] = shl nsw i32 %arg1, 1 273; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[SHL]], %arg2 274; CHECK: [[SEXTADD:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64 275; BB then 276; CHECK: [[BASE1:%[a-zA-Z_0-9-]+]] = add i64 [[SEXTADD]], 48 277; CHECK: [[ADDR1:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[BASE1]] to i32* 278; CHECK: load i32* [[ADDR1]] 279; BB else 280; CHECK: [[BASE2:%[a-zA-Z_0-9-]+]] = add i64 [[SEXTADD]], 48 281; CHECK: [[ADDR2:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[BASE2]] to i32* 282; CHECK: load i32* [[ADDR2]] 283; CHECK: ret 284define i32 @checkProfitability(i32 %arg1, i32 %arg2, i1 %test) { 285 %shl = shl nsw i32 %arg1, 1 286 %add1 = add nsw i32 %shl, %arg2 287 %sextidx1 = sext i32 %add1 to i64 288 %tmpptr = inttoptr i64 %sextidx1 to i32* 289 %arrayidx1 = getelementptr i32* %tmpptr, i64 12 290 br i1 %test, label %then, label %else 291then: 292 %res1 = load i32* %arrayidx1 293 br label %end 294else: 295 %res2 = load i32* %arrayidx1 296 br label %end 297end: 298 %tmp = phi i32 [%res1, %then], [%res2, %else] 299 %res = add i32 %tmp, %add1 300 %addr = inttoptr i32 %res to i32* 301 %final = load i32* %addr 302 ret i32 %final 303} 304