diff options
author | Florian Hahn <flo@fhahn.com> | 2024-12-17 11:52:15 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-17 11:52:15 +0000 |
commit | c1f5937eb4bf4002b8205873189f900364868fd5 (patch) | |
tree | f70aec62f658329ea904b105b0177daf5fa0c811 /llvm | |
parent | 1b8099040e9a919794eba3854486d46fa9018b94 (diff) | |
download | llvm-c1f5937eb4bf4002b8205873189f900364868fd5.zip llvm-c1f5937eb4bf4002b8205873189f900364868fd5.tar.gz llvm-c1f5937eb4bf4002b8205873189f900364868fd5.tar.bz2 |
[SelectOpt] Support BinOps with SExt operands. (#115879)
Building on top of https://github.com/llvm/llvm-project/pull/115489
extend support for binops with SExt operand.
PR: https://github.com/llvm/llvm-project/pull/115879
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/CodeGen/SelectOptimize.cpp | 15 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/selectopt-cast.ll | 120 |
2 files changed, 93 insertions, 42 deletions
diff --git a/llvm/lib/CodeGen/SelectOptimize.cpp b/llvm/lib/CodeGen/SelectOptimize.cpp index 98321a3..7b927e6 100644 --- a/llvm/lib/CodeGen/SelectOptimize.cpp +++ b/llvm/lib/CodeGen/SelectOptimize.cpp @@ -501,7 +501,8 @@ static Value *getTrueOrFalseValue( if (isa<ZExtInst>(AuxI) || isa<LShrOperator>(AuxI)) { CBO->setOperand(CondIdx, ConstantInt::get(CBO->getType(), 1)); } else { - assert(isa<AShrOperator>(AuxI) && "Unexpected opcode"); + assert((isa<AShrOperator>(AuxI) || isa<SExtInst>(AuxI)) && + "Unexpected opcode"); CBO->setOperand(CondIdx, ConstantInt::get(CBO->getType(), -1)); } @@ -761,6 +762,7 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB, // Auxiliary instruction are instructions that depends on a condition and have // zero or some constant value on True/False branch, such as: // * ZExt(1bit) + // * SExt(1bit) // * Not(1bit) // * A(L)Shr(Val), ValBitSize - 1, where there is a condition like `Val <= 0` // earlier in the BB. For conditions that check the sign of the Val compiler @@ -787,7 +789,7 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB, } Value *Cond; - if (match(I, m_OneUse(m_ZExt(m_Value(Cond)))) && + if (match(I, m_OneUse(m_ZExtOrSExt(m_Value(Cond)))) && Cond->getType()->isIntegerTy(1)) { bool Inverted = match(Cond, m_Not(m_Value(Cond))); return SelectInfo.insert({I, {Cond, true, Inverted, 0}}).first; @@ -828,16 +830,17 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB, // An BinOp(Aux(X), Y) can also be treated like a select, with condition X // and values Y|1 and Y. - // `Aux` can be either `ZExt(1bit)` or `XShr(Val), ValBitSize - 1` - // `BinOp` can be Add, Sub, Or + // `Aux` can be either `ZExt(1bit)`, `SExt(1bit)` or `XShr(Val), ValBitSize + // - 1` `BinOp` can be Add, Sub, Or Value *X; - auto MatchZExtPattern = m_c_BinOp(m_Value(), m_OneUse(m_ZExt(m_Value(X)))); + auto MatchZExtOrSExtPattern = + m_c_BinOp(m_Value(), m_OneUse(m_ZExtOrSExt(m_Value(X)))); auto MatchShiftPattern = m_c_BinOp(m_Value(), m_OneUse(m_Shr(m_Value(X), m_ConstantInt(Shift)))); // This check is unnecessary, but it prevents costly access to the // SelectInfo map. - if ((match(I, MatchZExtPattern) && X->getType()->isIntegerTy(1)) || + if ((match(I, MatchZExtOrSExtPattern) && X->getType()->isIntegerTy(1)) || (match(I, MatchShiftPattern) && X->getType()->getIntegerBitWidth() == Shift->getZExtValue() + 1)) { if (I->getOpcode() != Instruction::Add && diff --git a/llvm/test/CodeGen/AArch64/selectopt-cast.ll b/llvm/test/CodeGen/AArch64/selectopt-cast.ll index 48d3301..b862458 100644 --- a/llvm/test/CodeGen/AArch64/selectopt-cast.ll +++ b/llvm/test/CodeGen/AArch64/selectopt-cast.ll @@ -168,16 +168,22 @@ define void @test_add_sext(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.star ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ] +; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ] +; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ] ; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]] ; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8 ; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]] ; CHECK-NEXT: [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8 ; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]] ; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[CMP3]] to i64 -; CHECK-NEXT: [[J_NEXT]] = add nsw i64 [[J]], [[DEC]] +; CHECK-NEXT: [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]] +; CHECK-NEXT: br i1 [[CMP3_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END]] +; CHECK: select.true.sink: +; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[J]], -1 +; CHECK-NEXT: br label [[SELECT_END]] +; CHECK: select.end: +; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[TMP0]], [[SELECT_TRUE_SINK]] ], [ [[J]], [[LOOP]] ] ; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]] ; CHECK-NEXT: store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8 ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 @@ -215,9 +221,9 @@ define void @test_add_sext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i. ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ] +; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ] +; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ] ; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]] ; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8 ; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]] @@ -225,7 +231,13 @@ define void @test_add_sext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i. ; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]] ; CHECK-NEXT: [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true ; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64 -; CHECK-NEXT: [[J_NEXT]] = add nsw i64 [[J]], [[DEC]] +; CHECK-NEXT: [[NOT_CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]] +; CHECK-NEXT: br i1 [[NOT_CMP3_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]] +; CHECK: select.false.sink: +; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[J]], -1 +; CHECK-NEXT: br label [[SELECT_END]] +; CHECK: select.end: +; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP0]], [[SELECT_FALSE]] ] ; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]] ; CHECK-NEXT: store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8 ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 @@ -264,9 +276,9 @@ define void @test_add_sext_not_and_regular_select(ptr %dst, ptr %src, i64 %j.sta ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END1:%.*]] ] +; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END1]] ] +; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END1]] ] ; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]] ; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8 ; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]] @@ -274,8 +286,14 @@ define void @test_add_sext_not_and_regular_select(ptr %dst, ptr %src, i64 %j.sta ; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]] ; CHECK-NEXT: [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true ; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64 -; CHECK-NEXT: [[J_NEXT]] = add nsw i64 [[J]], [[DEC]] -; CHECK-NEXT: [[SINK:%.*]] = select i1 [[CMP3]], ptr [[L_I]], ptr [[L_J]] +; CHECK-NEXT: [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]] +; CHECK-NEXT: br i1 [[CMP3_FROZEN]], label [[SELECT_END1]], label [[SELECT_FALSE_SINK:%.*]] +; CHECK: select.false.sink: +; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[J]], -1 +; CHECK-NEXT: br label [[SELECT_END1]] +; CHECK: select.end: +; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP0]], [[SELECT_FALSE_SINK]] ] +; CHECK-NEXT: [[SINK:%.*]] = phi ptr [ [[L_I]], [[LOOP]] ], [ [[L_J]], [[SELECT_FALSE_SINK]] ] ; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]] ; CHECK-NEXT: store ptr [[SINK]], ptr [[GEP_DST]], align 8 ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 @@ -315,9 +333,9 @@ define void @test_add_sext_not_and_regular_select2(ptr %dst, ptr %src, i64 %j.st ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END1:%.*]] ] +; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END1]] ] +; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END1]] ] ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]] ; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX1]], align 8 ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]] @@ -327,10 +345,16 @@ define void @test_add_sext_not_and_regular_select2(ptr %dst, ptr %src, i64 %j.st ; CHECK-NEXT: [[ARRAYIDX1_I:%.*]] = getelementptr inbounds i64, ptr [[TMP1]], i64 [[P]] ; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[ARRAYIDX1_I]], align 8 ; CHECK-NEXT: [[CMP3:%.*]] = icmp slt i64 [[TMP2]], [[TMP3]] -; CHECK-NEXT: [[DOTSINK:%.*]] = select i1 [[CMP3]], ptr [[TMP0]], ptr [[TMP1]] +; CHECK-NEXT: [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]] +; CHECK-NEXT: br i1 [[CMP3_FROZEN]], label [[SELECT_END1]], label [[SELECT_FALSE:%.*]] +; CHECK: select.false.sink: +; CHECK-NEXT: [[TMP5:%.*]] = add nsw i64 [[J]], -1 +; CHECK-NEXT: br label [[SELECT_END1]] +; CHECK: select.end: +; CHECK-NEXT: [[DOTSINK:%.*]] = phi ptr [ [[TMP0]], [[LOOP]] ], [ [[TMP1]], [[SELECT_FALSE]] ] +; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP5]], [[SELECT_FALSE]] ] ; CHECK-NEXT: [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true ; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64 -; CHECK-NEXT: [[J_NEXT]] = add nsw i64 [[J]], [[DEC]] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]] ; CHECK-NEXT: store ptr [[DOTSINK]], ptr [[TMP4]], align 8 ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 @@ -529,16 +553,22 @@ define void @test_sub_sext(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.star ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ] +; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ] +; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ] ; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]] ; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8 ; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]] ; CHECK-NEXT: [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8 ; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]] ; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[CMP3]] to i64 -; CHECK-NEXT: [[J_NEXT]] = sub nsw i64 [[J]], [[DEC]] +; CHECK-NEXT: [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]] +; CHECK-NEXT: br i1 [[CMP3_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END]] +; CHECK: select.true.sink: +; CHECK-NEXT: [[TMP0:%.*]] = sub nsw i64 [[J]], -1 +; CHECK-NEXT: br label [[SELECT_END]] +; CHECK: select.end: +; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[TMP0]], [[SELECT_TRUE_SINK]] ], [ [[J]], [[LOOP]] ] ; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]] ; CHECK-NEXT: store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8 ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 @@ -576,9 +606,9 @@ define void @test_sub_sext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i. ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ] +; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ] +; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ] ; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]] ; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8 ; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]] @@ -586,7 +616,13 @@ define void @test_sub_sext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i. ; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]] ; CHECK-NEXT: [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true ; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64 -; CHECK-NEXT: [[J_NEXT]] = sub nsw i64 [[J]], [[DEC]] +; CHECK-NEXT: [[NOT_CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]] +; CHECK-NEXT: br i1 [[NOT_CMP3_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]] +; CHECK: select.false.sink: +; CHECK-NEXT: [[TMP0:%.*]] = sub nsw i64 [[J]], -1 +; CHECK-NEXT: br label [[SELECT_END]] +; CHECK: select.end: +; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP0]], [[SELECT_FALSE]] ] ; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]] ; CHECK-NEXT: store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8 ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 @@ -625,9 +661,9 @@ define void @test_sub_sext_not_and_regular_select(ptr %dst, ptr %src, i64 %j.sta ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END1:%.*]] ] +; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END1]] ] +; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END1]] ] ; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]] ; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8 ; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]] @@ -635,8 +671,14 @@ define void @test_sub_sext_not_and_regular_select(ptr %dst, ptr %src, i64 %j.sta ; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]] ; CHECK-NEXT: [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true ; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64 -; CHECK-NEXT: [[J_NEXT]] = sub nsw i64 [[J]], [[DEC]] -; CHECK-NEXT: [[SINK:%.*]] = select i1 [[CMP3]], ptr [[L_I]], ptr [[L_J]] +; CHECK-NEXT: [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]] +; CHECK-NEXT: br i1 [[CMP3_FROZEN]], label [[SELECT_END1]], label [[SELECT_FALSE_SINK:%.*]] +; CHECK: select.false.sink: +; CHECK-NEXT: [[TMP0:%.*]] = sub nsw i64 [[J]], -1 +; CHECK-NEXT: br label [[SELECT_END1]] +; CHECK: select.end: +; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP0]], [[SELECT_FALSE_SINK]] ] +; CHECK-NEXT: [[SINK:%.*]] = phi ptr [ [[L_I]], [[LOOP]] ], [ [[L_J]], [[SELECT_FALSE_SINK]] ] ; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]] ; CHECK-NEXT: store ptr [[SINK]], ptr [[GEP_DST]], align 8 ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 @@ -676,9 +718,9 @@ define void @test_sub_sext_not_and_regular_select2(ptr %dst, ptr %src, i64 %j.st ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END1:%.*]] ] +; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END1]] ] +; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END1]] ] ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]] ; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX1]], align 8 ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]] @@ -688,10 +730,16 @@ define void @test_sub_sext_not_and_regular_select2(ptr %dst, ptr %src, i64 %j.st ; CHECK-NEXT: [[ARRAYIDX1_I:%.*]] = getelementptr inbounds i64, ptr [[TMP1]], i64 [[P]] ; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[ARRAYIDX1_I]], align 8 ; CHECK-NEXT: [[CMP3:%.*]] = icmp slt i64 [[TMP2]], [[TMP3]] -; CHECK-NEXT: [[DOTSINK:%.*]] = select i1 [[CMP3]], ptr [[TMP0]], ptr [[TMP1]] +; CHECK-NEXT: [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]] +; CHECK-NEXT: br i1 [[CMP3_FROZEN]], label [[SELECT_END1]], label [[SELECT_FALSE:%.*]] +; CHECK: select.false.sink: +; CHECK-NEXT: [[TMP5:%.*]] = sub nsw i64 [[J]], -1 +; CHECK-NEXT: br label [[SELECT_END1]] +; CHECK: select.end: +; CHECK-NEXT: [[DOTSINK:%.*]] = phi ptr [ [[TMP0]], [[LOOP]] ], [ [[TMP1]], [[SELECT_FALSE]] ] +; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP5]], [[SELECT_FALSE]] ] ; CHECK-NEXT: [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true ; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64 -; CHECK-NEXT: [[J_NEXT]] = sub nsw i64 [[J]], [[DEC]] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]] ; CHECK-NEXT: store ptr [[DOTSINK]], ptr [[TMP4]], align 8 ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 |