brintos

brintos / llvm-project-archived public Read only

0
0
Text · 42.0 KiB · 7b4a94a Raw
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