Index: lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp =================================================================== --- lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp +++ lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp @@ -53,9 +53,16 @@ case Instruction::And: case Instruction::Or: case Instruction::Xor: + case Instruction::ShuffleVector: Ops.push_back(I->getOperand(0)); Ops.push_back(I->getOperand(1)); break; + case Instruction::Select: { + SelectInst *SI = cast(I); + Ops.push_back(SI->getTrueValue()); + Ops.push_back(SI->getFalseValue()); + break; + } default: llvm_unreachable("Unreachable!"); } @@ -114,7 +121,9 @@ case Instruction::Mul: case Instruction::And: case Instruction::Or: - case Instruction::Xor: { + case Instruction::Xor: + case Instruction::Select: + case Instruction::ShuffleVector: { SmallVector Operands; getRelevantOperands(I, Operands); for (Value *Operand : Operands) @@ -123,10 +132,10 @@ } default: // TODO: Can handle more cases here: - // 1. select, shufflevector, extractelement, insertelement - // 2. udiv, urem - // 3. shl, lshr, ashr - // 4. phi node(and loop handling) + // 1. udiv, urem + // 2. shl, lshr, ashr + // 3. phi node(and loop handling) + // 4. extractelement, insertelement // ... return false; } @@ -343,6 +352,20 @@ Res = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS); break; } + case Instruction::Select: { + SelectInst *SI = cast(I); + Value *TrueValue = getReducedOperand(SI->getTrueValue(), SclTy); + Value *FalseValue = getReducedOperand(SI->getFalseValue(), SclTy); + Res = Builder.CreateSelect(SI->getCondition(), TrueValue, FalseValue); + break; + } + case Instruction::ShuffleVector: { + ShuffleVectorInst *SI = cast(I); + Value *LHS = getReducedOperand(I->getOperand(0), SclTy); + Value *RHS = getReducedOperand(I->getOperand(1), SclTy); + Res = Builder.CreateShuffleVector(LHS, RHS, SI->getMask()); + break; + } default: llvm_unreachable("Unhandled instruction"); } Index: test/Transforms/AggressiveInstCombine/trunc_multi_uses.ll =================================================================== --- test/Transforms/AggressiveInstCombine/trunc_multi_uses.ll +++ test/Transforms/AggressiveInstCombine/trunc_multi_uses.ll @@ -114,6 +114,29 @@ ret void } +define void @multi_uses_select(i32 %X, i32 %Y, i1 %COND) { +; CHECK-LABEL: @multi_uses_select( +; CHECK-NEXT: [[A1:%.*]] = zext i32 [[X:%.*]] to i64 +; CHECK-NEXT: [[A2:%.*]] = zext i32 [[Y:%.*]] to i64 +; CHECK-NEXT: [[B1:%.*]] = select i1 [[COND:%.*]], i32 [[X]], i32 [[Y]] +; CHECK-NEXT: [[C1:%.*]] = mul i32 [[B1]], [[B1]] +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use32(i32 [[C1]]) +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use64(i64 [[A1]]) +; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use64(i64 [[A2]]) +; CHECK-NEXT: ret void +; + %A1 = zext i32 %X to i64 + %A2 = zext i32 %Y to i64 + %B1 = select i1 %COND, i64 %A1, i64 %A2 + %C1 = mul i64 %B1, %B1 + %T1 = trunc i64 %C1 to i32 + call i32 @use32(i32 %T1) + ; make sure zext have another use that is not post-dominated by the TruncInst. + call i32 @use64(i64 %A1) + call i32 @use64(i64 %A2) + ret void +} + define void @multi_use_vec_add(<2 x i32> %X) { ; CHECK-LABEL: @multi_use_vec_add( ; CHECK-NEXT: [[A1:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64> @@ -212,3 +235,50 @@ call <2 x i32> @use64_vec(<2 x i64> %A2) ret void } + +define void @multi_use_vec_select(<2 x i32> %X, <2 x i32> %Y, <2 x i1> %COND) { +; CHECK-LABEL: @multi_use_vec_select( +; CHECK-NEXT: [[A1:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64> +; CHECK-NEXT: [[A2:%.*]] = zext <2 x i32> [[Y:%.*]] to <2 x i64> +; CHECK-NEXT: [[B1:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i32> [[X]], <2 x i32> [[Y]] +; CHECK-NEXT: [[C1:%.*]] = mul <2 x i32> [[B1]], [[B1]] +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @use32_vec(<2 x i32> [[C1]]) +; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i32> @use64_vec(<2 x i64> [[A1]]) +; CHECK-NEXT: [[TMP3:%.*]] = call <2 x i32> @use64_vec(<2 x i64> [[A2]]) +; CHECK-NEXT: ret void +; + %A1 = zext <2 x i32> %X to <2 x i64> + %A2 = zext <2 x i32> %Y to <2 x i64> + %B1 = select <2 x i1> %COND, <2 x i64> %A1, <2 x i64> %A2 + %C1 = mul <2 x i64> %B1, %B1 + %T1 = trunc <2 x i64> %C1 to <2 x i32> + call <2 x i32> @use32_vec(<2 x i32> %T1) + ; make sure zext have another use that is not post-dominated by the TruncInst. + call <2 x i32> @use64_vec(<2 x i64> %A1) + call <2 x i32> @use64_vec(<2 x i64> %A2) + ret void +} + +define void @multi_use_vec_shufflevector(<2 x i32> %X, <2 x i32> %Y) { +; CHECK-LABEL: @multi_use_vec_shufflevector( +; CHECK-NEXT: [[A1:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64> +; CHECK-NEXT: [[A2:%.*]] = zext <2 x i32> [[Y:%.*]] to <2 x i64> +; CHECK-NEXT: [[B1:%.*]] = shufflevector <2 x i32> [[X]], <2 x i32> [[Y]], <2 x i32> +; CHECK-NEXT: [[C1:%.*]] = mul <2 x i32> [[B1]], [[B1]] +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @use32_vec(<2 x i32> [[C1]]) +; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i32> @use64_vec(<2 x i64> [[A1]]) +; CHECK-NEXT: [[TMP3:%.*]] = call <2 x i32> @use64_vec(<2 x i64> [[A2]]) +; CHECK-NEXT: ret void +; + %A1 = zext <2 x i32> %X to <2 x i64> + %A2 = zext <2 x i32> %Y to <2 x i64> + %B1 = shufflevector <2 x i64> %A1, <2 x i64> %A2, <2 x i32> + %C1 = mul <2 x i64> %B1, %B1 + %T1 = trunc <2 x i64> %C1 to <2 x i32> + call <2 x i32> @use32_vec(<2 x i32> %T1) + ; make sure zext have another use that is not post-dominated by the TruncInst. + call <2 x i32> @use64_vec(<2 x i64> %A1) + call <2 x i32> @use64_vec(<2 x i64> %A2) + ret void +} +