@@ -2372,7 +2372,7 @@ struct ComputeExpOpByLUTPattern : OpConversionPattern<math::ExpOp> {
23722372 }
23732373};
23742374
2375- // Lower the inverse of a float to a function call
2375+ // Lower the inverse of a float to a function call (CPP backend)
23762376// Convert the pattern-
23772377// %cst = arith.constant 1.000000e+00 : f32
23782378// %0 = arith.divf %cst, %arg1 : f32
@@ -2426,6 +2426,77 @@ struct ComputeInvOpByLUTPattern : OpConversionPattern<arith::DivFOp> {
24262426 }
24272427};
24282428
2429+ // Lower the inverse of a float to aievec.inv (LLVMIR backend for AIE2P)
2430+ // Supports both scalar f32 and vector<Nxf32> types.
2431+ // Convert the pattern-
2432+ // %cst = arith.constant 1.000000e+00 : f32
2433+ // %0 = arith.divf %cst, %arg1 : f32
2434+ // to -
2435+ // %0 = aievec.inv %arg1 : f32
2436+ // Also supports:
2437+ // %cst = arith.constant dense<1.0> : vector<16xf32>
2438+ // %0 = arith.divf %cst, %arg1 : vector<16xf32>
2439+ // to -
2440+ // %0 = aievec.inv %arg1 : vector<16xf32>
2441+ struct ConvertDivFToAIEVecInvOpPattern : OpConversionPattern<arith::DivFOp> {
2442+ using OpConversionPattern::OpConversionPattern;
2443+
2444+ LogicalResult
2445+ matchAndRewrite (arith::DivFOp divOp, OpAdaptor adaptor,
2446+ ConversionPatternRewriter &rewriter) const override {
2447+ Type srcType = adaptor.getLhs ().getType ();
2448+
2449+ // Check if LHS is defined by an operation
2450+ auto *defOp = divOp.getLhs ().getDefiningOp ();
2451+ if (!defOp)
2452+ return failure ();
2453+
2454+ auto constOp = dyn_cast<arith::ConstantOp>(defOp);
2455+ if (!constOp)
2456+ return failure ();
2457+
2458+ // Handle scalar f32 case
2459+ if (auto fType = dyn_cast<FloatType>(srcType)) {
2460+ if (fType .getWidth () != 32 )
2461+ return failure ();
2462+
2463+ auto floatAttr = dyn_cast<FloatAttr>(constOp.getValue ());
2464+ if (!floatAttr || !floatAttr.getValue ().isExactlyValue (1.0 ))
2465+ return failure ();
2466+
2467+ rewriter.replaceOpWithNewOp <aievec::InvOp>(divOp, srcType,
2468+ adaptor.getRhs ());
2469+ return success ();
2470+ }
2471+
2472+ // Handle vector f32 case
2473+ if (auto vecType = dyn_cast<VectorType>(srcType)) {
2474+ auto elemType = vecType.getElementType ();
2475+ if (!elemType.isF32 ())
2476+ return failure ();
2477+
2478+ // Check for supported vector sizes (16 or 32 lanes)
2479+ unsigned laneSize = getVectorLaneSize (vecType);
2480+ if (laneSize != 16 && laneSize != 32 )
2481+ return failure ();
2482+
2483+ // Check if it's a splat of 1.0
2484+ auto denseAttr = dyn_cast<DenseFPElementsAttr>(constOp.getValue ());
2485+ if (!denseAttr || !denseAttr.isSplat ())
2486+ return failure ();
2487+
2488+ if (!denseAttr.getSplatValue <APFloat>().isExactlyValue (1.0 ))
2489+ return failure ();
2490+
2491+ rewriter.replaceOpWithNewOp <aievec::InvOp>(divOp, vecType,
2492+ adaptor.getRhs ());
2493+ return success ();
2494+ }
2495+
2496+ return failure ();
2497+ }
2498+ };
2499+
24292500// Convert math.tanh to a function call to compute tanh(x) by look up tables
24302501struct ComputeTanhOpByLUTPattern : OpConversionPattern<math::TanhOp> {
24312502 using OpConversionPattern::OpConversionPattern;
@@ -3508,6 +3579,7 @@ populateAIEVecV2CommonConversionPatterns(RewritePatternSet &patterns,
35083579 >(patterns.getContext (), 128 , 1024 , 256 , 1024 );
35093580 patterns.add <
35103581 ComputeExpOpByLUTPattern,
3582+ ComputeInvOpByLUTPattern,
35113583 ComputeRsqrtOpPattern,
35123584 LowerVectorAddFOpToAIEVecAddElemOp,
35133585 LowerVectorSubFOpToAIEVecSubElemOp,
@@ -3521,7 +3593,6 @@ populateAIEVecV2CommonConversionPatterns(RewritePatternSet &patterns,
35213593 >(patterns.getContext ());
35223594 }
35233595 patterns.add <
3524- ComputeInvOpByLUTPattern,
35253596 ComputeTanhOpByLUTPattern,
35263597 ComputeSqrtOpAIE2Pattern,
35273598 ComputeErfOpPattern,
@@ -3629,10 +3700,11 @@ static void populateAIEVecV2PConversionPatterns(RewritePatternSet &patterns,
36293700 // AIE2p-specific broadcast pattern that handles 256-bit directly
36303701 patterns.add <ConvertSplatToAIEBroadcastAIE2p>(patterns.getContext ());
36313702 patterns.add <LowerVectorReductionAddBfloat16OpAIE2P>(patterns.getContext ());
3632- // For AIE2P with LLVMIR backend, use aievec.exp
3703+ // For AIE2P with LLVMIR backend, use aievec.exp and aievec.inv
36333704 // math.rsqrt is kept legal and will be lowered in AIEVecToLLVM pass
36343705 if (backend == TargetBackend::LLVMIR ) {
3635- patterns.add <ConvertMathExpToAIEVecExpOpPattern>(patterns.getContext ());
3706+ patterns.add <ConvertMathExpToAIEVecExpOpPattern,
3707+ ConvertDivFToAIEVecInvOpPattern>(patterns.getContext ());
36363708 }
36373709}
36383710
@@ -4066,6 +4138,41 @@ static void configureAIEVecV2PLegalizations(ConversionTarget &target,
40664138
40674139 return false ;
40684140 });
4141+
4142+ // AIE2P-specific legalization for divf 1.0/x pattern with LLVMIR backend
4143+ // Scalar f32 or vector<Nxf32> divf with constant 1.0 LHS is illegal
4144+ target.addDynamicallyLegalOp <arith::DivFOp>([](arith::DivFOp divfOp) {
4145+ Type srcType = divfOp.getLhs ().getType ();
4146+
4147+ // Check if LHS is defined by a constant operation
4148+ auto constOp =
4149+ dyn_cast_or_null<arith::ConstantOp>(divfOp.getLhs ().getDefiningOp ());
4150+ if (!constOp)
4151+ return true ;
4152+
4153+ // Scalar f32 case - check for exactly 1.0
4154+ if (srcType.isF32 ()) {
4155+ auto floatAttr = dyn_cast<FloatAttr>(constOp.getValue ());
4156+ if (floatAttr && floatAttr.getValue ().isExactlyValue (1.0 ))
4157+ return false ; // illegal - will be converted to aievec.inv
4158+ return true ;
4159+ }
4160+
4161+ // Vector f32 case - check for splat of exactly 1.0
4162+ if (auto vecType = dyn_cast<VectorType>(srcType)) {
4163+ if (vecType.getElementType ().isF32 ()) {
4164+ unsigned laneSize = getVectorLaneSize (vecType);
4165+ if (laneSize == 16 || laneSize == 32 ) {
4166+ auto denseAttr = dyn_cast<DenseFPElementsAttr>(constOp.getValue ());
4167+ if (denseAttr && denseAttr.isSplat () &&
4168+ denseAttr.getSplatValue <APFloat>().isExactlyValue (1.0 ))
4169+ return false ; // illegal - will be converted to aievec.inv
4170+ }
4171+ }
4172+ }
4173+
4174+ return true ;
4175+ });
40694176 }
40704177 // For CPP backend, exp remains legal (uses LUT pattern from common patterns)
40714178
0 commit comments