brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.0 KiB · 7846f82 Raw
609 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 32; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s3; RUN: llc < %s -mtriple=x86_64-win64 | FileCheck %s4; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' < %s -mtriple=x86_64-apple-macosx -S | FileCheck %s --check-prefix=OPTALL --check-prefix=OPT --check-prefix=NONSTRESS5; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' < %s -mtriple=x86_64-apple-macosx -S -stress-cgp-ext-ld-promotion | FileCheck %s --check-prefix=OPTALL --check-prefix=OPT --check-prefix=STRESS6; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' < %s -mtriple=x86_64-apple-macosx -S -disable-cgp-ext-ld-promotion | FileCheck %s --check-prefix=OPTALL --check-prefix=DISABLE7 8; rdar://73048389; CodeGenPrepare should move the zext into the block with the load10; so that SelectionDAG can select it with the load.11;12; CHECK-LABEL: foo:13; CHECK: movsbl ({{%rdi|%rcx}}), %eax14define void @foo(ptr %p, ptr %q) {15; OPTALL-LABEL: define void @foo(16; OPTALL-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) {17; OPTALL-NEXT:  entry:18; OPTALL-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 119; OPTALL-NEXT:    [[S:%.*]] = zext i8 [[T]] to i3220; OPTALL-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 2021; OPTALL-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]22; OPTALL:       true:23; OPTALL-NEXT:    store i32 [[S]], ptr [[Q]], align 424; OPTALL-NEXT:    ret void25; OPTALL:       false:26; OPTALL-NEXT:    ret void27;28entry:29  %t = load i8, ptr %p30  %a = icmp slt i8 %t, 2031  br i1 %a, label %true, label %false32true:33  %s = zext i8 %t to i3234  store i32 %s, ptr %q35  ret void36false:37  ret void38}39 40; Check that we manage to form a zextload is an operation with only one41; argument to explicitly extend is in the way.42; Make sure the operation is not promoted when the promotion pass is disabled.43define void @promoteOneArg(ptr %p, ptr %q) {44; OPT-LABEL: define void @promoteOneArg(45; OPT-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) {46; OPT-NEXT:  entry:47; OPT-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 148; OPT-NEXT:    [[S:%.*]] = zext i8 [[T]] to i3249; OPT-NEXT:    [[ADD:%.*]] = add nuw i32 [[S]], 250; OPT-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 2051; OPT-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]52; OPT:       true:53; OPT-NEXT:    store i32 [[ADD]], ptr [[Q]], align 454; OPT-NEXT:    ret void55; OPT:       false:56; OPT-NEXT:    ret void57;58; DISABLE-LABEL: define void @promoteOneArg(59; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) {60; DISABLE-NEXT:  entry:61; DISABLE-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 162; DISABLE-NEXT:    [[ADD:%.*]] = add nuw i8 [[T]], 263; DISABLE-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 2064; DISABLE-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]65; DISABLE:       true:66; DISABLE-NEXT:    [[S:%.*]] = zext i8 [[ADD]] to i3267; DISABLE-NEXT:    store i32 [[S]], ptr [[Q]], align 468; DISABLE-NEXT:    ret void69; DISABLE:       false:70; DISABLE-NEXT:    ret void71;72entry:73  %t = load i8, ptr %p74  %add = add nuw i8 %t, 275  %a = icmp slt i8 %t, 2076  br i1 %a, label %true, label %false77true:78  %s = zext i8 %add to i3279  store i32 %s, ptr %q80  ret void81false:82  ret void83}84 85; Check that we manage to form a sextload is an operation with only one86; argument to explicitly extend is in the way.87; Version with sext.88define void @promoteOneArgSExt(ptr %p, ptr %q) {89; OPT-LABEL: define void @promoteOneArgSExt(90; OPT-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) {91; OPT-NEXT:  entry:92; OPT-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 193; OPT-NEXT:    [[S:%.*]] = sext i8 [[T]] to i3294; OPT-NEXT:    [[ADD:%.*]] = add nsw i32 [[S]], 295; OPT-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 2096; OPT-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]97; OPT:       true:98; OPT-NEXT:    store i32 [[ADD]], ptr [[Q]], align 499; OPT-NEXT:    ret void100; OPT:       false:101; OPT-NEXT:    ret void102;103; DISABLE-LABEL: define void @promoteOneArgSExt(104; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) {105; DISABLE-NEXT:  entry:106; DISABLE-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1107; DISABLE-NEXT:    [[ADD:%.*]] = add nsw i8 [[T]], 2108; DISABLE-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20109; DISABLE-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]110; DISABLE:       true:111; DISABLE-NEXT:    [[S:%.*]] = sext i8 [[ADD]] to i32112; DISABLE-NEXT:    store i32 [[S]], ptr [[Q]], align 4113; DISABLE-NEXT:    ret void114; DISABLE:       false:115; DISABLE-NEXT:    ret void116;117entry:118  %t = load i8, ptr %p119  %add = add nsw i8 %t, 2120  %a = icmp slt i8 %t, 20121  br i1 %a, label %true, label %false122true:123  %s = sext i8 %add to i32124  store i32 %s, ptr %q125  ret void126false:127  ret void128}129 130; Check that we manage to form a zextload is an operation with two131; arguments to explicitly extend is in the way.132; Extending %add will create two extensions:133; 1. One for %b.134; 2. One for %t.135; #1 will not be removed as we do not know anything about %b.136; #2 may not be merged with the load because %t is used in a comparison.137; Since two extensions may be emitted in the end instead of one before the138; transformation, the regular heuristic does not apply the optimization.139define void @promoteTwoArgZext(ptr %p, ptr %q, i8 %b) {140; NONSTRESS-LABEL: define void @promoteTwoArgZext(141; NONSTRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {142; NONSTRESS-NEXT:  entry:143; NONSTRESS-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1144; NONSTRESS-NEXT:    [[ADD:%.*]] = add nuw i8 [[T]], [[B]]145; NONSTRESS-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20146; NONSTRESS-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]147; NONSTRESS:       true:148; NONSTRESS-NEXT:    [[S:%.*]] = zext i8 [[ADD]] to i32149; NONSTRESS-NEXT:    store i32 [[S]], ptr [[Q]], align 4150; NONSTRESS-NEXT:    ret void151; NONSTRESS:       false:152; NONSTRESS-NEXT:    ret void153;154; STRESS-LABEL: define void @promoteTwoArgZext(155; STRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {156; STRESS-NEXT:  entry:157; STRESS-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1158; STRESS-NEXT:    [[S:%.*]] = zext i8 [[T]] to i32159; STRESS-NEXT:    [[PROMOTED:%.*]] = zext i8 [[B]] to i32160; STRESS-NEXT:    [[ADD:%.*]] = add nuw i32 [[S]], [[PROMOTED]]161; STRESS-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20162; STRESS-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]163; STRESS:       true:164; STRESS-NEXT:    store i32 [[ADD]], ptr [[Q]], align 4165; STRESS-NEXT:    ret void166; STRESS:       false:167; STRESS-NEXT:    ret void168;169; DISABLE-LABEL: define void @promoteTwoArgZext(170; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {171; DISABLE-NEXT:  entry:172; DISABLE-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1173; DISABLE-NEXT:    [[ADD:%.*]] = add nuw i8 [[T]], [[B]]174; DISABLE-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20175; DISABLE-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]176; DISABLE:       true:177; DISABLE-NEXT:    [[S:%.*]] = zext i8 [[ADD]] to i32178; DISABLE-NEXT:    store i32 [[S]], ptr [[Q]], align 4179; DISABLE-NEXT:    ret void180; DISABLE:       false:181; DISABLE-NEXT:    ret void182;183entry:184  %t = load i8, ptr %p185  %add = add nuw i8 %t, %b186  %a = icmp slt i8 %t, 20187  br i1 %a, label %true, label %false188true:189  %s = zext i8 %add to i32190  store i32 %s, ptr %q191  ret void192false:193  ret void194}195 196; Check that we manage to form a sextload is an operation with two197; arguments to explicitly extend is in the way.198; Version with sext.199define void @promoteTwoArgSExt(ptr %p, ptr %q, i8 %b) {200; NONSTRESS-LABEL: define void @promoteTwoArgSExt(201; NONSTRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {202; NONSTRESS-NEXT:  entry:203; NONSTRESS-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1204; NONSTRESS-NEXT:    [[ADD:%.*]] = add nsw i8 [[T]], [[B]]205; NONSTRESS-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20206; NONSTRESS-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]207; NONSTRESS:       true:208; NONSTRESS-NEXT:    [[S:%.*]] = sext i8 [[ADD]] to i32209; NONSTRESS-NEXT:    store i32 [[S]], ptr [[Q]], align 4210; NONSTRESS-NEXT:    ret void211; NONSTRESS:       false:212; NONSTRESS-NEXT:    ret void213;214; STRESS-LABEL: define void @promoteTwoArgSExt(215; STRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {216; STRESS-NEXT:  entry:217; STRESS-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1218; STRESS-NEXT:    [[S:%.*]] = sext i8 [[T]] to i32219; STRESS-NEXT:    [[PROMOTED:%.*]] = sext i8 [[B]] to i32220; STRESS-NEXT:    [[ADD:%.*]] = add nsw i32 [[S]], [[PROMOTED]]221; STRESS-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20222; STRESS-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]223; STRESS:       true:224; STRESS-NEXT:    store i32 [[ADD]], ptr [[Q]], align 4225; STRESS-NEXT:    ret void226; STRESS:       false:227; STRESS-NEXT:    ret void228;229; DISABLE-LABEL: define void @promoteTwoArgSExt(230; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]]) {231; DISABLE-NEXT:  entry:232; DISABLE-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1233; DISABLE-NEXT:    [[ADD:%.*]] = add nsw i8 [[T]], [[B]]234; DISABLE-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20235; DISABLE-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]236; DISABLE:       true:237; DISABLE-NEXT:    [[S:%.*]] = sext i8 [[ADD]] to i32238; DISABLE-NEXT:    store i32 [[S]], ptr [[Q]], align 4239; DISABLE-NEXT:    ret void240; DISABLE:       false:241; DISABLE-NEXT:    ret void242;243entry:244  %t = load i8, ptr %p245  %add = add nsw i8 %t, %b246  %a = icmp slt i8 %t, 20247  br i1 %a, label %true, label %false248true:249  %s = sext i8 %add to i32250  store i32 %s, ptr %q251  ret void252false:253  ret void254}255 256; Check that we do not a zextload if we need to introduce more than257; one additional extension.258define void @promoteThreeArgZext(ptr %p, ptr %q, i8 %b, i8 %c) {259; NONSTRESS-LABEL: define void @promoteThreeArgZext(260; NONSTRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {261; NONSTRESS-NEXT:  entry:262; NONSTRESS-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1263; NONSTRESS-NEXT:    [[TMP:%.*]] = add nuw i8 [[T]], [[B]]264; NONSTRESS-NEXT:    [[ADD:%.*]] = add nuw i8 [[TMP]], [[C]]265; NONSTRESS-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20266; NONSTRESS-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]267; NONSTRESS:       true:268; NONSTRESS-NEXT:    [[S:%.*]] = zext i8 [[ADD]] to i32269; NONSTRESS-NEXT:    store i32 [[S]], ptr [[Q]], align 4270; NONSTRESS-NEXT:    ret void271; NONSTRESS:       false:272; NONSTRESS-NEXT:    ret void273;274; STRESS-LABEL: define void @promoteThreeArgZext(275; STRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {276; STRESS-NEXT:  entry:277; STRESS-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1278; STRESS-NEXT:    [[S:%.*]] = zext i8 [[T]] to i32279; STRESS-NEXT:    [[PROMOTED1:%.*]] = zext i8 [[B]] to i32280; STRESS-NEXT:    [[TMP:%.*]] = add nuw i32 [[S]], [[PROMOTED1]]281; STRESS-NEXT:    [[PROMOTED:%.*]] = zext i8 [[C]] to i32282; STRESS-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP]], [[PROMOTED]]283; STRESS-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20284; STRESS-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]285; STRESS:       true:286; STRESS-NEXT:    store i32 [[ADD]], ptr [[Q]], align 4287; STRESS-NEXT:    ret void288; STRESS:       false:289; STRESS-NEXT:    ret void290;291; DISABLE-LABEL: define void @promoteThreeArgZext(292; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {293; DISABLE-NEXT:  entry:294; DISABLE-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1295; DISABLE-NEXT:    [[TMP:%.*]] = add nuw i8 [[T]], [[B]]296; DISABLE-NEXT:    [[ADD:%.*]] = add nuw i8 [[TMP]], [[C]]297; DISABLE-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20298; DISABLE-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]299; DISABLE:       true:300; DISABLE-NEXT:    [[S:%.*]] = zext i8 [[ADD]] to i32301; DISABLE-NEXT:    store i32 [[S]], ptr [[Q]], align 4302; DISABLE-NEXT:    ret void303; DISABLE:       false:304; DISABLE-NEXT:    ret void305;306entry:307  %t = load i8, ptr %p308  %tmp = add nuw i8 %t, %b309  %add = add nuw i8 %tmp, %c310  %a = icmp slt i8 %t, 20311  br i1 %a, label %true, label %false312true:313  %s = zext i8 %add to i32314  store i32 %s, ptr %q315  ret void316false:317  ret void318}319 320; Check that we manage to form a zextload after promoting and merging321; two extensions.322define void @promoteMergeExtArgZExt(ptr %p, ptr %q, i16 %b) {323; NONSTRESS-LABEL: define void @promoteMergeExtArgZExt(324; NONSTRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {325; NONSTRESS-NEXT:  entry:326; NONSTRESS-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1327; NONSTRESS-NEXT:    [[EXT:%.*]] = zext i8 [[T]] to i16328; NONSTRESS-NEXT:    [[ADD:%.*]] = add nuw i16 [[EXT]], [[B]]329; NONSTRESS-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20330; NONSTRESS-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]331; NONSTRESS:       true:332; NONSTRESS-NEXT:    [[S:%.*]] = zext i16 [[ADD]] to i32333; NONSTRESS-NEXT:    store i32 [[S]], ptr [[Q]], align 4334; NONSTRESS-NEXT:    ret void335; NONSTRESS:       false:336; NONSTRESS-NEXT:    ret void337;338; STRESS-LABEL: define void @promoteMergeExtArgZExt(339; STRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {340; STRESS-NEXT:  entry:341; STRESS-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1342; STRESS-NEXT:    [[PROMOTED1:%.*]] = zext i8 [[T]] to i32343; STRESS-NEXT:    [[PROMOTED:%.*]] = zext i16 [[B]] to i32344; STRESS-NEXT:    [[ADD:%.*]] = add nuw i32 [[PROMOTED1]], [[PROMOTED]]345; STRESS-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20346; STRESS-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]347; STRESS:       true:348; STRESS-NEXT:    store i32 [[ADD]], ptr [[Q]], align 4349; STRESS-NEXT:    ret void350; STRESS:       false:351; STRESS-NEXT:    ret void352;353; DISABLE-LABEL: define void @promoteMergeExtArgZExt(354; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {355; DISABLE-NEXT:  entry:356; DISABLE-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1357; DISABLE-NEXT:    [[EXT:%.*]] = zext i8 [[T]] to i16358; DISABLE-NEXT:    [[ADD:%.*]] = add nuw i16 [[EXT]], [[B]]359; DISABLE-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20360; DISABLE-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]361; DISABLE:       true:362; DISABLE-NEXT:    [[S:%.*]] = zext i16 [[ADD]] to i32363; DISABLE-NEXT:    store i32 [[S]], ptr [[Q]], align 4364; DISABLE-NEXT:    ret void365; DISABLE:       false:366; DISABLE-NEXT:    ret void367;368entry:369  %t = load i8, ptr %p370  %ext = zext i8 %t to i16371  %add = add nuw i16 %ext, %b372  %a = icmp slt i8 %t, 20373  br i1 %a, label %true, label %false374true:375  %s = zext i16 %add to i32376  store i32 %s, ptr %q377  ret void378false:379  ret void380}381 382; Check that we manage to form a sextload after promoting and merging383; two extensions.384; Version with sext.385define void @promoteMergeExtArgSExt(ptr %p, ptr %q, i16 %b) {386; NONSTRESS-LABEL: define void @promoteMergeExtArgSExt(387; NONSTRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {388; NONSTRESS-NEXT:  entry:389; NONSTRESS-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1390; NONSTRESS-NEXT:    [[EXT:%.*]] = zext i8 [[T]] to i16391; NONSTRESS-NEXT:    [[ADD:%.*]] = add nsw i16 [[EXT]], [[B]]392; NONSTRESS-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20393; NONSTRESS-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]394; NONSTRESS:       true:395; NONSTRESS-NEXT:    [[S:%.*]] = sext i16 [[ADD]] to i32396; NONSTRESS-NEXT:    store i32 [[S]], ptr [[Q]], align 4397; NONSTRESS-NEXT:    ret void398; NONSTRESS:       false:399; NONSTRESS-NEXT:    ret void400;401; STRESS-LABEL: define void @promoteMergeExtArgSExt(402; STRESS-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {403; STRESS-NEXT:  entry:404; STRESS-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1405; STRESS-NEXT:    [[PROMOTED1:%.*]] = zext i8 [[T]] to i32406; STRESS-NEXT:    [[PROMOTED:%.*]] = sext i16 [[B]] to i32407; STRESS-NEXT:    [[ADD:%.*]] = add nsw i32 [[PROMOTED1]], [[PROMOTED]]408; STRESS-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20409; STRESS-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]410; STRESS:       true:411; STRESS-NEXT:    store i32 [[ADD]], ptr [[Q]], align 4412; STRESS-NEXT:    ret void413; STRESS:       false:414; STRESS-NEXT:    ret void415;416; DISABLE-LABEL: define void @promoteMergeExtArgSExt(417; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i16 [[B:%.*]]) {418; DISABLE-NEXT:  entry:419; DISABLE-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1420; DISABLE-NEXT:    [[EXT:%.*]] = zext i8 [[T]] to i16421; DISABLE-NEXT:    [[ADD:%.*]] = add nsw i16 [[EXT]], [[B]]422; DISABLE-NEXT:    [[A:%.*]] = icmp slt i8 [[T]], 20423; DISABLE-NEXT:    br i1 [[A]], label [[TRUE:%.*]], label [[FALSE:%.*]]424; DISABLE:       true:425; DISABLE-NEXT:    [[S:%.*]] = sext i16 [[ADD]] to i32426; DISABLE-NEXT:    store i32 [[S]], ptr [[Q]], align 4427; DISABLE-NEXT:    ret void428; DISABLE:       false:429; DISABLE-NEXT:    ret void430;431entry:432  %t = load i8, ptr %p433  %ext = zext i8 %t to i16434  %add = add nsw i16 %ext, %b435  %a = icmp slt i8 %t, 20436  br i1 %a, label %true, label %false437true:438  %s = sext i16 %add to i32439  store i32 %s, ptr %q440  ret void441false:442  ret void443}444 445; Check that we manage to catch all the extload opportunities that are exposed446; by the different iterations of codegen prepare.447; Moreover, check that we do not promote more than we need to.448; Here is what is happening in this test (not necessarly in this order):449; 1. We try to promote the operand of %sextadd.450;    a. This creates one sext of %ld2 and one of %zextld451;    b. The sext of %ld2 can be combine with %ld2, so we remove one sext but452;       introduced one. This is fine with the current heuristic: neutral.453;    => We have one zext of %zextld left and we created one sext of %ld2.454; 2. We try to promote the operand of %sextaddza.455;    a. This creates one sext of %zexta and one of %zextld456;    b. The sext of %zexta can be combined with the zext of %a.457;    c. The sext of %zextld leads to %ld and can be combined with it. This is458;       done by promoting %zextld. This is fine with the current heuristic:459;       neutral.460;    => We have created a new zext of %ld and we created one sext of %zexta.461; 3. We try to promote the operand of %sextaddb.462;    a. This creates one sext of %b and one of %zextld463;    b. The sext of %b is a dead-end, nothing to be done.464;    c. Same thing as 2.c. happens.465;    => We have created a new zext of %ld and we created one sext of %b.466; 4. We try to promote the operand of the zext of %zextld introduced in #1.467;    a. Same thing as 2.c. happens.468;    b. %zextld does not have any other uses. It is dead coded.469;    => We have created a new zext of %ld and we removed a zext of %zextld and470;       a zext of %ld.471; Currently we do not try to reuse existing extensions, so in the end we have472; 3 identical zext of %ld. The extensions will be CSE'ed by SDag.473define void @severalPromotions(ptr %addr1, ptr %addr2, i8 %a, i32 %b) {474; OPT-LABEL: define void @severalPromotions(475; OPT-SAME: ptr [[ADDR1:%.*]], ptr [[ADDR2:%.*]], i8 [[A:%.*]], i32 [[B:%.*]]) {476; OPT-NEXT:    [[LD:%.*]] = load i8, ptr [[ADDR1]], align 1477; OPT-NEXT:    [[PROMOTED4:%.*]] = zext i8 [[LD]] to i64478; OPT-NEXT:    [[PROMOTED3:%.*]] = zext i8 [[LD]] to i64479; OPT-NEXT:    [[LD2:%.*]] = load i32, ptr [[ADDR2]], align 4480; OPT-NEXT:    [[SEXTADD:%.*]] = sext i32 [[LD2]] to i64481; OPT-NEXT:    [[PROMOTED1:%.*]] = zext i8 [[LD]] to i64482; OPT-NEXT:    [[ADD:%.*]] = add nsw i64 [[SEXTADD]], [[PROMOTED1]]483; OPT-NEXT:    [[PROMOTED2:%.*]] = zext i8 [[A]] to i64484; OPT-NEXT:    [[ADDZA:%.*]] = add nsw i64 [[PROMOTED2]], [[PROMOTED3]]485; OPT-NEXT:    [[SEXTADDB:%.*]] = sext i32 [[B]] to i64486; OPT-NEXT:    [[ADDB:%.*]] = add nsw i64 [[SEXTADDB]], [[PROMOTED4]]487; OPT-NEXT:    call void @dummy(i64 [[ADD]], i64 [[ADDZA]], i64 [[ADDB]])488; OPT-NEXT:    ret void489;490; DISABLE-LABEL: define void @severalPromotions(491; DISABLE-SAME: ptr [[ADDR1:%.*]], ptr [[ADDR2:%.*]], i8 [[A:%.*]], i32 [[B:%.*]]) {492; DISABLE-NEXT:    [[LD:%.*]] = load i8, ptr [[ADDR1]], align 1493; DISABLE-NEXT:    [[ZEXTLD:%.*]] = zext i8 [[LD]] to i32494; DISABLE-NEXT:    [[LD2:%.*]] = load i32, ptr [[ADDR2]], align 4495; DISABLE-NEXT:    [[ADD:%.*]] = add nsw i32 [[LD2]], [[ZEXTLD]]496; DISABLE-NEXT:    [[SEXTADD:%.*]] = sext i32 [[ADD]] to i64497; DISABLE-NEXT:    [[ZEXTA:%.*]] = zext i8 [[A]] to i32498; DISABLE-NEXT:    [[ADDZA:%.*]] = add nsw i32 [[ZEXTA]], [[ZEXTLD]]499; DISABLE-NEXT:    [[SEXTADDZA:%.*]] = sext i32 [[ADDZA]] to i64500; DISABLE-NEXT:    [[ADDB:%.*]] = add nsw i32 [[B]], [[ZEXTLD]]501; DISABLE-NEXT:    [[SEXTADDB:%.*]] = sext i32 [[ADDB]] to i64502; DISABLE-NEXT:    call void @dummy(i64 [[SEXTADD]], i64 [[SEXTADDZA]], i64 [[SEXTADDB]])503; DISABLE-NEXT:    ret void504;505  %ld = load i8, ptr %addr1506  %zextld = zext i8 %ld to i32507  %ld2 = load i32, ptr %addr2508  %add = add nsw i32 %ld2, %zextld509  %sextadd = sext i32 %add to i64510  %zexta = zext i8 %a to i32511  %addza = add nsw i32 %zexta, %zextld512  %sextaddza = sext i32 %addza to i64513  %addb = add nsw i32 %b, %zextld514  %sextaddb = sext i32 %addb to i64515  call void @dummy(i64 %sextadd, i64 %sextaddza, i64 %sextaddb)516  ret void517}518 519declare void @dummy(i64, i64, i64)520 521; Make sure we do not try to promote vector types since the type promotion522; helper does not support them for now.523define void @vectorPromotion() {524; OPTALL-LABEL: define void @vectorPromotion() {525; OPTALL-NEXT:  entry:526; OPTALL-NEXT:    [[A:%.*]] = shl nuw nsw <2 x i32> zeroinitializer, splat (i32 8)527; OPTALL-NEXT:    [[B:%.*]] = zext <2 x i32> [[A]] to <2 x i64>528; OPTALL-NEXT:    ret void529;530entry:531  %a = shl nuw nsw <2 x i32> zeroinitializer, <i32 8, i32 8>532  %b = zext <2 x i32> %a to <2 x i64>533  ret void534}535 536@a = common global i32 0, align 4537@c = common global [2 x i32] zeroinitializer, align 4538 539; PR21978.540; Make sure we support promotion of operands that produces a Value as opposed541; to an instruction.542; This used to cause a crash.543define i32 @promotionOfArgEndsUpInValue(ptr %addr) {544; OPT-LABEL: define i32 @promotionOfArgEndsUpInValue(545; OPT-SAME: ptr [[ADDR:%.*]]) {546; OPT-NEXT:  entry:547; OPT-NEXT:    [[VAL:%.*]] = load i16, ptr [[ADDR]], align 2548; OPT-NEXT:    [[CONV3:%.*]] = sext i16 [[VAL]] to i32549; OPT-NEXT:    [[CMP:%.*]] = icmp ne ptr getelementptr inbounds ([2 x i32], ptr @c, i64 0, i64 1), @a550; OPT-NEXT:    [[PROMOTED1:%.*]] = zext i1 [[CMP]] to i32551; OPT-NEXT:    [[ADD:%.*]] = add nuw nsw i32 [[CONV3]], [[PROMOTED1]]552; OPT-NEXT:    ret i32 [[ADD]]553;554; DISABLE-LABEL: define i32 @promotionOfArgEndsUpInValue(555; DISABLE-SAME: ptr [[ADDR:%.*]]) {556; DISABLE-NEXT:  entry:557; DISABLE-NEXT:    [[VAL:%.*]] = load i16, ptr [[ADDR]], align 2558; DISABLE-NEXT:    [[CMP:%.*]] = icmp ne ptr getelementptr inbounds ([2 x i32], ptr @c, i64 0, i64 1), @a559; DISABLE-NEXT:    [[EXT:%.*]] = zext i1 [[CMP]] to i16560; DISABLE-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[VAL]], [[EXT]]561; DISABLE-NEXT:    [[CONV3:%.*]] = sext i16 [[ADD]] to i32562; DISABLE-NEXT:    ret i32 [[CONV3]]563;564entry:565  %val = load i16, ptr %addr566  %cmp = icmp ne ptr getelementptr inbounds ([2 x i32], ptr @c, i64 0, i64 1), @a567  %ext = zext i1 %cmp to i16568  %add = add nuw nsw i16 %val, %ext569  %conv3 = sext i16 %add to i32570  ret i32 %conv3571}572 573; Check that we see that one zext can be derived from the other for free.574define void @promoteTwoArgZextWithSourceExtendedTwice(ptr %p, ptr %q, i32 %b, ptr %addr) {575; OPT-LABEL: define void @promoteTwoArgZextWithSourceExtendedTwice(576; OPT-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]]) {577; OPT-NEXT:  entry:578; OPT-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1579; OPT-NEXT:    [[PROMOTED:%.*]] = zext i8 [[T]] to i64580; OPT-NEXT:    [[ZEXTT:%.*]] = zext i8 [[T]] to i32581; OPT-NEXT:    [[ADD:%.*]] = add nuw i32 [[ZEXTT]], [[B]]582; OPT-NEXT:    [[ADD2:%.*]] = add nuw i64 [[PROMOTED]], 12583; OPT-NEXT:    store i32 [[ADD]], ptr [[ADDR]], align 4584; OPT-NEXT:    store i64 [[ADD2]], ptr [[Q]], align 8585; OPT-NEXT:    ret void586;587; DISABLE-LABEL: define void @promoteTwoArgZextWithSourceExtendedTwice(588; DISABLE-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i32 [[B:%.*]], ptr [[ADDR:%.*]]) {589; DISABLE-NEXT:  entry:590; DISABLE-NEXT:    [[T:%.*]] = load i8, ptr [[P]], align 1591; DISABLE-NEXT:    [[ZEXTT:%.*]] = zext i8 [[T]] to i32592; DISABLE-NEXT:    [[ADD:%.*]] = add nuw i32 [[ZEXTT]], [[B]]593; DISABLE-NEXT:    [[ADD2:%.*]] = add nuw i32 [[ZEXTT]], 12594; DISABLE-NEXT:    store i32 [[ADD]], ptr [[ADDR]], align 4595; DISABLE-NEXT:    [[S:%.*]] = zext i32 [[ADD2]] to i64596; DISABLE-NEXT:    store i64 [[S]], ptr [[Q]], align 8597; DISABLE-NEXT:    ret void598;599entry:600  %t = load i8, ptr %p601  %zextt = zext i8 %t to i32602  %add = add nuw i32 %zextt, %b603  %add2 = add nuw i32 %zextt, 12604  store i32 %add, ptr%addr605  %s = zext i32 %add2 to i64606  store i64 %s, ptr %q607  ret void608}609