diff --git a/lib/Transforms/Scalar/Reassociate.cpp b/lib/Transforms/Scalar/Reassociate.cpp index 42e7aac9d84..67659bb50b0 100644 --- a/lib/Transforms/Scalar/Reassociate.cpp +++ b/lib/Transforms/Scalar/Reassociate.cpp @@ -2083,14 +2083,9 @@ void Reassociate::OptimizeInst(Instruction *I) { // writing other transformations simpler. if (I->getType()->isFloatingPointTy() || I->getType()->isVectorTy()) { - // FAdd and FMul can be commuted. - unsigned Opcode = I->getOpcode(); - if (Opcode == Instruction::FMul || Opcode == Instruction::FAdd) + if (I->isCommutative()) canonicalizeOperands(I); - // FIXME: We should commute vector instructions as well. However, this - // requires further analysis to determine the effect on later passes. - // Don't try to optimize vector instructions or anything that doesn't have // unsafe algebra. if (I->getType()->isVectorTy() || !I->hasUnsafeAlgebra()) diff --git a/test/Transforms/Reassociate/fast-ReassociateVector.ll b/test/Transforms/Reassociate/fast-ReassociateVector.ll index ab38edae0c4..eeae096bf94 100644 --- a/test/Transforms/Reassociate/fast-ReassociateVector.ll +++ b/test/Transforms/Reassociate/fast-ReassociateVector.ll @@ -11,11 +11,11 @@ define <4 x float> @test1() { ret <4 x float> %tmp2 } -; We don't currently commute integer vector operations. +; Commute integer vector operations. define <2 x i32> @test2(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: test2 ; CHECK-NEXT: %tmp1 = add <2 x i32> %x, %y -; CHECK-NEXT: %tmp2 = add <2 x i32> %y, %x +; CHECK-NEXT: %tmp2 = add <2 x i32> %x, %y ; CHECK-NEXT: %tmp3 = add <2 x i32> %tmp1, %tmp2 %tmp1 = add <2 x i32> %x, %y @@ -23,3 +23,51 @@ define <2 x i32> @test2(<2 x i32> %x, <2 x i32> %y) { %tmp3 = add <2 x i32> %tmp1, %tmp2 ret <2 x i32> %tmp3 } + +define <2 x i32> @test3(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: test3 +; CHECK-NEXT: %tmp1 = mul <2 x i32> %x, %y +; CHECK-NEXT: %tmp2 = mul <2 x i32> %x, %y +; CHECK-NEXT: %tmp3 = mul <2 x i32> %tmp1, %tmp2 + + %tmp1 = mul <2 x i32> %x, %y + %tmp2 = mul <2 x i32> %y, %x + %tmp3 = mul <2 x i32> %tmp1, %tmp2 + ret <2 x i32> %tmp3 +} + +define <2 x i32> @test4(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: test4 +; CHECK-NEXT: %tmp1 = and <2 x i32> %x, %y +; CHECK-NEXT: %tmp2 = and <2 x i32> %x, %y +; CHECK-NEXT: %tmp3 = and <2 x i32> %tmp1, %tmp2 + + %tmp1 = and <2 x i32> %x, %y + %tmp2 = and <2 x i32> %y, %x + %tmp3 = and <2 x i32> %tmp1, %tmp2 + ret <2 x i32> %tmp3 +} + +define <2 x i32> @test5(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: test5 +; CHECK-NEXT: %tmp1 = or <2 x i32> %x, %y +; CHECK-NEXT: %tmp2 = or <2 x i32> %x, %y +; CHECK-NEXT: %tmp3 = or <2 x i32> %tmp1, %tmp2 + + %tmp1 = or <2 x i32> %x, %y + %tmp2 = or <2 x i32> %y, %x + %tmp3 = or <2 x i32> %tmp1, %tmp2 + ret <2 x i32> %tmp3 +} + +define <2 x i32> @test6(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: test6 +; CHECK-NEXT: %tmp1 = xor <2 x i32> %x, %y +; CHECK-NEXT: %tmp2 = xor <2 x i32> %x, %y +; CHECK-NEXT: %tmp3 = xor <2 x i32> %tmp1, %tmp2 + + %tmp1 = xor <2 x i32> %x, %y + %tmp2 = xor <2 x i32> %y, %x + %tmp3 = xor <2 x i32> %tmp1, %tmp2 + ret <2 x i32> %tmp3 +}