1004 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' < %s -mtriple=aarch64-apple-ios -S | FileCheck -enable-var-scope %s --check-prefix=OPTALL --check-prefixes=OPT,NONSTRESS3; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' < %s -mtriple=aarch64-apple-ios -S -stress-cgp-ext-ld-promotion | FileCheck -enable-var-scope %s --check-prefixes=OPTALL,OPT,STRESS4; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' < %s -mtriple=aarch64-apple-ios -S -disable-cgp-ext-ld-promotion | FileCheck -enable-var-scope %s --check-prefixes=OPTALL,DISABLE5 6; CodeGenPrepare should move the zext into the block with the load7; so that SelectionDAG can select it with the load.8define void @foo(ptr %p, ptr %q) {9; OPTALL-LABEL: define void @foo(10; OPTALL-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) {11; OPTALL-NEXT: [[ENTRY:.*:]]12; OPTALL-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 113; OPTALL-NEXT: [[S:%.*]] = zext i8 [[T]] to i3214; OPTALL-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 2015; OPTALL-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]16; OPTALL: [[TRUE]]:17; OPTALL-NEXT: store i32 [[S]], ptr [[Q]], align 418; OPTALL-NEXT: ret void19; OPTALL: [[FALSE]]:20; OPTALL-NEXT: ret void21;22entry:23 %t = load i8, ptr %p24 %a = icmp slt i8 %t, 2025 br i1 %a, label %true, label %false26true:27 %s = zext i8 %t to i3228 store i32 %s, ptr %q29 ret void30false:31 ret void32}33 34; Check that we manage to form a zextload is an operation with only one35; argument to explicitly extend is in the way.36; Make sure the operation is not promoted when the promotion pass is disabled.37define void @promoteOneArg(ptr %p, ptr %q) {38; OPT-LABEL: define void @promoteOneArg(39; OPT-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) {40; OPT-NEXT: [[ENTRY:.*:]]41; OPT-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 142; OPT-NEXT: [[PROMOTED:%.*]] = zext i8 [[T]] to i3243; OPT-NEXT: [[ADD:%.*]] = add nuw i32 [[PROMOTED]], 244; OPT-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 2045; OPT-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]46; OPT: [[TRUE]]:47; OPT-NEXT: store i32 [[ADD]], ptr [[Q]], align 448; OPT-NEXT: ret void49; OPT: [[FALSE]]:50; OPT-NEXT: ret void51;52; DISABLE-LABEL: define void @promoteOneArg(53; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) {54; DISABLE-NEXT: [[ENTRY:.*:]]55; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 156; DISABLE-NEXT: [[ADD:%.*]] = add nuw i8 [[T]], 257; DISABLE-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 2058; DISABLE-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]59; DISABLE: [[TRUE]]:60; DISABLE-NEXT: [[S:%.*]] = zext i8 [[ADD]] to i3261; DISABLE-NEXT: store i32 [[S]], ptr [[Q]], align 462; DISABLE-NEXT: ret void63; DISABLE: [[FALSE]]:64; DISABLE-NEXT: ret void65;66entry:67 %t = load i8, ptr %p68 %add = add nuw i8 %t, 269 %a = icmp slt i8 %t, 2070 br i1 %a, label %true, label %false71true:72 %s = zext i8 %add to i3273 store i32 %s, ptr %q74 ret void75false:76 ret void77}78 79; Check that we manage to form a sextload is an operation with only one80; argument to explicitly extend is in the way.81; Version with sext.82define void @promoteOneArgSExt(ptr %p, ptr %q) {83; OPT-LABEL: define void @promoteOneArgSExt(84; OPT-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) {85; OPT-NEXT: [[ENTRY:.*:]]86; OPT-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 187; OPT-NEXT: [[PROMOTED:%.*]] = sext i8 [[T]] to i3288; OPT-NEXT: [[ADD:%.*]] = add nsw i32 [[PROMOTED]], 289; OPT-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 2090; OPT-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]91; OPT: [[TRUE]]:92; OPT-NEXT: store i32 [[ADD]], ptr [[Q]], align 493; OPT-NEXT: ret void94; OPT: [[FALSE]]:95; OPT-NEXT: ret void96;97; DISABLE-LABEL: define void @promoteOneArgSExt(98; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) {99; DISABLE-NEXT: [[ENTRY:.*:]]100; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1101; DISABLE-NEXT: [[ADD:%.*]] = add nsw i8 [[T]], 2102; DISABLE-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20103; DISABLE-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]104; DISABLE: [[TRUE]]:105; DISABLE-NEXT: [[S:%.*]] = sext i8 [[ADD]] to i32106; DISABLE-NEXT: store i32 [[S]], ptr [[Q]], align 4107; DISABLE-NEXT: ret void108; DISABLE: [[FALSE]]:109; DISABLE-NEXT: ret void110;111entry:112 %t = load i8, ptr %p113 %add = add nsw i8 %t, 2114 %a = icmp slt i8 %t, 20115 br i1 %a, label %true, label %false116true:117 %s = sext i8 %add to i32118 store i32 %s, ptr %q119 ret void120false:121 ret void122}123 124; Check that we manage to form a zextload is an operation with two125; arguments to explicitly extend is in the way.126; Extending %add will create two extensions:127; 1. One for %b.128; 2. One for %t.129; #1 will not be removed as we do not know anything about %b.130; #2 may not be merged with the load because %t is used in a comparison.131; Since two extensions may be emitted in the end instead of one before the132; transformation, the regular heuristic does not apply the optimization.133define void @promoteTwoArgZext(ptr %p, ptr %q, i8 %b) {134; NONSTRESS-LABEL: define void @promoteTwoArgZext(135; NONSTRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {136; NONSTRESS-NEXT: [[ENTRY:.*:]]137; NONSTRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1138; NONSTRESS-NEXT: [[ADD:%.*]] = add nuw i8 [[T]], [[B]]139; NONSTRESS-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20140; NONSTRESS-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]141; NONSTRESS: [[TRUE]]:142; NONSTRESS-NEXT: [[S:%.*]] = zext i8 [[ADD]] to i32143; NONSTRESS-NEXT: store i32 [[S]], ptr [[Q]], align 4144; NONSTRESS-NEXT: ret void145; NONSTRESS: [[FALSE]]:146; NONSTRESS-NEXT: ret void147;148; STRESS-LABEL: define void @promoteTwoArgZext(149; STRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {150; STRESS-NEXT: [[ENTRY:.*:]]151; STRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1152; STRESS-NEXT: [[PROMOTED:%.*]] = zext i8 [[T]] to i32153; STRESS-NEXT: [[PROMOTED1:%.*]] = zext i8 [[B]] to i32154; STRESS-NEXT: [[ADD:%.*]] = add nuw i32 [[PROMOTED]], [[PROMOTED1]]155; STRESS-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20156; STRESS-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]157; STRESS: [[TRUE]]:158; STRESS-NEXT: store i32 [[ADD]], ptr [[Q]], align 4159; STRESS-NEXT: ret void160; STRESS: [[FALSE]]:161; STRESS-NEXT: ret void162;163; DISABLE-LABEL: define void @promoteTwoArgZext(164; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {165; DISABLE-NEXT: [[ENTRY:.*:]]166; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1167; DISABLE-NEXT: [[ADD:%.*]] = add nuw i8 [[T]], [[B]]168; DISABLE-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20169; DISABLE-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]170; DISABLE: [[TRUE]]:171; DISABLE-NEXT: [[S:%.*]] = zext i8 [[ADD]] to i32172; DISABLE-NEXT: store i32 [[S]], ptr [[Q]], align 4173; DISABLE-NEXT: ret void174; DISABLE: [[FALSE]]:175; DISABLE-NEXT: ret void176;177entry:178 %t = load i8, ptr %p179 %add = add nuw i8 %t, %b180 %a = icmp slt i8 %t, 20181 br i1 %a, label %true, label %false182true:183 %s = zext i8 %add to i32184 store i32 %s, ptr %q185 ret void186false:187 ret void188}189 190; Check that we manage to form a sextload is an operation with two191; arguments to explicitly extend is in the way.192; Version with sext.193define void @promoteTwoArgSExt(ptr %p, ptr %q, i8 %b) {194; NONSTRESS-LABEL: define void @promoteTwoArgSExt(195; NONSTRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {196; NONSTRESS-NEXT: [[ENTRY:.*:]]197; NONSTRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1198; NONSTRESS-NEXT: [[ADD:%.*]] = add nsw i8 [[T]], [[B]]199; NONSTRESS-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20200; NONSTRESS-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]201; NONSTRESS: [[TRUE]]:202; NONSTRESS-NEXT: [[S:%.*]] = sext i8 [[ADD]] to i32203; NONSTRESS-NEXT: store i32 [[S]], ptr [[Q]], align 4204; NONSTRESS-NEXT: ret void205; NONSTRESS: [[FALSE]]:206; NONSTRESS-NEXT: ret void207;208; STRESS-LABEL: define void @promoteTwoArgSExt(209; STRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {210; STRESS-NEXT: [[ENTRY:.*:]]211; STRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1212; STRESS-NEXT: [[PROMOTED:%.*]] = sext i8 [[T]] to i32213; STRESS-NEXT: [[PROMOTED1:%.*]] = sext i8 [[B]] to i32214; STRESS-NEXT: [[ADD:%.*]] = add nsw i32 [[PROMOTED]], [[PROMOTED1]]215; STRESS-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20216; STRESS-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]217; STRESS: [[TRUE]]:218; STRESS-NEXT: store i32 [[ADD]], ptr [[Q]], align 4219; STRESS-NEXT: ret void220; STRESS: [[FALSE]]:221; STRESS-NEXT: ret void222;223; DISABLE-LABEL: define void @promoteTwoArgSExt(224; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {225; DISABLE-NEXT: [[ENTRY:.*:]]226; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1227; DISABLE-NEXT: [[ADD:%.*]] = add nsw i8 [[T]], [[B]]228; DISABLE-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20229; DISABLE-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]230; DISABLE: [[TRUE]]:231; DISABLE-NEXT: [[S:%.*]] = sext i8 [[ADD]] to i32232; DISABLE-NEXT: store i32 [[S]], ptr [[Q]], align 4233; DISABLE-NEXT: ret void234; DISABLE: [[FALSE]]:235; DISABLE-NEXT: ret void236;237entry:238 %t = load i8, ptr %p239 %add = add nsw i8 %t, %b240 %a = icmp slt i8 %t, 20241 br i1 %a, label %true, label %false242true:243 %s = sext i8 %add to i32244 store i32 %s, ptr %q245 ret void246false:247 ret void248}249 250; Check that we do not a zextload if we need to introduce more than251; one additional extension.252define void @promoteThreeArgZext(ptr %p, ptr %q, i8 %b, i8 %c) {253; NONSTRESS-LABEL: define void @promoteThreeArgZext(254; NONSTRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {255; NONSTRESS-NEXT: [[ENTRY:.*:]]256; NONSTRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1257; NONSTRESS-NEXT: [[TMP:%.*]] = add nuw i8 [[T]], [[B]]258; NONSTRESS-NEXT: [[ADD:%.*]] = add nuw i8 [[TMP]], [[C]]259; NONSTRESS-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20260; NONSTRESS-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]261; NONSTRESS: [[TRUE]]:262; NONSTRESS-NEXT: [[S:%.*]] = zext i8 [[ADD]] to i32263; NONSTRESS-NEXT: store i32 [[S]], ptr [[Q]], align 4264; NONSTRESS-NEXT: ret void265; NONSTRESS: [[FALSE]]:266; NONSTRESS-NEXT: ret void267;268; STRESS-LABEL: define void @promoteThreeArgZext(269; STRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {270; STRESS-NEXT: [[ENTRY:.*:]]271; STRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1272; STRESS-NEXT: [[PROMOTED2:%.*]] = zext i8 [[T]] to i32273; STRESS-NEXT: [[PROMOTED3:%.*]] = zext i8 [[B]] to i32274; STRESS-NEXT: [[TMP:%.*]] = add nuw i32 [[PROMOTED2]], [[PROMOTED3]]275; STRESS-NEXT: [[PROMOTED1:%.*]] = zext i8 [[C]] to i32276; STRESS-NEXT: [[ADD:%.*]] = add nuw i32 [[TMP]], [[PROMOTED1]]277; STRESS-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20278; STRESS-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]279; STRESS: [[TRUE]]:280; STRESS-NEXT: store i32 [[ADD]], ptr [[Q]], align 4281; STRESS-NEXT: ret void282; STRESS: [[FALSE]]:283; STRESS-NEXT: ret void284;285; DISABLE-LABEL: define void @promoteThreeArgZext(286; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {287; DISABLE-NEXT: [[ENTRY:.*:]]288; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1289; DISABLE-NEXT: [[TMP:%.*]] = add nuw i8 [[T]], [[B]]290; DISABLE-NEXT: [[ADD:%.*]] = add nuw i8 [[TMP]], [[C]]291; DISABLE-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20292; DISABLE-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]293; DISABLE: [[TRUE]]:294; DISABLE-NEXT: [[S:%.*]] = zext i8 [[ADD]] to i32295; DISABLE-NEXT: store i32 [[S]], ptr [[Q]], align 4296; DISABLE-NEXT: ret void297; DISABLE: [[FALSE]]:298; DISABLE-NEXT: ret void299;300entry:301 %t = load i8, ptr %p302 %tmp = add nuw i8 %t, %b303 %add = add nuw i8 %tmp, %c304 %a = icmp slt i8 %t, 20305 br i1 %a, label %true, label %false306true:307 %s = zext i8 %add to i32308 store i32 %s, ptr %q309 ret void310false:311 ret void312}313 314; Check that we manage to form a zextload after promoting and merging315; two extensions.316define void @promoteMergeExtArgZExt(ptr %p, ptr %q, i16 %b) {317; NONSTRESS-LABEL: define void @promoteMergeExtArgZExt(318; NONSTRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {319; NONSTRESS-NEXT: [[ENTRY:.*:]]320; NONSTRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1321; NONSTRESS-NEXT: [[EXT:%.*]] = zext i8 [[T]] to i16322; NONSTRESS-NEXT: [[ADD:%.*]] = add nuw i16 [[EXT]], [[B]]323; NONSTRESS-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20324; NONSTRESS-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]325; NONSTRESS: [[TRUE]]:326; NONSTRESS-NEXT: [[S:%.*]] = zext i16 [[ADD]] to i32327; NONSTRESS-NEXT: store i32 [[S]], ptr [[Q]], align 4328; NONSTRESS-NEXT: ret void329; NONSTRESS: [[FALSE]]:330; NONSTRESS-NEXT: ret void331;332; STRESS-LABEL: define void @promoteMergeExtArgZExt(333; STRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {334; STRESS-NEXT: [[ENTRY:.*:]]335; STRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1336; STRESS-NEXT: [[PROMOTED2:%.*]] = zext i8 [[T]] to i32337; STRESS-NEXT: [[PROMOTED1:%.*]] = zext i16 [[B]] to i32338; STRESS-NEXT: [[ADD:%.*]] = add nuw i32 [[PROMOTED2]], [[PROMOTED1]]339; STRESS-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20340; STRESS-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]341; STRESS: [[TRUE]]:342; STRESS-NEXT: store i32 [[ADD]], ptr [[Q]], align 4343; STRESS-NEXT: ret void344; STRESS: [[FALSE]]:345; STRESS-NEXT: ret void346;347; DISABLE-LABEL: define void @promoteMergeExtArgZExt(348; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {349; DISABLE-NEXT: [[ENTRY:.*:]]350; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1351; DISABLE-NEXT: [[EXT:%.*]] = zext i8 [[T]] to i16352; DISABLE-NEXT: [[ADD:%.*]] = add nuw i16 [[EXT]], [[B]]353; DISABLE-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20354; DISABLE-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]355; DISABLE: [[TRUE]]:356; DISABLE-NEXT: [[S:%.*]] = zext i16 [[ADD]] to i32357; DISABLE-NEXT: store i32 [[S]], ptr [[Q]], align 4358; DISABLE-NEXT: ret void359; DISABLE: [[FALSE]]:360; DISABLE-NEXT: ret void361;362entry:363 %t = load i8, ptr %p364 %ext = zext i8 %t to i16365 %add = add nuw i16 %ext, %b366 %a = icmp slt i8 %t, 20367 br i1 %a, label %true, label %false368true:369 %s = zext i16 %add to i32370 store i32 %s, ptr %q371 ret void372false:373 ret void374}375 376; Check that we manage to form a sextload after promoting and merging377; two extensions.378; Version with sext.379define void @promoteMergeExtArgSExt(ptr %p, ptr %q, i16 %b) {380; NONSTRESS-LABEL: define void @promoteMergeExtArgSExt(381; NONSTRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {382; NONSTRESS-NEXT: [[ENTRY:.*:]]383; NONSTRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1384; NONSTRESS-NEXT: [[EXT:%.*]] = zext i8 [[T]] to i16385; NONSTRESS-NEXT: [[ADD:%.*]] = add nsw i16 [[EXT]], [[B]]386; NONSTRESS-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20387; NONSTRESS-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]388; NONSTRESS: [[TRUE]]:389; NONSTRESS-NEXT: [[S:%.*]] = sext i16 [[ADD]] to i32390; NONSTRESS-NEXT: store i32 [[S]], ptr [[Q]], align 4391; NONSTRESS-NEXT: ret void392; NONSTRESS: [[FALSE]]:393; NONSTRESS-NEXT: ret void394;395; STRESS-LABEL: define void @promoteMergeExtArgSExt(396; STRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {397; STRESS-NEXT: [[ENTRY:.*:]]398; STRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1399; STRESS-NEXT: [[PROMOTED2:%.*]] = zext i8 [[T]] to i32400; STRESS-NEXT: [[PROMOTED1:%.*]] = sext i16 [[B]] to i32401; STRESS-NEXT: [[ADD:%.*]] = add nsw i32 [[PROMOTED2]], [[PROMOTED1]]402; STRESS-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20403; STRESS-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]404; STRESS: [[TRUE]]:405; STRESS-NEXT: store i32 [[ADD]], ptr [[Q]], align 4406; STRESS-NEXT: ret void407; STRESS: [[FALSE]]:408; STRESS-NEXT: ret void409;410; DISABLE-LABEL: define void @promoteMergeExtArgSExt(411; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {412; DISABLE-NEXT: [[ENTRY:.*:]]413; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1414; DISABLE-NEXT: [[EXT:%.*]] = zext i8 [[T]] to i16415; DISABLE-NEXT: [[ADD:%.*]] = add nsw i16 [[EXT]], [[B]]416; DISABLE-NEXT: [[A:%.*]] = icmp slt i8 [[T]], 20417; DISABLE-NEXT: br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]418; DISABLE: [[TRUE]]:419; DISABLE-NEXT: [[S:%.*]] = sext i16 [[ADD]] to i32420; DISABLE-NEXT: store i32 [[S]], ptr [[Q]], align 4421; DISABLE-NEXT: ret void422; DISABLE: [[FALSE]]:423; DISABLE-NEXT: ret void424;425entry:426 %t = load i8, ptr %p427 %ext = zext i8 %t to i16428 %add = add nsw i16 %ext, %b429 %a = icmp slt i8 %t, 20430 br i1 %a, label %true, label %false431true:432 %s = sext i16 %add to i32433 store i32 %s, ptr %q434 ret void435false:436 ret void437}438 439; Check that we manage to catch all the extload opportunities that are exposed440; by the different iterations of codegen prepare.441; Moreover, check that we do not promote more than we need to.442; Here is what is happening in this test (not necessarly in this order):443; 1. We try to promote the operand of %sextadd.444; a. This creates one sext of %ld2 and one of %zextld445; b. The sext of %ld2 can be combine with %ld2, so we remove one sext but446; introduced one. This is fine with the current heuristic: neutral.447; => We have one zext of %zextld left and we created one sext of %ld2.448; 2. We try to promote the operand of %sextaddza.449; a. This creates one sext of %zexta and one of %zextld450; b. The sext of %zexta can be combined with the zext of %a.451; c. The sext of %zextld leads to %ld and can be combined with it. This is452; done by promoting %zextld. This is fine with the current heuristic:453; neutral.454; => We have created a new zext of %ld and we created one sext of %zexta.455; 3. We try to promote the operand of %sextaddb.456; a. This creates one sext of %b and one of %zextld457; b. The sext of %b is a dead-end, nothing to be done.458; c. Same thing as 2.c. happens.459; => We have created a new zext of %ld and we created one sext of %b.460; 4. We try to promote the operand of the zext of %zextld introduced in #1.461; a. Same thing as 2.c. happens.462; b. %zextld does not have any other uses. It is dead coded.463; => We have created a new zext of %ld and we removed a zext of %zextld and464; a zext of %ld.465; Currently we do not try to reuse existing extensions, so in the end we have466; 3 identical zext of %ld. The extensions will be CSE'ed by SDag.467define void @severalPromotions(ptr %addr1, ptr %addr2, i8 %a, i32 %b) {468; OPT-LABEL: define void @severalPromotions(469; OPT-SAME: ptr [[ADDR1:%.*]], ptr [[ADDR2:%.*]], i8 [[A:%.*]], i32 [[B:%.*]]) {470; OPT-NEXT: [[LD:%.*]] = load i8, ptr [[ADDR1]], align 1471; OPT-NEXT: [[PROMOTED9:%.*]] = zext i8 [[LD]] to i64472; OPT-NEXT: [[PROMOTED6:%.*]] = zext i8 [[LD]] to i64473; OPT-NEXT: [[LD2:%.*]] = load i32, ptr [[ADDR2]], align 4474; OPT-NEXT: [[PROMOTED:%.*]] = sext i32 [[LD2]] to i64475; OPT-NEXT: [[PROMOTED2:%.*]] = zext i8 [[LD]] to i64476; OPT-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED]], [[PROMOTED2]]477; OPT-NEXT: [[PROMOTED5:%.*]] = zext i8 [[A]] to i64478; OPT-NEXT: [[ADDZA:%.*]] = add nsw i64 [[PROMOTED5]], [[PROMOTED6]]479; OPT-NEXT: [[PROMOTED7:%.*]] = sext i32 [[B]] to i64480; OPT-NEXT: [[ADDB:%.*]] = add nsw i64 [[PROMOTED7]], [[PROMOTED9]]481; OPT-NEXT: call void @dummy(i64 [[ADD]], i64 [[ADDZA]], i64 [[ADDB]])482; OPT-NEXT: ret void483;484; DISABLE-LABEL: define void @severalPromotions(485; DISABLE-SAME: ptr [[ADDR1:%.*]], ptr [[ADDR2:%.*]], i8 [[A:%.*]], i32 [[B:%.*]]) {486; DISABLE-NEXT: [[LD:%.*]] = load i8, ptr [[ADDR1]], align 1487; DISABLE-NEXT: [[ZEXTLD:%.*]] = zext i8 [[LD]] to i32488; DISABLE-NEXT: [[LD2:%.*]] = load i32, ptr [[ADDR2]], align 4489; DISABLE-NEXT: [[ADD:%.*]] = add nsw i32 [[LD2]], [[ZEXTLD]]490; DISABLE-NEXT: [[SEXTADD:%.*]] = sext i32 [[ADD]] to i64491; DISABLE-NEXT: [[ZEXTA:%.*]] = zext i8 [[A]] to i32492; DISABLE-NEXT: [[ADDZA:%.*]] = add nsw i32 [[ZEXTA]], [[ZEXTLD]]493; DISABLE-NEXT: [[SEXTADDZA:%.*]] = sext i32 [[ADDZA]] to i64494; DISABLE-NEXT: [[ADDB:%.*]] = add nsw i32 [[B]], [[ZEXTLD]]495; DISABLE-NEXT: [[SEXTADDB:%.*]] = sext i32 [[ADDB]] to i64496; DISABLE-NEXT: call void @dummy(i64 [[SEXTADD]], i64 [[SEXTADDZA]], i64 [[SEXTADDB]])497; DISABLE-NEXT: ret void498;499 %ld = load i8, ptr %addr1500 %zextld = zext i8 %ld to i32501 %ld2 = load i32, ptr %addr2502 %add = add nsw i32 %ld2, %zextld503 %sextadd = sext i32 %add to i64504 %zexta = zext i8 %a to i32505 %addza = add nsw i32 %zexta, %zextld506 %sextaddza = sext i32 %addza to i64507 %addb = add nsw i32 %b, %zextld508 %sextaddb = sext i32 %addb to i64509 call void @dummy(i64 %sextadd, i64 %sextaddza, i64 %sextaddb)510 ret void511}512 513declare void @dummy(i64, i64, i64)514 515; Make sure we do not try to promote vector types since the type promotion516; helper does not support them for now.517define void @vectorPromotion() {518; OPTALL-LABEL: define void @vectorPromotion() {519; OPTALL-NEXT: [[ENTRY:.*:]]520; OPTALL-NEXT: [[A:%.*]] = shl nuw nsw <2 x i32> zeroinitializer, splat (i32 8)521; OPTALL-NEXT: [[B:%.*]] = zext <2 x i32> [[A]] to <2 x i64>522; OPTALL-NEXT: ret void523;524entry:525 %a = shl nuw nsw <2 x i32> zeroinitializer, <i32 8, i32 8>526 %b = zext <2 x i32> %a to <2 x i64>527 ret void528}529 530@a = common global i32 0, align 4531@c = common global [2 x i32] zeroinitializer, align 4532 533; Make sure we support promotion of operands that produces a Value as opposed534; to an instruction.535; This used to cause a crash.536define i32 @promotionOfArgEndsUpInValue(ptr %addr) {537; OPT-LABEL: define i32 @promotionOfArgEndsUpInValue(538; OPT-SAME: ptr [[ADDR:%.*]]) {539; OPT-NEXT: [[ENTRY:.*:]]540; OPT-NEXT: [[VAL:%.*]] = load i16, ptr [[ADDR]], align 2541; OPT-NEXT: [[PROMOTED:%.*]] = sext i16 [[VAL]] to i32542; OPT-NEXT: [[CMP:%.*]] = icmp ne ptr getelementptr inbounds ([2 x i32], ptr @c, i64 0, i64 1), @a543; OPT-NEXT: [[PROMOTED2:%.*]] = zext i1 [[CMP]] to i32544; OPT-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[PROMOTED]], [[PROMOTED2]]545; OPT-NEXT: ret i32 [[ADD]]546;547; DISABLE-LABEL: define i32 @promotionOfArgEndsUpInValue(548; DISABLE-SAME: ptr [[ADDR:%.*]]) {549; DISABLE-NEXT: [[ENTRY:.*:]]550; DISABLE-NEXT: [[VAL:%.*]] = load i16, ptr [[ADDR]], align 2551; DISABLE-NEXT: [[CMP:%.*]] = icmp ne ptr getelementptr inbounds ([2 x i32], ptr @c, i64 0, i64 1), @a552; DISABLE-NEXT: [[EXT:%.*]] = zext i1 [[CMP]] to i16553; DISABLE-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[VAL]], [[EXT]]554; DISABLE-NEXT: [[CONV3:%.*]] = sext i16 [[ADD]] to i32555; DISABLE-NEXT: ret i32 [[CONV3]]556;557entry:558 %val = load i16, ptr %addr559 %cmp = icmp ne ptr getelementptr inbounds ([2 x i32], ptr @c, i64 0, i64 1), @a560 %ext = zext i1 %cmp to i16561 %add = add nuw nsw i16 %val, %ext562 %conv3 = sext i16 %add to i32563 ret i32 %conv3564}565 566; Check that we see that one zext can be derived from the other for free.567define void @promoteTwoArgZextWithSourceExtendedTwice(ptr %p, ptr %q, i32 %b, ptr %addr) {568; OPT-LABEL: define void @promoteTwoArgZextWithSourceExtendedTwice(569; OPT-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]]) {570; OPT-NEXT: [[ENTRY:.*:]]571; OPT-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1572; OPT-NEXT: [[PROMOTED1:%.*]] = zext i8 [[T]] to i64573; OPT-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32574; OPT-NEXT: [[ADD:%.*]] = add nuw i32 [[ZEXTT]], [[B]]575; OPT-NEXT: [[ADD2:%.*]] = add nuw i64 [[PROMOTED1]], 12576; OPT-NEXT: store i32 [[ADD]], ptr [[ADDR]], align 4577; OPT-NEXT: store i64 [[ADD2]], ptr [[Q]], align 8578; OPT-NEXT: ret void579;580; DISABLE-LABEL: define void @promoteTwoArgZextWithSourceExtendedTwice(581; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]]) {582; DISABLE-NEXT: [[ENTRY:.*:]]583; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1584; DISABLE-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32585; DISABLE-NEXT: [[ADD:%.*]] = add nuw i32 [[ZEXTT]], [[B]]586; DISABLE-NEXT: [[ADD2:%.*]] = add nuw i32 [[ZEXTT]], 12587; DISABLE-NEXT: store i32 [[ADD]], ptr [[ADDR]], align 4588; DISABLE-NEXT: [[S:%.*]] = zext i32 [[ADD2]] to i64589; DISABLE-NEXT: store i64 [[S]], ptr [[Q]], align 8590; DISABLE-NEXT: ret void591;592entry:593 %t = load i8, ptr %p594 %zextt = zext i8 %t to i32595 %add = add nuw i32 %zextt, %b596 %add2 = add nuw i32 %zextt, 12597 store i32 %add, ptr %addr598 %s = zext i32 %add2 to i64599 store i64 %s, ptr %q600 ret void601}602 603; Check that we do not increase the cost of the code.604; The input has one free zext and one free sext. If we would have promoted605; all the way through the load we would end up with a free zext and a606; non-free sext (of %b).607define void @doNotPromoteFreeSExtFromAddrMode(ptr %p, i32 %b, ptr %addr) {608; NONSTRESS-LABEL: define void @doNotPromoteFreeSExtFromAddrMode(609; NONSTRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]]) {610; NONSTRESS-NEXT: [[ENTRY:.*:]]611; NONSTRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1612; NONSTRESS-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32613; NONSTRESS-NEXT: [[ADD:%.*]] = add nsw i32 [[ZEXTT]], [[B]]614; NONSTRESS-NEXT: [[IDX64:%.*]] = sext i32 [[ADD]] to i64615; NONSTRESS-NEXT: [[STADDR:%.*]] = getelementptr inbounds i32, ptr [[ADDR]], i64 [[IDX64]]616; NONSTRESS-NEXT: store i32 [[ADD]], ptr [[STADDR]], align 4617; NONSTRESS-NEXT: ret void618;619; STRESS-LABEL: define void @doNotPromoteFreeSExtFromAddrMode(620; STRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]]) {621; STRESS-NEXT: [[ENTRY:.*:]]622; STRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1623; STRESS-NEXT: [[PROMOTED3:%.*]] = zext i8 [[T]] to i64624; STRESS-NEXT: [[PROMOTED2:%.*]] = sext i32 [[B]] to i64625; STRESS-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED3]], [[PROMOTED2]]626; STRESS-NEXT: [[PROMOTED:%.*]] = trunc i64 [[ADD]] to i32627; STRESS-NEXT: [[STADDR:%.*]] = getelementptr inbounds i32, ptr [[ADDR]], i64 [[ADD]]628; STRESS-NEXT: store i32 [[PROMOTED]], ptr [[STADDR]], align 4629; STRESS-NEXT: ret void630;631; DISABLE-LABEL: define void @doNotPromoteFreeSExtFromAddrMode(632; DISABLE-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]]) {633; DISABLE-NEXT: [[ENTRY:.*:]]634; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1635; DISABLE-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32636; DISABLE-NEXT: [[ADD:%.*]] = add nsw i32 [[ZEXTT]], [[B]]637; DISABLE-NEXT: [[IDX64:%.*]] = sext i32 [[ADD]] to i64638; DISABLE-NEXT: [[STADDR:%.*]] = getelementptr inbounds i32, ptr [[ADDR]], i64 [[IDX64]]639; DISABLE-NEXT: store i32 [[ADD]], ptr [[STADDR]], align 4640; DISABLE-NEXT: ret void641;642entry:643 %t = load i8, ptr %p644 %zextt = zext i8 %t to i32645 %add = add nsw i32 %zextt, %b646 %idx64 = sext i32 %add to i64647 %staddr = getelementptr inbounds i32, ptr %addr, i64 %idx64648 store i32 %add, ptr %staddr649 ret void650}651 652; Check that we do not increase the cost of the code.653; The input has one free zext and one free sext. If we would have promoted654; all the way through the load we would end up with a free zext and a655; non-free sext (of %b).656define void @doNotPromoteFreeSExtFromAddrMode64(ptr %p, i32 %b, ptr %addr, i64 %stuff) {657; NONSTRESS-LABEL: define void @doNotPromoteFreeSExtFromAddrMode64(658; NONSTRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]], i64 [[STUFF:%.*]]) {659; NONSTRESS-NEXT: [[ENTRY:.*:]]660; NONSTRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1661; NONSTRESS-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32662; NONSTRESS-NEXT: [[ADD:%.*]] = add nsw i32 [[ZEXTT]], [[B]]663; NONSTRESS-NEXT: [[IDX64:%.*]] = sext i32 [[ADD]] to i64664; NONSTRESS-NEXT: [[STADDR:%.*]] = getelementptr inbounds i64, ptr [[ADDR]], i64 [[IDX64]]665; NONSTRESS-NEXT: store i64 [[STUFF]], ptr [[STADDR]], align 8666; NONSTRESS-NEXT: ret void667;668; STRESS-LABEL: define void @doNotPromoteFreeSExtFromAddrMode64(669; STRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]], i64 [[STUFF:%.*]]) {670; STRESS-NEXT: [[ENTRY:.*:]]671; STRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1672; STRESS-NEXT: [[PROMOTED2:%.*]] = zext i8 [[T]] to i64673; STRESS-NEXT: [[PROMOTED1:%.*]] = sext i32 [[B]] to i64674; STRESS-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED2]], [[PROMOTED1]]675; STRESS-NEXT: [[STADDR:%.*]] = getelementptr inbounds i64, ptr [[ADDR]], i64 [[ADD]]676; STRESS-NEXT: store i64 [[STUFF]], ptr [[STADDR]], align 8677; STRESS-NEXT: ret void678;679; DISABLE-LABEL: define void @doNotPromoteFreeSExtFromAddrMode64(680; DISABLE-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]], i64 [[STUFF:%.*]]) {681; DISABLE-NEXT: [[ENTRY:.*:]]682; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1683; DISABLE-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32684; DISABLE-NEXT: [[ADD:%.*]] = add nsw i32 [[ZEXTT]], [[B]]685; DISABLE-NEXT: [[IDX64:%.*]] = sext i32 [[ADD]] to i64686; DISABLE-NEXT: [[STADDR:%.*]] = getelementptr inbounds i64, ptr [[ADDR]], i64 [[IDX64]]687; DISABLE-NEXT: store i64 [[STUFF]], ptr [[STADDR]], align 8688; DISABLE-NEXT: ret void689;690entry:691 %t = load i8, ptr %p692 %zextt = zext i8 %t to i32693 %add = add nsw i32 %zextt, %b694 %idx64 = sext i32 %add to i64695 %staddr = getelementptr inbounds i64, ptr %addr, i64 %idx64696 store i64 %stuff, ptr %staddr697 ret void698}699 700; Check that we do not increase the cost of the code.701; The input has one free zext and one free sext. If we would have promoted702; all the way through the load we would end up with a free zext and a703; non-free sext (of %b).704define void @doNotPromoteFreeSExtFromAddrMode128(ptr %p, i32 %b, ptr %addr, i128 %stuff) {705; NONSTRESS-LABEL: define void @doNotPromoteFreeSExtFromAddrMode128(706; NONSTRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]], i128 [[STUFF:%.*]]) {707; NONSTRESS-NEXT: [[ENTRY:.*:]]708; NONSTRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1709; NONSTRESS-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32710; NONSTRESS-NEXT: [[ADD:%.*]] = add nsw i32 [[ZEXTT]], [[B]]711; NONSTRESS-NEXT: [[IDX64:%.*]] = sext i32 [[ADD]] to i64712; NONSTRESS-NEXT: [[STADDR:%.*]] = getelementptr inbounds i128, ptr [[ADDR]], i64 [[IDX64]]713; NONSTRESS-NEXT: store i128 [[STUFF]], ptr [[STADDR]], align 16714; NONSTRESS-NEXT: ret void715;716; STRESS-LABEL: define void @doNotPromoteFreeSExtFromAddrMode128(717; STRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]], i128 [[STUFF:%.*]]) {718; STRESS-NEXT: [[ENTRY:.*:]]719; STRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1720; STRESS-NEXT: [[PROMOTED2:%.*]] = zext i8 [[T]] to i64721; STRESS-NEXT: [[PROMOTED1:%.*]] = sext i32 [[B]] to i64722; STRESS-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED2]], [[PROMOTED1]]723; STRESS-NEXT: [[STADDR:%.*]] = getelementptr inbounds i128, ptr [[ADDR]], i64 [[ADD]]724; STRESS-NEXT: store i128 [[STUFF]], ptr [[STADDR]], align 16725; STRESS-NEXT: ret void726;727; DISABLE-LABEL: define void @doNotPromoteFreeSExtFromAddrMode128(728; DISABLE-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]], i128 [[STUFF:%.*]]) {729; DISABLE-NEXT: [[ENTRY:.*:]]730; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1731; DISABLE-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32732; DISABLE-NEXT: [[ADD:%.*]] = add nsw i32 [[ZEXTT]], [[B]]733; DISABLE-NEXT: [[IDX64:%.*]] = sext i32 [[ADD]] to i64734; DISABLE-NEXT: [[STADDR:%.*]] = getelementptr inbounds i128, ptr [[ADDR]], i64 [[IDX64]]735; DISABLE-NEXT: store i128 [[STUFF]], ptr [[STADDR]], align 16736; DISABLE-NEXT: ret void737;738entry:739 %t = load i8, ptr %p740 %zextt = zext i8 %t to i32741 %add = add nsw i32 %zextt, %b742 %idx64 = sext i32 %add to i64743 %staddr = getelementptr inbounds i128, ptr %addr, i64 %idx64744 store i128 %stuff, ptr %staddr745 ret void746}747 748 749; Check that we do not increase the cost of the code.750; The input has one free zext and one free sext. If we would have promoted751; all the way through the load we would end up with a free zext and a752; non-free sext (of %b).753define void @promoteSExtFromAddrMode256(ptr %p, i32 %b, ptr %addr, i256 %stuff) {754; OPT-LABEL: define void @promoteSExtFromAddrMode256(755; OPT-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]], i256 [[STUFF:%.*]]) {756; OPT-NEXT: [[ENTRY:.*:]]757; OPT-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1758; OPT-NEXT: [[PROMOTED2:%.*]] = zext i8 [[T]] to i64759; OPT-NEXT: [[PROMOTED1:%.*]] = sext i32 [[B]] to i64760; OPT-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED2]], [[PROMOTED1]]761; OPT-NEXT: [[STADDR:%.*]] = getelementptr inbounds i256, ptr [[ADDR]], i64 [[ADD]]762; OPT-NEXT: store i256 [[STUFF]], ptr [[STADDR]], align 16763; OPT-NEXT: ret void764;765; DISABLE-LABEL: define void @promoteSExtFromAddrMode256(766; DISABLE-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]], i256 [[STUFF:%.*]]) {767; DISABLE-NEXT: [[ENTRY:.*:]]768; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1769; DISABLE-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32770; DISABLE-NEXT: [[ADD:%.*]] = add nsw i32 [[ZEXTT]], [[B]]771; DISABLE-NEXT: [[IDX64:%.*]] = sext i32 [[ADD]] to i64772; DISABLE-NEXT: [[STADDR:%.*]] = getelementptr inbounds i256, ptr [[ADDR]], i64 [[IDX64]]773; DISABLE-NEXT: store i256 [[STUFF]], ptr [[STADDR]], align 16774; DISABLE-NEXT: ret void775;776entry:777 %t = load i8, ptr %p778 %zextt = zext i8 %t to i32779 %add = add nsw i32 %zextt, %b780 %idx64 = sext i32 %add to i64781 %staddr = getelementptr inbounds i256, ptr %addr, i64 %idx64782 store i256 %stuff, ptr %staddr783 ret void784}785 786; Check that we do not increase the cost of the code.787; The input has one free zext and one free zext.788; When we promote all the way through the load, we end up with789; a free zext and a non-free zext (of %b).790; However, the current target lowering says zext i32 to i64 is free791; so the promotion happens because the cost did not change and may792; expose more opportunities.793; This would need to be fixed at some point.794;795; This transformation should really happen only for stress mode.796define void @doNotPromoteFreeZExtFromAddrMode(ptr %p, i32 %b, ptr %addr) {797; NONSTRESS-LABEL: define void @doNotPromoteFreeZExtFromAddrMode(798; NONSTRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]]) {799; NONSTRESS-NEXT: [[ENTRY:.*:]]800; NONSTRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1801; NONSTRESS-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32802; NONSTRESS-NEXT: [[ADD:%.*]] = add nuw i32 [[ZEXTT]], [[B]]803; NONSTRESS-NEXT: [[IDX64:%.*]] = zext i32 [[ADD]] to i64804; NONSTRESS-NEXT: [[STADDR:%.*]] = getelementptr inbounds i32, ptr [[ADDR]], i64 [[IDX64]]805; NONSTRESS-NEXT: store i32 [[ADD]], ptr [[STADDR]], align 4806; NONSTRESS-NEXT: ret void807;808; STRESS-LABEL: define void @doNotPromoteFreeZExtFromAddrMode(809; STRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]]) {810; STRESS-NEXT: [[ENTRY:.*:]]811; STRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1812; STRESS-NEXT: [[PROMOTED3:%.*]] = zext i8 [[T]] to i64813; STRESS-NEXT: [[PROMOTED2:%.*]] = zext i32 [[B]] to i64814; STRESS-NEXT: [[ADD:%.*]] = add nuw i64 [[PROMOTED3]], [[PROMOTED2]]815; STRESS-NEXT: [[PROMOTED:%.*]] = trunc i64 [[ADD]] to i32816; STRESS-NEXT: [[STADDR:%.*]] = getelementptr inbounds i32, ptr [[ADDR]], i64 [[ADD]]817; STRESS-NEXT: store i32 [[PROMOTED]], ptr [[STADDR]], align 4818; STRESS-NEXT: ret void819;820; DISABLE-LABEL: define void @doNotPromoteFreeZExtFromAddrMode(821; DISABLE-SAME: ptr [[P:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]]) {822; DISABLE-NEXT: [[ENTRY:.*:]]823; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1824; DISABLE-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32825; DISABLE-NEXT: [[ADD:%.*]] = add nuw i32 [[ZEXTT]], [[B]]826; DISABLE-NEXT: [[IDX64:%.*]] = zext i32 [[ADD]] to i64827; DISABLE-NEXT: [[STADDR:%.*]] = getelementptr inbounds i32, ptr [[ADDR]], i64 [[IDX64]]828; DISABLE-NEXT: store i32 [[ADD]], ptr [[STADDR]], align 4829; DISABLE-NEXT: ret void830;831entry:832 %t = load i8, ptr %p833 %zextt = zext i8 %t to i32834 %add = add nuw i32 %zextt, %b835 %idx64 = zext i32 %add to i64836 %staddr = getelementptr inbounds i32, ptr %addr, i64 %idx64837 store i32 %add, ptr %staddr838 ret void839}840 841define i64 @doNotPromoteFreeSExtFromShift(ptr %p, i32 %b) {842; NONSTRESS-LABEL: define i64 @doNotPromoteFreeSExtFromShift(843; NONSTRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]]) {844; NONSTRESS-NEXT: [[ENTRY:.*:]]845; NONSTRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1846; NONSTRESS-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32847; NONSTRESS-NEXT: [[ADD:%.*]] = add nsw i32 [[ZEXTT]], [[B]]848; NONSTRESS-NEXT: [[IDX64:%.*]] = sext i32 [[ADD]] to i64849; NONSTRESS-NEXT: [[STADDR:%.*]] = shl i64 [[IDX64]], 12850; NONSTRESS-NEXT: ret i64 [[STADDR]]851;852; STRESS-LABEL: define i64 @doNotPromoteFreeSExtFromShift(853; STRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]]) {854; STRESS-NEXT: [[ENTRY:.*:]]855; STRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1856; STRESS-NEXT: [[PROMOTED2:%.*]] = zext i8 [[T]] to i64857; STRESS-NEXT: [[PROMOTED1:%.*]] = sext i32 [[B]] to i64858; STRESS-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED2]], [[PROMOTED1]]859; STRESS-NEXT: [[STADDR:%.*]] = shl i64 [[ADD]], 12860; STRESS-NEXT: ret i64 [[STADDR]]861;862; DISABLE-LABEL: define i64 @doNotPromoteFreeSExtFromShift(863; DISABLE-SAME: ptr [[P:%.*]], i32 [[B:%.*]]) {864; DISABLE-NEXT: [[ENTRY:.*:]]865; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1866; DISABLE-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32867; DISABLE-NEXT: [[ADD:%.*]] = add nsw i32 [[ZEXTT]], [[B]]868; DISABLE-NEXT: [[IDX64:%.*]] = sext i32 [[ADD]] to i64869; DISABLE-NEXT: [[STADDR:%.*]] = shl i64 [[IDX64]], 12870; DISABLE-NEXT: ret i64 [[STADDR]]871;872entry:873 %t = load i8, ptr %p874 %zextt = zext i8 %t to i32875 %add = add nsw i32 %zextt, %b876 %idx64 = sext i32 %add to i64877 %staddr = shl i64 %idx64, 12878 ret i64 %staddr879}880 881; Same comment as doNotPromoteFreeZExtFromAddrMode.882;883; This transformation should really happen only for stress mode.884define i64 @doNotPromoteFreeZExtFromShift(ptr %p, i32 %b) {885; NONSTRESS-LABEL: define i64 @doNotPromoteFreeZExtFromShift(886; NONSTRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]]) {887; NONSTRESS-NEXT: [[ENTRY:.*:]]888; NONSTRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1889; NONSTRESS-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32890; NONSTRESS-NEXT: [[ADD:%.*]] = add nuw i32 [[ZEXTT]], [[B]]891; NONSTRESS-NEXT: [[IDX64:%.*]] = zext i32 [[ADD]] to i64892; NONSTRESS-NEXT: [[STADDR:%.*]] = shl i64 [[IDX64]], 12893; NONSTRESS-NEXT: ret i64 [[STADDR]]894;895; STRESS-LABEL: define i64 @doNotPromoteFreeZExtFromShift(896; STRESS-SAME: ptr [[P:%.*]], i32 [[B:%.*]]) {897; STRESS-NEXT: [[ENTRY:.*:]]898; STRESS-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1899; STRESS-NEXT: [[PROMOTED2:%.*]] = zext i8 [[T]] to i64900; STRESS-NEXT: [[PROMOTED1:%.*]] = zext i32 [[B]] to i64901; STRESS-NEXT: [[ADD:%.*]] = add nuw i64 [[PROMOTED2]], [[PROMOTED1]]902; STRESS-NEXT: [[STADDR:%.*]] = shl i64 [[ADD]], 12903; STRESS-NEXT: ret i64 [[STADDR]]904;905; DISABLE-LABEL: define i64 @doNotPromoteFreeZExtFromShift(906; DISABLE-SAME: ptr [[P:%.*]], i32 [[B:%.*]]) {907; DISABLE-NEXT: [[ENTRY:.*:]]908; DISABLE-NEXT: [[T:%.*]] = load i8, ptr [[P]], align 1909; DISABLE-NEXT: [[ZEXTT:%.*]] = zext i8 [[T]] to i32910; DISABLE-NEXT: [[ADD:%.*]] = add nuw i32 [[ZEXTT]], [[B]]911; DISABLE-NEXT: [[IDX64:%.*]] = zext i32 [[ADD]] to i64912; DISABLE-NEXT: [[STADDR:%.*]] = shl i64 [[IDX64]], 12913; DISABLE-NEXT: ret i64 [[STADDR]]914;915entry:916 %t = load i8, ptr %p917 %zextt = zext i8 %t to i32918 %add = add nuw i32 %zextt, %b919 %idx64 = zext i32 %add to i64920 %staddr = shl i64 %idx64, 12921 ret i64 %staddr922}923 924; The input has one free zext and one non-free sext.925; When we promote all the way through to the load, we end up with926; a free zext, a free sext (%ld1), and a non-free sext (of %cst).927; However, we when generate load pair and the free sext(%ld1) becomes928; non-free. So technically, we trade a non-free sext to two non-free929; sext.930; This would need to be fixed at some point.931;932; This transformation should really happen only for stress mode.933define i64 @doNotPromoteBecauseOfPairedLoad(ptr %p, i32 %cst) {934; OPT-LABEL: define i64 @doNotPromoteBecauseOfPairedLoad(935; OPT-SAME: ptr [[P:%.*]], i32 [[CST:%.*]]) {936; OPT-NEXT: [[LD0:%.*]] = load i32, ptr [[P]], align 4937; OPT-NEXT: [[IDXLD1:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 1938; OPT-NEXT: [[LD1:%.*]] = load i32, ptr [[IDXLD1]], align 4939; OPT-NEXT: [[PROMOTED:%.*]] = sext i32 [[LD1]] to i64940; OPT-NEXT: [[PROMOTED1:%.*]] = sext i32 [[CST]] to i64941; OPT-NEXT: [[RES:%.*]] = add nsw i64 [[PROMOTED]], [[PROMOTED1]]942; OPT-NEXT: [[ZEXTLD0:%.*]] = zext i32 [[LD0]] to i64943; OPT-NEXT: [[FINAL:%.*]] = add i64 [[RES]], [[ZEXTLD0]]944; OPT-NEXT: ret i64 [[FINAL]]945;946; DISABLE-LABEL: define i64 @doNotPromoteBecauseOfPairedLoad(947; DISABLE-SAME: ptr [[P:%.*]], i32 [[CST:%.*]]) {948; DISABLE-NEXT: [[LD0:%.*]] = load i32, ptr [[P]], align 4949; DISABLE-NEXT: [[IDXLD1:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 1950; DISABLE-NEXT: [[LD1:%.*]] = load i32, ptr [[IDXLD1]], align 4951; DISABLE-NEXT: [[RES:%.*]] = add nsw i32 [[LD1]], [[CST]]952; DISABLE-NEXT: [[SEXTRES:%.*]] = sext i32 [[RES]] to i64953; DISABLE-NEXT: [[ZEXTLD0:%.*]] = zext i32 [[LD0]] to i64954; DISABLE-NEXT: [[FINAL:%.*]] = add i64 [[SEXTRES]], [[ZEXTLD0]]955; DISABLE-NEXT: ret i64 [[FINAL]]956;957 %ld0 = load i32, ptr %p958 %idxLd1 = getelementptr inbounds i32, ptr %p, i64 1959 %ld1 = load i32, ptr %idxLd1960 %res = add nsw i32 %ld1, %cst961 %sextres = sext i32 %res to i64962 %zextLd0 = zext i32 %ld0 to i64963 %final = add i64 %sextres, %zextLd0964 ret i64 %final965}966 967define i64 @promoteZextShl(i1 %c, ptr %P) {968; OPT-LABEL: define i64 @promoteZextShl(969; OPT-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {970; OPT-NEXT: [[ENTRY:.*:]]971; OPT-NEXT: [[LD:%.*]] = load i16, ptr [[P]], align 2972; OPT-NEXT: [[PROMOTED1:%.*]] = zext i16 [[LD]] to i64973; OPT-NEXT: br i1 [[C]], label %[[END:.*]], label %[[IF_THEN:.*]]974; OPT: [[IF_THEN]]:975; OPT-NEXT: [[SHL2:%.*]] = shl nsw i64 [[PROMOTED1]], 1976; OPT-NEXT: ret i64 [[SHL2]]977; OPT: [[END]]:978; OPT-NEXT: ret i64 0979;980; DISABLE-LABEL: define i64 @promoteZextShl(981; DISABLE-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {982; DISABLE-NEXT: [[ENTRY:.*:]]983; DISABLE-NEXT: [[LD:%.*]] = load i16, ptr [[P]], align 2984; DISABLE-NEXT: [[Z:%.*]] = zext i16 [[LD]] to i32985; DISABLE-NEXT: br i1 [[C]], label %[[END:.*]], label %[[IF_THEN:.*]]986; DISABLE: [[IF_THEN]]:987; DISABLE-NEXT: [[SHL2:%.*]] = shl nsw i32 [[Z]], 1988; DISABLE-NEXT: [[R:%.*]] = sext i32 [[SHL2]] to i64989; DISABLE-NEXT: ret i64 [[R]]990; DISABLE: [[END]]:991; DISABLE-NEXT: ret i64 0992;993entry:994 %ld = load i16, ptr %P995 br i1 %c, label %end, label %if.then996if.then:997 %z = zext i16 %ld to i32998 %shl2 = shl nsw i32 %z, 1999 %r = sext i32 %shl2 to i641000 ret i64 %r1001end:1002 ret i64 01003}1004